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

Side by Side Diff: media/audio/mac/audio_manager_mac.cc

Issue 23533045: Implement GetDefaultOutputDeviceID, GetAssociatedOutputDeviceID and ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/mac/audio_manager_mac.h" 5 #include "media/audio/mac/audio_manager_mac.h"
6 6
7 #include <CoreAudio/AudioHardware.h> 7 #include <CoreAudio/AudioHardware.h>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 const std::string& device_id) { 179 const std::string& device_id) {
180 AudioObjectPropertyAddress property_address = { 180 AudioObjectPropertyAddress property_address = {
181 kAudioHardwarePropertyDevices, 181 kAudioHardwarePropertyDevices,
182 kAudioObjectPropertyScopeGlobal, 182 kAudioObjectPropertyScopeGlobal,
183 kAudioObjectPropertyElementMaster 183 kAudioObjectPropertyElementMaster
184 }; 184 };
185 AudioDeviceID audio_device_id = kAudioObjectUnknown; 185 AudioDeviceID audio_device_id = kAudioObjectUnknown;
186 UInt32 device_size = sizeof(audio_device_id); 186 UInt32 device_size = sizeof(audio_device_id);
187 OSStatus result = -1; 187 OSStatus result = -1;
188 188
189 if (device_id == AudioManagerBase::kDefaultDeviceId) { 189 if (device_id == AudioManagerBase::kDefaultDeviceId || device_id.empty()) {
190 // Default Device. 190 // Default Device.
191 property_address.mSelector = is_input ? 191 property_address.mSelector = is_input ?
192 kAudioHardwarePropertyDefaultInputDevice : 192 kAudioHardwarePropertyDefaultInputDevice :
193 kAudioHardwarePropertyDefaultOutputDevice; 193 kAudioHardwarePropertyDefaultOutputDevice;
194 194
195 result = AudioObjectGetPropertyData(kAudioObjectSystemObject, 195 result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
196 &property_address, 196 &property_address,
197 0, 197 0,
198 0, 198 0,
199 &device_size, 199 &device_size,
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 int sample_rate = HardwareSampleRateForDevice(device); 434 int sample_rate = HardwareSampleRateForDevice(device);
435 if (!sample_rate) 435 if (!sample_rate)
436 sample_rate = kFallbackSampleRate; 436 sample_rate = kFallbackSampleRate;
437 437
438 // TODO(xians): query the native channel layout for the specific device. 438 // TODO(xians): query the native channel layout for the specific device.
439 return AudioParameters( 439 return AudioParameters(
440 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 440 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
441 sample_rate, 16, buffer_size); 441 sample_rate, 16, buffer_size);
442 } 442 }
443 443
444 std::string AudioManagerMac::GetAssociatedOutputDeviceID(
445 const std::string& input_device_id) {
446 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id);
447 if (device == kAudioObjectUnknown)
448 return std::string();
449
450 UInt32 size = 0;
451 AudioObjectPropertyAddress pa = {
452 kAudioDevicePropertyRelatedDevices,
henrika (OOO until Aug 14) 2013/09/07 08:04:25 Guess thus guy is the key here. Nice.
453 kAudioObjectPropertyScopeOutput,
454 kAudioObjectPropertyElementMaster
455 };
456 OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size);
457 if (result || !size)
458 return std::string();
459
460 int device_count = size / sizeof(AudioDeviceID);
461 scoped_ptr_malloc<AudioDeviceID>
462 devices(reinterpret_cast<AudioDeviceID*>(malloc(size)));
henrika (OOO until Aug 14) 2013/09/07 08:04:25 I always hesitate to use reinterpret; you don't ;-
tommi (sloooow) - chröme 2013/09/08 19:11:19 Not when it's the right thing to do ;)
463 result = AudioObjectGetPropertyData(
464 device, &pa, 0, NULL, &size, devices.get());
465 if (result)
466 return std::string();
467
468 for (int i = 0; i < device_count; ++i) {
469 // Get the number of output channels of the device.
470 pa.mSelector = kAudioDevicePropertyStreams;
471 size = 0;
472 result = AudioObjectGetPropertyDataSize(devices.get()[i],
henrika (OOO until Aug 14) 2013/09/07 08:04:25 Nit, I did clang-format on my latest CL and I thin
tommi (sloooow) - chröme 2013/09/08 19:11:19 This is fine style-wize and consistent with all ot
473 &pa,
474 0,
475 NULL,
476 &size);
477 if (result || !size)
478 continue; // Skip if there aren't any output channels.
henrika (OOO until Aug 14) 2013/09/07 08:04:25 Don't we have methods to detect number of output d
tommi (sloooow) - chröme 2013/09/08 19:11:19 See line 453 where the "scope" is set to output. W
479
480 // Get device UID.
481 CFStringRef uid = NULL;
482 size = sizeof(uid);
483 pa.mSelector = kAudioDevicePropertyDeviceUID;
484 result = AudioObjectGetPropertyData(devices.get()[i],
485 &pa,
486 0,
487 NULL,
488 &size,
489 &uid);
490 if (result || !uid)
491 continue;
492
493 std::string ret(base::SysCFStringRefToUTF8(uid));
henrika (OOO until Aug 14) 2013/09/07 08:04:25 What does these IDs look like?
tommi (sloooow) - chröme 2013/09/08 19:11:19 Here's an example of a USB device I tested with: i
494 CFRelease(uid);
495 return ret;
496 }
497
498 // No matching device found.
499 return std::string();
500 }
501
444 AudioOutputStream* AudioManagerMac::MakeLinearOutputStream( 502 AudioOutputStream* AudioManagerMac::MakeLinearOutputStream(
445 const AudioParameters& params) { 503 const AudioParameters& params) {
446 return MakeLowLatencyOutputStream(params, std::string(), std::string()); 504 return MakeLowLatencyOutputStream(params, std::string(), std::string());
447 } 505 }
448 506
449 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream( 507 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
450 const AudioParameters& params, 508 const AudioParameters& params,
451 const std::string& device_id, 509 const std::string& device_id,
452 const std::string& input_device_id) { 510 const std::string& input_device_id) {
453 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; 511 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, input_device_id); 558 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, input_device_id);
501 if (audio_device_id == kAudioObjectUnknown) 559 if (audio_device_id == kAudioObjectUnknown)
502 return NULL; 560 return NULL;
503 561
504 return new AudioSynchronizedStream(this, 562 return new AudioSynchronizedStream(this,
505 params, 563 params,
506 audio_device_id, 564 audio_device_id,
507 kAudioDeviceUnknown); 565 kAudioDeviceUnknown);
508 } 566 }
509 567
568 std::string AudioManagerMac::GetDefaultOutputDeviceID() {
569 AudioDeviceID device_id = kAudioObjectUnknown;
570 if (!GetDefaultOutputDevice(&device_id))
571 return std::string();
572
573 const AudioObjectPropertyAddress property_address = {
574 kAudioDevicePropertyDeviceUID,
575 kAudioObjectPropertyScopeGlobal,
576 kAudioObjectPropertyElementMaster
577 };
578 CFStringRef device_uid = NULL;
579 UInt32 size = sizeof(device_uid);
580 OSStatus status = AudioObjectGetPropertyData(device_id, &property_address, 0,
henrika (OOO until Aug 14) 2013/09/07 08:04:25 Different style than above ;-)
tommi (sloooow) - chröme 2013/09/08 19:11:19 Fixed.
581 NULL, &size, &device_uid);
582 if (status != kAudioHardwareNoError || !device_uid)
583 return std::string();
584
585 std::string ret(base::SysCFStringRefToUTF8(device_uid));
586 CFRelease(device_uid);
587
588 return ret;
589 }
590
510 AudioInputStream* AudioManagerMac::MakeLinearInputStream( 591 AudioInputStream* AudioManagerMac::MakeLinearInputStream(
511 const AudioParameters& params, const std::string& device_id) { 592 const AudioParameters& params, const std::string& device_id) {
512 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 593 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
513 return new PCMQueueInAudioInputStream(this, params); 594 return new PCMQueueInAudioInputStream(this, params);
514 } 595 }
515 596
516 AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream( 597 AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream(
517 const AudioParameters& params, const std::string& device_id) { 598 const AudioParameters& params, const std::string& device_id) {
518 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 599 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
519 // Gets the AudioDeviceID that refers to the AudioOutputDevice with the device 600 // Gets the AudioDeviceID that refers to the AudioOutputDevice with the device
520 // unique id. This AudioDeviceID is used to set the device for Audio Unit. 601 // unique id. This AudioDeviceID is used to set the device for Audio Unit.
521 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id); 602 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id);
522 AudioInputStream* stream = NULL; 603 AudioInputStream* stream = NULL;
523 if (audio_device_id != kAudioObjectUnknown) 604 if (audio_device_id != kAudioObjectUnknown)
524 stream = new AUAudioInputStream(this, params, audio_device_id); 605 stream = new AUAudioInputStream(this, params, audio_device_id);
525 606
526 return stream; 607 return stream;
527 } 608 }
528 609
529 AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters( 610 AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters(
530 const std::string& output_device_id, 611 const std::string& output_device_id,
531 const AudioParameters& input_params) { 612 const AudioParameters& input_params) {
532 // TODO(tommi): Support |output_device_id|. 613 AudioDeviceID device = GetAudioDeviceIdByUId(true, output_device_id);
533 DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; 614 if (device == kAudioObjectUnknown) {
615 DLOG(ERROR) << "Invalid device " << output_device_id;
henrika (OOO until Aug 14) 2013/09/07 08:04:25 I would say Invalid output device just in case
tommi (sloooow) - chröme 2013/09/08 19:11:19 Done.
616 return AudioParameters();
617 }
618
534 int hardware_channels = 2; 619 int hardware_channels = 2;
henrika (OOO until Aug 14) 2013/09/07 08:04:25 Don't understand this "fallback" scheme. Do you?
tommi (sloooow) - chröme 2013/09/08 19:11:19 Not really. I guess there must be a case where we
535 if (!GetDefaultOutputChannels(&hardware_channels)) { 620 if (!GetDeviceChannels(device, kAudioDevicePropertyScopeOutput,
621 &hardware_channels)) {
536 // Fallback to stereo. 622 // Fallback to stereo.
537 hardware_channels = 2; 623 hardware_channels = 2;
538 } 624 }
539 625
540 ChannelLayout channel_layout = GuessChannelLayout(hardware_channels); 626 ChannelLayout channel_layout = GuessChannelLayout(hardware_channels);
541 627
542 const int hardware_sample_rate = AUAudioOutputStream::HardwareSampleRate(); 628 const int hardware_sample_rate = HardwareSampleRateForDevice(device);
543 const int buffer_size = ChooseBufferSize(hardware_sample_rate); 629 const int buffer_size = ChooseBufferSize(hardware_sample_rate);
544 630
545 int input_channels = 0; 631 int input_channels = 0;
546 if (input_params.IsValid()) { 632 if (input_params.IsValid()) {
547 input_channels = input_params.input_channels(); 633 input_channels = input_params.input_channels();
548 634
549 if (input_channels > 0) { 635 if (input_channels > 0) {
550 // TODO(crogers): given the limitations of the AudioOutputStream 636 // TODO(crogers): given the limitations of the AudioOutputStream
henrika (OOO until Aug 14) 2013/09/07 08:04:25 Change crogers to xians?
tommi (sloooow) - chröme 2013/09/08 19:11:19 Done.
551 // back-ends used with synchronized I/O, we hard-code to stereo. 637 // back-ends used with synchronized I/O, we hard-code to stereo.
552 // Specifically, this is a limitation of AudioSynchronizedStream which 638 // Specifically, this is a limitation of AudioSynchronizedStream which
553 // can be removed as part of the work to consolidate these back-ends. 639 // can be removed as part of the work to consolidate these back-ends.
554 channel_layout = CHANNEL_LAYOUT_STEREO; 640 channel_layout = CHANNEL_LAYOUT_STEREO;
555 } 641 }
556 } 642 }
557 643
558 AudioParameters params( 644 AudioParameters params(
559 AudioParameters::AUDIO_PCM_LOW_LATENCY, 645 AudioParameters::AUDIO_PCM_LOW_LATENCY,
560 channel_layout, 646 channel_layout,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 current_sample_rate_ = new_sample_rate; 691 current_sample_rate_ = new_sample_rate;
606 current_output_device_ = new_output_device; 692 current_output_device_ = new_output_device;
607 NotifyAllOutputDeviceChangeListeners(); 693 NotifyAllOutputDeviceChangeListeners();
608 } 694 }
609 695
610 AudioManager* CreateAudioManager() { 696 AudioManager* CreateAudioManager() {
611 return new AudioManagerMac(); 697 return new AudioManagerMac();
612 } 698 }
613 699
614 } // namespace media 700 } // namespace media
OLDNEW
« media/audio/audio_manager_unittest.cc ('K') | « media/audio/mac/audio_manager_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698