Simple RGB LED controller for Mac OS X
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AppDelegate.m 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. //
  2. // AppDelegate.m
  3. // CaseLights
  4. //
  5. // Created by Thomas Buck on 21.12.15.
  6. // Copyright © 2015 xythobuz. All rights reserved.
  7. //
  8. #import "AppDelegate.h"
  9. #import "Serial.h"
  10. #import "GPUStats.h"
  11. #import <SystemInfoKit/SystemInfoKit.h>
  12. #define PREF_SERIAL_PORT @"SerialPort"
  13. #define PREF_LIGHTS_STATE @"LightState"
  14. #define PREF_LED_MODE @"LEDMode"
  15. #define TEXT_CPU_USAGE @"CPU Usage"
  16. #define TEXT_RAM_USAGE @"RAM Usage"
  17. #define TEXT_GPU_USAGE @"GPU Usage"
  18. #define TEXT_VRAM_USAGE @"VRAM Usage"
  19. #define TEXT_CPU_TEMPERATURE @"CPU Temperature"
  20. #define TEXT_GPU_TEMPERATURE @"GPU Temperature"
  21. @interface AppDelegate ()
  22. @property (weak) NSMenuItem *lastLEDMode;
  23. @end
  24. @implementation AppDelegate
  25. @synthesize statusMenu, application;
  26. @synthesize menuColors, menuAnimations, menuVisualizations, menuPorts;
  27. @synthesize buttonOff, buttonLights;
  28. @synthesize statusItem, statusImage;
  29. @synthesize staticColors;
  30. @synthesize serial, lastLEDMode;
  31. - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
  32. serial = [[Serial alloc] init];
  33. lastLEDMode = nil;
  34. // Prepare status bar menu
  35. statusImage = [NSImage imageNamed:@"MenuIcon"];
  36. [statusImage setTemplate:YES];
  37. statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
  38. [statusItem setImage:statusImage];
  39. [statusItem setMenu:statusMenu];
  40. // Set default configuration values, load existing ones
  41. NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
  42. NSMutableDictionary *appDefaults = [NSMutableDictionary dictionaryWithObject:@"" forKey:PREF_SERIAL_PORT];
  43. [appDefaults setObject:[NSNumber numberWithBool:NO] forKey:PREF_LIGHTS_STATE];
  44. [appDefaults setObject:@"" forKey:PREF_LED_MODE];
  45. [store registerDefaults:appDefaults];
  46. [store synchronize];
  47. NSString *savedPort = [store stringForKey:PREF_SERIAL_PORT];
  48. BOOL turnOnLights = [store boolForKey:PREF_LIGHTS_STATE];
  49. NSString *lastMode = [store stringForKey:PREF_LED_MODE];
  50. if ([lastMode isEqualToString:@""]) {
  51. [buttonOff setState:NSOnState];
  52. }
  53. // Prepare static colors menu
  54. staticColors = [NSDictionary dictionaryWithObjectsAndKeys:
  55. [NSColor colorWithCalibratedRed:1.0f green:0.0f blue:0.0f alpha:0.0f], @"Red",
  56. [NSColor colorWithCalibratedRed:0.0f green:1.0f blue:0.0f alpha:0.0f], @"Green",
  57. [NSColor colorWithCalibratedRed:0.0f green:0.0f blue:1.0f alpha:0.0f], @"Blue",
  58. [NSColor colorWithCalibratedRed:0.0f green:1.0f blue:1.0f alpha:0.0f], @"Cyan",
  59. [NSColor colorWithCalibratedRed:1.0f green:0.0f blue:1.0f alpha:0.0f], @"Magenta",
  60. [NSColor colorWithCalibratedRed:1.0f green:1.0f blue:0.0f alpha:0.0f], @"Yellow",
  61. [NSColor colorWithCalibratedRed:1.0f green:1.0f blue:1.0f alpha:0.0f], @"White",
  62. nil];
  63. for (NSString *key in [staticColors allKeys]) {
  64. NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:key action:@selector(selectedVisualization:) keyEquivalent:@""];
  65. if ([key isEqualToString:lastMode]) {
  66. [item setState:NSOnState];
  67. }
  68. [menuColors addItem:item];
  69. }
  70. // TODO Prepare animations menu
  71. JSKSystemMonitor *systemMonitor = [JSKSystemMonitor systemMonitor];
  72. #ifdef DEBUG
  73. JSKMCPUUsageInfo cpuUsageInfo = systemMonitor.cpuUsageInfo;
  74. NSLog(@"CPU Usage: %.3f%%\n", cpuUsageInfo.usage);
  75. JSKMMemoryUsageInfo memoryUsageInfo = systemMonitor.memoryUsageInfo;
  76. NSLog(@"Memory Usage: %.2fGB Free, %.2fGB Used, %.2fGB Active, %.2fGB Inactive, %.2fGB Compressed, %.2fGB Wired\n", memoryUsageInfo.freeMemory / (1024.0 * 1024.0 * 1024.0), memoryUsageInfo.usedMemory / (1024.0 * 1024.0 * 1024.0), memoryUsageInfo.activeMemory / (1024.0 * 1024.0 * 1024.0), memoryUsageInfo.inactiveMemory / (1024.0 * 1024.0 * 1024.0), memoryUsageInfo.compressedMemory / (1024.0 * 1024.0 * 1024.0), memoryUsageInfo.wiredMemory / (1024.0 * 1024.0 * 1024.0));
  77. #endif
  78. // Add CPU Usage menu item
  79. NSMenuItem *cpuUsageItem = [[NSMenuItem alloc] initWithTitle:TEXT_CPU_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
  80. if ([lastMode isEqualToString:TEXT_CPU_USAGE]) {
  81. [cpuUsageItem setState:NSOnState];
  82. }
  83. [menuVisualizations addItem:cpuUsageItem];
  84. // Add Memory Usage item
  85. NSMenuItem *memoryUsageItem = [[NSMenuItem alloc] initWithTitle:TEXT_RAM_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
  86. if ([lastMode isEqualToString:TEXT_RAM_USAGE]) {
  87. [memoryUsageItem setState:NSOnState];
  88. }
  89. [menuVisualizations addItem:memoryUsageItem];
  90. // Check if GPU Stats are available, add menu items if so
  91. NSNumber *usage;
  92. NSNumber *freeVRAM;
  93. NSNumber *usedVRAM;
  94. if ([GPUStats getGPUUsage:&usage freeVRAM:&freeVRAM usedVRAM:&usedVRAM] != 0) {
  95. NSLog(@"Error reading GPU information\n");
  96. } else {
  97. NSMenuItem *itemUsage = [[NSMenuItem alloc] initWithTitle:TEXT_GPU_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
  98. if ([lastMode isEqualToString:TEXT_GPU_USAGE]) {
  99. [itemUsage setState:NSOnState];
  100. }
  101. [menuVisualizations addItem:itemUsage];
  102. NSMenuItem *itemVRAM = [[NSMenuItem alloc] initWithTitle:TEXT_VRAM_USAGE action:@selector(selectedVisualization:) keyEquivalent:@""];
  103. if ([lastMode isEqualToString:TEXT_VRAM_USAGE]) {
  104. [itemVRAM setState:NSOnState];
  105. }
  106. [menuVisualizations addItem:itemVRAM];
  107. }
  108. // Check available temperatures and add menu items
  109. JSKSMC *smc = [JSKSMC smc];
  110. for (int i = 0; i < [[smc workingTempKeys] count]; i++) {
  111. NSString *key = [smc.workingTempKeys objectAtIndex:i];
  112. #ifdef DEBUG
  113. NSString *name = [smc humanReadableNameForKey:key];
  114. NSLog(@"Sensor \"%@\": \"%@\"\n", key, name);
  115. #endif
  116. if ([key isEqualToString:@"TC0D"]) {
  117. NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:TEXT_CPU_TEMPERATURE action:@selector(selectedVisualization:) keyEquivalent:@""];
  118. if ([lastMode isEqualToString:TEXT_CPU_TEMPERATURE]) {
  119. [item setState:NSOnState];
  120. }
  121. [menuVisualizations addItem:item];
  122. }
  123. if ([key isEqualToString:@"TG0D"]) {
  124. NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:TEXT_GPU_TEMPERATURE action:@selector(selectedVisualization:) keyEquivalent:@""];
  125. if ([lastMode isEqualToString:TEXT_GPU_TEMPERATURE]) {
  126. [item setState:NSOnState];
  127. }
  128. [menuVisualizations addItem:item];
  129. }
  130. }
  131. // Prepare serial port menu
  132. NSArray *ports = [Serial listSerialPorts];
  133. if ([ports count] > 0) {
  134. [menuPorts removeAllItems];
  135. for (int i = 0; i < [ports count]; i++) {
  136. // Add Menu Item for this port
  137. NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[ports objectAtIndex:i] action:@selector(selectedSerialPort:) keyEquivalent:@""];
  138. [menuPorts addItem:item];
  139. // Set Enabled if it was used the last time
  140. if ((savedPort != nil) && [[ports objectAtIndex:i] isEqualToString:savedPort]) {
  141. [[menuPorts itemAtIndex:i] setState:NSOnState];
  142. // Try to open serial port
  143. [serial setPortName:savedPort];
  144. if ([serial openPort]) {
  145. // Unselect it when an error occured opening the port
  146. [[menuPorts itemAtIndex:i] setState:NSOffState];
  147. }
  148. }
  149. }
  150. }
  151. // Restore previously used lights configuration
  152. if (turnOnLights) {
  153. // TODO Turn on lights
  154. [buttonLights setState:NSOnState];
  155. } else {
  156. // TODO Turn off lights
  157. }
  158. // TODO Restore previously used LED configuration
  159. }
  160. - (void)applicationWillTerminate:(NSNotification *)aNotification {
  161. // Close serial port, if it was opened
  162. if ([serial isOpen]) {
  163. [serial closePort];
  164. }
  165. }
  166. - (IBAction)relistSerialPorts:(id)sender {
  167. // Refill port list
  168. NSArray *ports = [Serial listSerialPorts];
  169. [menuPorts removeAllItems];
  170. for (int i = 0; i < [ports count]; i++) {
  171. // Add Menu Item for this port
  172. NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[ports objectAtIndex:i] action:@selector(selectedSerialPort:) keyEquivalent:@""];
  173. [menuPorts addItem:item];
  174. // Mark it if it is currently open
  175. if ([serial isOpen]) {
  176. if ([[ports objectAtIndex:i] isEqualToString:[serial portName]]) {
  177. [[menuPorts itemAtIndex:i] setState:NSOnState];
  178. }
  179. }
  180. }
  181. }
  182. - (IBAction)turnLEDsOff:(NSMenuItem *)sender {
  183. if ([sender state] == NSOffState) {
  184. lastLEDMode = nil;
  185. // Turn off all other LED menu items
  186. for (int i = 0; i < [menuColors numberOfItems]; i++) {
  187. if ([[menuColors itemAtIndex:i] state] == NSOnState) {
  188. lastLEDMode = [menuColors itemAtIndex:i];
  189. }
  190. [[menuColors itemAtIndex:i] setState:NSOffState];
  191. }
  192. for (int i = 0; i < [menuAnimations numberOfItems]; i++) {
  193. if ([[menuAnimations itemAtIndex:i] state] == NSOnState) {
  194. lastLEDMode = [menuAnimations itemAtIndex:i];
  195. }
  196. [[menuAnimations itemAtIndex:i] setState:NSOffState];
  197. }
  198. for (int i = 0; i < [menuVisualizations numberOfItems]; i++) {
  199. if ([[menuVisualizations itemAtIndex:i] state] == NSOnState) {
  200. lastLEDMode = [menuVisualizations itemAtIndex:i];
  201. }
  202. [[menuVisualizations itemAtIndex:i] setState:NSOffState];
  203. }
  204. // Turn on "off" menu item
  205. [sender setState:NSOnState];
  206. // Store changed value in preferences
  207. NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
  208. [store setObject:@"" forKey:PREF_LED_MODE];
  209. [store synchronize];
  210. #ifdef DEBUG
  211. NSLog(@"Stored new mode: \"\"!\n");
  212. #endif
  213. // TODO Send command to turn off LEDs
  214. } else {
  215. // Try to restore last LED setting
  216. if (lastLEDMode != nil) {
  217. [self selectedVisualization:lastLEDMode];
  218. }
  219. }
  220. }
  221. - (IBAction)toggleLights:(NSMenuItem *)sender {
  222. if ([sender state] == NSOffState) {
  223. // TODO Turn on lights
  224. [sender setState:NSOnState];
  225. } else {
  226. // TODO Turn off lights
  227. [sender setState:NSOffState];
  228. }
  229. // Store changed value in preferences
  230. NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
  231. [store setBool:([sender state] == NSOnState) forKey:PREF_LIGHTS_STATE];
  232. [store synchronize];
  233. }
  234. - (void)selectedVisualization:(NSMenuItem *)sender {
  235. // Turn off all other LED menu items
  236. for (int i = 0; i < [menuColors numberOfItems]; i++) {
  237. [[menuColors itemAtIndex:i] setState:NSOffState];
  238. }
  239. for (int i = 0; i < [menuAnimations numberOfItems]; i++) {
  240. [[menuAnimations itemAtIndex:i] setState:NSOffState];
  241. }
  242. for (int i = 0; i < [menuVisualizations numberOfItems]; i++) {
  243. [[menuVisualizations itemAtIndex:i] setState:NSOffState];
  244. }
  245. [buttonOff setState:NSOffState];
  246. [sender setState:NSOnState];
  247. if ([sender.title isEqualToString:TEXT_GPU_USAGE]) {
  248. // TODO store new selection
  249. // TODO send command
  250. } else if ([sender.title isEqualToString:TEXT_VRAM_USAGE]) {
  251. // TODO store new selection
  252. // TODO send command
  253. } else if ([sender.title isEqualToString:TEXT_GPU_TEMPERATURE]) {
  254. // TODO store new selection
  255. // TODO send command
  256. } else if ([sender.title isEqualToString:TEXT_CPU_USAGE]) {
  257. // TODO store new selection
  258. // TODO send command
  259. } else if ([sender.title isEqualToString:TEXT_CPU_TEMPERATURE]) {
  260. // TODO store new selection
  261. // TODO send command
  262. } else if ([sender.title isEqualToString:TEXT_RAM_USAGE]) {
  263. // TODO store new selection
  264. // TODO send command
  265. } else {
  266. BOOL found = NO;
  267. // Check if a static color was selected
  268. for (NSString *key in [staticColors allKeys]) {
  269. if ([sender.title isEqualToString:key]) {
  270. found = YES;
  271. // TODO store new selection
  272. // TODO send command
  273. }
  274. }
  275. if (found) goto end_found;
  276. // TODO Check if an animation was selected
  277. NSLog(@"Unknown LED Visualization selected!\n");
  278. return;
  279. }
  280. end_found: {
  281. // Store changed value in preferences
  282. NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
  283. [store setObject:[sender title] forKey:PREF_LED_MODE];
  284. [store synchronize];
  285. #ifdef DEBUG
  286. NSLog(@"Stored new mode: \"%@\"!\n", [sender title]);
  287. #endif
  288. }
  289. }
  290. - (void)selectedSerialPort:(NSMenuItem *)source {
  291. // Store selection for next start-up
  292. NSUserDefaults *store = [NSUserDefaults standardUserDefaults];
  293. [store setObject:[source title] forKey:PREF_SERIAL_PORT];
  294. [store synchronize];
  295. // De-select all other ports
  296. for (int i = 0; i < [menuPorts numberOfItems]; i++) {
  297. [[menuPorts itemAtIndex:i] setState:NSOffState];
  298. }
  299. // Select only the current port
  300. [source setState:NSOnState];
  301. // Close previously opened port, if any
  302. if ([serial isOpen]) {
  303. [serial closePort];
  304. }
  305. // Try to open selected port
  306. [serial setPortName:[source title]];
  307. if ([serial openPort] != 0) {
  308. [source setState:NSOffState];
  309. } else {
  310. // TODO Restore the current configuration
  311. }
  312. }
  313. - (IBAction)showAbout:(id)sender {
  314. [NSApp activateIgnoringOtherApps:YES];
  315. [application orderFrontStandardAboutPanel:self];
  316. }
  317. @end