OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/device_monitor_mac.h" | 5 #include "content/browser/device_monitor_mac.h" |
6 | 6 |
7 #include <IOKit/audio/IOAudioDefines.h> | |
8 #include <IOKit/usb/IOUSBLib.h> | 7 #include <IOKit/usb/IOUSBLib.h> |
9 | 8 |
10 #include "base/logging.h" | 9 #include "base/logging.h" |
11 #include "base/mac/scoped_cftyperef.h" | 10 #include "base/mac/scoped_cftyperef.h" |
12 #include "base/mac/scoped_ioobject.h" | 11 #include "base/mac/scoped_ioobject.h" |
13 | 12 |
14 namespace content { | 13 namespace content { |
15 | 14 |
16 namespace { | 15 namespace { |
17 | 16 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 // Remove the notification port from the message runloop. | 90 // Remove the notification port from the message runloop. |
92 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), | 91 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), |
93 IONotificationPortGetRunLoopSource(notification_port_), | 92 IONotificationPortGetRunLoopSource(notification_port_), |
94 kCFRunLoopCommonModes); | 93 kCFRunLoopCommonModes); |
95 | 94 |
96 // Destroy the notification port allocated by IONotificationPortCreate. | 95 // Destroy the notification port allocated by IONotificationPortCreate. |
97 IONotificationPortDestroy(notification_port_); | 96 IONotificationPortDestroy(notification_port_); |
98 } | 97 } |
99 | 98 |
100 void DeviceMonitorMac::RegisterAudioServices() { | 99 void DeviceMonitorMac::RegisterAudioServices() { |
101 CFMutableDictionaryRef dictionary = | 100 // We can't use IOService for audio since IOKit notification will come prior |
102 IOServiceMatching(kIOAudioDeviceClassName); | 101 // to the driver is actually fully initialized, and this has two issues: |
103 RegisterServices(dictionary, &AudioDeviceCallback); | 102 // 1, device enumeration is not correct. |
| 103 // 2, it might crash if the device is being enumerated at the same time as |
| 104 // as being initialized. See issue 153411 for details. |
| 105 AudioObjectPropertyAddress property = { |
| 106 kAudioHardwarePropertyDevices, |
| 107 kAudioObjectPropertyScopeGlobal, |
| 108 kAudioObjectPropertyElementMaster |
| 109 }; |
| 110 AudioObjectAddPropertyListener(kAudioObjectSystemObject, &property, |
| 111 &AudioDeviceCallback, this); |
104 } | 112 } |
105 | 113 |
106 void DeviceMonitorMac::RegisterVideoServices() { | 114 void DeviceMonitorMac::RegisterVideoServices() { |
107 CFMutableDictionaryRef dictionary = CreateMatchingDictionaryForUSBDevices( | 115 CFMutableDictionaryRef dictionary = CreateMatchingDictionaryForUSBDevices( |
108 kUSBVideoInterfaceClass, kUSBVideoControlSubClass); | 116 kUSBVideoInterfaceClass, kUSBVideoControlSubClass); |
109 RegisterServices(dictionary, &VideoDeviceCallback); | 117 RegisterServices(dictionary, &VideoDeviceCallback); |
110 } | 118 } |
111 | 119 |
112 void DeviceMonitorMac::RegisterServices(CFMutableDictionaryRef dictionary, | 120 void DeviceMonitorMac::RegisterServices(CFMutableDictionaryRef dictionary, |
113 IOServiceMatchingCallback callback) { | 121 IOServiceMatchingCallback callback) { |
(...skipping 13 matching lines...) Expand all Loading... |
127 callback, | 135 callback, |
128 this, | 136 this, |
129 &service); | 137 &service); |
130 | 138 |
131 // Store the pointer of the object to release the memory when shutting | 139 // Store the pointer of the object to release the memory when shutting |
132 // down the services. | 140 // down the services. |
133 notification_iterators_.push_back(&service); | 141 notification_iterators_.push_back(&service); |
134 } | 142 } |
135 } | 143 } |
136 | 144 |
137 void DeviceMonitorMac::AudioDeviceCallback(void *context, | 145 OSStatus DeviceMonitorMac::AudioDeviceCallback( |
138 io_iterator_t iterator) { | 146 AudioObjectID object, UInt32 size, |
139 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(iterator)); | 147 const AudioObjectPropertyAddress addresses[], void* context) { |
140 object; | 148 for (UInt32 i = 0; i < size; ++i) { |
141 object.reset(IOIteratorNext(iterator))) { | 149 if (addresses[i].mSelector == kAudioHardwarePropertyDevices) { |
142 if (context) { | 150 if (context) { |
143 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged( | 151 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged( |
144 base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); | 152 base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); |
| 153 break; |
| 154 } |
145 } | 155 } |
146 } | 156 } |
| 157 |
| 158 return noErr; |
147 } | 159 } |
148 | 160 |
149 void DeviceMonitorMac::VideoDeviceCallback(void *context, | 161 void DeviceMonitorMac::VideoDeviceCallback(void *context, |
150 io_iterator_t iterator) { | 162 io_iterator_t iterator) { |
151 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(iterator)); | 163 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(iterator)); |
152 object; | 164 object; |
153 object.reset(IOIteratorNext(iterator))) { | 165 object.reset(IOIteratorNext(iterator))) { |
154 if (context) { | 166 if (context) { |
155 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged( | 167 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged( |
156 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); | 168 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); |
157 } | 169 } |
158 } | 170 } |
159 } | 171 } |
160 | 172 |
161 void DeviceMonitorMac::NotifyDeviceChanged( | 173 void DeviceMonitorMac::NotifyDeviceChanged( |
162 base::SystemMonitor::DeviceType type) { | 174 base::SystemMonitor::DeviceType type) { |
163 // TODO(xians): Remove the global variable for SystemMonitor. | 175 // TODO(xians): Remove the global variable for SystemMonitor. |
164 base::SystemMonitor::Get()->ProcessDevicesChanged(type); | 176 base::SystemMonitor::Get()->ProcessDevicesChanged(type); |
165 } | 177 } |
166 | 178 |
167 } // namespace content | 179 } // namespace content |
OLD | NEW |