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> | |
Avi (use Gerrit)
2012/08/06 13:54:37
You don't need to include this; the include below
no longer working on chromium
2012/08/06 19:53:12
Done.
| |
8 #include <CoreFoundation/CoreFoundation.h> | |
9 #include <IOKit/usb/IOUSBLib.h> | |
10 | |
11 #include "base/logging.h" | |
12 #include "base/mac/scoped_cftyperef.h" | |
13 #include "base/mac/scoped_ioobject.h" | |
14 | |
15 namespace content { | |
16 | |
17 namespace { | |
18 | |
19 CFMutableDictionaryRef CreateMatchingDictionary( | |
20 SInt32 interface_class_code, SInt32 interface_subclass_code) { | |
21 CFMutableDictionaryRef matching_dictionary = IOServiceMatching( | |
22 kIOUSBInterfaceClassName); | |
23 base::mac::ScopedCFTypeRef<CFNumberRef> number_ref(CFNumberCreate( | |
24 kCFAllocatorDefault, kCFNumberSInt32Type, &interface_class_code)); | |
25 DCHECK(number_ref); | |
26 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceClass), | |
27 number_ref); | |
28 | |
29 number_ref.reset(CFNumberCreate(kCFAllocatorDefault, | |
30 kCFNumberSInt32Type, | |
31 &interface_subclass_code)); | |
32 DCHECK(number_ref); | |
33 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceSubClass), | |
34 number_ref); | |
35 | |
36 return matching_dictionary; | |
37 } | |
38 | |
39 void AddCallbackToIOService(IONotificationPortRef port, | |
40 const io_name_t type, | |
41 CFMutableDictionaryRef dictionary, | |
42 IOServiceMatchingCallback callback, | |
43 void* context) { | |
44 // Retain additional dictionary references because each call to | |
45 // IOServiceAddMatchingNotification consumes one reference. | |
46 dictionary = (CFMutableDictionaryRef)(CFRetain(dictionary)); | |
Avi (use Gerrit)
2012/08/06 13:54:37
I already commented on this. Why do you feel you n
no longer working on chromium
2012/08/06 19:53:12
I should have removed it from the previous set of
| |
47 | |
48 io_iterator_t devices_iterator = 0; | |
Avi (use Gerrit)
2012/08/06 13:54:37
The iterator itself needs to be a base::mac::Scope
no longer working on chromium
2012/08/06 19:53:12
Thanks for pointing out, this does leak.
I have to
| |
49 kern_return_t err = IOServiceAddMatchingNotification(port, | |
50 type, | |
51 dictionary, | |
52 callback, | |
53 context, | |
54 &devices_iterator); | |
55 if (err) { | |
56 NOTREACHED() << "Failed to register the IO mached notification for type " | |
Avi (use Gerrit)
2012/08/06 13:54:37
s/mached/matched/
no longer working on chromium
2012/08/06 19:53:12
Done.
| |
57 << type; | |
58 return; | |
59 } | |
60 | |
61 // Iterate over set of matching devices to access already-present devices | |
62 // and to arm the notification. | |
63 base::mac::ScopedIOObject<io_service_t> this_object( | |
64 IOIteratorNext(devices_iterator)); | |
65 for (; this_object; this_object.reset(IOIteratorNext(devices_iterator))); | |
Avi (use Gerrit)
2012/08/06 13:54:37
Do we want to do something with the objects we're
no longer working on chromium
2012/08/06 19:53:12
My understanding here is simply loop through the e
Avi (use Gerrit)
2012/08/06 20:29:47
Do we need to fire a first-time changed callback?
no longer working on chromium
2012/08/06 22:01:10
This for loop does the same as calling a first-tim
| |
66 } | |
67 | |
68 void RegisterCallbacks(IONotificationPortRef port, | |
69 CFMutableDictionaryRef dictionary, | |
70 IOServiceMatchingCallback callback, | |
71 void* context) { | |
72 // Add a callback which will be called when a video device is plugged in. | |
73 AddCallbackToIOService(port, | |
74 kIOMatchedNotification, | |
75 dictionary, | |
76 callback, | |
77 context); | |
78 | |
79 // Add a callback which will be called when a video device is terminated. | |
80 AddCallbackToIOService(port, | |
81 kIOTerminatedNotification, | |
82 dictionary, | |
83 callback, | |
84 context); | |
85 } | |
86 | |
87 } // namespace | |
88 | |
89 DeviceMonitorMac::DeviceMonitorMac() { | |
90 CFRunLoopRef runloop = CFRunLoopGetCurrent(); | |
91 CFRetain(runloop); | |
Avi (use Gerrit)
2012/08/06 13:54:37
Why are you retaining this? Please address my earl
no longer working on chromium
2012/08/06 19:53:12
This should have been removed too. Sorry.
| |
92 | |
93 // Add the notification port to the run loop. | |
94 notification_port_ = IONotificationPortCreate(kIOMasterPortDefault); | |
95 DCHECK(notification_port_); | |
96 CFRunLoopSourceRef notification_cfsource = | |
97 IONotificationPortGetRunLoopSource(notification_port_); | |
98 | |
99 RegisterVideoCallbacks(); | |
100 RegisterAudioCallbacks(); | |
101 CFRunLoopAddSource(runloop, notification_cfsource, kCFRunLoopCommonModes); | |
102 } | |
103 | |
104 DeviceMonitorMac::~DeviceMonitorMac() { | |
105 // Remove the sleep notification port from the application runloop. | |
106 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), | |
107 IONotificationPortGetRunLoopSource(notification_port_), | |
108 kCFRunLoopCommonModes); | |
109 | |
110 // Destroy the notification port allocated by IONotificationPortCreate. | |
111 IONotificationPortDestroy(notification_port_); | |
112 } | |
113 | |
114 void DeviceMonitorMac::RegisterVideoCallbacks() { | |
115 CFMutableDictionaryRef matching_dictionary = CreateMatchingDictionary( | |
116 kUSBVideoInterfaceClass, kUSBVideoControlSubClass); | |
117 | |
118 RegisterCallbacks(notification_port_, | |
119 matching_dictionary, | |
120 &VideoDeviceChangedCallback, | |
121 this); | |
122 } | |
123 | |
124 void DeviceMonitorMac::RegisterAudioCallbacks() { | |
125 CFMutableDictionaryRef matching_dictionary = CreateMatchingDictionary( | |
126 kUSBAudioInterfaceClass, kUSBAudioControlSubClass); | |
127 | |
128 RegisterCallbacks(notification_port_, | |
129 matching_dictionary, | |
130 &AudioDeviceChangedCallback, | |
131 this); | |
132 } | |
133 | |
134 void DeviceMonitorMac::VideoDeviceChangedCallback(void *context, | |
135 io_iterator_t devices) { | |
136 base::mac::ScopedIOObject<io_service_t> this_object(IOIteratorNext(devices)); | |
137 for (; this_object; this_object.reset(IOIteratorNext(devices))) { | |
138 if (context) { | |
139 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged( | |
140 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); | |
141 } | |
142 IOObjectRelease(this_object); | |
Avi (use Gerrit)
2012/08/06 13:54:37
Wha? No, the ScopedIOObject releases.
no longer working on chromium
2012/08/06 19:53:12
Done.
| |
143 } | |
144 } | |
145 | |
146 void DeviceMonitorMac::AudioDeviceChangedCallback(void *context, | |
147 io_iterator_t devices) { | |
148 base::mac::ScopedIOObject<io_service_t> this_object(IOIteratorNext(devices)); | |
149 for (; this_object; this_object.reset(IOIteratorNext(devices))) { | |
150 if (context) { | |
151 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged( | |
152 base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); | |
153 } | |
154 IOObjectRelease(this_object); | |
Avi (use Gerrit)
2012/08/06 13:54:37
Ditto.
no longer working on chromium
2012/08/06 19:53:12
Done.
| |
155 } | |
156 } | |
157 | |
158 void DeviceMonitorMac::NotifyDeviceChanged( | |
159 base::SystemMonitor::DeviceType type) { | |
160 base::SystemMonitor::Get()->ProcessDevicesChanged(type); | |
161 } | |
162 | |
163 } // namespace content | |
OLD | NEW |