Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(490)

Side by Side Diff: content/browser/device_monitor_mac.cc

Issue 10824162: add device notification to Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed linux bots. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/device_monitor_mac.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 <IOKit/audio/IOAudioDefines.h>
8 #include <IOKit/usb/IOUSBLib.h>
9
10 #include "base/logging.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #include "base/mac/scoped_ioobject.h"
13
14 namespace content {
15
16 namespace {
17
18 const io_name_t kServices[] = {
19 kIOFirstPublishNotification,
20 kIOTerminatedNotification,
21 };
22
23 CFMutableDictionaryRef CreateMatchingDictionaryForUSBDevices(
24 SInt32 interface_class_code, SInt32 interface_subclass_code) {
25 CFMutableDictionaryRef matching_dictionary =
26 IOServiceMatching(kIOUSBInterfaceClassName);
27 base::mac::ScopedCFTypeRef<CFNumberRef> number_ref(CFNumberCreate(
28 kCFAllocatorDefault, kCFNumberSInt32Type, &interface_class_code));
29 DCHECK(number_ref);
30 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceClass),
31 number_ref);
32
33 number_ref.reset(CFNumberCreate(kCFAllocatorDefault,
34 kCFNumberSInt32Type,
35 &interface_subclass_code));
36 DCHECK(number_ref);
37 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceSubClass),
38 number_ref);
39
40 return matching_dictionary;
41 }
42
43 void RegisterCallbackToIOService(IONotificationPortRef port,
44 const io_name_t type,
45 CFMutableDictionaryRef dictionary,
46 IOServiceMatchingCallback callback,
47 void* context,
48 io_iterator_t* service) {
49 kern_return_t err = IOServiceAddMatchingNotification(port,
50 type,
51 dictionary,
52 callback,
53 context,
54 service);
55 if (err) {
56 NOTREACHED() << "Failed to register the IO matched notification for type "
57 << type;
58 return;
59 }
60 DCHECK(*service);
61
62 // Iterate over set of matching devices to access already-present devices
63 // and to arm the notification.
64 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(*service));
65 object;
66 object.reset(IOIteratorNext(*service))) {};
67 }
68
69 } // namespace
70
71 DeviceMonitorMac::DeviceMonitorMac() {
72 // Add the notification port to the run loop.
73 notification_port_ = IONotificationPortCreate(kIOMasterPortDefault);
74 DCHECK(notification_port_);
75
76 RegisterAudioServices();
77 RegisterVideoServices();
78
79 CFRunLoopAddSource(CFRunLoopGetCurrent(),
80 IONotificationPortGetRunLoopSource(notification_port_),
81 kCFRunLoopCommonModes);
82 }
83
84 DeviceMonitorMac::~DeviceMonitorMac() {
85 // Stop the notifications and free the objects.
86 for (size_t i = 0; i < notification_iterators_.size(); ++i) {
87 IOObjectRelease(*notification_iterators_[i]);
88 }
89 notification_iterators_.clear();
90
91 // Remove the notification port from the message runloop.
92 CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
93 IONotificationPortGetRunLoopSource(notification_port_),
94 kCFRunLoopCommonModes);
95
96 // Destroy the notification port allocated by IONotificationPortCreate.
97 IONotificationPortDestroy(notification_port_);
98 }
99
100 void DeviceMonitorMac::RegisterAudioServices() {
101 CFMutableDictionaryRef dictionary =
102 IOServiceMatching(kIOAudioDeviceClassName);
103 RegisterServices(dictionary, &AudioDeviceCallback);
104 }
105
106 void DeviceMonitorMac::RegisterVideoServices() {
107 CFMutableDictionaryRef dictionary = CreateMatchingDictionaryForUSBDevices(
108 kUSBVideoInterfaceClass, kUSBVideoControlSubClass);
109 RegisterServices(dictionary, &VideoDeviceCallback);
110 }
111
112 void DeviceMonitorMac::RegisterServices(CFMutableDictionaryRef dictionary,
113 IOServiceMatchingCallback callback) {
114 // Add callback to the service.
115 for (size_t i = 0; i < arraysize(kServices); ++i) {
116 // |dictionary| comes in with a reference count as 1. Since each call to
117 // IOServiceAddMatchingNotification consumes one reference, we need to
118 // retain |arraysize(kServices) -1| additional dictionary references.
119 if (i < (arraysize(kServices) - 1))
120 CFRetain(dictionary);
121
122 // Register callback to each service.
123 io_iterator_t service;
124 RegisterCallbackToIOService(notification_port_,
125 kServices[i],
126 dictionary,
127 callback,
128 this,
129 &service);
130
131 // Store the pointer of the object to release the memory when shutting
132 // down the services.
133 notification_iterators_.push_back(&service);
134 }
135 }
136
137 void DeviceMonitorMac::AudioDeviceCallback(void *context,
138 io_iterator_t iterator) {
139 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(iterator));
140 object;
141 object.reset(IOIteratorNext(iterator))) {
142 if (context) {
143 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged(
144 base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
145 }
146 }
147 }
148
149 void DeviceMonitorMac::VideoDeviceCallback(void *context,
150 io_iterator_t iterator) {
151 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(iterator));
152 object;
153 object.reset(IOIteratorNext(iterator))) {
154 if (context) {
155 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged(
156 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
157 }
158 }
159 }
160
161 void DeviceMonitorMac::NotifyDeviceChanged(
162 base::SystemMonitor::DeviceType type) {
163 // TODO(xians): Remove the global variable for SystemMonitor.
164 base::SystemMonitor::Get()->ProcessDevicesChanged(type);
165 }
166
167 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/device_monitor_mac.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698