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

Unified Diff: content/browser/device_monitor_mac.mm

Issue 10824162: add device notification to Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/device_monitor_mac.mm
diff --git a/content/browser/device_monitor_mac.mm b/content/browser/device_monitor_mac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..dfc6ca1c65d1bf67a0737c9d178dbffdabc62831
--- /dev/null
+++ b/content/browser/device_monitor_mac.mm
@@ -0,0 +1,174 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/device_monitor_mac.h"
+
+#include "base/logging.h"
+#include "base/system_monitor/system_monitor.h"
+
+#include <CoreFoundation/CFNumber.h>
tommi (sloooow) - chröme 2012/08/03 11:24:29 shouldn't these be above the chrome includes?
no longer working on chromium 2012/08/03 13:07:07 done.
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/usb/IOUSBLib.h>
+
+namespace content {
+
+namespace {
+
+DeviceMonitorMac* InstanceFromContext(void* context) {
+ return reinterpret_cast<DeviceMonitorMac*>(context);
+}
+
+void AddValueToDictionary(CFMutableDictionaryRef dictionary,
+ SInt32 code,
+ const void *key) {
+ CFNumberRef number_ref = CFNumberCreate(kCFAllocatorDefault,
+ kCFNumberSInt32Type,
+ &code);
+ if (!number_ref) {
+ NOTREACHED() << "failed to create CFNumberRef for " << code;
+ return;
+ }
+
+ CFDictionaryAddValue(dictionary, key, number_ref);
+ CFRelease(number_ref);
+
+ dictionary = (CFMutableDictionaryRef)(CFRetain(dictionary));
tommi (sloooow) - chröme 2012/08/03 11:24:29 fix cast or is this how things are done in mm land
no longer working on chromium 2012/08/03 13:07:07 neither static_cast nor reinterpret_cast passes th
+}
+
+void VideoDeviceChangedCallback(void *context, io_iterator_t devices) {
tommi (sloooow) - chröme 2012/08/03 11:24:29 void* context. In order to allow this method to c
no longer working on chromium 2012/08/03 13:07:07 Done.
+ io_object_t thisObject;
+ while ((thisObject = IOIteratorNext(devices))) {
+ if (context)
+ InstanceFromContext(context)->NotifyVideoDeviceChanged();
+
+ IOObjectRelease(thisObject);
+ }
+}
+
+void AudioDeviceChangedCallback(void *context, io_iterator_t devices) {
tommi (sloooow) - chröme 2012/08/03 11:24:29 same as above.
no longer working on chromium 2012/08/03 13:07:07 Done.
+ io_object_t thisObject;
+ while ((thisObject = IOIteratorNext(devices))) {
+ if (context)
+ InstanceFromContext(context)->NotifyAudioDeviceChanged();
+
+ IOObjectRelease(thisObject);
+ }
+}
+
+} // namespace
+
+DeviceMonitorMac::DeviceMonitorMac() {
+ CFRunLoopRef runloop = CFRunLoopGetCurrent ();
tommi (sloooow) - chröme 2012/08/03 11:24:29 no space before ()
no longer working on chromium 2012/08/03 13:07:07 Done.
+ CFRetain (runloop);
+
+ // Add the notification port to the run loop.
+ IONotificationPortRef notification_port =
+ IONotificationPortCreate (kIOMasterPortDefault);
tommi (sloooow) - chröme 2012/08/03 11:24:29 same here. please fix throughout
no longer working on chromium 2012/08/03 13:07:07 Done.
+ CFRunLoopSourceRef notification_cfsource =
+ IONotificationPortGetRunLoopSource (notification_port);
+
+ RegisterVideoCallbacks(notification_port);
+ RegisterAudioCallbacks(notification_port);
+ CFRunLoopAddSource(runloop, notification_cfsource, kCFRunLoopCommonModes);
+}
+
+void DeviceMonitorMac::RegisterVideoCallbacks(IONotificationPortRef port) {
+ SInt32 interface_class_code = kUSBVideoInterfaceClass;
+ SInt32 interface_subclass_code = kUSBVideoControlSubClass;
+ CFMutableDictionaryRef matching_dictionary = IOServiceMatching(
+ kIOUSBInterfaceClassName);
+ AddValueToDictionary(matching_dictionary, interface_class_code,
+ CFSTR(kUSBInterfaceClass));
+ AddValueToDictionary(matching_dictionary, interface_subclass_code,
+ CFSTR(kUSBInterfaceSubClass));
+
+ // Add a callback which will be called when a video device is plugged in.
+ io_iterator_t new_devices_iterator = 0;
+ kern_return_t err = IOServiceAddMatchingNotification(
+ port,
+ kIOMatchedNotification,
+ matching_dictionary,
+ &VideoDeviceChangedCallback,
+ this,
+ &new_devices_iterator);
+ if (err) {
+ NOTREACHED() << "Failed to register the video IO mached notification";
+ return;
+ }
+ VideoDeviceChangedCallback(NULL, new_devices_iterator);
+
+ // Add a callback which will be called when a video device is terminated.
+ io_iterator_t lost_devices_iterator = 0;
+ err = IOServiceAddMatchingNotification(
+ port,
+ kIOTerminatedNotification,
+ matching_dictionary,
+ &VideoDeviceChangedCallback,
+ this,
+ &lost_devices_iterator);
+ if (err) {
+ NOTREACHED() << "Failed to register the video IO terminated notification";
+ return;
+ }
+ VideoDeviceChangedCallback(NULL, lost_devices_iterator);
+}
+
+void DeviceMonitorMac::RegisterAudioCallbacks(IONotificationPortRef port) {
+ SInt32 interface_class_code = kUSBAudioInterfaceClass;
+ SInt32 interface_subclass_code = kUSBAudioControlSubClass;
+ CFMutableDictionaryRef matching_dictionary = IOServiceMatching(
+ kIOUSBInterfaceClassName);
+ AddValueToDictionary(matching_dictionary, interface_class_code,
+ CFSTR(kUSBInterfaceClass));
+ AddValueToDictionary(matching_dictionary, interface_subclass_code,
+ CFSTR(kUSBInterfaceSubClass));
+
+ // Add a callback which will be called when a audio device is plugged in.
+ io_iterator_t added_devices_iterator = 0;
+ kern_return_t err = IOServiceAddMatchingNotification(
+ port,
+ kIOMatchedNotification,
+ matching_dictionary,
+ &AudioDeviceChangedCallback,
+ this,
+ &added_devices_iterator);
+ if (err) {
+ NOTREACHED() << "Failed to register the audio IO mached notification";
+ return;
+ }
+ // Iterate over set of matching devices to access already-present devices
+ // and to arm the notification.
+ AudioDeviceChangedCallback(NULL, added_devices_iterator);
+
+ // Add a callback which will be called when a audio device is terminated.
+ io_iterator_t removed_devices_iterator = 0;
+ err = IOServiceAddMatchingNotification(
+ port,
+ kIOTerminatedNotification,
+ matching_dictionary,
+ &AudioDeviceChangedCallback,
+ this,
+ &removed_devices_iterator);
+ if (err) {
+ NOTREACHED() << "Failed to register the audio IO terminated notification";
tommi (sloooow) - chröme 2012/08/03 11:24:29 fix indent
no longer working on chromium 2012/08/03 13:07:07 Done.
+ return;
+ }
+ // Iterate over set of matching devices to release each one and to
+ // arm the notification.
+ AudioDeviceChangedCallback(NULL, removed_devices_iterator);
+}
+
+void DeviceMonitorMac::NotifyAudioDeviceChanged() {
+ base::SystemMonitor* monitor = base::SystemMonitor::Get();
+ monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
+}
+
+void DeviceMonitorMac::NotifyVideoDeviceChanged() {
+ base::SystemMonitor* monitor = base::SystemMonitor::Get();
+ monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
+}
+
+DeviceMonitorMac::~DeviceMonitorMac() {}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698