瀏覽代碼

Added EZAudio framework, already listing available audio input devices and storing selection. Visualization still missing.

Thomas Buck 9 年之前
父節點
當前提交
2c1b62156b
共有 5 個文件被更改,包括 277 次插入23 次删除
  1. 62
    2
      CaseLights.xcodeproj/project.pbxproj
  2. 6
    1
      CaseLights/AppDelegate.h
  3. 201
    18
      CaseLights/AppDelegate.m
  4. 7
    1
      CaseLights/Base.lproj/MainMenu.xib
  5. 1
    1
      CaseLights/Info.plist

+ 62
- 2
CaseLights.xcodeproj/project.pbxproj 查看文件

@@ -7,6 +7,8 @@
7 7
 	objects = {
8 8
 
9 9
 /* Begin PBXBuildFile section */
10
+		E9101B871C36B11500720A6E /* EZAudioOSX.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E9101B831C36B0C100720A6E /* EZAudioOSX.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
11
+		E9101B881C36B4B100720A6E /* EZAudioOSX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9101B831C36B0C100720A6E /* EZAudioOSX.framework */; };
10 12
 		E9109B111C2AACF400726111 /* SystemInfoKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9109B0B1C2AAC1B00726111 /* SystemInfoKit.framework */; };
11 13
 		E9109B151C2AAEFD00726111 /* SystemInfoKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E9109B0B1C2AAC1B00726111 /* SystemInfoKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
12 14
 		E9109B191C2AAFE100726111 /* GPUStats.m in Sources */ = {isa = PBXBuildFile; fileRef = E9109B181C2AAFE100726111 /* GPUStats.m */; };
@@ -19,6 +21,27 @@
19 21
 /* End PBXBuildFile section */
20 22
 
21 23
 /* Begin PBXContainerItemProxy section */
24
+		E9101B801C36B0C100720A6E /* PBXContainerItemProxy */ = {
25
+			isa = PBXContainerItemProxy;
26
+			containerPortal = E9101B7B1C36B0C100720A6E /* EZAudio.xcodeproj */;
27
+			proxyType = 2;
28
+			remoteGlobalIDString = 469F4CF31B749F7800666A46;
29
+			remoteInfo = EZAudioiOS;
30
+		};
31
+		E9101B821C36B0C100720A6E /* PBXContainerItemProxy */ = {
32
+			isa = PBXContainerItemProxy;
33
+			containerPortal = E9101B7B1C36B0C100720A6E /* EZAudio.xcodeproj */;
34
+			proxyType = 2;
35
+			remoteGlobalIDString = 8A5A4B9C1BBBDCB200A8A048;
36
+			remoteInfo = EZAudioOSX;
37
+		};
38
+		E9101B851C36B10C00720A6E /* PBXContainerItemProxy */ = {
39
+			isa = PBXContainerItemProxy;
40
+			containerPortal = E9101B7B1C36B0C100720A6E /* EZAudio.xcodeproj */;
41
+			proxyType = 1;
42
+			remoteGlobalIDString = 8A5A4B9B1BBBDCB200A8A048;
43
+			remoteInfo = EZAudioOSX;
44
+		};
22 45
 		E9109B0A1C2AAC1B00726111 /* PBXContainerItemProxy */ = {
23 46
 			isa = PBXContainerItemProxy;
24 47
 			containerPortal = E9109B051C2AAC1B00726111 /* SystemInfoKit.xcodeproj */;
@@ -49,6 +72,7 @@
49 72
 			dstPath = "";
50 73
 			dstSubfolderSpec = 10;
51 74
 			files = (
75
+				E9101B871C36B11500720A6E /* EZAudioOSX.framework in CopyFiles */,
52 76
 				E9109B151C2AAEFD00726111 /* SystemInfoKit.framework in CopyFiles */,
53 77
 			);
54 78
 			runOnlyForDeploymentPostprocessing = 0;
@@ -56,6 +80,7 @@
56 80
 /* End PBXCopyFilesBuildPhase section */
57 81
 
58 82
 /* Begin PBXFileReference section */
83
+		E9101B7B1C36B0C100720A6E /* EZAudio.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = EZAudio.xcodeproj; path = EZAudio/EZAudio.xcodeproj; sourceTree = "<group>"; };
59 84
 		E9109B051C2AAC1B00726111 /* SystemInfoKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SystemInfoKit.xcodeproj; path = JSystemInfoKit/SystemInfoKit.xcodeproj; sourceTree = "<group>"; };
60 85
 		E9109B171C2AAFE100726111 /* GPUStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUStats.h; path = CaseLights/GPUStats.h; sourceTree = "<group>"; };
61 86
 		E9109B181C2AAFE100726111 /* GPUStats.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUStats.m; path = CaseLights/GPUStats.m; sourceTree = "<group>"; };
@@ -78,12 +103,22 @@
78 103
 			buildActionMask = 2147483647;
79 104
 			files = (
80 105
 				E9109B111C2AACF400726111 /* SystemInfoKit.framework in Frameworks */,
106
+				E9101B881C36B4B100720A6E /* EZAudioOSX.framework in Frameworks */,
81 107
 			);
