diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2013-01-13 21:36:26 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2013-01-13 21:36:26 -0600 |
| commit | 13469f2db4376879d3e2db9d76fcf94e31708280 (patch) | |
| tree | 997a5bb032b8da7ee18a103d9920a5f82a6a06cb /Source/Core | |
| parent | 47792b02a526597642e8e4e40991c0fb108b521d (diff) | |
| parent | 202c005e61c12e546a69fb290ace57e170196c6a (diff) | |
Merge branch 'pulseaudio-simple'
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/AudioCommon/Src/PulseAudioStream.cpp | 287 | ||||
| -rw-r--r-- | Source/Core/AudioCommon/Src/PulseAudioStream.h | 23 | ||||
| -rw-r--r-- | Source/Core/DolphinWX/Src/ConfigMain.cpp | 3 |
3 files changed, 50 insertions, 263 deletions
diff --git a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp index 4851b4bd12..923a338190 100644 --- a/Source/Core/AudioCommon/Src/PulseAudioStream.cpp +++ b/Source/Core/AudioCommon/Src/PulseAudioStream.cpp @@ -22,31 +22,31 @@ #include "PulseAudioStream.h" -#define BUFFER_SIZE 4096 -#define BUFFER_SIZE_BYTES (BUFFER_SIZE * 4) - -PulseAudio::PulseAudio(CMixer *mixer) - : SoundStream(mixer), thread_running(false), mainloop(NULL) - , context(NULL), stream(NULL), iVolume(100) +namespace { - mix_buffer = new u8[BUFFER_SIZE_BYTES]; +const size_t BUFFER_SAMPLES = 512; +const size_t CHANNEL_COUNT = 2; +const size_t BUFFER_SIZE = BUFFER_SAMPLES * CHANNEL_COUNT; } -PulseAudio::~PulseAudio() -{ - delete [] mix_buffer; -} +PulseAudio::PulseAudio(CMixer *mixer) + : SoundStream(mixer) + , mix_buffer(BUFFER_SIZE) + , thread() + , run_thread() + , pa() +{} bool PulseAudio::Start() { - thread_running = true; + run_thread = true; thread = std::thread(std::mem_fun(&PulseAudio::SoundLoop), this); return true; } void PulseAudio::Stop() { - thread_running = false; + run_thread = false; thread.join(); } @@ -60,260 +60,53 @@ void PulseAudio::SoundLoop() { Common::SetCurrentThreadName("Audio thread - pulse"); - thread_running = PulseInit(); - - while (thread_running) - { - int frames_to_deliver = 512; - m_mixer->Mix((short *)mix_buffer, frames_to_deliver); - if (!Write(mix_buffer, frames_to_deliver * 4)) - ERROR_LOG(AUDIO, "PulseAudio failure writing data"); - } - PulseShutdown(); -} - -bool PulseAudio::PulseInit() -{ - // The Sample format to use - const pa_sample_spec ss = - { - PA_SAMPLE_S16LE, - m_mixer->GetSampleRate(), - 2 - }; - - mainloop = pa_threaded_mainloop_new(); - - context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "dolphin-emu"); - pa_context_set_state_callback(context, ContextStateCB, this); - - if (pa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) + if (PulseInit()) { - ERROR_LOG(AUDIO, "PulseAudio failed to connect context: %s", - pa_strerror(pa_context_errno(context))); - return false; - } - - pa_threaded_mainloop_lock(mainloop); - pa_threaded_mainloop_start(mainloop); - - for (;;) - { - pa_context_state_t state; - - state = pa_context_get_state(context); - - if (state == PA_CONTEXT_READY) - break; - - if (!PA_CONTEXT_IS_GOOD(state)) + while (run_thread) { - ERROR_LOG(AUDIO, "PulseAudio context state failure: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; + m_mixer->Mix(&mix_buffer[0], mix_buffer.size() / CHANNEL_COUNT); + Write(&mix_buffer[0], mix_buffer.size() * sizeof(s16)); } - // Wait until the context is ready - pa_threaded_mainloop_wait(mainloop); + PulseShutdown(); } - - if (!(stream = pa_stream_new(context, "emulator", &ss, NULL))) - { - ERROR_LOG(AUDIO, "PulseAudio failed to create playback stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - // Set callbacks for the playback stream - pa_stream_set_state_callback(stream, StreamStateCB, this); - pa_stream_set_write_callback(stream, StreamWriteCB, this); - - if (pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_NOFLAGS, NULL, NULL) < 0) - { - ERROR_LOG(AUDIO, "PulseAudio failed to connect playback stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - for (;;) - { - pa_stream_state_t state; - - state = pa_stream_get_state(stream); - - if (state == PA_STREAM_READY) - break; - - if (!PA_STREAM_IS_GOOD(state)) - { - ERROR_LOG(AUDIO, "PulseAudio stream state failure: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - // Wait until the stream is ready - pa_threaded_mainloop_wait(mainloop); - } - - pa_threaded_mainloop_unlock(mainloop); - - SetVolume(iVolume); - - NOTICE_LOG(AUDIO, "Pulse successfully initialized."); - return true; } -void PulseAudio::PulseShutdown() +bool PulseAudio::PulseInit() { - if (mainloop) - pa_threaded_mainloop_stop(mainloop); + pa_sample_spec ss = {}; + ss.format = PA_SAMPLE_S16LE; + ss.channels = 2; + ss.rate = m_mixer->GetSampleRate(); - if (stream) - pa_stream_unref(stream); + int error; + pa = pa_simple_new(nullptr, "dolphin-emu", PA_STREAM_PLAYBACK, + nullptr, "audio", &ss, nullptr, nullptr, &error); - if (context) + if (!pa) { - pa_context_disconnect(context); - pa_context_unref(context); - } - - if (mainloop) - pa_threaded_mainloop_free(mainloop); -} - -void PulseAudio::SignalMainLoop() -{ - pa_threaded_mainloop_signal(mainloop, 0); -} - -void PulseAudio::ContextStateCB(pa_context *c, void *userdata) -{ - switch (pa_context_get_state(c)) - { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - ((PulseAudio *)userdata)->SignalMainLoop(); - break; - - default: - break; + ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", + pa_strerror(error)); + return false; } -} - -void PulseAudio::StreamStateCB(pa_stream *s, void * userdata) -{ - switch (pa_stream_get_state(s)) + else { - case PA_STREAM_READY: - case PA_STREAM_TERMINATED: - case PA_STREAM_FAILED: - ((PulseAudio *)userdata)->SignalMainLoop(); - break; - - default: - break; + NOTICE_LOG(AUDIO, "Pulse successfully initialized."); + return true; } } -void PulseAudio::StreamWriteCB(pa_stream *s, size_t length, void *userdata) -{ - ((PulseAudio *)userdata)->SignalMainLoop(); -} - -static bool StateIsGood(pa_context *context, pa_stream *stream) +void PulseAudio::PulseShutdown() { - if (!context || !PA_CONTEXT_IS_GOOD(pa_context_get_state(context)) || - !stream || !PA_STREAM_IS_GOOD(pa_stream_get_state(stream))) - { - if ((context && pa_context_get_state(context) == PA_CONTEXT_FAILED) || - (stream && pa_stream_get_state(stream) == PA_STREAM_FAILED)) - { - ERROR_LOG(AUDIO, "PulseAudio state failure: %s", - pa_strerror(pa_context_errno(context))); - } - else - { - ERROR_LOG(AUDIO, "PulseAudio state failure: %s", - pa_strerror(PA_ERR_BADSTATE)); - } - return false; - } - return true; + pa_simple_free(pa); } -bool PulseAudio::Write(const void *data, size_t length) +void PulseAudio::Write(const void *data, size_t length) { - if (!data || length == 0 || !stream) - return false; - - pa_threaded_mainloop_lock(mainloop); - - if (!StateIsGood(context, stream)) + int error; + if (pa_simple_write(pa, data, length, &error) < 0) { - pa_threaded_mainloop_unlock(mainloop); - return false; + ERROR_LOG(AUDIO, "PulseAudio failed to write data: %s", + pa_strerror(error)); } - - while (length > 0) - { - size_t l; - int r; - - while (!(l = pa_stream_writable_size(stream))) - { - pa_threaded_mainloop_wait(mainloop); - if (!StateIsGood(context, stream)) - { - pa_threaded_mainloop_unlock(mainloop); - return false; - } - } - - if (l == (size_t)-1) - { - ERROR_LOG(AUDIO, "PulseAudio invalid stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - if (l > length) - l = length; - - r = pa_stream_write(stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); - if (r < 0) - { - ERROR_LOG(AUDIO, "PulseAudio error writing to stream: %s", - pa_strerror(pa_context_errno(context))); - pa_threaded_mainloop_unlock(mainloop); - return false; - } - - data = (const uint8_t*) data + l; - length -= l; - } - - pa_threaded_mainloop_unlock(mainloop); - return true; -} - -void PulseAudio::SetVolume(int volume) -{ - iVolume = volume; - - if (!stream) - return; - - pa_cvolume cvolume; - const pa_channel_map *channels = pa_stream_get_channel_map(stream); - pa_cvolume_set(&cvolume, channels->channels, - iVolume * (PA_VOLUME_NORM - PA_VOLUME_MUTED) / 100); - - pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), - &cvolume, NULL, this); } diff --git a/Source/Core/AudioCommon/Src/PulseAudioStream.h b/Source/Core/AudioCommon/Src/PulseAudioStream.h index f3a5a43e79..38399e2506 100644 --- a/Source/Core/AudioCommon/Src/PulseAudioStream.h +++ b/Source/Core/AudioCommon/Src/PulseAudioStream.h @@ -19,7 +19,8 @@ #define _PULSE_AUDIO_STREAM_H #if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO -#include <pulse/pulseaudio.h> +#include <pulse/simple.h> +#include <pulse/error.h> #endif #include "Common.h" @@ -27,16 +28,16 @@ #include "Thread.h" +#include <vector> + class PulseAudio : public SoundStream { #if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO public: PulseAudio(CMixer *mixer); - virtual ~PulseAudio(); virtual bool Start(); virtual void Stop(); - virtual void SetVolume(int volume); static bool isValid() {return true;} @@ -46,22 +47,16 @@ public: private: virtual void SoundLoop(); + bool PulseInit(); void PulseShutdown(); - bool Write(const void *data, size_t bytes); - void SignalMainLoop(); - static void ContextStateCB(pa_context *c, void *userdata); - static void StreamStateCB(pa_stream *s, void * userdata); - static void StreamWriteCB(pa_stream *s, size_t length, void *userdata); + void Write(const void *data, size_t bytes); - u8 *mix_buffer; + std::vector<s16> mix_buffer; std::thread thread; - volatile bool thread_running; + volatile bool run_thread; - pa_threaded_mainloop *mainloop; - pa_context *context; - pa_stream *stream; - int iVolume; + pa_simple* pa; #else public: PulseAudio(CMixer *mixer) : SoundStream(mixer) {} diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 12deddb572..42dc5df20b 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -966,8 +966,7 @@ bool CConfigMain::SupportsVolumeChanges(std::string backend) return (backend == BACKEND_DIRECTSOUND || backend == BACKEND_COREAUDIO || backend == BACKEND_OPENAL || - backend == BACKEND_XAUDIO2 || - backend == BACKEND_PULSEAUDIO); + backend == BACKEND_XAUDIO2); } |
