first working pass
[usblister.git] / usblister / usblisterAppDelegate.m
1 //
2 //  usblisterAppDelegate.m
3 //  usblister
4 //
5 //  Created by Rex Feany on 4/8/11.
6 //  Copyright 2011 Fnordsoft, Inc. All rights reserved.
7 //
8
9 #import "usblisterAppDelegate.h"
10
11 #include <stdio.h>
12 #include <IOKit/IOCFPlugIn.h>
13 #include <IOKit/hid/IOHIDKeys.h>
14 #include <CoreFoundation/CoreFoundation.h>
15
16 #import "OutlineData.h"
17
18 @implementation usblisterAppDelegate
19
20 @synthesize window;
21 @synthesize field;
22 @synthesize button;
23 @synthesize hash_a;
24 @synthesize array_a;
25 @synthesize tabs;
26 @synthesize data;
27 @synthesize outline;
28
29 static NSArray *kv_pair(NSString *key, id value)
30 {
31     return [NSArray arrayWithObjects:key, value, nil];
32 }
33                                                 
34 static NSArray *dict_to_array(NSDictionary *d)
35 {
36     NSMutableArray *a = [NSMutableArray array];
37     [d enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
38             if ([obj isKindOfClass:[NSDictionary class]]) {
39             obj = dict_to_array(obj);
40             }
41             [a addObject:kv_pair(key, obj)];
42         }
43     ];
44     return a;
45 }
46
47 static BOOL iterate(NSMutableArray *hash_a, NSMutableArray *array_a, const io_name_t plane) {
48     IOReturn result;
49     io_iterator_t hidObjectIterator = 0;
50     io_object_t hidDevice = IO_OBJECT_NULL;
51     CFMutableDictionaryRef hidProperties = 0;
52     
53     result = IORegistryCreateIterator(kIOMasterPortDefault, kIOUSBPlane, kIORegistryIterateRecursively, &hidObjectIterator);
54     
55     if ((result != kIOReturnSuccess) || (hidObjectIterator == 0)) {
56         NSLog(@"Can't obtain an IO iterator\n");
57         return NO;
58     }
59     
60     while ((hidDevice = IOIteratorNext(hidObjectIterator))) {
61         hidProperties = 0;
62         result = IORegistryEntryCreateCFProperties(hidDevice, &hidProperties,
63                                                    kCFAllocatorDefault, kNilOptions);
64         if ((result == KERN_SUCCESS) && hidProperties) {
65             NSDictionary *d = (NSDictionary *)hidProperties;
66             NSString *s = [d objectForKey:@"USB Product Name"];
67             
68             if (s) {
69                 CFRetain(hidProperties);
70                 [hash_a addObject:d];
71                 [array_a addObject:kv_pair(s, dict_to_array(d))];
72             }
73         }
74         IOObjectRelease(hidDevice);
75     }
76     IOObjectRelease(hidObjectIterator);
77     return YES;
78 }
79
80 static BOOL magic(NSMutableArray *hash_a, NSMutableArray *array_a) {
81     [hash_a removeAllObjects];
82     [array_a removeAllObjects];
83     
84     if (!iterate(hash_a, array_a, kIOUSBPlane)) return NO;
85     
86     return YES;
87 }
88
89 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
90 {
91     // Insert code here to initialize your application
92     [self performSelector:@selector(scanClick:) withObject:nil afterDelay:.3];
93     NSLog(@"wtf");
94 }
95
96 - (IBAction)scanClick:(id)sender {
97     if (self.hash_a == nil) {
98         self.hash_a = [NSMutableArray array];
99     }
100     if (self.array_a == nil) {
101         self.array_a = [NSMutableArray array];
102     }
103     if (self.data == nil) {
104         self.data = [[OutlineData alloc] init];
105         self.data.data = self.array_a;
106         [self.outline setDataSource:self.data];
107     }
108     magic(self.hash_a, self.array_a);
109     [self.field setString:[NSString stringWithFormat:@"%@", self.hash_a]];
110     [self.outline reloadData];
111 }
112
113 - (IBAction)saveClick:(id)sender {
114     NSSavePanel *spanel = [NSSavePanel savePanel];
115     NSArray *array = [NSArray arrayWithObject:@"txt"];
116     
117     [spanel setAllowedFileTypes:array];    
118     
119     if ([spanel runModal] == NSFileHandlingPanelOKButton) {
120         NSString *str = [self.field string];
121         [str writeToURL:[spanel URL] atomically:FALSE encoding:NSASCIIStringEncoding error:NULL];
122     }
123 }
124
125 - (BOOL)textView:(NSTextView *)aTextView shouldChangeTextInRange:(NSRange)affectedCharRange replacementString:(NSString *)replacementString {
126     return NO;
127 }
128
129
130 @end
131