82 108
 			runOnlyForDeploymentPostprocessing = 0;
83 109
 		};
84 110
 /* End PBXFrameworksBuildPhase section */
85 111
 
86 112
 /* Begin PBXGroup section */
113
+		E9101B7C1C36B0C100720A6E /* Products */ = {
114
+			isa = PBXGroup;
115
+			children = (
116
+				E9101B811C36B0C100720A6E /* EZAudioiOS.framework */,
117
+				E9101B831C36B0C100720A6E /* EZAudioOSX.framework */,
118
+			);
119
+			name = Products;
120
+			sourceTree = "<group>";
121
+		};
87 122
 		E9109B061C2AAC1B00726111 /* Products */ = {
88 123
 			isa = PBXGroup;
89 124
 			children = (
@@ -110,6 +145,7 @@
110 145
 		E9F13DF51C28B3D3004C6B95 = {
111 146
 			isa = PBXGroup;
112 147
 			children = (
148
+				E9101B7B1C36B0C100720A6E /* EZAudio.xcodeproj */,
113 149
 				E9109B051C2AAC1B00726111 /* SystemInfoKit.xcodeproj */,
114 150
 				E9F13E001C28B3D3004C6B95 /* CaseLights */,
115 151
 				E9F13DFF1C28B3D3004C6B95 /* Products */,
@@ -162,6 +198,7 @@
162 198
 			buildRules = (
163 199
 			);
164 200
 			dependencies = (
201
+				E9101B861C36B10C00720A6E /* PBXTargetDependency */,
165 202
 				E9109B131C2AAD2E00726111 /* PBXTargetDependency */,
166 203
 			);
167 204
 			name = CaseLights;
@@ -196,6 +233,10 @@
196 233
 			projectDirPath = "";
197 234
 			projectReferences = (
198 235
 				{
236
+					ProductGroup = E9101B7C1C36B0C100720A6E /* Products */;
237
+					ProjectRef = E9101B7B1C36B0C100720A6E /* EZAudio.xcodeproj */;
238
+				},
239
+				{
199 240
 					ProductGroup = E9109B061C2AAC1B00726111 /* Products */;
200 241
 					ProjectRef = E9109B051C2AAC1B00726111 /* SystemInfoKit.xcodeproj */;
201 242
 				},
@@ -208,6 +249,20 @@
208 249
 /* End PBXProject section */
209 250
 
210 251
 /* Begin PBXReferenceProxy section */
252
+		E9101B811C36B0C100720A6E /* EZAudioiOS.framework */ = {
253
+			isa = PBXReferenceProxy;
254
+			fileType = wrapper.framework;
255
+			path = EZAudioiOS.framework;
256
+			remoteRef = E9101B801C36B0C100720A6E /* PBXContainerItemProxy */;
257
+			sourceTree = BUILT_PRODUCTS_DIR;
258
+		};
259
+		E9101B831C36B0C100720A6E /* EZAudioOSX.framework */ = {
260
+			isa = PBXReferenceProxy;
261
+			fileType = wrapper.framework;
262
+			path = EZAudioOSX.framework;
263
+			remoteRef = E9101B821C36B0C100720A6E /* PBXContainerItemProxy */;
264
+			sourceTree = BUILT_PRODUCTS_DIR;
265
+		};
211 266
 		E9109B0B1C2AAC1B00726111 /* SystemInfoKit.framework */ = {
212 267
 			isa = PBXReferenceProxy;
213 268
 			fileType = wrapper.framework;
@@ -269,6 +324,11 @@
269 324
 /* End PBXSourcesBuildPhase section */
270 325
 
271 326
 /* Begin PBXTargetDependency section */
327
+		E9101B861C36B10C00720A6E /* PBXTargetDependency */ = {
328
+			isa = PBXTargetDependency;
329
+			name = EZAudioOSX;
330
+			targetProxy = E9101B851C36B10C00720A6E /* PBXContainerItemProxy */;
331
+		};
272 332
 		E9109B131C2AAD2E00726111 /* PBXTargetDependency */ = {
273 333
 			isa = PBXTargetDependency;
274 334
 			name = SystemInfoKit;
@@ -377,7 +437,7 @@
377 437
 				MACOSX_DEPLOYMENT_TARGET = 10.8;
378 438
 				PRODUCT_BUNDLE_IDENTIFIER = de.xythobuz.CaseLights;
379 439
 				PRODUCT_NAME = "$(TARGET_NAME)";
380
-				USER_HEADER_SEARCH_PATHS = "JSystemInfoKit/**";
440
+				USER_HEADER_SEARCH_PATHS = "JSystemInfoKit/** EZAudio/EZAudio/**";
381 441
 			};
382 442
 			name = Debug;
383 443
 		};
@@ -392,7 +452,7 @@
392 452
 				MACOSX_DEPLOYMENT_TARGET = 10.8;
393 453
 				PRODUCT_BUNDLE_IDENTIFIER = de.xythobuz.CaseLights;
394 454
 				PRODUCT_NAME = "$(TARGET_NAME)";
395
-				USER_HEADER_SEARCH_PATHS = "JSystemInfoKit/**";
455
+				USER_HEADER_SEARCH_PATHS = "JSystemInfoKit/** EZAudio/EZAudio/**";
396 456
 			};
397 457
 			name = Release;
398 458
 		};

+ 6
- 1
CaseLights/AppDelegate.h 查看文件

@@ -8,9 +8,12 @@
8 8
 
9 9
 #import <Cocoa/Cocoa.h>
10 10
 
11
+#import "EZAudio.h"
12
+#import "SystemInfoKit/SystemInfoKit.h"
13
+
11 14
 @class Serial;
12 15
 
13
-@interface AppDelegate : NSObject <NSApplicationDelegate>
16
+@interface AppDelegate : NSObject <NSApplicationDelegate, EZMicrophoneDelegate>
14 17
 
15 18
 @property (weak) IBOutlet NSMenu *statusMenu;
16 19
 @property (weak) IBOutlet NSApplication *application;
@@ -20,6 +23,8 @@
20 23
 @property (weak) IBOutlet NSMenu *menuVisualizations;
21 24
 @property (weak) IBOutlet NSMenuItem *menuItemDisplays;
22 25
 @property (weak) IBOutlet NSMenu *menuDisplays;
26
+@property (weak) IBOutlet NSMenuItem *menuItemAudio;
27
+@property (weak) IBOutlet NSMenu *menuAudio;
23 28
 @property (weak) IBOutlet NSMenu *menuPorts;
24 29
 
25 30
 @property (weak) IBOutlet NSMenuItem *buttonOff;

+ 201
- 18
CaseLights/AppDelegate.m 查看文件

@@ -11,10 +11,10 @@
11 11
 #import "GPUStats.h"
12 12
 #import "Screenshot.h"
13 13
 
14
-#import "SystemInfoKit/SystemInfoKit.h"
15
-
14
+// These are the values stored persistently in the preferences
16 15
 #define PREF_SERIAL_PORT @"SerialPort"
17 16
 #define PREF_LIGHTS_STATE @"LightState"
17
+// LED Mode contains the last selected mode as menu item text
18 18
 #define PREF_LED_MODE @"LEDMode"
19 19
 #define PREF_BRIGHTNESS @"Brightness"
20 20
 #define PREF_COLOR @"ManualColor"
@@ -29,7 +29,9 @@
29 29
 #define TEXT_RGB_FADE @"RGB Fade"
30 30
 #define TEXT_HSV_FADE @"HSV Fade"
31 31
 #define TEXT_RANDOM @"Random"
32
+#define TEXT_TEMPLATE_AUDIO @"AudioDevice_%@"
32 33
 
34
+// SMC keys are checked for existence and used for reading
33 35
 #define KEY_CPU_TEMPERATURE @"TC0D"
34 36
 #define KEY_GPU_TEMPERATURE @"TG0D"
35 37
 
@@ -53,6 +55,11 @@
53 55
 #define AVERAGE_COLOR_PERFORMANCE_INC 10
54 56
 #define DISPLAY_DELAY 0.1
55 57
 
58
+// Used to identify selected menu items
59
+// displays are all tags >= 0
60
+#define MENU_ITEM_TAG_NOTHING -1
61
+#define MENU_ITEM_TAG_AUDIO -2
62
+
56 63
 @interface AppDelegate ()
57 64
 
58 65
 @property (strong) NSStatusItem *statusItem;
@@ -61,6 +68,7 @@
61 68
 @property (strong) NSTimer *animation;
62 69
 @property (strong) Serial *serial;
63 70
 @property (strong) NSMenuItem *lastLEDMode;
71
+@property (strong) EZMicrophone *microphone;
64 72
 
65 73
 @end
66 74
 
@@ -69,11 +77,12 @@
69 77
 @synthesize statusMenu, application;
70 78
 @synthesize menuColors, menuAnimations, menuVisualizations, menuPorts;
71 79
 @synthesize menuItemDisplays, menuDisplays;
80
+@synthesize menuItemAudio, menuAudio;
72 81
 @synthesize buttonOff, buttonLights;
73 82
 @synthesize brightnessItem, brightnessSlider, brightnessLabel;
74 83
 @synthesize statusItem, statusImage;
75 84
 @synthesize staticColors, animation;
76
-@synthesize serial, lastLEDMode;
85
+@synthesize serial, lastLEDMode, microphone;
77 86
 @synthesize menuItemColor;
78 87
 
79 88
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
@@ -82,6 +91,7 @@
82 91
     serial = [[Serial alloc] init];
83 92
     lastLEDMode = nil;
84 93
     animation = nil;
94
+    microphone = nil;
85 95
     
86 96
     // Prepare status bar menu
87 97
     statusImage = [NSImage imageNamed:@"MenuIcon"];
@@ -120,7 +130,7 @@
120 130
         for (int i = 0; i < [ports count]; i++) {
121 131
             // Add Menu Item for this port
122 132
             NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[ports objectAtIndex:i] action:@selector(selectedSerialPort:) keyEquivalent:@""];
123
-            [item setTag:-1];
133
+            [item setTag:MENU_ITEM_TAG_NOTHING];
124 134
             [menuPorts addItem:item];
125 135
             
126 136
             // Set Enabled if it was used the last time
@@ -155,7 +165,7 @@
155 165
                     nil];
156 166
     for (NSString *key in [staticColors allKeys]) {
157 167
         NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:key action:@selector(selectedVisualization:) keyEquivalent:@""];
158
-        [item setTag:-1];
168
+        [item setTag:MENU_ITEM_TAG_NOTHING];
159 169
         if ([key isEqualToString:lastMode]) {
160 170
             [self selectedVisualization:item];
161 171
         }
@@ -169,7 +179,7 @@
169 179
         }
170 180
         [menuItemColor setState:NSOnState];
171 181
     }
