ソースを参照

Added some basic GUI code

Thomas Buck 9年前
コミット
6c0d5234f7

+ 6
- 0
CaseLights.xcodeproj/project.pbxproj ファイルの表示

@@ -7,6 +7,7 @@
7 7
 	objects = {
8 8
 
9 9
 /* Begin PBXBuildFile section */
10
+		E9AB18011C29F8CD00BF3C51 /* Serial.m in Sources */ = {isa = PBXBuildFile; fileRef = E9AB18001C29F8CD00BF3C51 /* Serial.m */; };
10 11
 		E9F13E031C28B3D3004C6B95 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F13E021C28B3D3004C6B95 /* AppDelegate.m */; };
11 12
 		E9F13E061C28B3D3004C6B95 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F13E051C28B3D3004C6B95 /* main.m */; };
12 13
 		E9F13E081C28B3D3004C6B95 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E9F13E071C28B3D3004C6B95 /* Assets.xcassets */; };
@@ -14,6 +15,8 @@
14 15
 /* End PBXBuildFile section */
15 16
 
16 17
 /* Begin PBXFileReference section */
18
+		E9AB17FF1C29F8CD00BF3C51 /* Serial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Serial.h; sourceTree = "<group>"; };
19
+		E9AB18001C29F8CD00BF3C51 /* Serial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Serial.m; sourceTree = "<group>"; };
17 20
 		E9F13DFE1C28B3D3004C6B95 /* CaseLights.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CaseLights.app; sourceTree = BUILT_PRODUCTS_DIR; };
18 21
 		E9F13E011C28B3D3004C6B95 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
19 22
 		E9F13E021C28B3D3004C6B95 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -58,6 +61,8 @@
58 61
 				E9F13E071C28B3D3004C6B95 /* Assets.xcassets */,
59 62
 				E9F13E091C28B3D3004C6B95 /* MainMenu.xib */,
60 63
 				E9F13E0C1C28B3D3004C6B95 /* Info.plist */,
64
+				E9AB17FF1C29F8CD00BF3C51 /* Serial.h */,
65
+				E9AB18001C29F8CD00BF3C51 /* Serial.m */,
61 66
 				E9F13E041C28B3D3004C6B95 /* Supporting Files */,
62 67
 			);
63 68
 			path = CaseLights;
@@ -158,6 +163,7 @@
158 163
 			isa = PBXSourcesBuildPhase;
159 164
 			buildActionMask = 2147483647;
160 165
 			files = (
166
+				E9AB18011C29F8CD00BF3C51 /* Serial.m in Sources */,
161 167
 				E9F13E061C28B3D3004C6B95 /* main.m in Sources */,
162 168
 				E9F13E031C28B3D3004C6B95 /* AppDelegate.m in Sources */,
163 169
 			);

+ 10
- 0
CaseLights/AppDelegate.h ファイルの表示

@@ -12,8 +12,18 @@
12 12
 
13 13
 @property (weak) IBOutlet NSMenu *statusMenu;
14 14
 
15
+@property (weak) IBOutlet NSMenu *menuColors;
16
+@property (weak) IBOutlet NSMenu *menuAnimations;
17
+@property (weak) IBOutlet NSMenu *menuVisualizations;
18
+@property (weak) IBOutlet NSMenu *menuPorts;
19
+
20
+@property (weak) IBOutlet NSMenuItem *buttonOff;
21
+@property (weak) IBOutlet NSMenuItem *buttonLights;
22
+
15 23
 @property (strong) NSStatusItem *statusItem;
16 24
 @property (strong) NSImage *statusImage;
17 25
 
26
+@property (strong) NSDictionary *staticColors;
27
+
18 28
 @end
19 29
 

+ 132
- 2
CaseLights/AppDelegate.m ファイルの表示

@@ -7,6 +7,10 @@
7 7
 //
8 8
 
9 9
 #import "AppDelegate.h"
10
+#import "Serial.h"
11
+
12
+#define PREF_SERIAL_PORT @"SerialPort"
13
+#define PREF_LIGHTS_STATE @"LightState"
10 14
 
11 15
 @interface AppDelegate ()
12 16
 
@@ -15,18 +19,144 @@
15 19
 @implementation AppDelegate
16 20
 
17 21
 @synthesize statusMenu, statusItem, statusImage;
22
+@synthesize menuColors, menuAnimations, menuVisualizations, menuPorts;
23
+@synthesize buttonOff, buttonLights;
24
+@synthesize staticColors;
18 25
 
19 26
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
27
+    // Prepare status bar menu
20 28
     statusImage = [NSImage imageNamed:@"MenuIcon"];
