| 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 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 bool is_suspending_; | 254 bool is_suspending_; |
| 255 const bool is_monitoring_; | 255 const bool is_monitoring_; |
| 256 base::TimeTicks earliest_start_time_; | 256 base::TimeTicks earliest_start_time_; |
| 257 base::ThreadChecker thread_checker_; | 257 base::ThreadChecker thread_checker_; |
| 258 | 258 |
| 259 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); | 259 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); |
| 260 }; | 260 }; |
| 261 | 261 |
| 262 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) | 262 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) |
| 263 : AudioManagerBase(audio_log_factory), | 263 : AudioManagerBase(audio_log_factory), |
| 264 current_sample_rate_(0) { | 264 current_sample_rate_(0), |
| 265 current_output_device_ = kAudioDeviceUnknown; | 265 current_output_device_(kAudioDeviceUnknown) { |
| 266 | |
| 267 SetMaxOutputStreamsAllowed(kMaxOutputStreams); | 266 SetMaxOutputStreamsAllowed(kMaxOutputStreams); |
| 268 | 267 |
| 269 // Task must be posted last to avoid races from handing out "this" to the | 268 // Task must be posted last to avoid races from handing out "this" to the |
| 270 // audio thread. Always PostTask even if we're on the right thread since | 269 // audio thread. Always PostTask even if we're on the right thread since |
| 271 // AudioManager creation is on the startup path and this may be slow. | 270 // AudioManager creation is on the startup path and this may be slow. |
| 272 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 271 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 273 &AudioManagerMac::CreateDeviceListener, base::Unretained(this))); | 272 &AudioManagerMac::InitializeOnAudioThread, base::Unretained(this))); |
| 274 } | 273 } |
| 275 | 274 |
| 276 AudioManagerMac::~AudioManagerMac() { | 275 AudioManagerMac::~AudioManagerMac() { |
| 277 if (GetTaskRunner()->BelongsToCurrentThread()) { | 276 if (GetTaskRunner()->BelongsToCurrentThread()) { |
| 278 DestroyDeviceListener(); | 277 ShutdownOnAudioThread(); |
| 279 } else { | 278 } else { |
| 280 // It's safe to post a task here since Shutdown() will wait for all tasks to | 279 // It's safe to post a task here since Shutdown() will wait for all tasks to |
| 281 // complete before returning. | 280 // complete before returning. |
| 282 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 281 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 283 &AudioManagerMac::DestroyDeviceListener, base::Unretained(this))); | 282 &AudioManagerMac::ShutdownOnAudioThread, base::Unretained(this))); |
| 284 } | 283 } |
| 285 | 284 |
| 286 Shutdown(); | 285 Shutdown(); |
| 287 } | 286 } |
| 288 | 287 |
| 289 bool AudioManagerMac::HasAudioOutputDevices() { | 288 bool AudioManagerMac::HasAudioOutputDevices() { |
| 290 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); | 289 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); |
| 291 } | 290 } |
| 292 | 291 |
| 293 bool AudioManagerMac::HasAudioInputDevices() { | 292 bool AudioManagerMac::HasAudioInputDevices() { |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 } | 557 } |
| 559 | 558 |
| 560 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream( | 559 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream( |
| 561 const AudioParameters& params, | 560 const AudioParameters& params, |
| 562 const std::string& device_id) { | 561 const std::string& device_id) { |
| 563 AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id); | 562 AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id); |
| 564 if (device == kAudioObjectUnknown) { | 563 if (device == kAudioObjectUnknown) { |
| 565 DLOG(ERROR) << "Failed to open output device: " << device_id; | 564 DLOG(ERROR) << "Failed to open output device: " << device_id; |
| 566 return NULL; | 565 return NULL; |
| 567 } | 566 } |
| 567 |
| 568 // Lazily create the audio device listener on the first stream creation. |
| 569 if (!output_device_listener_) { |
| 570 output_device_listener_.reset(new AudioDeviceListenerMac(base::Bind( |
| 571 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this)))); |
| 572 // Only set the current output device for the default device. |
| 573 if (device_id == AudioManagerBase::kDefaultDeviceId || device_id.empty()) |
| 574 current_output_device_ = device; |
| 575 // Just use the current sample rate since we don't allow non-native sample |
| 576 // rates on OSX. |
| 577 current_sample_rate_ = params.sample_rate(); |
| 578 } |
| 579 |
| 568 return new AUHALStream(this, params, device); | 580 return new AUHALStream(this, params, device); |
| 569 } | 581 } |
| 570 | 582 |
| 571 std::string AudioManagerMac::GetDefaultOutputDeviceID() { | 583 std::string AudioManagerMac::GetDefaultOutputDeviceID() { |
| 572 AudioDeviceID device_id = kAudioObjectUnknown; | 584 AudioDeviceID device_id = kAudioObjectUnknown; |
| 573 if (!GetDefaultOutputDevice(&device_id)) | 585 if (!GetDefaultOutputDevice(&device_id)) |
| 574 return std::string(); | 586 return std::string(); |
| 575 | 587 |
| 576 const AudioObjectPropertyAddress property_address = { | 588 const AudioObjectPropertyAddress property_address = { |
| 577 kAudioDevicePropertyDeviceUID, | 589 kAudioDevicePropertyDeviceUID, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 // can be removed as part of the work to consolidate these back-ends. | 680 // can be removed as part of the work to consolidate these back-ends. |
| 669 channel_layout = CHANNEL_LAYOUT_STEREO; | 681 channel_layout = CHANNEL_LAYOUT_STEREO; |
| 670 } | 682 } |
| 671 | 683 |
| 672 return AudioParameters( | 684 return AudioParameters( |
| 673 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, output_channels, | 685 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, output_channels, |
| 674 input_channels, hardware_sample_rate, 16, buffer_size, | 686 input_channels, hardware_sample_rate, 16, buffer_size, |
| 675 AudioParameters::NO_EFFECTS); | 687 AudioParameters::NO_EFFECTS); |
| 676 } | 688 } |
| 677 | 689 |
| 678 void AudioManagerMac::CreateDeviceListener() { | 690 void AudioManagerMac::InitializeOnAudioThread() { |
| 679 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 691 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 680 | |
| 681 // Get a baseline for the sample-rate and current device, | |
| 682 // so we can intelligently handle device notifications only when necessary. | |
| 683 current_sample_rate_ = HardwareSampleRate(); | |
| 684 if (!GetDefaultOutputDevice(¤t_output_device_)) | |
| 685 current_output_device_ = kAudioDeviceUnknown; | |
| 686 | |
| 687 output_device_listener_.reset(new AudioDeviceListenerMac(base::Bind( | |
| 688 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this)))); | |
| 689 power_observer_.reset(new AudioPowerObserver()); | 692 power_observer_.reset(new AudioPowerObserver()); |
| 690 } | 693 } |
| 691 | 694 |
| 692 void AudioManagerMac::DestroyDeviceListener() { | 695 void AudioManagerMac::ShutdownOnAudioThread() { |
| 693 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 696 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 694 output_device_listener_.reset(); | 697 output_device_listener_.reset(); |
| 695 power_observer_.reset(); | 698 power_observer_.reset(); |
| 696 } | 699 } |
| 697 | 700 |
| 698 void AudioManagerMac::HandleDeviceChanges() { | 701 void AudioManagerMac::HandleDeviceChanges() { |
| 699 if (!GetTaskRunner()->BelongsToCurrentThread()) { | 702 if (!GetTaskRunner()->BelongsToCurrentThread()) { |
| 700 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 703 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
| 701 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this))); | 704 &AudioManagerMac::HandleDeviceChanges, base::Unretained(this))); |
| 702 return; | 705 return; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 bool AudioManagerMac::ShouldDeferOutputStreamStart() { | 738 bool AudioManagerMac::ShouldDeferOutputStreamStart() { |
| 736 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 739 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 737 return power_observer_->ShouldDeferOutputStreamStart(); | 740 return power_observer_->ShouldDeferOutputStreamStart(); |
| 738 } | 741 } |
| 739 | 742 |
| 740 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { | 743 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { |
| 741 return new AudioManagerMac(audio_log_factory); | 744 return new AudioManagerMac(audio_log_factory); |
| 742 } | 745 } |
| 743 | 746 |
| 744 } // namespace media | 747 } // namespace media |
| OLD | NEW |