Chromium Code Reviews| 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 |