172
-    [menuItemColor setTag:-1];
182
+    [menuItemColor setTag:MENU_ITEM_TAG_NOTHING];
173 183
     [menuColors addItem:menuItemColor];
174 184
     
175 185
     // Prepare animations menu
@@ -180,7 +190,7 @@
180 190
                                  nil];
181 191
     for (NSString *key in animationStrings) {
182 192
         NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:key action:@selector(selectedVisualization:) keyEquivalent:@""];
183
-        [item setTag:-1];
193
+        [item setTag:MENU_ITEM_TAG_NOTHING];
184 194
         if ([key isEqualToString:lastMode]) {
185 195
             [self selectedVisualization:item];
186 196
         }
@@ -189,7 +199,7 @@
189 199
     
190 200
     // Add CPU Usage menu item
191 201
     NSMenuItem *cpuUsageItem = [[NSMenuItem alloc] initWithTitle:TEXT_CPU_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
192
-    [cpuUsageItem setTag:-1];
202
+    [cpuUsageItem setTag:MENU_ITEM_TAG_NOTHING];
193 203
     if ([lastMode isEqualToString:TEXT_CPU_USAGE]) {
194 204
         [self selectedVisualization:cpuUsageItem];
195 205
     }
@@ -197,7 +207,7 @@
197 207
     
198 208
     // Add Memory Usage item
199 209
     NSMenuItem *memoryUsageItem = [[NSMenuItem alloc] initWithTitle:TEXT_RAM_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
200
-    [memoryUsageItem setTag:-1];
210
+    [memoryUsageItem setTag:MENU_ITEM_TAG_NOTHING];
201 211
     if ([lastMode isEqualToString:TEXT_RAM_USAGE]) {
202 212
         [self selectedVisualization:memoryUsageItem];
203 213
     }
@@ -211,14 +221,14 @@
211 221
         NSLog(@"Error reading GPU information\n");
212 222
     } else {
213 223
         NSMenuItem *itemUsage = [[NSMenuItem alloc] initWithTitle:TEXT_GPU_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
214
-        [itemUsage setTag:-1];
224
+        [itemUsage setTag:MENU_ITEM_TAG_NOTHING];
215 225
         if ([lastMode isEqualToString:TEXT_GPU_USAGE]) {
216 226
             [self selectedVisualization:itemUsage];
217 227
         }
218 228
         [menuVisualizations addItem:itemUsage];
219 229
         
220 230
         NSMenuItem *itemVRAM = [[NSMenuItem alloc] initWithTitle:TEXT_VRAM_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
221
-        [itemVRAM setTag:-1];
231
+        [itemVRAM setTag:MENU_ITEM_TAG_NOTHING];
222 232
         if ([lastMode isEqualToString:TEXT_VRAM_USAGE]) {
223 233
             [self selectedVisualization:itemVRAM];
224 234
         }
@@ -237,7 +247,7 @@
237 247
 
238 248
         if ([key isEqualToString:KEY_CPU_TEMPERATURE]) {
239 249
             NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:TEXT_CPU_TEMPERATURE action:@selector(selectedVisualization:) keyEquivalent:@""];
240
-            [item setTag:-1];
250
+            [item setTag:MENU_ITEM_TAG_NOTHING];
241 251
             if ([lastMode isEqualToString:TEXT_CPU_TEMPERATURE]) {
242 252
                 [self selectedVisualization:item];
243 253
             }
@@ -246,7 +256,7 @@
246 256
         
247 257
         if ([key isEqualToString:KEY_GPU_TEMPERATURE]) {
248 258
             NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:TEXT_GPU_TEMPERATURE action:@selector(selectedVisualization:) keyEquivalent:@""];
249
-            [item setTag:-1];
259
+            [item setTag:MENU_ITEM_TAG_NOTHING];
250 260
             if ([lastMode isEqualToString:TEXT_GPU_TEMPERATURE]) {
251 261
                 [self selectedVisualization:item];
252 262
             }
@@ -273,6 +283,28 @@
273 283
     [Screenshot init:self];
274 284
     NSArray *displayIDs = [Screenshot listDisplays];
275 285
     [self updateDisplayUI:displayIDs];
286
+    
287
+    // List available audio input devices and add menu items
288
+    NSArray *inputDevices = [EZAudioDevice inputDevices];
289
+    [menuAudio removeAllItems];
290
+    for (int i = 0; i < [inputDevices count]; i++) {
291
+        EZAudioDevice *dev = [inputDevices objectAtIndex:i];
292
+        
293
+#ifdef DEBUG
294
+        NSLog(@"Audio input device: \"%@\"\n", [dev name]);
295
+#endif
296
+        
297
+        NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[dev name] action:@selector(selectedVisualization:) keyEquivalent:@""];
298
+        [item setTag:MENU_ITEM_TAG_AUDIO];
299
+        NSString *lastModeString = [NSString stringWithFormat:TEXT_TEMPLATE_AUDIO, [dev name]];
300
+        if ([lastModeString isEqualToString:lastMode]) {
301
+            [self selectedVisualization:item];
302
+        }
303
+        [menuAudio addItem:item];
304
+    }
305
+    if ([inputDevices count] > 0) {
306
+        [menuItemAudio setHidden:NO];
307
+    }
276 308
 }
277 309
 
278 310
 - (void)applicationWillTerminate:(NSNotification *)aNotification {
@@ -282,6 +314,12 @@
282 314
         animation = nil;
283 315
     }
284 316
     
317
+    // Stop previous audio data retrieval
318
+    if (microphone != nil) {
319
+        [microphone stopFetchingAudio];
320
+        microphone = nil;
321
+    }
322
+    
285 323
     // Remove display callback
286 324
     [Screenshot close:self];
287 325
     
@@ -337,6 +375,12 @@
337 375
         animation = nil;
338 376
     }
339 377
     
378
+    // Stop previous audio data retrieval
379
+    if (microphone != nil) {
380
+        [microphone stopFetchingAudio];
381
+        microphone = nil;
382
+    }
383
+    
340 384
     // Turn off all other LED menu items
341 385
     if (menuColors != nil) {
342 386
         for (int i = 0; i < [menuColors numberOfItems]; i++) {
@@ -353,6 +397,11 @@
353 397
             [[menuVisualizations itemAtIndex:i] setState:NSOffState];
354 398
         }
355 399
     }
400
+    if (menuAudio != nil) {
401
+        for (int i = 0; i < [menuAudio numberOfItems]; i++) {
402
+            [[menuAudio itemAtIndex:i] setState:NSOffState];
403
+        }
404
+    }
356 405
     if (menuDisplays != nil) {
357 406
         for (int i = 0; i < [menuDisplays numberOfItems]; i++) {
358 407
             [[menuDisplays itemAtIndex:i] setState:NSOffState];
@@ -383,13 +432,32 @@
383 432
 }
384 433
 
385 434
 - (IBAction)relistSerialPorts:(id)sender {
435
+    // Refill audio device list
436
+    NSArray *inputDevices = [EZAudioDevice inputDevices];
437
+    [menuAudio removeAllItems];
438
+    for (int i = 0; i < [inputDevices count]; i++) {
439
+        EZAudioDevice *dev = [inputDevices objectAtIndex:i];
440
+        NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[dev name] action:@selector(selectedVisualization:) keyEquivalent:@""];
441
+        [item setTag:MENU_ITEM_TAG_AUDIO];
442
+        NSString *lastModeString = [NSString stringWithFormat:TEXT_TEMPLATE_AUDIO, [dev name]];
443
+        if ([lastModeString isEqualToString:[[NSUserDefaults standardUserDefaults] stringForKey:PREF_LED_MODE]]) {
444
+            [self selectedVisualization:item];
445
+        }
446
+        [menuAudio addItem:item];
447
+    }
448
+    if ([inputDevices count] > 0) {
449
+        [menuItemAudio setHidden:NO];
450
+    } else {
451
+        [menuItemAudio setHidden:YES];
452
+    }
453
+    
386 454
     // Refill port list
387 455
     NSArray *ports = [Serial listSerialPorts];
388 456
     [menuPorts removeAllItems];
389 457
     for (int i = 0; i < [ports count]; i++) {
390 458
         // Add Menu Item for this port
391 459
         NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[ports objectAtIndex:i] action:@selector(selectedSerialPort:) keyEquivalent:@""];
392
-        [item setTag:-1];
460
+        [item setTag:MENU_ITEM_TAG_NOTHING];
393 461
         [menuPorts addItem:item];
394 462
         
395 463
         // Mark it if it is currently open
@@ -422,7 +490,7 @@
422 490
     [application orderFrontColorPanel:cp];
423 491
 }
424 492
 
425
-- (void)colorSelected:(id)sender {
493
+- (void)colorSelected:(NSColorPanel *)sender {
426 494
     [self setLightsColor:[sender color]];
427 495
 }
428 496
 
@@ -451,6 +519,12 @@
451 519
             [animation invalidate];
452 520
             animation = nil;
453 521
         }
522
+        
523
+        // Stop previous audio data retrieval
524
+        if (microphone != nil) {
525
+            [microphone stopFetchingAudio];
526
+            microphone = nil;
527
+        }
454 528
 
455 529
         // Turn off all other LED menu items
456 530
         for (int i = 0; i < [menuColors numberOfItems]; i++) {
@@ -471,6 +545,12 @@
471 545
             }
472 546
             [[menuVisualizations itemAtIndex:i] setState:NSOffState];
473 547
         }
