olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "media/audio/audio_system_impl.h" |
| 6 | |
Max Morin | 64be5b2 | 2018-05-24 22:01:13 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 9 | #include "base/memory/ptr_util.h" |
| 10 | #include "base/single_thread_task_runner.h" |
| 11 | #include "base/task_runner_util.h" |
Max Morin | 64be5b2 | 2018-05-24 22:01:13 | [diff] [blame] | 12 | #include "media/audio/audio_device_description.h" |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 13 | #include "media/audio/audio_manager.h" |
olka | 3dfb4cf | 2017-04-11 15:43:28 | [diff] [blame] | 14 | #include "media/base/bind_to_current_loop.h" |
olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 15 | |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 16 | // Using base::Unretained for |audio_manager_| is safe since AudioManager is |
| 17 | // deleted after audio thread is stopped. |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 18 | |
| 19 | // No need to bind the callback to the current loop if we are on the audio |
| 20 | // thread. However, the client still expects to receive the reply |
| 21 | // asynchronously, so we always post the helper function, which will |
| 22 | // syncronously call the (bound to current loop or not) callback. Thus the |
| 23 | // client always receives the callback on the thread it accesses AudioSystem on. |
| 24 | |
olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 25 | namespace media { |
| 26 | |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 27 | namespace { |
| 28 | |
| 29 | void GetInputStreamParametersOnAudioThread( |
| 30 | AudioManager* audio_manager, |
| 31 | const std::string& device_id, |
| 32 | AudioSystem::OnAudioParamsCallback on_params_cb) { |
| 33 | AudioSystemHelper(audio_manager) |
| 34 | .GetInputStreamParameters(device_id, std::move(on_params_cb)); |
| 35 | } |
| 36 | |
| 37 | void GetOutputStreamParametersOnAudioThread( |
| 38 | AudioManager* audio_manager, |
| 39 | const std::string& device_id, |
| 40 | AudioSystem::OnAudioParamsCallback on_params_cb) { |
| 41 | AudioSystemHelper(audio_manager) |
| 42 | .GetOutputStreamParameters(device_id, std::move(on_params_cb)); |
| 43 | } |
| 44 | |
| 45 | void HasInputDevicesOnAudioThread( |
| 46 | AudioManager* audio_manager, |
| 47 | AudioSystem::OnBoolCallback on_has_devices_cb) { |
| 48 | AudioSystemHelper(audio_manager) |
| 49 | .HasInputDevices(std::move(on_has_devices_cb)); |
| 50 | } |
| 51 | |
| 52 | void HasOutputDevicesOnAudioThread( |
| 53 | AudioManager* audio_manager, |
| 54 | AudioSystem::OnBoolCallback on_has_devices_cb) { |
| 55 | AudioSystemHelper(audio_manager) |
| 56 | .HasOutputDevices(std::move(on_has_devices_cb)); |
| 57 | } |
| 58 | |
| 59 | void GetDeviceDescriptionsOnAudioThread( |
| 60 | AudioManager* audio_manager, |
| 61 | bool for_input, |
| 62 | AudioSystem::OnDeviceDescriptionsCallback on_descriptions_cb) { |
| 63 | AudioSystemHelper(audio_manager) |
| 64 | .GetDeviceDescriptions(for_input, std::move(on_descriptions_cb)); |
| 65 | } |
| 66 | |
| 67 | void GetAssociatedOutputDeviceIDOnAudioThread( |
| 68 | AudioManager* audio_manager, |
| 69 | const std::string& input_device_id, |
| 70 | AudioSystem::OnDeviceIdCallback on_device_id_cb) { |
| 71 | AudioSystemHelper(audio_manager) |
| 72 | .GetAssociatedOutputDeviceID(input_device_id, std::move(on_device_id_cb)); |
| 73 | } |
| 74 | |
| 75 | void GetInputDeviceInfoOnAudioThread( |
| 76 | AudioManager* audio_manager, |
| 77 | const std::string& input_device_id, |
| 78 | AudioSystem::OnInputDeviceInfoCallback on_input_device_info_cb) { |
| 79 | AudioSystemHelper(audio_manager) |
| 80 | .GetInputDeviceInfo(input_device_id, std::move(on_input_device_info_cb)); |
| 81 | } |
| 82 | |
| 83 | } // namespace |
| 84 | |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 85 | template <typename... Args> |
| 86 | inline base::OnceCallback<void(Args...)> |
| 87 | AudioSystemImpl::MaybeBindToCurrentLoop( |
| 88 | base::OnceCallback<void(Args...)> callback) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 89 | return audio_manager_->GetTaskRunner()->BelongsToCurrentThread() |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 90 | ? std::move(callback) |
| 91 | : media::BindToCurrentLoop(std::move(callback)); |
| 92 | } |
| 93 | |
Olga Sharonova | a234a0a | 2018-02-16 11:12:23 | [diff] [blame] | 94 | // static |
| 95 | std::unique_ptr<AudioSystem> AudioSystemImpl::CreateInstance() { |
| 96 | DCHECK(AudioManager::Get()) << "AudioManager instance is not created"; |
| 97 | return std::make_unique<AudioSystemImpl>(AudioManager::Get()); |
| 98 | } |
| 99 | |
olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 100 | AudioSystemImpl::AudioSystemImpl(AudioManager* audio_manager) |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 101 | : audio_manager_(audio_manager) { |
| 102 | DETACH_FROM_THREAD(thread_checker_); |
olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | void AudioSystemImpl::GetInputStreamParameters( |
| 106 | const std::string& device_id, |
Olga Sharonova | 62ff2e0 | 2017-08-31 22:27:26 | [diff] [blame] | 107 | OnAudioParamsCallback on_params_cb) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 108 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 109 | audio_manager_->GetTaskRunner()->PostTask( |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 110 | FROM_HERE, |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 111 | base::BindOnce(&GetInputStreamParametersOnAudioThread, |
| 112 | base::Unretained(audio_manager_), device_id, |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 113 | MaybeBindToCurrentLoop(std::move(on_params_cb)))); |
olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 114 | } |
| 115 | |
olka | a39bab4 | 2017-03-14 17:10:15 | [diff] [blame] | 116 | void AudioSystemImpl::GetOutputStreamParameters( |
| 117 | const std::string& device_id, |
Olga Sharonova | 62ff2e0 | 2017-08-31 22:27:26 | [diff] [blame] | 118 | OnAudioParamsCallback on_params_cb) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 119 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 120 | audio_manager_->GetTaskRunner()->PostTask( |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 121 | FROM_HERE, |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 122 | base::BindOnce(&GetOutputStreamParametersOnAudioThread, |
| 123 | base::Unretained(audio_manager_), device_id, |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 124 | MaybeBindToCurrentLoop(std::move(on_params_cb)))); |
olka | a39bab4 | 2017-03-14 17:10:15 | [diff] [blame] | 125 | } |
| 126 | |
Olga Sharonova | 62ff2e0 | 2017-08-31 22:27:26 | [diff] [blame] | 127 | void AudioSystemImpl::HasInputDevices(OnBoolCallback on_has_devices_cb) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 128 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 129 | audio_manager_->GetTaskRunner()->PostTask( |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 130 | FROM_HERE, |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 131 | base::BindOnce(&HasInputDevicesOnAudioThread, |
| 132 | base::Unretained(audio_manager_), |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 133 | MaybeBindToCurrentLoop(std::move(on_has_devices_cb)))); |
olka | f608870 | 2017-02-10 19:52:09 | [diff] [blame] | 134 | } |
| 135 | |
Olga Sharonova | 62ff2e0 | 2017-08-31 22:27:26 | [diff] [blame] | 136 | void AudioSystemImpl::HasOutputDevices(OnBoolCallback on_has_devices_cb) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 137 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 138 | audio_manager_->GetTaskRunner()->PostTask( |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 139 | FROM_HERE, |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 140 | base::BindOnce(&HasOutputDevicesOnAudioThread, |
| 141 | base::Unretained(audio_manager_), |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 142 | MaybeBindToCurrentLoop(std::move(on_has_devices_cb)))); |
olka | e1920d9 | 2017-04-07 14:52:31 | [diff] [blame] | 143 | } |
| 144 | |
olka | 4e2655a | 2017-03-21 18:17:15 | [diff] [blame] | 145 | void AudioSystemImpl::GetDeviceDescriptions( |
Olga Sharonova | 62ff2e0 | 2017-08-31 22:27:26 | [diff] [blame] | 146 | bool for_input, |
| 147 | OnDeviceDescriptionsCallback on_descriptions_cb) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 148 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 149 | audio_manager_->GetTaskRunner()->PostTask( |
Max Morin | 64be5b2 | 2018-05-24 22:01:13 | [diff] [blame] | 150 | FROM_HERE, base::BindOnce(&GetDeviceDescriptionsOnAudioThread, |
| 151 | base::Unretained(audio_manager_), for_input, |
| 152 | MaybeBindToCurrentLoop( |
| 153 | WrapCallbackWithDeviceNameLocalization( |
| 154 | std::move(on_descriptions_cb))))); |
olka | 4e2655a | 2017-03-21 18:17:15 | [diff] [blame] | 155 | } |
| 156 | |
olka | 3dfb4cf | 2017-04-11 15:43:28 | [diff] [blame] | 157 | void AudioSystemImpl::GetAssociatedOutputDeviceID( |
| 158 | const std::string& input_device_id, |
| 159 | OnDeviceIdCallback on_device_id_cb) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 160 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 161 | audio_manager_->GetTaskRunner()->PostTask( |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 162 | FROM_HERE, |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 163 | base::BindOnce(&GetAssociatedOutputDeviceIDOnAudioThread, |
| 164 | base::Unretained(audio_manager_), input_device_id, |
Olga Sharonova | 9b1ae1e | 2017-09-04 12:24:29 | [diff] [blame] | 165 | MaybeBindToCurrentLoop(std::move(on_device_id_cb)))); |
olka | 3dfb4cf | 2017-04-11 15:43:28 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | void AudioSystemImpl::GetInputDeviceInfo( |
| 169 | const std::string& input_device_id, |
| 170 | OnInputDeviceInfoCallback on_input_device_info_cb) { |
Olga Sharonova | e7b1eb2 | 2017-09-13 14:41:47 | [diff] [blame] | 171 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 172 | audio_manager_->GetTaskRunner()->PostTask( |
| 173 | FROM_HERE, |
| 174 | base::BindOnce( |
| 175 | &GetInputDeviceInfoOnAudioThread, base::Unretained(audio_manager_), |
| 176 | input_device_id, |
| 177 | MaybeBindToCurrentLoop(std::move(on_input_device_info_cb)))); |
Olga Sharonova | bb57812 | 2017-08-31 19:18:38 | [diff] [blame] | 178 | } |
| 179 | |
olka | ef762c9 | 2017-02-06 16:45:16 | [diff] [blame] | 180 | } // namespace media |