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

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: moved the .mm to .cc, changed const struct back to stuct 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/usb/IOUSBLib.h>
8
9 #include "base/logging.h"
10 #include "base/mac/scoped_cftyperef.h"
11 #include "base/mac/scoped_ioobject.h"
12
13 namespace content {
14
15 namespace {
16
17 struct {
no longer working on chromium 2012/08/08 09:23:16 We can't use const struct here because we need to
Mark Mentovai 2012/08/08 12:38:03 That’s exactly the problem I was illustrating. It
18 base::SystemMonitor::DeviceType device_type;
19 const io_name_t service_type;
20 } kDeviceServices[] = {
21 // Add new services here if needed.
22 { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kIOMatchedNotification },
23 { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kIOTerminatedNotification },
24 { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kIOMatchedNotification },
25 { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kIOTerminatedNotification },
26 };
27
28 CFMutableDictionaryRef CreateMatchingDictionary(
29 SInt32 interface_class_code, SInt32 interface_subclass_code) {
30 CFMutableDictionaryRef matching_dictionary = IOServiceMatching(
31 kIOUSBInterfaceClassName);
32 base::mac::ScopedCFTypeRef<CFNumberRef> number_ref(CFNumberCreate(
33 kCFAllocatorDefault, kCFNumberSInt32Type, &interface_class_code));
34 DCHECK(number_ref);
35 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceClass),
36 number_ref);
37
38 number_ref.reset(CFNumberCreate(kCFAllocatorDefault,
39 kCFNumberSInt32Type,
40 &interface_subclass_code));
41 DCHECK(number_ref);
42 CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBInterfaceSubClass),
43 number_ref);
44
45 return matching_dictionary;
46 }
47
48 void AddCallbackToIOService(IONotificationPortRef port,
49 const io_name_t type,
50 CFMutableDictionaryRef dictionary,
51 IOServiceMatchingCallback callback,
52 void* context,
53 io_iterator_t* notification) {
54 kern_return_t err = IOServiceAddMatchingNotification(port,
55 type,
56 dictionary,
57 callback,
58 context,
59 notification);
60 if (err) {
61 NOTREACHED() << "Failed to register the IO matched notification for type "
62 << type;
63 return;
64 }
65 DCHECK(*notification);
66
67 // Iterate over set of matching devices to access already-present devices
68 // and to arm the notification.
69 base::mac::ScopedIOObject<io_service_t> this_object(
70 IOIteratorNext(*notification));
71 for (; this_object; this_object.reset(IOIteratorNext(*notification)));
72 }
73
74 } // namespace
75
76 DeviceMonitorMac::DeviceMonitorMac() {
77
78 // Add the notification port to the run loop.
79 notification_port_ = IONotificationPortCreate(kIOMasterPortDefault);
80 DCHECK(notification_port_);
81
82 RegisterServices();
83
84 CFRunLoopAddSource(CFRunLoopGetCurrent(),
85 IONotificationPortGetRunLoopSource(notification_port_),
86 kCFRunLoopCommonModes);
87 }
88
89 DeviceMonitorMac::~DeviceMonitorMac() {
90 // Stop the notifications and free the objects.
91 for (size_t i = 0; i < arraysize(kDeviceServices); ++i) {
92 IOObjectRelease(notification_iterators_[i]);
93 }
94
95 // Remove the sleep notification port from the application runloop.
96 CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
97 IONotificationPortGetRunLoopSource(notification_port_),
98 kCFRunLoopCommonModes);
99
100 // Destroy the notification port allocated by IONotificationPortCreate.
101 IONotificationPortDestroy(notification_port_);
102 }
103
104 void DeviceMonitorMac::RegisterServices() {
105 notification_iterators_.reset(new io_iterator_t[arraysize(kDeviceServices)]);
106 CFMutableDictionaryRef matching_dictionary;
107 for (size_t i = 0; i < arraysize(kDeviceServices); ++i) {
108 switch (kDeviceServices[i].device_type) {
109 case base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE:
110 matching_dictionary = CreateMatchingDictionary(
111 kUSBAudioInterfaceClass, kUSBAudioControlSubClass);
112 break;
113 case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE:
114 matching_dictionary = CreateMatchingDictionary(
115 kUSBVideoInterfaceClass, kUSBVideoControlSubClass);
116 break;
117 default:
118 NOTREACHED();
119 return;
120 }
121
122 // Add callback to the service.
123 AddCallbackToIOService(notification_port_,
124 kDeviceServices[i].service_type,
125 matching_dictionary,
126 &DeviceChangedCallback,
127 static_cast<void*>(&kDeviceServices[i].device_type),
128 &notification_iterators_[i]);
129 }
130 }
131
132 void DeviceMonitorMac::DeviceChangedCallback(void *context,
133 io_iterator_t iterator) {
134 base::mac::ScopedIOObject<io_service_t> this_object(IOIteratorNext(iterator));
135 for (; this_object; this_object.reset(IOIteratorNext(iterator))) {
136 if (context) {
137 base::SystemMonitor::DeviceType device_type =
138 *reinterpret_cast<base::SystemMonitor::DeviceType*>(context);
139 DCHECK(device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE ||
140 device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
141 // TODO(xians): Remove the global variable for SystemMonitor.
142 base::SystemMonitor::Get()->ProcessDevicesChanged(device_type);
143 }
144 }
145 }
146
147 } // 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