OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/device_monitor_mac.h" | |
6 | |
7 #include <CoreFoundation/CFNumber.h> | |
8 #include <CoreFoundation/CoreFoundation.h> | |
9 #include <IOKit/usb/IOUSBLib.h> | |
10 | |
11 #include "base/logging.h" | |
12 | |
13 namespace content { | |
14 | |
15 namespace { | |
16 | |
17 DeviceMonitorMac* InstanceFromContext(void* context) { | |
Avi (use Gerrit)
2012/08/03 19:41:23
Does this help in readability? I'd think folding i
no longer working on chromium
2012/08/06 09:43:12
Done.
| |
18 return reinterpret_cast<DeviceMonitorMac*>(context); | |
19 } | |
20 | |
21 void AddValueToDictionary(CFMutableDictionaryRef dictionary, | |
Avi (use Gerrit)
2012/08/03 19:41:23
Ditto. If you use scoped_cftyperef, this collapses
no longer working on chromium
2012/08/06 09:43:12
Done.
| |
22 SInt32 code, | |
23 const void *key) { | |
24 CFNumberRef number_ref = CFNumberCreate(kCFAllocatorDefault, | |
Avi (use Gerrit)
2012/08/03 19:41:23
scoped_cftyperef.
no longer working on chromium
2012/08/06 09:43:12
Done.
| |
25 kCFNumberSInt32Type, | |
26 &code); | |
27 if (!number_ref) { | |
28 NOTREACHED() << "failed to create CFNumberRef for " << code; | |
29 return; | |
30 } | |
31 | |
32 CFDictionaryAddValue(dictionary, key, number_ref); | |
33 CFRelease(number_ref); | |
34 } | |
35 | |
36 CFMutableDictionaryRef CreateMachingDictionary(SInt32 interface_class_code, | |
Avi (use Gerrit)
2012/08/03 19:41:23
s/CreateMachingDictionary/CreateMatchingDictionary
no longer working on chromium
2012/08/06 09:43:12
Done.
| |
37 SInt32 interface_subclass_code) { | |
38 CFMutableDictionaryRef matching_dictionary = IOServiceMatching( | |
39 kIOUSBInterfaceClassName); | |
40 AddValueToDictionary(matching_dictionary, interface_class_code, | |
41 CFSTR(kUSBInterfaceClass)); | |
42 AddValueToDictionary(matching_dictionary, interface_subclass_code, | |
43 CFSTR(kUSBInterfaceSubClass)); | |
44 | |
45 return matching_dictionary; | |
46 } | |
47 | |
48 void AddCallbackToIOService(IONotificationPortRef port, | |
49 const io_name_t type, | |
50 CFMutableDictionaryRef dictionary, | |
51 IOServiceMatchingCallback callback, | |
52 void* context) { | |
53 // Retain additional dictionary references because each call to | |
54 // IOServiceAddMatchingNotification consumes one reference. | |
55 dictionary = (CFMutableDictionaryRef)(CFRetain(dictionary)); | |
Avi (use Gerrit)
2012/08/03 19:41:23
Huh? Just do
CFRetain(dictionary);
Why do you fe
no longer working on chromium
2012/08/06 09:43:12
From the silly example code, removed.
Avi (use Gerrit)
2012/08/06 13:54:37
This is not removed in the latest snapshot.
| |
56 | |
57 io_iterator_t devices_iterator = 0; | |
58 kern_return_t err = IOServiceAddMatchingNotification(port, | |
59 type, | |
60 dictionary, | |
61 callback, | |
62 context, | |
63 &devices_iterator); | |
64 if (err) { | |
65 NOTREACHED() << "Failed to register the IO mached notification for type " | |
66 << type; | |
67 return; | |
68 } | |
69 | |
70 // Iterate over set of matching devices to access already-present devices | |
71 // and to arm the notification. | |
72 io_object_t thisObject; | |
Avi (use Gerrit)
2012/08/03 19:41:23
base::mac::ScopedIOObject<io_object_t>? Also, this
no longer working on chromium
2012/08/06 09:43:12
Done.
| |
73 while ((thisObject = IOIteratorNext(devices_iterator))) | |
74 IOObjectRelease(thisObject); | |
75 } | |
76 | |
77 } // namespace | |
78 | |
79 DeviceMonitorMac::DeviceMonitorMac() { | |
80 CFRunLoopRef runloop = CFRunLoopGetCurrent(); | |
81 CFRetain(runloop); | |
Avi (use Gerrit)
2012/08/03 19:41:23
Why the retain?
no longer working on chromium
2012/08/06 09:43:12
Sorry, uncleaned debugging code.
Avi (use Gerrit)
2012/08/06 13:54:37
This isn't fixed in the latest snapshot either.
| |
82 | |
83 // Add the notification port to the run loop. | |
84 IONotificationPortRef notification_port = | |
85 IONotificationPortCreate(kIOMasterPortDefault); | |
Avi (use Gerrit)
2012/08/03 19:41:23
Where is the matching IONotificationPortDestroy?
no longer working on chromium
2012/08/06 09:43:12
Oh, thanks for pointing out, that example code I w
| |
86 CFRunLoopSourceRef notification_cfsource = | |
87 IONotificationPortGetRunLoopSource(notification_port); | |
88 | |
89 RegisterVideoCallbacks(notification_port); | |
90 RegisterAudioCallbacks(notification_port); | |
91 CFRunLoopAddSource(runloop, notification_cfsource, kCFRunLoopCommonModes); | |
92 } | |
93 | |
94 void DeviceMonitorMac::RegisterVideoCallbacks(IONotificationPortRef port) { | |
95 CFMutableDictionaryRef matching_dictionary = CreateMachingDictionary( | |
96 kUSBVideoInterfaceClass, kUSBVideoControlSubClass); | |
97 | |
98 // Add a callback which will be called when a video device is plugged in. | |
99 AddCallbackToIOService(port, | |
100 kIOMatchedNotification, | |
101 matching_dictionary, | |
102 &VideoDeviceChangedCallback, | |
103 this); | |
104 | |
105 | |
106 // Add a callback which will be called when a video device is terminated. | |
107 AddCallbackToIOService(port, | |
108 kIOTerminatedNotification, | |
109 matching_dictionary, | |
110 &VideoDeviceChangedCallback, | |
111 this); | |
112 } | |
113 | |
114 void DeviceMonitorMac::RegisterAudioCallbacks(IONotificationPortRef port) { | |
115 CFMutableDictionaryRef matching_dictionary = CreateMachingDictionary( | |
116 kUSBAudioInterfaceClass, kUSBAudioControlSubClass); | |
117 | |
118 // Add a callback which will be called when a audio device is plugged in. | |
119 AddCallbackToIOService(port, | |
120 kIOMatchedNotification, | |
121 matching_dictionary, | |
122 &AudioDeviceChangedCallback, | |
123 this); | |
124 | |
125 // Add a callback which will be called when a audio device is terminated. | |
126 AddCallbackToIOService(port, | |
127 kIOTerminatedNotification, | |
128 matching_dictionary, | |
129 &AudioDeviceChangedCallback, | |
130 this); | |
131 } | |
132 | |
133 void DeviceMonitorMac::VideoDeviceChangedCallback(void *context, | |
134 io_iterator_t devices) { | |
135 io_object_t thisObject; | |
136 while ((thisObject = IOIteratorNext(devices))) { | |
Avi (use Gerrit)
2012/08/03 19:41:23
See previous note about IOIteratorNext.
no longer working on chromium
2012/08/06 09:43:12
Done.
| |
137 if (context) { | |
138 InstanceFromContext(context)->NotifyDeviceChanged( | |
139 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); | |
140 } | |
141 IOObjectRelease(thisObject); | |
142 } | |
143 } | |
144 | |
145 void DeviceMonitorMac::AudioDeviceChangedCallback(void *context, | |
146 io_iterator_t devices) { | |
147 io_object_t thisObject; | |
148 while ((thisObject = IOIteratorNext(devices))) { | |
Avi (use Gerrit)
2012/08/03 19:41:23
Ditto.
no longer working on chromium
2012/08/06 09:43:12
Done.
| |
149 if (context) { | |
150 InstanceFromContext(context)->NotifyDeviceChanged( | |
151 base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); | |
152 } | |
153 IOObjectRelease(thisObject); | |
154 } | |
155 } | |
156 | |
157 void DeviceMonitorMac::NotifyDeviceChanged( | |
158 base::SystemMonitor::DeviceType type) { | |
159 base::SystemMonitor::Get()->ProcessDevicesChanged(type); | |
160 } | |
161 | |
162 | |
163 DeviceMonitorMac::~DeviceMonitorMac() {} | |
164 | |
165 } // namespace content | |
OLD | NEW |