548
+        for (int i = 0; i < [menuAudio numberOfItems]; i++) {
549
+            if ([[menuAudio itemAtIndex:i] state] == NSOnState) {
550
+                lastLEDMode = [menuAudio itemAtIndex:i];
551
+            }
552
+            [[menuAudio itemAtIndex:i] setState:NSOffState];
553
+        }
474 554
         for (int i = 0; i < [menuDisplays numberOfItems]; i++) {
475 555
             if ([[menuDisplays itemAtIndex:i] state] == NSOnState) {
476 556
                 lastLEDMode = [menuDisplays itemAtIndex:i];
@@ -530,6 +610,12 @@
530 610
         animation = nil;
531 611
     }
532 612
     
613
+    // Stop previous audio data retrieval
614
+    if (microphone != nil) {
615
+        [microphone stopFetchingAudio];
616
+        microphone = nil;
617
+    }
618
+    
533 619
     // Schedule next invocation for this animation...
534 620
     if ([mode isEqualToString:TEXT_GPU_USAGE]) {
535 621
         animation = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(visualizeGPUUsage:) userInfo:mode repeats:YES];
@@ -569,6 +655,12 @@
569 655
         animation = nil;
570 656
     }
571 657
     
658
+    // Stop previous audio data retrieval
659
+    if (microphone != nil) {
660
+        [microphone stopFetchingAudio];
661
+        microphone = nil;
662
+    }
663
+    
572 664
     // Schedule next invocation for this animation...
