| 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_output.h" | 5 #include "media/audio/pulse/pulse_output.h" |
| 6 | 6 |
| 7 #include <pulse/pulseaudio.h> | 7 #include <pulse/pulseaudio.h> |
| 8 | 8 |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "media/audio/audio_manager_base.h" | 10 #include "media/audio/audio_manager_base.h" |
| 11 #include "media/audio/audio_parameters.h" | 11 #include "media/audio/audio_parameters.h" |
| 12 #include "media/audio/audio_util.h" | 12 #include "media/audio/audio_util.h" |
| 13 #include "media/audio/pulse/pulse_util.h" | 13 #include "media/audio/pulse/pulse_util.h" |
| 14 | 14 |
| 15 namespace media { | 15 namespace media { |
| 16 | 16 |
| 17 using pulse::AutoPulseLock; | 17 using pulse::AutoPulseLock; |
| 18 using pulse::WaitForOperationCompletion; | 18 using pulse::WaitForOperationCompletion; |
| 19 | 19 |
| 20 // static, pa_context_notify_cb | 20 // static, pa_context_notify_cb |
| 21 void PulseAudioOutputStream::ContextNotifyCallback(pa_context* c, | 21 void PulseAudioOutputStream::ContextNotifyCallback(pa_context* c, |
| 22 void* p_this) { | 22 void* p_this) { |
| 23 PulseAudioOutputStream* stream = static_cast<PulseAudioOutputStream*>(p_this); | 23 PulseAudioOutputStream* stream = static_cast<PulseAudioOutputStream*>(p_this); |
| 24 | 24 |
| 25 // Forward unexpected failures to the AudioSourceCallback if available. All | 25 // Forward unexpected failures to the AudioSourceCallback if available. All |
| 26 // these variables are only modified under pa_threaded_mainloop_lock() so this | 26 // these variables are only modified under pa_threaded_mainloop_lock() so this |
| 27 // should be thread safe. | 27 // should be thread safe. |
| 28 if (c && stream->source_callback_ && | 28 if (c && stream->source_callback_ && |
| 29 pa_context_get_state(c) == PA_CONTEXT_FAILED) { | 29 pa_context_get_state(c) == PA_CONTEXT_FAILED) { |
| 30 stream->source_callback_->OnError(stream, pa_context_errno(c)); | 30 stream->source_callback_->OnError(stream); |
| 31 } | 31 } |
| 32 | 32 |
| 33 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); | 33 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); |
| 34 } | 34 } |
| 35 | 35 |
| 36 // static, pa_stream_notify_cb | 36 // static, pa_stream_notify_cb |
| 37 void PulseAudioOutputStream::StreamNotifyCallback(pa_stream* s, void* p_this) { | 37 void PulseAudioOutputStream::StreamNotifyCallback(pa_stream* s, void* p_this) { |
| 38 PulseAudioOutputStream* stream = static_cast<PulseAudioOutputStream*>(p_this); | 38 PulseAudioOutputStream* stream = static_cast<PulseAudioOutputStream*>(p_this); |
| 39 | 39 |
| 40 // Forward unexpected failures to the AudioSourceCallback if available. All | 40 // Forward unexpected failures to the AudioSourceCallback if available. All |
| 41 // these variables are only modified under pa_threaded_mainloop_lock() so this | 41 // these variables are only modified under pa_threaded_mainloop_lock() so this |
| 42 // should be thread safe. | 42 // should be thread safe. |
| 43 if (s && stream->source_callback_ && | 43 if (s && stream->source_callback_ && |
| 44 pa_stream_get_state(s) == PA_STREAM_FAILED) { | 44 pa_stream_get_state(s) == PA_STREAM_FAILED) { |
| 45 stream->source_callback_->OnError( | 45 stream->source_callback_->OnError(stream); |
| 46 stream, pa_context_errno(stream->pa_context_)); | |
| 47 } | 46 } |
| 48 | 47 |
| 49 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); | 48 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); |
| 50 } | 49 } |
| 51 | 50 |
| 52 // static, pa_stream_request_cb_t | 51 // static, pa_stream_request_cb_t |
| 53 void PulseAudioOutputStream::StreamRequestCallback(pa_stream* s, size_t len, | 52 void PulseAudioOutputStream::StreamRequestCallback(pa_stream* s, size_t len, |
| 54 void* p_this) { | 53 void* p_this) { |
| 55 // Fulfill write request; must always result in a pa_stream_write() call. | 54 // Fulfill write request; must always result in a pa_stream_write() call. |
| 56 static_cast<PulseAudioOutputStream*>(p_this)->FulfillWriteRequest(len); | 55 static_cast<PulseAudioOutputStream*>(p_this)->FulfillWriteRequest(len); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 // Note: If this ever changes to output raw float the data must be clipped | 268 // Note: If this ever changes to output raw float the data must be clipped |
| 270 // and sanitized since it may come from an untrusted source such as NaCl. | 269 // and sanitized since it may come from an untrusted source such as NaCl. |
| 271 audio_bus_->ToInterleaved( | 270 audio_bus_->ToInterleaved( |
| 272 audio_bus_->frames(), params_.bits_per_sample() / 8, buffer); | 271 audio_bus_->frames(), params_.bits_per_sample() / 8, buffer); |
| 273 media::AdjustVolume(buffer, bytes_to_fill, params_.channels(), | 272 media::AdjustVolume(buffer, bytes_to_fill, params_.channels(), |
| 274 params_.bits_per_sample() / 8, volume_); | 273 params_.bits_per_sample() / 8, volume_); |
| 275 | 274 |
| 276 if (pa_stream_write(pa_stream_, buffer, bytes_to_fill, NULL, 0LL, | 275 if (pa_stream_write(pa_stream_, buffer, bytes_to_fill, NULL, 0LL, |
| 277 PA_SEEK_RELATIVE) < 0) { | 276 PA_SEEK_RELATIVE) < 0) { |
| 278 if (source_callback_) { | 277 if (source_callback_) { |
| 279 source_callback_->OnError(this, pa_context_errno(pa_context_)); | 278 source_callback_->OnError(this); |
| 280 } | 279 } |
| 281 } | 280 } |
| 282 | 281 |
| 283 bytes_remaining -= bytes_to_fill; | 282 bytes_remaining -= bytes_to_fill; |
| 284 } | 283 } |
| 285 } | 284 } |
| 286 | 285 |
| 287 void PulseAudioOutputStream::Start(AudioSourceCallback* callback) { | 286 void PulseAudioOutputStream::Start(AudioSourceCallback* callback) { |
| 288 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 287 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); |
| 289 CHECK(callback); | 288 CHECK(callback); |
| 290 CHECK(pa_stream_); | 289 CHECK(pa_stream_); |
| 291 | 290 |
| 292 AutoPulseLock auto_lock(pa_mainloop_); | 291 AutoPulseLock auto_lock(pa_mainloop_); |
| 293 | 292 |
| 294 // Ensure the context and stream are ready. | 293 // Ensure the context and stream are ready. |
| 295 if (pa_context_get_state(pa_context_) != PA_CONTEXT_READY && | 294 if (pa_context_get_state(pa_context_) != PA_CONTEXT_READY && |
| 296 pa_stream_get_state(pa_stream_) != PA_STREAM_READY) { | 295 pa_stream_get_state(pa_stream_) != PA_STREAM_READY) { |
| 297 callback->OnError(this, pa_context_errno(pa_context_)); | 296 callback->OnError(this); |
| 298 return; | 297 return; |
| 299 } | 298 } |
| 300 | 299 |
| 301 source_callback_ = callback; | 300 source_callback_ = callback; |
| 302 | 301 |
| 303 // Uncork (resume) the stream. | 302 // Uncork (resume) the stream. |
| 304 pa_operation* operation = pa_stream_cork( | 303 pa_operation* operation = pa_stream_cork( |
| 305 pa_stream_, 0, &pulse::StreamSuccessCallback, pa_mainloop_); | 304 pa_stream_, 0, &pulse::StreamSuccessCallback, pa_mainloop_); |
| 306 WaitForOperationCompletion(pa_mainloop_, operation); | 305 WaitForOperationCompletion(pa_mainloop_, operation); |
| 307 } | 306 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 335 volume_ = static_cast<float>(volume); | 334 volume_ = static_cast<float>(volume); |
| 336 } | 335 } |
| 337 | 336 |
| 338 void PulseAudioOutputStream::GetVolume(double* volume) { | 337 void PulseAudioOutputStream::GetVolume(double* volume) { |
| 339 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 338 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); |
| 340 | 339 |
| 341 *volume = volume_; | 340 *volume = volume_; |
| 342 } | 341 } |
| 343 | 342 |
| 344 } // namespace media | 343 } // namespace media |
| OLD | NEW |