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

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: use kIOAudioDeviceClassName to cover the bluetooth devices and changed to use std::vector 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
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 {
Mark Mentovai 2012/08/14 15:37:05 We also usually put a blank line after opening a n
no longer working on chromium 2012/08/14 15:59:36 Done.
17 const io_name_t kServices[] = {
18 kIOFirstPublishNotification,
19 kIOTerminatedNotification,
20 };
21
22 CFMutableDictionaryRef CreateMatchingDictionaryForUSBDevices(
23 SInt32 interface_class_code, SInt32 interface_subclass_code) {
24 CFMutableDictionaryRef matching_dictionary = IOServiceMatching(
Mark Mentovai 2012/08/14 15:37:05 This is more legible when you break the line after
no longer working on chromium 2012/08/14 15:59:36 Done.
25 kIOUSBInterfaceClassName);
26 base::mac::ScopedCFTypeRef<CFNumberRef> number_ref(CFNumberCreate(
27 kCFAllocatorDefault, kCFNumberSInt32Type, &interface_class_code));
28 DCHECK(number_ref);
29 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceClass),
30 number_ref);
31
32 number_ref.reset(CFNumberCreate(kCFAllocatorDefault,
33 kCFNumberSInt32Type,
34 &interface_subclass_code));
35 DCHECK(number_ref);
36 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceSubClass),
37 number_ref);
38
39 return matching_dictionary;
40 }
41
42 void RegisterCallbackToIOService(IONotificationPortRef port,
43 const io_name_t type,
44 CFMutableDictionaryRef dictionary,
45 IOServiceMatchingCallback callback,
46 void* context,
47 io_iterator_t* service) {
48 kern_return_t err = IOServiceAddMatchingNotification(port,
49 type,
50 dictionary,
51 callback,
52 context,
53 service);
54 if (err) {
55 NOTREACHED() << "Failed to register the IO matched notification for type "
56 << type;
57 return;
58 }
59 DCHECK(*service);
60
61 // Iterate over set of matching devices to access already-present devices
62 // and to arm the notification.
63 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(*service));
64 object;
65 object.reset(IOIteratorNext(*service))) {};
66 }
67
68 } // namespace
69
70 DeviceMonitorMac::DeviceMonitorMac() {
71
Mark Mentovai 2012/08/14 15:37:05 But we don’t usually begin functions (or construct
no longer working on chromium 2012/08/14 15:59:36 Done.
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 sleep notification port from the application runloop.
Mark Mentovai 2012/08/14 15:37:05 This seems like a copy-paste job. This code has no
no longer working on chromium 2012/08/14 15:59:36 Done.
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 = IOServiceMatching(
Mark Mentovai 2012/08/14 15:37:05 Rewrap for readability as I suggested on line 24.
no longer working on chromium 2012/08/14 15:59:36 Done.
102 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 // Retain |arraysize(kServices) -1| additional dictionary references because
Mark Mentovai 2012/08/14 15:37:05 I don’t understand why you only do this for arrays
no longer working on chromium 2012/08/14 15:59:36 When creating the CFMutableDictionaryRef, the ref
Mark Mentovai 2012/08/14 16:02:53 xians1 wrote:
117 // each call to IOServiceAddMatchingNotification consumes one reference.
118 if (i < (arraysize(kServices) - 1))
119 CFRetain(dictionary);
120
121 // Register callback to each service.
122 io_iterator_t service;
123 RegisterCallbackToIOService(notification_port_,
124 kServices[i],
125 dictionary,
126 callback,
127 this,
128 &service);
129
130 // Store the pointer of the object to release the memory when shutting
131 // down the services.
132 notification_iterators_.push_back(&service);
133 }
134 }
135
136 void DeviceMonitorMac::AudioDeviceCallback(void *context,
137 io_iterator_t iterator) {
138 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(iterator));
139 object;
140 object.reset(IOIteratorNext(iterator))) {
141 if (context) {
142 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged(
143 base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
144 }
145 }
146 }
147
148 void DeviceMonitorMac::VideoDeviceCallback(void *context,
149 io_iterator_t iterator) {
150 for (base::mac::ScopedIOObject<io_service_t> object(IOIteratorNext(iterator));
151 object;
152 object.reset(IOIteratorNext(iterator))) {
153 if (context) {
154 reinterpret_cast<DeviceMonitorMac*>(context)->NotifyDeviceChanged(
155 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
156 }
157 }
158 }
159
160 void DeviceMonitorMac::NotifyDeviceChanged(
161 base::SystemMonitor::DeviceType type) {
162 // TODO(xians): Remove the global variable for SystemMonitor.
163 base::SystemMonitor::Get()->ProcessDevicesChanged(type);
164 }
165
166 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698