573 665
     animation = [NSTimer scheduledTimerWithTimeInterval:DISPLAY_DELAY target:self selector:@selector(visualizeDisplay:) userInfo:[NSNumber numberWithInteger:[sender tag]] repeats:YES];
574 666
     
@@ -593,6 +685,11 @@
593 685
             [[menuVisualizations itemAtIndex:i] setState:NSOffState];
594 686
         }
595 687
     }
688
+    if (menuAudio != nil) {
689
+        for (int i = 0; i < [menuAudio numberOfItems]; i++) {
690
+            [[menuAudio itemAtIndex:i] setState:NSOffState];
691
+        }
692
+    }
596 693
     if (menuDisplays != nil) {
597 694
         for (int i = 0; i < [menuDisplays numberOfItems]; i++) {
598 695
             [[menuDisplays itemAtIndex:i] setState:NSOffState];
@@ -603,13 +700,40 @@
603 700
     
604 701
     // Check if it is a display
605 702
     BOOL found = NO;
606
-    if ([sender tag] > -1) {
703
+    if ([sender tag] > MENU_ITEM_TAG_NOTHING) {
607 704
         found = YES;
608 705
         [self displayVisualization:sender];
609 706
     }
610 707
     
708
+    // Check if it is an audio input device
709
+    if ((found == NO) && ([sender tag] == MENU_ITEM_TAG_AUDIO)) {
710
+        found = YES;
711
+        BOOL foundDev = NO;
712
+        NSArray *audioDevices = [EZAudioDevice inputDevices];
713
+        for (int  i = 0; i < [audioDevices count]; i++) {
714
+            EZAudioDevice *dev = [audioDevices objectAtIndex:i];
715
+            if ([[dev name] isEqualToString:[sender title]]) {
716
+                // Found device
717
+                foundDev = YES;
718
+                if (microphone != nil) {
719
+                    [microphone stopFetchingAudio];
720
+                    microphone = nil;
721
+                }
722
+                microphone = [EZMicrophone microphoneWithDelegate:self];
723
+                [microphone setDevice:dev];
724
+                [microphone startFetchingAudio];
725
+                break;
726
+            }
727
+        }
728
+        if (foundDev == NO) {
729
+            NSLog(@"Couldn't find device \"%@\"\n", [sender title]);
730
+            [sender setState:NSOffState];
731
+            return; // Don't store new mode
732
+        }
733
+    }
734
+    
611 735
     // Check if it is the manual color select item
612
-    if ([sender.title isEqualToString:TEXT_MANUAL]) {
736
+    if ((found == NO) && ([sender.title isEqualToString:TEXT_MANUAL])) {
613 737
         found = YES;
614 738
         [self colorSelected:[NSColorPanel sharedColorPanel]];
615 739
     }
@@ -626,6 +750,12 @@
626 750
                     animation = nil;
627 751
                 }
628 752
                 
753
+                // Stop previous audio data retrieval
754
+                if (microphone != nil) {
755
+                    [microphone stopFetchingAudio];
756
+                    microphone = nil;
757
+                }
758
+                
629 759
                 NSColor *color = [staticColors valueForKey:key];
630 760
                 unsigned char red = [color redComponent] * 255;
631 761
                 unsigned char green = [color greenComponent] * 255;
@@ -647,7 +777,13 @@
647 777
     
648 778
     // Store changed value in preferences
649 779
     NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
650
-    [store setObject:[sender title] forKey:PREF_LED_MODE];
780
+    if ([sender tag] == MENU_ITEM_TAG_AUDIO) {
781
+        // Prepend text for audio device names
782
+        NSString *tmp = [NSString stringWithFormat:TEXT_TEMPLATE_AUDIO, [sender title]];
783
+        [store setObject:tmp forKey:PREF_LED_MODE];
784
+    } else {
785
+        [store setObject:[sender title] forKey:PREF_LED_MODE];
786
+    }
651 787
     [store synchronize];
652 788
     
653 789
 #ifdef DEBUG
@@ -695,6 +831,16 @@
695 831
                 [self selectedVisualization:[menuVisualizations itemAtIndex:i]];
696 832
             }
697 833
         }
834
+        for (int i = 0; i < [menuAudio numberOfItems]; i++) {
835
+            if ([[menuAudio itemAtIndex:i] state] == NSOnState) {
836
+                [self selectedVisualization:[menuAudio itemAtIndex:i]];
837
+            }
838
+        }
839
+        for (int i = 0; i < [menuDisplays numberOfItems]; i++) {
840
+            if ([[menuDisplays itemAtIndex:i] state] == NSOnState) {
841
+                [self selectedVisualization:[menuDisplays itemAtIndex:i]];
842
+            }
843
+        }
698 844
         if ([buttonOff state] == NSOnState) {
699 845
             [buttonOff setState:NSOffState];
700 846
             [self turnLEDsOff:buttonOff];
@@ -712,6 +858,43 @@
712 858
     [application orderFrontStandardAboutPanel:self];
713 859
 }
714 860
 
861
+- (void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize {
862
+    if (microphone == nil) {
863
+        return; // Old buffer from before we changed mode
864
+    }
865
+    
866
+    // TODO visualize sound data somehow
867
+    //NSLog(@".");
868
+}
869
+
870
+// ------------------------------------------------------
871
+// ----------------- Microphone Delegate ----------------
872
+// ------------------------------------------------------
873
+
874
+- (void)microphone:(EZMicrophone *)microphone hasAudioReceived:(float **)buffer withBufferSize:(UInt32)bufferSize withNumberOfChannels:(UInt32)numberOfChannels {
875
+    __weak typeof (self) weakSelf = self;
876
+    
877
+    if (weakSelf.microphone == nil) {
878
+        return;
879
+    }
880
+    
881
+    // Getting audio data as an array of float buffer arrays that can be fed into the
882
+    // EZAudioPlot, EZAudioPlotGL, or whatever visualization you would like to do with
883
+    // the microphone data.
884
+    dispatch_async(dispatch_get_main_queue(),^{
885
+        // buffer[0] = left channel, buffer[1] = right channel
886
+        [weakSelf updateBuffer:buffer[0] withBufferSize:bufferSize];
887
+    });
888
+}
889
+
890
+- (void)microphone:(EZMicrophone *)microphone changedDevice:(EZAudioDevice *)device {
891
+    // This is not always guaranteed to occur on the main thread so make sure you
892
+    // wrap it in a GCD block
893
+    dispatch_async(dispatch_get_main_queue(), ^{
894
+        NSLog(@"Changed audio input device: %@", [device name]);
895
+    });
896
+}
897
+
715 898
 // ------------------------------------------------------
716 899
 // ------------------- Visualizations -------------------
717 900
 // ------------------------------------------------------

+ 7
- 1
CaseLights/Base.lproj/MainMenu.xib 查看文件

@@ -21,8 +21,10 @@
21 21
                 <outlet property="buttonLights" destination="tLQ-BA-kGu" id="FZv-Ju-l7n"/>
22 22
                 <outlet property="buttonOff" destination="gT4-tm-Hvn" id="EEv-lf-Qo7"/>
23 23
                 <outlet property="menuAnimations" destination="FJm-ND-abA" id="iGI-Hg-tms"/>
24
+                <outlet property="menuAudio" destination="KUj-jy-iwd" id="ct3-CS-KXG"/>
24 25
                 <outlet property="menuColors" destination="ZKz-ek-t6c" id="B2S-fy-Ca6"/>
25 26
                 <outlet property="menuDisplays" destination="Qgx-6D-9dl" id="MaT-c8-dLX"/>
27
+                <outlet property="menuItemAudio" destination="gx8-7I-Lmt" id="LjY-fB-ViX"/>
26 28
                 <outlet property="menuItemDisplays" destination="1Cz-Xz-d16" id="rRz-n5-n2P"/>
27 29
                 <outlet property="menuPorts" destination="lFU-D0-M5p" id="pHd-AA-S3J"/>
28 30
                 <outlet property="menuVisualizations" destination="yZl-ae-7SI" id="b2b-dW-mvy"/>
@@ -697,6 +699,10 @@
697 699
                     <modifierMask key="keyEquivalentModifierMask"/>
698 700
                     <menu key="submenu" title="Displays" id="Qgx-6D-9dl"/>
699 701
                 </menuItem>
702
+                <menuItem title="Audio Inputs" hidden="YES" id="gx8-7I-Lmt">
703
+                    <modifierMask key="keyEquivalentModifierMask"/>
704
+                    <menu key="submenu" title="Audio Inputs" id="KUj-jy-iwd"/>
705
+                </menuItem>
700 706
                 <menuItem title="Brightness" id="Oh0-1U-yDg">
701 707
                     <modifierMask key="keyEquivalentModifierMask"/>
702 708
                     <menu key="submenu" title="Brightness" id="jRu-sM-3xB">
@@ -732,7 +738,7 @@
732 738
                         </items>
733 739
                     </menu>
734 740
                 </menuItem>
735
-                <menuItem title="Relist Serial Ports" id="jVd-gl-Z6F">
741
+                <menuItem title="Relist Devices" id="jVd-gl-Z6F">
736 742
                     <modifierMask key="keyEquivalentModifierMask"/>
737 743
                     <connections>
738 744
                         <action selector="relistSerialPorts:" target="Voe-Tx-rLC" id="iFU-PL-xR8"/>

+ 1
- 1
CaseLights/Info.plist 查看文件

@@ -21,7 +21,7 @@
21 21
 	<key>CFBundleSignature</key>
22 22
 	<string>????</string>
23 23
 	<key>CFBundleVersion</key>
24
-	<string>172</string>
24
+	<string>180</string>
25 25
 	<key>LSApplicationCategoryType</key>
26 26
 	<string>public.app-category.utilities</string>
27 27
 	<key>LSMinimumSystemVersion</key>

Loading…
取消
儲存