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/pulse/pulse_input.h" | 5 #include "media/audio/pulse/pulse_input.h" |
6 | 6 |
7 #include <pulse/pulseaudio.h> | 7 #include <pulse/pulseaudio.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 pa_cvolume pa_volume; | 210 pa_cvolume pa_volume; |
211 pa_cvolume_set(&pa_volume, channels_, volume); | 211 pa_cvolume_set(&pa_volume, channels_, volume); |
212 operation = pa_context_set_source_volume_by_index( | 212 operation = pa_context_set_source_volume_by_index( |
213 pa_context_, index, &pa_volume, NULL, NULL); | 213 pa_context_, index, &pa_volume, NULL, NULL); |
214 | 214 |
215 // Don't need to wait for this task to complete. | 215 // Don't need to wait for this task to complete. |
216 pa_operation_unref(operation); | 216 pa_operation_unref(operation); |
217 } | 217 } |
218 | 218 |
219 double PulseAudioInputStream::GetVolume() { | 219 double PulseAudioInputStream::GetVolume() { |
220 AutoPulseLock auto_lock(pa_mainloop_); | 220 if (pa_threaded_mainloop_in_thread(pa_mainloop_)) { |
221 if (!handle_) | 221 // When being called by the pulse thread, GetVolume() is asynchronous and |
222 // called under AutoPulseLock. | |
223 if (!handle_) | |
224 return 0.0; | |
225 | |
226 size_t index = pa_stream_get_device_index(handle_); | |
227 pa_operation* operation = pa_context_get_source_info_by_index( | |
228 pa_context_, index, &VolumeCallback, this); | |
229 // Do not wait for the operation since we can't block the pulse thread. | |
230 pa_operation_unref(operation); | |
231 | |
232 // Return zero and the callback will asynchronously update the |volume_|. | |
222 return 0.0; | 233 return 0.0; |
234 } else { | |
235 // Called by other thread, put an AutoPulseLock and wait for the operation. | |
236 AutoPulseLock auto_lock(pa_mainloop_); | |
237 if (!handle_) | |
238 return 0.0; | |
223 | 239 |
224 size_t index = pa_stream_get_device_index(handle_); | 240 size_t index = pa_stream_get_device_index(handle_); |
225 pa_operation* operation = pa_context_get_source_info_by_index( | 241 pa_operation* operation = pa_context_get_source_info_by_index( |
226 pa_context_, index, &VolumeCallback, this); | 242 pa_context_, index, &VolumeCallback, this); |
227 WaitForOperationCompletion(pa_mainloop_, operation); | 243 WaitForOperationCompletion(pa_mainloop_, operation); |
228 | 244 |
229 return volume_; | 245 return volume_; |
246 } | |
230 } | 247 } |
231 | 248 |
232 // static, used by pa_stream_set_read_callback. | 249 // static, used by pa_stream_set_read_callback. |
233 void PulseAudioInputStream::ReadCallback(pa_stream* handle, | 250 void PulseAudioInputStream::ReadCallback(pa_stream* handle, |
234 size_t length, | 251 size_t length, |
235 void* user_data) { | 252 void* user_data) { |
236 PulseAudioInputStream* stream = | 253 PulseAudioInputStream* stream = |
237 reinterpret_cast<PulseAudioInputStream*>(user_data); | 254 reinterpret_cast<PulseAudioInputStream*>(user_data); |
238 | 255 |
239 stream->ReadData(); | 256 stream->ReadData(); |
(...skipping 14 matching lines...) Expand all Loading... | |
254 if (stream->channels_ != info->channel_map.channels) | 271 if (stream->channels_ != info->channel_map.channels) |
255 stream->channels_ = info->channel_map.channels; | 272 stream->channels_ = info->channel_map.channels; |
256 | 273 |
257 pa_volume_t volume = PA_VOLUME_MUTED; // Minimum possible value. | 274 pa_volume_t volume = PA_VOLUME_MUTED; // Minimum possible value. |
258 // Use the max volume of any channel as the volume. | 275 // Use the max volume of any channel as the volume. |
259 for (int i = 0; i < stream->channels_; ++i) { | 276 for (int i = 0; i < stream->channels_; ++i) { |
260 if (volume < info->volume.values[i]) | 277 if (volume < info->volume.values[i]) |
261 volume = info->volume.values[i]; | 278 volume = info->volume.values[i]; |
262 } | 279 } |
263 | 280 |
264 stream->volume_ = static_cast<double>(volume); | 281 stream->volume_ = static_cast<double>(volume); |
DaleCurtis
2013/02/25 18:52:18
I'd add a comment here that this is thread safe be
no longer working on chromium
2013/02/26 12:02:51
Done.
| |
265 } | 282 } |
266 | 283 |
267 // static, used by pa_stream_set_state_callback. | 284 // static, used by pa_stream_set_state_callback. |
268 void PulseAudioInputStream::StreamNotifyCallback(pa_stream* s, | 285 void PulseAudioInputStream::StreamNotifyCallback(pa_stream* s, |
269 void* user_data) { | 286 void* user_data) { |
270 PulseAudioInputStream* stream = | 287 PulseAudioInputStream* stream = |
271 reinterpret_cast<PulseAudioInputStream*>(user_data); | 288 reinterpret_cast<PulseAudioInputStream*>(user_data); |
272 if (s && stream->callback_ && | 289 if (s && stream->callback_ && |
273 pa_stream_get_state(s) == PA_STREAM_FAILED) { | 290 pa_stream_get_state(s) == PA_STREAM_FAILED) { |
274 stream->callback_->OnError(stream, pa_context_errno(stream->pa_context_)); | 291 stream->callback_->OnError(stream, pa_context_errno(stream->pa_context_)); |
275 } | 292 } |
276 | 293 |
277 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); | 294 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); |
278 } | 295 } |
279 | 296 |
280 void PulseAudioInputStream::ReadData() { | 297 void PulseAudioInputStream::ReadData() { |
281 uint32 hardware_delay = pulse::GetHardwareLatencyInBytes( | 298 uint32 hardware_delay = pulse::GetHardwareLatencyInBytes( |
282 handle_, params_.sample_rate(), params_.GetBytesPerFrame()); | 299 handle_, params_.sample_rate(), params_.GetBytesPerFrame()); |
283 | 300 |
284 // Update the AGC volume level once every second. Note that, | 301 // Update the AGC volume level once every second. Note that, |
285 // |volume| is also updated each time SetVolume() is called | 302 // |volume| is also updated each time SetVolume() is called |
286 // through IPC by the render-side AGC. | 303 // through IPC by the render-side AGC. |
304 // QueryAgcVolume() will trigger a callback to asynchronously update the | |
305 // |volume_|. | |
DaleCurtis
2013/02/25 18:52:18
This needs some mention of the fact that the |norm
no longer working on chromium
2013/02/26 12:02:51
Done.
| |
287 double normalized_volume = 0.0; | 306 double normalized_volume = 0.0; |
288 QueryAgcVolume(&normalized_volume); | 307 QueryAgcVolume(&normalized_volume); |
308 normalized_volume = volume_ / GetMaxVolume(); | |
289 | 309 |
290 do { | 310 do { |
291 size_t length = 0; | 311 size_t length = 0; |
292 const void* data = NULL; | 312 const void* data = NULL; |
293 pa_stream_peek(handle_, &data, &length); | 313 pa_stream_peek(handle_, &data, &length); |
294 if (!data || length == 0) | 314 if (!data || length == 0) |
295 break; | 315 break; |
296 | 316 |
297 buffer_->Append(reinterpret_cast<const uint8*>(data), length); | 317 buffer_->Append(reinterpret_cast<const uint8*>(data), length); |
298 | 318 |
(...skipping 15 matching lines...) Expand all Loading... | |
314 DLOG(WARNING) << "OnData is being called consecutively, sleep 5ms to " | 334 DLOG(WARNING) << "OnData is being called consecutively, sleep 5ms to " |
315 << "wait until render consumes the data"; | 335 << "wait until render consumes the data"; |
316 base::PlatformThread::Sleep( | 336 base::PlatformThread::Sleep( |
317 base::TimeDelta::FromMilliseconds(5)); | 337 base::TimeDelta::FromMilliseconds(5)); |
318 } | 338 } |
319 | 339 |
320 pa_threaded_mainloop_signal(pa_mainloop_, 0); | 340 pa_threaded_mainloop_signal(pa_mainloop_, 0); |
321 } | 341 } |
322 | 342 |
323 } // namespace media | 343 } // namespace media |
OLD | NEW |