21 29
     [statusImage setTemplate:YES];
22
-    
23 30
     statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
24 31
     [statusItem setImage:statusImage];
25 32
     [statusItem setMenu:statusMenu];
33
+    
34
+    // Set default configuration values, load existing ones
35
+    NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
36
+    NSMutableDictionary *appDefaults = [NSMutableDictionary dictionaryWithObject:@"" forKey:PREF_SERIAL_PORT];
37
+    [appDefaults setObject:[NSNumber numberWithBool:NO] forKey:PREF_LIGHTS_STATE];
38
+    [store registerDefaults:appDefaults];
39
+    [store synchronize];
40
+    NSString *savedPort = [store stringForKey:PREF_SERIAL_PORT];
41
+    BOOL turnOnLights = [store boolForKey:PREF_LIGHTS_STATE];
42
+    
43
+    // Prepare static colors menu
44
+    staticColors = [NSDictionary dictionaryWithObjectsAndKeys:
45
+                    [NSColor colorWithCalibratedRed:1.0f green:0.0f blue:0.0f alpha:0.0f], @"Red",
46
+                    [NSColor colorWithCalibratedRed:0.0f green:1.0f blue:0.0f alpha:0.0f], @"Green",
47
+                    [NSColor colorWithCalibratedRed:0.0f green:0.0f blue:1.0f alpha:0.0f], @"Blue",
48
+                    [NSColor colorWithCalibratedRed:0.0f green:1.0f blue:1.0f alpha:0.0f], @"Cyan",
49
+                    [NSColor colorWithCalibratedRed:1.0f green:0.0f blue:1.0f alpha:0.0f], @"Magenta",
50
+                    [NSColor colorWithCalibratedRed:1.0f green:1.0f blue:0.0f alpha:0.0f], @"Yellow",
51
+                    [NSColor colorWithCalibratedRed:1.0f green:1.0f blue:1.0f alpha:0.0f], @"White",
52
+                    nil];
53
+    for (NSString *key in [staticColors allKeys]) {
54
+        NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:key action:@selector(selectedStaticColor:) keyEquivalent:@""];
55
+        [menuColors addItem:item];
56
+        
57
+        // TODO Enable item if it was last used
58
+    }
59
+    
60
+    // TODO Prepare animations menu
61
+    
62
+    // TODO Prepare visualizations menu
63
+    
64
+    // Prepare serial port menu
65
+    NSArray *ports = [Serial listSerialPorts];
66
+    if ([ports count] > 0) {
67
+        [menuPorts removeAllItems];
68
+        for (int i = 0; i < [ports count]; i++) {
69
+            // Add Menu Item for this port
70
+            NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[ports objectAtIndex:i] action:@selector(selectedSerialPort:) keyEquivalent:@""];
71
+            [menuPorts addItem:item];
72
+            
73
+            // Set Enabled if it was used the last time
74
+            if ((savedPort != nil) && [[ports objectAtIndex:i] isEqualToString:savedPort]) {
75
+                [[menuPorts itemAtIndex:i] setState:NSOnState];
76
+            }
77
+        }
78
+    }
79
+    
80
+    // TODO Open serial port, if it was already specified and found
81
+    
82
+    // Restore previously used lights configuration
83
+    if (turnOnLights) {
84
+        // TODO Turn on lights
85
+        
86
+        [buttonLights setState:NSOnState];
87
+    } else {
88
+        // TODO Turn off lights
89
+        
90
+    }
91
+    
92
+    // TODO Restore previously used LED configuration
26 93
 }
27 94
 
