-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.m
More file actions
201 lines (175 loc) · 7.38 KB
/
Copy pathmain.m
File metadata and controls
201 lines (175 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#import <AVFoundation/AVFoundation.h>
#import <Cocoa/Cocoa.h>
// MARK: - Automation Script Source
static NSString *const kAutomationScript =
@"on selectHeadPointerCamera(cameraName)\n"
" tell application \"System Settings\" to activate\n"
" open location "
"\"x-apple.systempreferences:com.apple.Accessibility-Settings.extension?"
"PointerControl\"\n"
" tell application \"System Events\"\n"
" tell application process \"System Settings\"\n"
" repeat until exists (window \"Pointer Control\")\n"
" delay 0.5\n"
" end repeat\n"
" tell window \"Pointer Control\"\n"
" try\n"
" set rightGroup to group 1 of scroll area 1 of group "
"1 of splitter group 1 of group 1\n"
" set foundRow to missing value\n"
" repeat with uiGroup in groups of rightGroup\n"
" if (exists static text \"Head pointer\" of "
"uiGroup) then\n"
" set foundRow to uiGroup\n"
" exit repeat\n"
" end if\n"
" end repeat\n"
" if foundRow is missing value then\n"
" display dialog \"Could not find 'Head pointer' "
"settings row.\" buttons {\"OK\"} default button \"OK\"\n"
" return\n"
" end if\n"
" click button 1 of foundRow\n"
" repeat until exists sheet 1\n"
" delay 0.1\n"
" end repeat\n"
" tell sheet 1\n"
" if (exists button \"Camera Options…\" of group 1 "
"of scroll area 1) then\n"
" click button \"Camera Options…\" of group 1 "
"of scroll area 1\n"
" delay 0.5\n"
" end if\n"
" set foundPopup to missing value\n"
" try\n"
" set foundPopup to pop up button \"Camera\" "
"of group 1 of scroll area 1\n"
" on error\n"
" try\n"
" set foundPopup to pop up button 1 of "
"group 1 of scroll area 1\n"
" end try\n"
" end try\n"
" if foundPopup is not missing value then\n"
" click foundPopup\n"
" delay 0.2\n"
" click menu item cameraName of menu 1 of "
"foundPopup\n"
" else\n"
" display dialog \"Could not find Camera "
"selection menu.\"\n"
" end if\n"
" if exists button \"OK\" then\n"
" click button \"OK\"\n"
" else if exists button \"Done\" then\n"
" click button \"Done\"\n"
" end if\n"
" end tell\n"
" on error errMsg\n"
" display dialog \"Automation Error: \" & errMsg\n"
" end try\n"
" end tell\n"
" end tell\n"
" end tell\n"
"end selectHeadPointerCamera";
// MARK: - App Delegate
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property(strong, nonatomic) NSStatusItem *statusItem;
@property(strong, nonatomic) AVCaptureDeviceDiscoverySession *discoverySession;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Setup Status Item
self.statusItem = [[NSStatusBar systemStatusBar]
statusItemWithLength:NSVariableStatusItemLength];
NSImage *image = [NSImage imageWithSystemSymbolName:@"video.fill"
accessibilityDescription:@"Camera Switcher"];
self.statusItem.button.image = image;
// Setup Discovery Session
self.discoverySession = [AVCaptureDeviceDiscoverySession
discoverySessionWithDeviceTypes:@[
AVCaptureDeviceTypeBuiltInWideAngleCamera,
AVCaptureDeviceTypeExternalUnknown
]
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionUnspecified];
// Build Menu
[self constructMenu];
// Notifications
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(rebuildMenu)
name:AVCaptureDeviceWasConnectedNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(rebuildMenu)
name:AVCaptureDeviceWasDisconnectedNotification
object:nil];
}
- (void)rebuildMenu {
dispatch_async(dispatch_get_main_queue(), ^{
[self constructMenu];
});
}
- (void)constructMenu {
NSMenu *menu = [[NSMenu alloc] init];
[menu addItemWithTitle:@"Head Pointer Camera" action:nil keyEquivalent:@""];
[menu addItem:[NSMenuItem separatorItem]];
NSArray<AVCaptureDevice *> *devices = self.discoverySession.devices;
if (devices.count == 0) {
[menu addItemWithTitle:@"No Cameras Found" action:nil keyEquivalent:@""];
} else {
for (AVCaptureDevice *device in devices) {
NSMenuItem *item =
[[NSMenuItem alloc] initWithTitle:device.localizedName
action:@selector(cameraSelected:)
keyEquivalent:@""];
item.target = self;
item.representedObject = device.localizedName;
[menu addItem:item];
}
}
[menu addItem:[NSMenuItem separatorItem]];
[menu addItemWithTitle:@"Quit" action:@selector(quitApp) keyEquivalent:@"q"];
self.statusItem.menu = menu;
}
- (void)cameraSelected:(NSMenuItem *)sender {
NSString *cameraName = sender.representedObject;
NSLog(@"Switching to camera: %@", cameraName);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
[self runAutomationForCamera:cameraName];
});
}
- (void)runAutomationForCamera:(NSString *)cameraName {
NSAppleScript *script =
[[NSAppleScript alloc] initWithSource:kAutomationScript];
// We need to call the handler "selectHeadPointerCamera(cameraName)"
// NSAppleScript doesn't easily support calling handlers with arguments
// directly without NSAppleEventDescriptor ceremony. Easier way: Append the
// call to the script source dynamically.
NSString *command = [NSString
stringWithFormat:@"\nselectHeadPointerCamera(\"%@\")", cameraName];
NSString *fullScript = [kAutomationScript stringByAppendingString:command];
NSAppleScript *runScript = [[NSAppleScript alloc] initWithSource:fullScript];
NSDictionary *errorInfo = nil;
[runScript executeAndReturnError:&errorInfo];
if (errorInfo) {
NSLog(@"AppleScript Error: %@", errorInfo);
}
}
- (void)quitApp {
[NSApp terminate:nil];
}
@end
// MARK: - Main
int main(int argc, const char *argv[]) {
@autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *delegate = [[AppDelegate alloc] init];
app.delegate = delegate;
[app run];
}
return 0;
}