Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 bool is_suspending_; | 266 bool is_suspending_; |
| 267 const bool is_monitoring_; | 267 const bool is_monitoring_; |
| 268 base::TimeTicks earliest_start_time_; | 268 base::TimeTicks earliest_start_time_; |
| 269 base::ThreadChecker thread_checker_; | 269 base::ThreadChecker thread_checker_; |
| 270 | 270 |
| 271 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); | 271 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); |
| 272 }; | 272 }; |
| 273 | 273 |
| 274 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) | 274 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) |
| 275 : AudioManagerBase(audio_log_factory), | 275 : AudioManagerBase(audio_log_factory), |
| 276 current_sample_rate_(0) { | 276 current_sample_rate_(0), |
| 277 current_output_device_ = kAudioDeviceUnknown; | 277 current_output_device_(kAudioDeviceUnknown) { |
| 278 | |
| 279 SetMaxOutputStreamsAllowed(kMaxOutputStreams); | 278 SetMaxOutputStreamsAllowed(kMaxOutputStreams); |
| 280 | 279 |
| 281 // Task must be posted last to avoid races from handing out "this" to the | 280 // Task must be posted last to avoid races from handing out "this" to the |
| 282 // audio thread. Always PostTask even if we're on the right thread since | 281 // audio thread. Always PostTask even if we're on the right thread since |
| 283 // AudioManager creation is on the startup path and this may be slow. | 282 // AudioManager creation is on the startup path and this may be slow. |
| 284 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 283 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 285 &AudioManagerMac::CreateDeviceListener, base::Unretained(this))); | 284 &AudioManagerMac::InitializeOnAudioThread, base::Unretained(this))); |
| 286 } | 285 } |
| 287 | 286 |
| 288 AudioManagerMac::~AudioManagerMac() { | 287 AudioManagerMac::~AudioManagerMac() { |
| 289 if (GetTaskRunner()->BelongsToCurrentThread()) { | 288 if (GetTaskRunner()->BelongsToCurrentThread()) { |
| 290 DestroyDeviceListener(); | 289 ShutdownOnAudioThread(); |
| 291 } else { | 290 } else { |
| 292 // It's safe to post a task here since Shutdown() will wait for all tasks to | 291 // It's safe to post a task here since Shutdown() will wait for all tasks to |
| 293 // complete before returning. | 292 // complete before returning. |
| 294 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 293 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 295 &AudioManagerMac::DestroyDeviceListener, base::Unretained(this))); | 294 &AudioManagerMac::ShutdownOnAudioThread, base::Unretained(this))); |
| 296 } | 295 } |
| 297 | 296 |
| 298 Shutdown(); | 297 Shutdown(); |
| 299 } | 298 } |
| 300 | 299 |
| 301 bool AudioManagerMac::HasAudioOutputDevices() { | 300 bool AudioManagerMac::HasAudioOutputDevices() { |
| 302 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); | 301 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); |
| 303 } | 302 } |
| 304 | 303 |
| 305 bool AudioManagerMac::HasAudioInputDevices() { | 304 bool AudioManagerMac::HasAudioInputDevices() { |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 const AudioParameters& params, | 572 const AudioParameters& params, |
| 574 const std::string& device_id, | 573 const std::string& device_id, |
| 575 const std::string& input_device_id) { | 574 const std::string& input_device_id) { |
| 576 // Handle basic output with no input channels. | 575 // Handle basic output with no input channels. |
| 577 if (params.input_channels() == 0) { | 576 if (params.input_channels() == 0) { |
| 578 AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id); | 577 AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id); |
| 579 if (device == kAudioObjectUnknown) { | 578 if (device == kAudioObjectUnknown) { |
| 580 DLOG(ERROR) << "Failed to open output device: " << device_id; | 579 DLOG(ERROR) << "Failed to open output device: " << device_id; |
| 581 return NULL; | 580 return NULL; |
| 582 } | 581 } |
| 582 | |
| 583 // Lazily create the audio device listener on the first stream creation. | |
| 584 if (!output_device_listener_) { | |
| 585 output_device_listener_.reset(new AudioDeviceListenerMac(base::Bind( | |
| 586 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this)))); | |
| 587 // Only set the current output device for the default device. | |
| 588 if (device_id.empty()) | |
|
tommi (sloooow) - chröme
2014/02/13 06:56:20
Check for AudioManagerBase::kDefaultDeviceId?
DaleCurtis
2014/02/13 19:24:35
That's only for input no?
DaleCurtis
2014/02/13 20:31:53
Done.
| |
| 589 current_output_device_ = device; | |
| 590 // Just use the current sample rate since we don't allow non-native sample | |
| 591 // rates on OSX. | |
| 592 current_sample_rate_ = params.sample_rate(); | |
| 593 } | |
| 594 | |
| 583 return new AUHALStream(this, params, device); | 595 return new AUHALStream(this, params, device); |
| 584 } | 596 } |
| 585 | 597 |
| 586 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; | 598 DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; |
| 587 | 599 |
| 588 // TODO(xians): support more than stereo input. | 600 // TODO(xians): support more than stereo input. |
| 589 if (params.input_channels() != 2) { | 601 if (params.input_channels() != 2) { |
| 590 // WebAudio is currently hard-coded to 2 channels so we should not | 602 // WebAudio is currently hard-coded to 2 channels so we should not |
| 591 // see this case. | 603 // see this case. |
| 592 NOTREACHED() << "Only stereo input is currently supported!"; | 604 NOTREACHED() << "Only stereo input is currently supported!"; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 734 // can be removed as part of the work to consolidate these back-ends. | 746 // can be removed as part of the work to consolidate these back-ends. |
| 735 channel_layout = CHANNEL_LAYOUT_STEREO; | 747 channel_layout = CHANNEL_LAYOUT_STEREO; |
| 736 } | 748 } |
| 737 | 749 |
| 738 return AudioParameters( | 750 return AudioParameters( |
| 739 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, output_channels, | 751 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, output_channels, |
| 740 input_channels, hardware_sample_rate, 16, buffer_size, | 752 input_channels, hardware_sample_rate, 16, buffer_size, |
| 741 AudioParameters::NO_EFFECTS); | 753 AudioParameters::NO_EFFECTS); |
| 742 } | 754 } |
| 743 | 755 |
| 744 void AudioManagerMac::CreateDeviceListener() { | 756 void AudioManagerMac::InitializeOnAudioThread() { |
| 745 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 757 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 746 | |
| 747 // Get a baseline for the sample-rate and current device, | |
| 748 // so we can intelligently handle device notifications only when necessary. | |
| 749 current_sample_rate_ = HardwareSampleRate(); | |
| 750 if (!GetDefaultOutputDevice(¤t_output_device_)) | |
| 751 current_output_device_ = kAudioDeviceUnknown; | |
| 752 | |
| 753 output_device_listener_.reset(new AudioDeviceListenerMac(base::Bind( | |
| 754 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this)))); | |
| 755 power_observer_.reset(new AudioPowerObserver()); | 758 power_observer_.reset(new AudioPowerObserver()); |
| 756 } | 759 } |
| 757 | 760 |
| 758 void AudioManagerMac::DestroyDeviceListener() { | 761 void AudioManagerMac::ShutdownOnAudioThread() { |
| 759 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 762 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 760 output_device_listener_.reset(); | 763 output_device_listener_.reset(); |
| 761 power_observer_.reset(); | 764 power_observer_.reset(); |
| 762 } | 765 } |
| 763 | 766 |
| 764 void AudioManagerMac::HandleDeviceChanges() { | 767 void AudioManagerMac::HandleDeviceChanges() { |
| 765 if (!GetTaskRunner()->BelongsToCurrentThread()) { | 768 if (!GetTaskRunner()->BelongsToCurrentThread()) { |
| 766 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 769 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 767 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this))); | 770 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this))); |
| 768 return; | 771 return; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 bool AudioManagerMac::ShouldDeferOutputStreamStart() { | 804 bool AudioManagerMac::ShouldDeferOutputStreamStart() { |
| 802 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 805 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 803 return power_observer_->ShouldDeferOutputStreamStart(); | 806 return power_observer_->ShouldDeferOutputStreamStart(); |
| 804 } | 807 } |
| 805 | 808 |
| 806 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { | 809 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { |
| 807 return new AudioManagerMac(audio_log_factory); | 810 return new AudioManagerMac(audio_log_factory); |
| 808 } | 811 } |
| 809 | 812 |
| 810 } // namespace media | 813 } // namespace media |
| OLD | NEW |