28 95
 - (void)applicationWillTerminate:(NSNotification *)aNotification {
29
-    // Insert code here to tear down your application
96
+    // TODO Close serial port, if it was specified and opened
97
+    
98
+}
99
+
100
+- (IBAction)turnLEDsOff:(NSMenuItem *)sender {
101
+    if ([sender state] == NSOffState) {
102
+        // Turn off all other LED menu items
103
+        for (int i = 0; i < [menuColors numberOfItems]; i++) {
104
+            [[menuColors itemAtIndex:i] setState:NSOffState];
105
+        }
106
+        for (int i = 0; i < [menuAnimations numberOfItems]; i++) {
107
+            [[menuAnimations itemAtIndex:i] setState:NSOffState];
108
+        }
109
+        for (int i = 0; i < [menuVisualizations numberOfItems]; i++) {
110
+            [[menuVisualizations itemAtIndex:i] setState:NSOffState];
111
+        }
112
+        
113
+        // Turn on "off" menu item
114
+        [sender setState:NSOnState];
115
+        
116
+        // TODO Send command to turn off LEDs
117
+    } else {
118
+        // TODO Try to restore last LED setting
119
+    }
120
+}
121
+
122
+- (IBAction)toggleLights:(NSMenuItem *)sender {
123
+    if ([sender state] == NSOffState) {
124
+        // TODO Turn on lights
125
+        
126
+        [sender setState:NSOnState];
127
+    } else {
128
+        // TODO Turn off lights
129
+        
130
+        [sender setState:NSOffState];
131
+    }
132
+    
133
+    // Store changed value in preferences
134
+    NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
135
+    [store setBool:([sender state] == NSOnState) forKey:PREF_LIGHTS_STATE];
136
+    [store synchronize];
137
+}
138
+
139
+- (void)selectedStaticColor:(NSMenuItem *)source {
140
+    
141
+}
142
+
143
+- (void)selectedSerialPort:(NSMenuItem *)source {
144
+    // Store selection for next start-up
145
+    NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
146
+    [store setObject:[source title] forKey:PREF_SERIAL_PORT];
147
+    [store synchronize];
148
+    
149
+    // De-select all other ports
150
+    for (int i = 0; i < [menuPorts numberOfItems]; i++) {
151
+        [[menuPorts itemAtIndex:i] setState:NSOffState];
152
+    }
153
+    
154
+    // Select only the current port
155
+    [source setState:NSOnState];
156
+    
157
+    // TODO Close previously opened port, if any
158
+    
159
+    // TODO Try to open selected port
30 160
 }
31 161
 
32 162
 @end

+ 20
- 48
CaseLights/Base.lproj/MainMenu.xib ファイルの表示

@@ -14,6 +14,12 @@
14 14
         <customObject id="-3" userLabel="Application" customClass="NSObject"/>
15 15
         <customObject id="Voe-Tx-rLC" customClass="AppDelegate">
16 16
             <connections>
17
+                <outlet property="buttonLights" destination="tLQ-BA-kGu" id="FZv-Ju-l7n"/>
18
+                <outlet property="buttonOff" destination="gT4-tm-Hvn" id="EEv-lf-Qo7"/>
19
+                <outlet property="menuAnimations" destination="FJm-ND-abA" id="iGI-Hg-tms"/>
20
+                <outlet property="menuColors" destination="ZKz-ek-t6c" id="B2S-fy-Ca6"/>
21
+                <outlet property="menuPorts" destination="lFU-D0-M5p" id="pHd-AA-S3J"/>
22
+                <outlet property="menuVisualizations" destination="yZl-ae-7SI" id="b2b-dW-mvy"/>
17 23
                 <outlet property="statusMenu" destination="g7M-LS-DgA" id="txO-T1-8yD"/>
18 24
             </connections>
19 25
         </customObject>
@@ -671,60 +677,26 @@
671 677
             <items>
672 678
                 <menuItem title="Color Presets" id="n9c-Wh-TZw">
673 679
                     <modifierMask key="keyEquivalentModifierMask"/>
674
-                    <menu key="submenu" title="Color Presets" id="ZKz-ek-t6c">
675
-                        <items>
676
-                            <menuItem title="Red" id="IlX-tU-VCP">
677
-                                <modifierMask key="keyEquivalentModifierMask"/>
678
-                            </menuItem>
679
-                            <menuItem title="Green" id="SxE-sX-kXr">
680
-                                <modifierMask key="keyEquivalentModifierMask"/>
681
-                            </menuItem>
682
-                            <menuItem title="Blue" id="Nmo-Lq-eed">
683
-                                <modifierMask key="keyEquivalentModifierMask"/>
684
-                            </menuItem>
685
-                            <menuItem title="Yellow" id="jGz-Kp-OP9">
686
-                                <modifierMask key="keyEquivalentModifierMask"/>
687
-                            </menuItem>
688
-                            <menuItem title="Pink" id="qtS-y4-5Yx">
689
-                                <modifierMask key="keyEquivalentModifierMask"/>
690
-                            </menuItem>
691
-                            <menuItem title="White" id="E2D-Kn-Y1D">
692
-                                <modifierMask key="keyEquivalentModifierMask"/>
693
-                            </menuItem>
694
-                            <menuItem title="Orange" id="pU6-cU-a3D">
695
-                                <modifierMask key="keyEquivalentModifierMask"/>
696
-                            </menuItem>
697
-                            <menuItem title="Aquamarin" id="D0a-Bv-uWf">
698
-                                <modifierMask key="keyEquivalentModifierMask"/>
699
-                            </menuItem>
700
-                            <menuItem title="Purple" id="IlT-ov-cdQ">
701
-                                <modifierMask key="keyEquivalentModifierMask"/>
702
-                            </menuItem>
703
-                        </items>
704
-                    </menu>
680
+                    <menu key="submenu" title="Color Presets" id="ZKz-ek-t6c"/>
705 681
                 </menuItem>
