| Index: media/audio/mac/aggregate_device_manager.cc
|
| diff --git a/media/audio/mac/aggregate_device_manager.cc b/media/audio/mac/aggregate_device_manager.cc
|
| deleted file mode 100644
|
| index c7f323322e77a8b56b57339905e539730427fd61..0000000000000000000000000000000000000000
|
| --- a/media/audio/mac/aggregate_device_manager.cc
|
| +++ /dev/null
|
| @@ -1,371 +0,0 @@
|
| -// Copyright 2013 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 "media/audio/mac/aggregate_device_manager.h"
|
| -
|
| -#include <CoreAudio/AudioHardware.h>
|
| -#include <string>
|
| -
|
| -#include "base/mac/mac_logging.h"
|
| -#include "base/mac/scoped_cftyperef.h"
|
| -#include "media/audio/audio_parameters.h"
|
| -#include "media/audio/mac/audio_manager_mac.h"
|
| -
|
| -using base::ScopedCFTypeRef;
|
| -
|
| -namespace media {
|
| -
|
| -AggregateDeviceManager::AggregateDeviceManager()
|
| - : plugin_id_(kAudioObjectUnknown),
|
| - input_device_(kAudioDeviceUnknown),
|
| - output_device_(kAudioDeviceUnknown),
|
| - aggregate_device_(kAudioObjectUnknown) {
|
| -}
|
| -
|
| -AggregateDeviceManager::~AggregateDeviceManager() {
|
| - DestroyAggregateDevice();
|
| -}
|
| -
|
| -AudioDeviceID AggregateDeviceManager::GetDefaultAggregateDevice() {
|
| - AudioDeviceID current_input_device;
|
| - AudioDeviceID current_output_device;
|
| - AudioManagerMac::GetDefaultInputDevice(¤t_input_device);
|
| - AudioManagerMac::GetDefaultOutputDevice(¤t_output_device);
|
| -
|
| - if (AudioManagerMac::HardwareSampleRateForDevice(current_input_device) !=
|
| - AudioManagerMac::HardwareSampleRateForDevice(current_output_device)) {
|
| - // TODO(crogers): with some extra work we can make aggregate devices work
|
| - // if the clock domain is the same but the sample-rate differ.
|
| - // For now we fallback to the synchronized path.
|
| - return kAudioDeviceUnknown;
|
| - }
|
| -
|
| - // Use a lazily created aggregate device if it's already available
|
| - // and still appropriate.
|
| - if (aggregate_device_ != kAudioObjectUnknown) {
|
| - // TODO(crogers): handle default device changes for synchronized I/O.
|
| - // For now, we check to make sure the default devices haven't changed
|
| - // since we lazily created the aggregate device.
|
| - if (current_input_device == input_device_ &&
|
| - current_output_device == output_device_)
|
| - return aggregate_device_;
|
| -
|
| - // For now, once lazily created don't attempt to create another
|
| - // aggregate device.
|
| - return kAudioDeviceUnknown;
|
| - }
|
| -
|
| - input_device_ = current_input_device;
|
| - output_device_ = current_output_device;
|
| -
|
| - // Only create an aggregrate device if the clock domains match.
|
| - UInt32 input_clockdomain = GetClockDomain(input_device_);
|
| - UInt32 output_clockdomain = GetClockDomain(output_device_);
|
| - DVLOG(1) << "input_clockdomain: " << input_clockdomain;
|
| - DVLOG(1) << "output_clockdomain: " << output_clockdomain;
|
| -
|
| - if (input_clockdomain == 0 || input_clockdomain != output_clockdomain)
|
| - return kAudioDeviceUnknown;
|
| -
|
| - OSStatus result = CreateAggregateDevice(
|
| - input_device_,
|
| - output_device_,
|
| - &aggregate_device_);
|
| - if (result != noErr)
|
| - DestroyAggregateDevice();
|
| -
|
| - return aggregate_device_;
|
| -}
|
| -
|
| -CFStringRef AggregateDeviceManager::GetDeviceUID(AudioDeviceID id) {
|
| - static const AudioObjectPropertyAddress kDeviceUIDAddress = {
|
| - kAudioDevicePropertyDeviceUID,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - // As stated in the CoreAudio header (AudioHardwareBase.h),
|
| - // the caller is responsible for releasing the device_UID.
|
| - CFStringRef device_UID;
|
| - UInt32 size = sizeof(device_UID);
|
| - OSStatus result = AudioObjectGetPropertyData(
|
| - id,
|
| - &kDeviceUIDAddress,
|
| - 0,
|
| - 0,
|
| - &size,
|
| - &device_UID);
|
| -
|
| - return (result == noErr) ? device_UID : NULL;
|
| -}
|
| -
|
| -void AggregateDeviceManager::GetDeviceName(
|
| - AudioDeviceID id, char* name, UInt32 size) {
|
| - static const AudioObjectPropertyAddress kDeviceNameAddress = {
|
| - kAudioDevicePropertyDeviceName,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - OSStatus result = AudioObjectGetPropertyData(
|
| - id,
|
| - &kDeviceNameAddress,
|
| - 0,
|
| - 0,
|
| - &size,
|
| - name);
|
| -
|
| - if (result != noErr && size > 0)
|
| - name[0] = 0;
|
| -}
|
| -
|
| -UInt32 AggregateDeviceManager::GetClockDomain(AudioDeviceID device_id) {
|
| - static const AudioObjectPropertyAddress kClockDomainAddress = {
|
| - kAudioDevicePropertyClockDomain,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - UInt32 clockdomain = 0;
|
| - UInt32 size = sizeof(UInt32);
|
| - OSStatus result = AudioObjectGetPropertyData(
|
| - device_id,
|
| - &kClockDomainAddress,
|
| - 0,
|
| - 0,
|
| - &size,
|
| - &clockdomain);
|
| -
|
| - return (result == noErr) ? clockdomain : 0;
|
| -}
|
| -
|
| -OSStatus AggregateDeviceManager::GetPluginID(AudioObjectID* id) {
|
| - DCHECK(id);
|
| -
|
| - // Get the audio hardware plugin.
|
| - CFStringRef bundle_name = CFSTR("com.apple.audio.CoreAudio");
|
| -
|
| - AudioValueTranslation plugin_translation;
|
| - plugin_translation.mInputData = &bundle_name;
|
| - plugin_translation.mInputDataSize = sizeof(bundle_name);
|
| - plugin_translation.mOutputData = id;
|
| - plugin_translation.mOutputDataSize = sizeof(*id);
|
| -
|
| - static const AudioObjectPropertyAddress kPlugInAddress = {
|
| - kAudioHardwarePropertyPlugInForBundleID,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - UInt32 size = sizeof(plugin_translation);
|
| - OSStatus result = AudioObjectGetPropertyData(
|
| - kAudioObjectSystemObject,
|
| - &kPlugInAddress,
|
| - 0,
|
| - 0,
|
| - &size,
|
| - &plugin_translation);
|
| -
|
| - DVLOG(1) << "CoreAudio plugin ID: " << *id;
|
| -
|
| - return result;
|
| -}
|
| -
|
| -CFMutableDictionaryRef
|
| -AggregateDeviceManager::CreateAggregateDeviceDictionary(
|
| - AudioDeviceID input_id,
|
| - AudioDeviceID output_id) {
|
| - CFMutableDictionaryRef aggregate_device_dict = CFDictionaryCreateMutable(
|
| - NULL,
|
| - 0,
|
| - &kCFTypeDictionaryKeyCallBacks,
|
| - &kCFTypeDictionaryValueCallBacks);
|
| - if (!aggregate_device_dict)
|
| - return NULL;
|
| -
|
| - const CFStringRef kAggregateDeviceName =
|
| - CFSTR("ChromeAggregateAudioDevice");
|
| - const CFStringRef kAggregateDeviceUID =
|
| - CFSTR("com.google.chrome.AggregateAudioDevice");
|
| -
|
| - // Add name and UID of the device to the dictionary.
|
| - CFDictionaryAddValue(
|
| - aggregate_device_dict,
|
| - CFSTR(kAudioAggregateDeviceNameKey),
|
| - kAggregateDeviceName);
|
| - CFDictionaryAddValue(
|
| - aggregate_device_dict,
|
| - CFSTR(kAudioAggregateDeviceUIDKey),
|
| - kAggregateDeviceUID);
|
| -
|
| - // Add a "private aggregate key" to the dictionary.
|
| - // The 1 value means that the created aggregate device will
|
| - // only be accessible from the process that created it, and
|
| - // won't be visible to outside processes.
|
| - int value = 1;
|
| - ScopedCFTypeRef<CFNumberRef> aggregate_device_number(CFNumberCreate(
|
| - NULL,
|
| - kCFNumberIntType,
|
| - &value));
|
| - CFDictionaryAddValue(
|
| - aggregate_device_dict,
|
| - CFSTR(kAudioAggregateDeviceIsPrivateKey),
|
| - aggregate_device_number);
|
| -
|
| - return aggregate_device_dict;
|
| -}
|
| -
|
| -CFMutableArrayRef
|
| -AggregateDeviceManager::CreateSubDeviceArray(
|
| - CFStringRef input_device_UID, CFStringRef output_device_UID) {
|
| - CFMutableArrayRef sub_devices_array = CFArrayCreateMutable(
|
| - NULL,
|
| - 0,
|
| - &kCFTypeArrayCallBacks);
|
| -
|
| - CFArrayAppendValue(sub_devices_array, input_device_UID);
|
| - CFArrayAppendValue(sub_devices_array, output_device_UID);
|
| -
|
| - return sub_devices_array;
|
| -}
|
| -
|
| -OSStatus AggregateDeviceManager::CreateAggregateDevice(
|
| - AudioDeviceID input_id,
|
| - AudioDeviceID output_id,
|
| - AudioDeviceID* aggregate_device) {
|
| - DCHECK(aggregate_device);
|
| -
|
| - const size_t kMaxDeviceNameLength = 256;
|
| -
|
| - scoped_ptr<char[]> input_device_name(new char[kMaxDeviceNameLength]);
|
| - GetDeviceName(
|
| - input_id,
|
| - input_device_name.get(),
|
| - sizeof(input_device_name));
|
| - DVLOG(1) << "Input device: \n" << input_device_name;
|
| -
|
| - scoped_ptr<char[]> output_device_name(new char[kMaxDeviceNameLength]);
|
| - GetDeviceName(
|
| - output_id,
|
| - output_device_name.get(),
|
| - sizeof(output_device_name));
|
| - DVLOG(1) << "Output device: \n" << output_device_name;
|
| -
|
| - OSStatus result = GetPluginID(&plugin_id_);
|
| - if (result != noErr)
|
| - return result;
|
| -
|
| - // Create a dictionary for the aggregate device.
|
| - ScopedCFTypeRef<CFMutableDictionaryRef> aggregate_device_dict(
|
| - CreateAggregateDeviceDictionary(input_id, output_id));
|
| - if (!aggregate_device_dict)
|
| - return -1;
|
| -
|
| - // Create the aggregate device.
|
| - static const AudioObjectPropertyAddress kCreateAggregateDeviceAddress = {
|
| - kAudioPlugInCreateAggregateDevice,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - UInt32 size = sizeof(*aggregate_device);
|
| - result = AudioObjectGetPropertyData(
|
| - plugin_id_,
|
| - &kCreateAggregateDeviceAddress,
|
| - sizeof(aggregate_device_dict),
|
| - &aggregate_device_dict,
|
| - &size,
|
| - aggregate_device);
|
| - if (result != noErr) {
|
| - DLOG(ERROR) << "Error creating aggregate audio device!";
|
| - return result;
|
| - }
|
| -
|
| - // Set the sub-devices for the aggregate device.
|
| - // In this case we use two: the input and output devices.
|
| -
|
| - ScopedCFTypeRef<CFStringRef> input_device_UID(GetDeviceUID(input_id));
|
| - ScopedCFTypeRef<CFStringRef> output_device_UID(GetDeviceUID(output_id));
|
| - if (!input_device_UID || !output_device_UID) {
|
| - DLOG(ERROR) << "Error getting audio device UID strings.";
|
| - return -1;
|
| - }
|
| -
|
| - ScopedCFTypeRef<CFMutableArrayRef> sub_devices_array(
|
| - CreateSubDeviceArray(input_device_UID, output_device_UID));
|
| - if (sub_devices_array == NULL) {
|
| - DLOG(ERROR) << "Error creating sub-devices array.";
|
| - return -1;
|
| - }
|
| -
|
| - static const AudioObjectPropertyAddress kSetSubDevicesAddress = {
|
| - kAudioAggregateDevicePropertyFullSubDeviceList,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - size = sizeof(CFMutableArrayRef);
|
| - result = AudioObjectSetPropertyData(
|
| - *aggregate_device,
|
| - &kSetSubDevicesAddress,
|
| - 0,
|
| - NULL,
|
| - size,
|
| - &sub_devices_array);
|
| - if (result != noErr) {
|
| - DLOG(ERROR) << "Error setting aggregate audio device sub-devices!";
|
| - return result;
|
| - }
|
| -
|
| - // Use the input device as the master device.
|
| - static const AudioObjectPropertyAddress kSetMasterDeviceAddress = {
|
| - kAudioAggregateDevicePropertyMasterSubDevice,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - size = sizeof(CFStringRef);
|
| - result = AudioObjectSetPropertyData(
|
| - *aggregate_device,
|
| - &kSetMasterDeviceAddress,
|
| - 0,
|
| - NULL,
|
| - size,
|
| - &input_device_UID);
|
| - if (result != noErr) {
|
| - DLOG(ERROR) << "Error setting aggregate audio device master device!";
|
| - return result;
|
| - }
|
| -
|
| - DVLOG(1) << "New aggregate device: " << *aggregate_device;
|
| - return noErr;
|
| -}
|
| -
|
| -void AggregateDeviceManager::DestroyAggregateDevice() {
|
| - if (aggregate_device_ == kAudioObjectUnknown)
|
| - return;
|
| -
|
| - static const AudioObjectPropertyAddress kDestroyAddress = {
|
| - kAudioPlugInDestroyAggregateDevice,
|
| - kAudioObjectPropertyScopeGlobal,
|
| - kAudioObjectPropertyElementMaster
|
| - };
|
| -
|
| - UInt32 size = sizeof(aggregate_device_);
|
| - OSStatus result = AudioObjectGetPropertyData(
|
| - plugin_id_,
|
| - &kDestroyAddress,
|
| - 0,
|
| - NULL,
|
| - &size,
|
| - &aggregate_device_);
|
| - if (result != noErr) {
|
| - DLOG(ERROR) << "Error destroying aggregate audio device!";
|
| - return;
|
| - }
|
| -
|
| - aggregate_device_ = kAudioObjectUnknown;
|
| -}
|
| -
|
| -} // namespace media
|
|
|