blob: c8251a1f8059c5a5bcef48451a9ef00fa25d3e8d [file] [log] [blame]
// 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"
#import <QTKit/QTKit.h>
#include "base/logging.h"
namespace content {
class DeviceMonitorMac::QTMonitorImpl {
public:
explicit QTMonitorImpl(DeviceMonitorMac* monitor);
virtual ~QTMonitorImpl() {}
void Start();
void Stop();
private:
void CountDevices();
void OnAttributeChanged(NSNotification* notification);
void OnDeviceChanged();
DeviceMonitorMac* monitor_;
int number_audio_devices_;
int number_video_devices_;
id device_arrival_;
id device_removal_;
id device_change_;
DISALLOW_COPY_AND_ASSIGN(QTMonitorImpl);
};
DeviceMonitorMac::QTMonitorImpl::QTMonitorImpl(DeviceMonitorMac* monitor)
: monitor_(monitor),
number_audio_devices_(0),
number_video_devices_(0),
device_arrival_(nil),
device_removal_(nil) {
DCHECK(monitor);
}
void DeviceMonitorMac::QTMonitorImpl::Start() {
CountDevices();
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
device_arrival_ =
[nc addObserverForName:QTCaptureDeviceWasConnectedNotification
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
OnDeviceChanged();}];
device_removal_ =
[nc addObserverForName:QTCaptureDeviceWasDisconnectedNotification
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
OnDeviceChanged();}];
device_change_ =
[nc addObserverForName:QTCaptureDeviceAttributeDidChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
OnAttributeChanged(notification);}];
}
void DeviceMonitorMac::QTMonitorImpl::Stop() {
if (!monitor_)
return;
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:device_arrival_];
[nc removeObserver:device_removal_];
[nc removeObserver:device_change_];
}
void DeviceMonitorMac::QTMonitorImpl::OnAttributeChanged(
NSNotification* notification) {
if ([[[notification userInfo] objectForKey:QTCaptureDeviceChangedAttributeKey]
isEqualToString:QTCaptureDeviceSuspendedAttribute])
OnDeviceChanged();
}
void DeviceMonitorMac::QTMonitorImpl::CountDevices() {
NSArray* devices = [QTCaptureDevice inputDevices];
number_video_devices_ = 0;
number_audio_devices_ = 0;
for (QTCaptureDevice* device in devices) {
// Act as if suspended video capture devices are not attached. For
// example, a laptop's internal webcam is suspended when the lid is closed.
if (([device hasMediaType:QTMediaTypeVideo] ||
[device hasMediaType:QTMediaTypeMuxed]) &&
![[device attributeForKey:QTCaptureDeviceSuspendedAttribute] boolValue])
++number_video_devices_;
if ([device hasMediaType:QTMediaTypeSound] ||
[device hasMediaType:QTMediaTypeMuxed])
++number_audio_devices_;
}
}
void DeviceMonitorMac::QTMonitorImpl::OnDeviceChanged() {
int number_video_devices = number_video_devices_;
int number_audio_devices = number_audio_devices_;
CountDevices();
if (number_video_devices_ != number_video_devices)
monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
if (number_audio_devices_ != number_audio_devices)
monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
}
DeviceMonitorMac::DeviceMonitorMac() {
qt_monitor_.reset(new QTMonitorImpl(this));
qt_monitor_->Start();
}
DeviceMonitorMac::~DeviceMonitorMac() {
qt_monitor_->Stop();
}
void DeviceMonitorMac::NotifyDeviceChanged(
base::SystemMonitor::DeviceType type) {
// TODO(xians): Remove the global variable for SystemMonitor.
base::SystemMonitor::Get()->ProcessDevicesChanged(type);
}
} // namespace content