706
-                <menuItem title="Visualizations" id="Ydc-Gt-rOt">
682
+                <menuItem title="Animations" id="93N-lv-QQC">
707 683
                     <modifierMask key="keyEquivalentModifierMask"/>
708
-                    <menu key="submenu" title="Visualizations" id="yZl-ae-7SI">
709
-                        <items>
710
-                            <menuItem title="CPU Usage" id="rtI-Yu-3jn">
711
-                                <modifierMask key="keyEquivalentModifierMask"/>
712
-                            </menuItem>
713
-                            <menuItem title="CPU Temperature" id="hSc-c9-Duc">
714
-                                <modifierMask key="keyEquivalentModifierMask"/>
715
-                            </menuItem>
716
-                            <menuItem title="GPU Temperature" id="faB-Yd-HLr">
717
-                                <modifierMask key="keyEquivalentModifierMask"/>
718
-                            </menuItem>
719
-                        </items>
720
-                    </menu>
684
+                    <menu key="submenu" title="Animations" id="FJm-ND-abA"/>
721 685
                 </menuItem>
722
-                <menuItem title="Turn LEDs off" id="gT4-tm-Hvn">
686
+                <menuItem title="Visualizations" id="Ydc-Gt-rOt">
723 687
                     <modifierMask key="keyEquivalentModifierMask"/>
688
+                    <menu key="submenu" title="Visualizations" id="yZl-ae-7SI"/>
689
+                </menuItem>
690
+                <menuItem title="Turn LEDs off" keyEquivalent="e" id="gT4-tm-Hvn">
691
+                    <connections>
692
+                        <action selector="turnLEDsOff:" target="Voe-Tx-rLC" id="FQw-v8-IbT"/>
693
+                    </connections>
724 694
                 </menuItem>
725 695
                 <menuItem isSeparatorItem="YES" id="umI-9c-ZzN"/>
726
-                <menuItem title="UV Lights" id="tLQ-BA-kGu">
727
-                    <modifierMask key="keyEquivalentModifierMask"/>
696
+                <menuItem title="UV Lights" keyEquivalent="w" id="tLQ-BA-kGu">
697
+                    <connections>
698
+                        <action selector="toggleLights:" target="Voe-Tx-rLC" id="eLZ-43-xtu"/>
699
+                    </connections>
728 700
                 </menuItem>
729 701
                 <menuItem isSeparatorItem="YES" id="Bgw-0M-KDy"/>
730 702
                 <menuItem title="Serial Port" id="K0K-po-BF0">

+ 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>21</string>
24
+	<string>33</string>
25 25
 	<key>LSApplicationCategoryType</key>
26 26
 	<string>public.app-category.utilities</string>
27 27
 	<key>LSMinimumSystemVersion</key>

+ 15
- 0
CaseLights/Serial.h ファイルの表示

@@ -0,0 +1,15 @@
1
+//
2
+//  Serial.h
3
+//  SerialGamepad
4
+//
5
+//  Created by Thomas Buck on 14.12.15.
6
+//  Copyright © 2015 xythobuz. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+
11
+@interface Serial : NSObject
12
+
13
++ (NSArray *)listSerialPorts;
14
+
15
+@end

+ 138
- 0
CaseLights/Serial.m ファイルの表示

@@ -0,0 +1,138 @@
1
+//
2
+//  Serial.m
3
+//  SerialGamepad / CaseLights
4
+//
5
+//  For more informations refer to this document:
6
+//  https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html
7
+//
8
+//  Created by Thomas Buck on 14.12.15.
9
+//  Copyright © 2015 xythobuz. All rights reserved.
10
+//
11
+
12
+#import <IOKit/serial/IOSerialKeys.h>
13
+
14
+#import "Serial.h"
15
+
16
+kern_return_t findSerialPorts(io_iterator_t *matches);
17
+kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize);
18
+
19
+@implementation Serial
20
+
21
++ (NSArray *)listSerialPorts {
22
+    // Get Iterator with all serial ports
23
+    io_iterator_t serialPortIterator;
24
+    kern_return_t kernResult = findSerialPorts(&serialPortIterator);
25
+    
26
+    // Create 2D array
27
+    char **portList;
28
+    portList = malloc(100 * sizeof(char *));
29
+    for (int i = 0; i < 100; i++) portList[i] = malloc(200 * sizeof(char));
30
+    
31
+    // Copy device name into C-String array
32
+    kernResult = getSerialPortPath(serialPortIterator, portList, 100, 200);
33
+    IOObjectRelease(serialPortIterator);
34
+    
35
+    // Copy contents into NSString Array
36
+    NSString *stringList[100];
37
+    NSUInteger realCount = 0;
38
+    while (portList[realCount] != NULL) {
39
+        stringList[realCount] = [NSString stringWithCString:portList[realCount] encoding:NSUTF8StringEncoding];
40
+        realCount++;
41
+    }
42
+    
43
+    // Destroy 2D array
44
+    for (int i = 0; i < 100; i++) free(portList[i]);
45
+    free(portList);
46
+    
47
+    // And return them as NSArray
48
+    return [[NSArray alloc] initWithObjects:stringList count:realCount];
49
+}
50
+
51
+@end
52
+
53
+kern_return_t findSerialPorts(io_iterator_t *matches) {
54
+    kern_return_t kernResult;
55
+    mach_port_t masterPort;
56
+    CFMutableDictionaryRef classesToMatch;
57
+    
58
+    kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
59
+    if (KERN_SUCCESS != kernResult) {
60
+        NSLog(@"IOMasterPort returned %d\n", kernResult);
61
+        return kernResult;
62
+    }
63
+    
64
+    // Serial devices are instances of class IOSerialBSDClient.
65
+    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
66
+    if (classesToMatch == NULL) {
67
+        NSLog(@"IOServiceMatching returned a NULL dictionary.\n");
68
+    } else {
69
+        CFDictionarySetValue(classesToMatch,
70
+                             CFSTR(kIOSerialBSDTypeKey),
71
+                             CFSTR(kIOSerialBSDRS232Type));
72
+        
73
+        // Each serial device object has a property with key
74
+        // kIOSerialBSDTypeKey and a value that is one of
75
+        // kIOSerialBSDAllTypes, kIOSerialBSDModemType,
76
+        // or kIOSerialBSDRS232Type. You can change the
77
+        // matching dictionary to find other types of serial
78
+        // devices by changing the last parameter in the above call
79
+        // to CFDictionarySetValue.
80
+    }
81
+    
82
+    kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, matches);
83
+    if (KERN_SUCCESS != kernResult) {
84
+        NSLog(@"IOServiceGetMatchingServices returned %d\n", kernResult);
85
+        return kernResult;
86
+    }
87
+    
88
+    return kernResult;
89
+}
90
+
91
+kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize) {
92
+    io_object_t modemService;
93
+    kern_return_t kernResult = KERN_FAILURE;
94
+    CFIndex i = 0;
95
+    
96
+    while ((modemService = IOIteratorNext(serialPortIterator)) && (i < (maxPathCount - 1))) {
97
+        CFTypeRef   deviceFilePathAsCFString;
98
+        
99
+        // Get the callout device's path (/dev/cu.xxxxx).
100
+        // The callout device should almost always be
101
+        // used. You would use the dialin device (/dev/tty.xxxxx) when
102
+        // monitoring a serial port for
103
+        // incoming calls, for example, a fax listener.
104
+        
105
+        deviceFilePathAsCFString = IORegistryEntryCreateCFProperty(modemService,
106
+                                                                   CFSTR(kIODialinDeviceKey),
107
+                                                                   kCFAllocatorDefault,
108
+                                                                   0);
109
+        if (deviceFilePathAsCFString) {
110
+            Boolean result;
111
+            
112
+            deviceFilePath[i][0] = '\0';
113
+            
114
+            // Convert the path from a CFString to a NULL-terminated C string
115
+            // for use with the POSIX open() call.
116
+            
117
+            result = CFStringGetCString(deviceFilePathAsCFString,
118
+                                        deviceFilePath[i],
119
+                                        maxPathSize,
120
+                                        kCFStringEncodingASCII);
121
+            CFRelease(deviceFilePathAsCFString);
122
+            
123
+            if (result) {
124
+                //NSLog(@"BSD path: %s\n", deviceFilePath[i]);
125
+                i++;
126
+                kernResult = KERN_SUCCESS;
127
+            }
128
+        }
129
+        
130
+        // Release the io_service_t now that we are done with it.
131
+        
132
+        (void) IOObjectRelease(modemService);
133
+    }
134
+    
135
+    deviceFilePath[i] = NULL;
136
+    
137
+    return kernResult;
138
+}

読み込み中…
キャンセル
保存