From 95a1b7e9b53a93726853fa16e8daad1dd721dd5d Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 19 Mar 2012 16:31:33 -0700 Subject: [PATCH] Remove AudioPlayer::OpenStream and CloseStream Instead, just pass the provider to the constructor and let the player worry about when to create its things. The ability to explicitly open and close the playback wasn't actually required for anything, and it complicated the implementations of the players. --- aegisub/src/audio_controller.cpp | 24 +++-- aegisub/src/audio_player.cpp | 11 ++- aegisub/src/audio_player_alsa.cpp | 49 ++-------- aegisub/src/audio_player_alsa.h | 6 +- aegisub/src/audio_player_dsound.cpp | 43 +++------ aegisub/src/audio_player_dsound.h | 23 +---- aegisub/src/audio_player_dsound2.cpp | 50 +++------- aegisub/src/audio_player_dsound2.h | 15 +-- aegisub/src/audio_player_openal.cpp | 29 +----- aegisub/src/audio_player_openal.h | 6 +- aegisub/src/audio_player_oss.cpp | 39 +++----- aegisub/src/audio_player_oss.h | 16 ++-- aegisub/src/audio_player_portaudio.cpp | 20 ++-- aegisub/src/audio_player_portaudio.h | 11 +-- aegisub/src/audio_player_pulse.cpp | 101 ++++++--------------- aegisub/src/audio_player_pulse.h | 16 +--- aegisub/src/include/aegisub/audio_player.h | 11 +-- 17 files changed, 131 insertions(+), 339 deletions(-) diff --git a/aegisub/src/audio_controller.cpp b/aegisub/src/audio_controller.cpp index 4e7480f00..3ca5ffc6c 100644 --- a/aegisub/src/audio_controller.cpp +++ b/aegisub/src/audio_controller.cpp @@ -114,14 +114,24 @@ void AudioController::OnPlaybackTimer(wxTimerEvent &) void AudioController::OnComputerSuspending(wxPowerEvent &) { Stop(); - player->CloseStream(); + delete player; + player = 0; } void AudioController::OnComputerResuming(wxPowerEvent &) { if (provider) - player->OpenStream(); + { + try + { + player = AudioPlayerFactory::GetAudioPlayer(provider); + } + catch (...) + { + CloseAudio(); + } + } } #endif @@ -135,9 +145,7 @@ void AudioController::OnAudioPlayerChanged() try { - player = AudioPlayerFactory::GetAudioPlayer(); - player->SetProvider(provider); - player->OpenStream(); + player = AudioPlayerFactory::GetAudioPlayer(provider); } catch (...) { @@ -238,15 +246,11 @@ void AudioController::OpenAudio(const wxString &url) try { - player = AudioPlayerFactory::GetAudioPlayer(); - player->SetProvider(provider); - player->OpenStream(); + player = AudioPlayerFactory::GetAudioPlayer(provider); } catch (...) { - delete player; delete provider; - player = 0; provider = 0; throw; } diff --git a/aegisub/src/audio_player.cpp b/aegisub/src/audio_player.cpp index e3e310c5e..7f9f8a4ad 100644 --- a/aegisub/src/audio_player.cpp +++ b/aegisub/src/audio_player.cpp @@ -60,18 +60,19 @@ #include "compat.h" #include "main.h" -AudioPlayer::AudioPlayer() { - provider = NULL; +AudioPlayer::AudioPlayer(AudioProvider *provider) +: provider(provider) +{ } -AudioPlayer* AudioPlayerFactory::GetAudioPlayer() { +AudioPlayer* AudioPlayerFactory::GetAudioPlayer(AudioProvider *provider) { std::vector list = GetClasses(OPT_GET("Audio/Player")->GetString()); if (list.empty()) throw agi::NoAudioPlayersError("No audio players are available.", 0); std::string error; for (size_t i = 0; i < list.size(); ++i) { try { - return Create(list[i]); + return Create(list[i], provider); } catch (agi::AudioPlayerOpenError const& err) { error += list[i] + " factory: " + err.GetChainedMessage() + "\n"; @@ -102,4 +103,4 @@ void AudioPlayerFactory::RegisterProviders() { #endif } -template<> AudioPlayerFactory::map *FactoryBase::classes = NULL; +template<> AudioPlayerFactory::map *FactoryBase::classes = NULL; diff --git a/aegisub/src/audio_player_alsa.cpp b/aegisub/src/audio_player_alsa.cpp index f2b74307e..691154d29 100644 --- a/aegisub/src/audio_player_alsa.cpp +++ b/aegisub/src/audio_player_alsa.cpp @@ -366,42 +366,22 @@ do_setup: } -AlsaPlayer::AlsaPlayer() -: ps(new PlaybackState) +AlsaPlayer::AlsaPlayer(AudioProvider *provider) +: AudioPlayer(provider) +, ps(new PlaybackState) { - open = false; -} - - -AlsaPlayer::~AlsaPlayer() -{ - CloseStream(); -} - - -void AlsaPlayer::OpenStream() -{ - if (open) return; - - CloseStream(); - - ps->Reset(); ps->provider = provider; wxString device_name = lagi_wxString(OPT_GET("Player/Audio/ALSA/Device")->GetString()); ps->device_name = std::string(device_name.utf8_str()); - if (pthread_create(&thread, 0, &playback_thread, ps.get()) == 0) - open = true; - else + if (pthread_create(&thread, 0, &playback_thread, ps.get()) != 0) throw agi::AudioPlayerOpenError("AlsaPlayer: Creating the playback thread failed", 0); } -void AlsaPlayer::CloseStream() +AlsaPlayer::~AlsaPlayer() { - if (!open) return; - { PthreadMutexLocker ml(ps->mutex); ps->signal_stop = true; @@ -411,15 +391,11 @@ void AlsaPlayer::CloseStream() } pthread_join(thread, 0); // FIXME: check for errors - - open = false; } void AlsaPlayer::Play(int64_t start, int64_t count) { - OpenStream(); - PthreadMutexLocker ml(ps->mutex); ps->signal_start = true; ps->signal_stop = true; // make sure to stop any ongoing playback first @@ -431,8 +407,6 @@ void AlsaPlayer::Play(int64_t start, int64_t count) void AlsaPlayer::Stop() { - if (!open) return; - PthreadMutexLocker ml(ps->mutex); ps->signal_stop = true; LOG_D("audio/player/alsa") << "stop stream, stop signal"; @@ -442,13 +416,12 @@ void AlsaPlayer::Stop() bool AlsaPlayer::IsPlaying() { PthreadMutexLocker ml(ps->mutex); - return open && ps->playing; + return ps->playing; } void AlsaPlayer::SetEndPosition(int64_t pos) { - if (!open) return; PthreadMutexLocker ml(ps->mutex); ps->end_position = pos; } @@ -456,8 +429,6 @@ void AlsaPlayer::SetEndPosition(int64_t pos) void AlsaPlayer::SetCurrentPosition(int64_t pos) { - if (!open) return; - PthreadMutexLocker ml(ps->mutex); if (!ps->playing) return; @@ -471,14 +442,12 @@ void AlsaPlayer::SetCurrentPosition(int64_t pos) int64_t AlsaPlayer::GetStartPosition() { - if (!open) return 0; PthreadMutexLocker ml(ps->mutex); return ps->start_position; } int64_t AlsaPlayer::GetEndPosition() { - if (!open) return 0; PthreadMutexLocker ml(ps->mutex); return ps->end_position; } @@ -486,8 +455,6 @@ int64_t AlsaPlayer::GetEndPosition() int64_t AlsaPlayer::GetCurrentPosition() { - if (!open) return 0; - int64_t lastpos; timespec lasttime; int64_t samplerate; @@ -516,8 +483,6 @@ int64_t AlsaPlayer::GetCurrentPosition() void AlsaPlayer::SetVolume(double vol) { - if (!open) return; - PthreadMutexLocker ml(ps->mutex); ps->volume = vol; ps->signal_volume = true; @@ -527,8 +492,6 @@ void AlsaPlayer::SetVolume(double vol) double AlsaPlayer::GetVolume() { - if (!open) return 1.0; - PthreadMutexLocker ml(ps->mutex); return ps->volume; } diff --git a/aegisub/src/audio_player_alsa.h b/aegisub/src/audio_player_alsa.h index a28e0322e..48fa445e3 100644 --- a/aegisub/src/audio_player_alsa.h +++ b/aegisub/src/audio_player_alsa.h @@ -47,15 +47,11 @@ struct PlaybackState; class AlsaPlayer : public AudioPlayer { agi::scoped_ptr ps; pthread_t thread; - bool open; public: - AlsaPlayer(); + AlsaPlayer(AudioProvider *provider); ~AlsaPlayer(); - void OpenStream(); - void CloseStream(); - void Play(int64_t start, int64_t count); void Stop(); bool IsPlaying(); diff --git a/aegisub/src/audio_player_dsound.cpp b/aegisub/src/audio_player_dsound.cpp index a6198369d..fff18a026 100644 --- a/aegisub/src/audio_player_dsound.cpp +++ b/aegisub/src/audio_player_dsound.cpp @@ -46,30 +46,20 @@ #include "main.h" #include "utils.h" -/// @brief Constructor -/// -DirectSoundPlayer::DirectSoundPlayer() { - playing = false; - volume = 1.0f; - playPos = 0; - startPos = 0; - endPos = 0; - offset = 0; - - buffer = NULL; - directSound = NULL; - thread = NULL; -} - -/// @brief Destructor -/// -DirectSoundPlayer::~DirectSoundPlayer() { - CloseStream(); -} - -/// @brief Open stream -/// -void DirectSoundPlayer::OpenStream() { +DirectSoundPlayer::DirectSoundPlayer(AudioProvider *provider) +: AudioPlayer(provider) +, playing(false) +, volume(1.0f) +, offset(0) +, bufSize(0) +, playPos(0) +, startPos(0) +, endPos(0) +, startTime(0) +, directSound(0) +, buffer(0) +, thread(0) +{ // Initialize the DirectSound object HRESULT res; res = DirectSoundCreate8(&DSDEVID_DefaultPlayback,&directSound,NULL); // TODO: support selecting audio device @@ -114,10 +104,7 @@ void DirectSoundPlayer::OpenStream() { offset = 0; } -/// @brief Close stream -/// -void DirectSoundPlayer::CloseStream() { - // Stop it +DirectSoundPlayer::~DirectSoundPlayer() { Stop(); // Unref the DirectSound buffer diff --git a/aegisub/src/audio_player_dsound.h b/aegisub/src/audio_player_dsound.h index 22ad73974..2fd3dcb0a 100644 --- a/aegisub/src/audio_player_dsound.h +++ b/aegisub/src/audio_player_dsound.h @@ -115,42 +115,21 @@ private: DirectSoundPlayerThread *thread; public: - DirectSoundPlayer(); + DirectSoundPlayer(AudioProvider *provider); ~DirectSoundPlayer(); - void OpenStream(); - void CloseStream(); - void Play(int64_t start,int64_t count); void Stop(); - /// @brief DOCME - /// @return - /// bool IsPlaying() { return playing; } - /// @brief DOCME - /// @return - /// int64_t GetStartPosition() { return startPos; } - - /// @brief DOCME - /// @return - /// int64_t GetEndPosition() { return endPos; } int64_t GetCurrentPosition(); void SetEndPosition(int64_t pos); void SetCurrentPosition(int64_t pos); - /// @brief DOCME - /// @param vol - /// @return - /// void SetVolume(double vol) { volume = vol; } - - /// @brief DOCME - /// @return - /// double GetVolume() { return volume; } }; #endif diff --git a/aegisub/src/audio_player_dsound2.cpp b/aegisub/src/audio_player_dsound2.cpp index 80ef1be67..e4e47c20c 100644 --- a/aegisub/src/audio_player_dsound2.cpp +++ b/aegisub/src/audio_player_dsound2.cpp @@ -801,7 +801,8 @@ bool DirectSoundPlayer2Thread::IsDead() } } -DirectSoundPlayer2::DirectSoundPlayer2() +DirectSoundPlayer2::DirectSoundPlayer2(AudioProvider *provider) +: AudioPlayer(provider) { // The buffer will hold BufferLength times WantedLatency milliseconds of audio WantedLatency = OPT_GET("Player/Audio/DirectSound/Buffer Latency")->GetInt(); @@ -812,6 +813,16 @@ DirectSoundPlayer2::DirectSoundPlayer2() WantedLatency = 100; if (BufferLength <= 0) BufferLength = 5; + + try + { + thread.reset(new DirectSoundPlayer2Thread(provider, WantedLatency, BufferLength)); + } + catch (const char *msg) + { + LOG_E("audio/player/dsound") << msg; + throw agi::AudioPlayerOpenError(msg, 0); + } } DirectSoundPlayer2::~DirectSoundPlayer2() @@ -828,47 +839,10 @@ bool DirectSoundPlayer2::IsThreadAlive() return thread; } -void DirectSoundPlayer2::OpenStream() -{ - if (IsThreadAlive()) return; - - try - { - thread.reset(new DirectSoundPlayer2Thread(provider, WantedLatency, BufferLength)); - } - catch (const char *msg) - { - LOG_E("audio/player/dsound") << msg; - } -} - -void DirectSoundPlayer2::CloseStream() -{ - thread.reset(); -} - -void DirectSoundPlayer2::SetProvider(AudioProvider *new_provider) -{ - try - { - if (IsThreadAlive() && new_provider != provider) - { - thread.reset(new DirectSoundPlayer2Thread(new_provider, WantedLatency, BufferLength)); - } - - AudioPlayer::SetProvider(new_provider); - } - catch (const char *msg) - { - LOG_E("audio/player/dsound") << msg; - } -} - void DirectSoundPlayer2::Play(int64_t start,int64_t count) { try { - OpenStream(); thread->Play(start, count); } catch (const char *msg) diff --git a/aegisub/src/audio_player_dsound2.h b/aegisub/src/audio_player_dsound2.h index 0cd3cbfbd..8dcb02e40 100644 --- a/aegisub/src/audio_player_dsound2.h +++ b/aegisub/src/audio_player_dsound2.h @@ -64,23 +64,10 @@ class DirectSoundPlayer2 : public AudioPlayer { public: /// @brief Constructor - DirectSoundPlayer2(); + DirectSoundPlayer2(AudioProvider *provider); /// @brief Destructor ~DirectSoundPlayer2(); - /// @brief Prepare for playback - /// - /// This means creating the playback thread - void OpenStream(); - /// @brief Shutdown playback - void CloseStream(); - - /// @brief Change audio provider used - /// @param provider New audio provider to use - /// - /// Will re-create the playback thread if the provider changed and playback was open - void SetProvider(AudioProvider *provider); - /// @brief Start playback /// @param start First audio frame to play /// @param count Number of audio frames to play diff --git a/aegisub/src/audio_player_openal.cpp b/aegisub/src/audio_player_openal.cpp index 5f53e503f..b3089c12f 100644 --- a/aegisub/src/audio_player_openal.cpp +++ b/aegisub/src/audio_player_openal.cpp @@ -52,8 +52,8 @@ DEFINE_SIMPLE_EXCEPTION(OpenALException, agi::AudioPlayerOpenError, "audio/open/player/openal") -OpenALPlayer::OpenALPlayer() -: open(false) +OpenALPlayer::OpenALPlayer(AudioProvider *provider) +: AudioPlayer(provider) , playing(false) , volume(1.f) , samplerate(0) @@ -64,17 +64,6 @@ OpenALPlayer::OpenALPlayer() , device(0) , context(0) { -} - -OpenALPlayer::~OpenALPlayer() -{ - CloseStream(); -} - -void OpenALPlayer::OpenStream() -{ - CloseStream(); - bpf = provider->GetChannels() * provider->GetBytesPerSample(); try { // Open device @@ -112,27 +101,16 @@ void OpenALPlayer::OpenStream() // Determine buffer length samplerate = provider->GetSampleRate(); decode_buffer.resize(samplerate * bpf / num_buffers / 2); // buffers for half a second of audio - - // Now ready - open = true; } -void OpenALPlayer::CloseStream() +OpenALPlayer::~OpenALPlayer() { - if (!open) return; - Stop(); alDeleteSources(1, &source); alDeleteBuffers(num_buffers, buffers); alcDestroyContext(context); alcCloseDevice(device); - - context = 0; - device = 0; - - // No longer working - open = false; } void OpenALPlayer::Play(int64_t start, int64_t count) @@ -165,7 +143,6 @@ void OpenALPlayer::Play(int64_t start, int64_t count) void OpenALPlayer::Stop() { - if (!open) return; if (!playing) return; // Reset data diff --git a/aegisub/src/audio_player_openal.h b/aegisub/src/audio_player_openal.h index 91caaadc1..3f306481c 100644 --- a/aegisub/src/audio_player_openal.h +++ b/aegisub/src/audio_player_openal.h @@ -64,7 +64,6 @@ class OpenALPlayer : public AudioPlayer, wxTimer { /// Number of OpenAL buffers to use static const ALsizei num_buffers = 8; - bool open; ///< Is the player ready to play? bool playing; ///< Is audio currently playing? float volume; ///< Current audio volume @@ -106,12 +105,9 @@ protected: void Notify(); public: - OpenALPlayer(); + OpenALPlayer(AudioProvider *provider); ~OpenALPlayer(); - void OpenStream(); - void CloseStream(); - void Play(int64_t start,int64_t count); void Stop(); bool IsPlaying() { return playing; } diff --git a/aegisub/src/audio_player_oss.cpp b/aegisub/src/audio_player_oss.cpp index f9c6a917b..63fbb65ba 100644 --- a/aegisub/src/audio_player_oss.cpp +++ b/aegisub/src/audio_player_oss.cpp @@ -52,25 +52,29 @@ DEFINE_SIMPLE_EXCEPTION(OSSError, agi::AudioPlayerOpenError, "audio/player/open/oss") -OSSPlayer::OSSPlayer() +OSSPlayer::OSSPlayer(AudioProvider *provider) +: AudioPlayer(provider) +, rate(0) +, thread(0) +, playing(false) +, volume(1.0f) +, start_frame(0) +, cur_frame(0) +, end_frame(0) +, bpf(0) +, dspdev(0) { - volume = 1.0f; - open = false; - playing = false; - start_frame = cur_frame = end_frame = bpf = 0; - provider = 0; - thread = 0; + OpenStream(); } OSSPlayer::~OSSPlayer() { - CloseStream(); + Stop(); + ::close(dspdev); } void OSSPlayer::OpenStream() { - CloseStream(); - bpf = provider->GetChannels() * provider->GetBytesPerSample(); // Open device @@ -114,20 +118,6 @@ void OSSPlayer::OpenStream() if (ioctl(dspdev, SNDCTL_DSP_SPEED, &rate) < 0) { throw OSSError("OSS player: setting samplerate failed", 0); } - - // Now ready - open = true; -} - -void OSSPlayer::CloseStream() -{ - if (!open) return; - - Stop(); - ::close(dspdev); - - // No longer working - open = false; } void OSSPlayer::Play(int64_t start, int64_t count) @@ -146,7 +136,6 @@ void OSSPlayer::Play(int64_t start, int64_t count) void OSSPlayer::Stop() { - if (!open) return; if (!playing) return; // Stop the thread diff --git a/aegisub/src/audio_player_oss.h b/aegisub/src/audio_player_oss.h index d94c1bbe7..afa0296d9 100644 --- a/aegisub/src/audio_player_oss.h +++ b/aegisub/src/audio_player_oss.h @@ -79,13 +79,10 @@ public: class OSSPlayer : public AudioPlayer { friend class OSSPlayerThread; - /// Is the output file handle initialized and ready to be written to? - bool open; - /// sample rate of audio unsigned int rate; - /// Worker thread that does the actual writing + /// Worker thread that does the actual writing OSSPlayerThread *thread; /// Is the player currently playing? @@ -106,15 +103,14 @@ class OSSPlayer : public AudioPlayer { /// bytes per frame unsigned long bpf; - // OSS audio device handle + /// OSS audio device handle volatile int dspdev; -public: - OSSPlayer(); - ~OSSPlayer(); - void OpenStream(); - void CloseStream(); + +public: + OSSPlayer(AudioProvider *provider); + ~OSSPlayer(); void Play(int64_t start, int64_t count); void Stop(); diff --git a/aegisub/src/audio_player_portaudio.cpp b/aegisub/src/audio_player_portaudio.cpp index 16f3faa0d..d81d6ecfd 100644 --- a/aegisub/src/audio_player_portaudio.cpp +++ b/aegisub/src/audio_player_portaudio.cpp @@ -71,9 +71,11 @@ static const PaHostApiTypeId pa_host_api_priority[] = { }; static const size_t pa_host_api_priority_count = sizeof(pa_host_api_priority) / sizeof(pa_host_api_priority[0]); -PortAudioPlayer::PortAudioPlayer() -: volume(1.0f) +PortAudioPlayer::PortAudioPlayer(AudioProvider *provider) +: AudioPlayer(provider) +, volume(1.0f) , pa_start(0.0) +, stream(0) { PaError err = Pa_Initialize(); @@ -92,6 +94,9 @@ PortAudioPlayer::PortAudioPlayer() if (devices.empty()) throw PortAudioError("No PortAudio output devices found", 0); + + if (provider) + OpenStream(); } void PortAudioPlayer::GatherDevices(PaHostApiIndex host_idx) { @@ -120,6 +125,10 @@ void PortAudioPlayer::GatherDevices(PaHostApiIndex host_idx) { } PortAudioPlayer::~PortAudioPlayer() { + if (stream) { + Stop(); + Pa_CloseStream(stream); + } Pa_Terminate(); } @@ -172,11 +181,6 @@ void PortAudioPlayer::OpenStream() { throw PortAudioError("Failed initializing PortAudio stream: " + error, 0); } -void PortAudioPlayer::CloseStream() { - Stop(); - Pa_CloseStream(stream); -} - void PortAudioPlayer::paStreamFinishedCallback(void *) { LOG_D("audio/player/portaudio") << "stopping stream"; } @@ -271,7 +275,7 @@ wxArrayString PortAudioPlayer::GetOutputDevices() { list.push_back("Default"); try { - PortAudioPlayer player; + PortAudioPlayer player(0); for (std::map::iterator it = player.devices.begin(); it != player.devices.end(); ++it) list.push_back(lagi_wxString(it->first)); diff --git a/aegisub/src/audio_player_portaudio.h b/aegisub/src/audio_player_portaudio.h index d026272dc..dcb64afc5 100644 --- a/aegisub/src/audio_player_portaudio.h +++ b/aegisub/src/audio_player_portaudio.h @@ -48,6 +48,8 @@ extern "C" { #include #endif +class wxArrayString; + /// @class PortAudioPlayer /// @brief PortAudio Player /// @@ -93,18 +95,15 @@ class PortAudioPlayer : public AudioPlayer { /// @param host_idx Host API ID void GatherDevices(PaHostApiIndex host_idx); + void OpenStream(); + public: /// @brief Constructor - PortAudioPlayer(); + PortAudioPlayer(AudioProvider *provider); /// @brief Destructor ~PortAudioPlayer(); - /// @brief Open stream - void OpenStream(); - /// @brief Close stream - void CloseStream(); - /// @brief Play audio. /// @param start Start position. /// @param count Frame count diff --git a/aegisub/src/audio_player_pulse.cpp b/aegisub/src/audio_player_pulse.cpp index 518ed6dc4..cbfe9e6fd 100644 --- a/aegisub/src/audio_player_pulse.cpp +++ b/aegisub/src/audio_player_pulse.cpp @@ -39,7 +39,9 @@ #ifdef WITH_LIBPULSE #ifndef AGI_PRE -#include +#include + +#include #endif #include "audio_player_pulse.h" @@ -48,38 +50,30 @@ #include "include/aegisub/audio_provider.h" #include "utils.h" -PulseAudioPlayer::PulseAudioPlayer() -: context_notify(0, 1) +#include + +PulseAudioPlayer::PulseAudioPlayer(AudioProvider *provider) +: AudioPlayer(provider) +, volume(1.0f) +, is_playing(false) +, start_frame(0) +, cur_frame(0) +, end_frame(0) +, bpf(0) +, context_notify(0, 1) , context_success(0, 1) , stream_notify(0, 1) , stream_success(0, 1) +, paerror(0) { - volume = 1.0f; - paerror = 0; - open = false; - is_playing = false; -} - -PulseAudioPlayer::~PulseAudioPlayer() -{ - CloseStream(); -} - -void PulseAudioPlayer::OpenStream() -{ - if (open) CloseStream(); - // Initialise a mainloop - //printf("Initialising threaded main loop\n"); mainloop = pa_threaded_mainloop_new(); - if (!mainloop) { + if (!mainloop) throw agi::AudioPlayerOpenError("Failed to initialise PulseAudio threaded mainloop object", 0); - } - //printf("Starting main loop\n"); + pa_threaded_mainloop_start(mainloop); // Create context - //printf("Creating context\n"); context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Aegisub"); if (!context) { pa_threaded_mainloop_free(mainloop); @@ -88,8 +82,8 @@ void PulseAudioPlayer::OpenStream() pa_context_set_state_callback(context, (pa_context_notify_cb_t)pa_context_notify, this); // Connect the context - //printf("Connecting context\n"); pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); + // Wait for connection while (true) { context_notify.Wait(); @@ -105,7 +99,6 @@ void PulseAudioPlayer::OpenStream() } // otherwise loop once more } - //printf("Context connected\n"); // Set up stream bpf = provider->GetChannels() * provider->GetBytesPerSample(); @@ -115,7 +108,7 @@ void PulseAudioPlayer::OpenStream() ss.channels = provider->GetChannels(); pa_channel_map map; pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT); - //printf("Creating stream\n"); + stream = pa_stream_new(context, "Sound", &ss, &map); if (!stream) { // argh! @@ -129,10 +122,9 @@ void PulseAudioPlayer::OpenStream() pa_stream_set_write_callback(stream, (pa_stream_request_cb_t)pa_stream_write, this); // Connect stream - //printf("Connecting playback stream\n"); paerror = pa_stream_connect_playback(stream, NULL, NULL, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_NOT_MONOTONOUS|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); if (paerror) { - printf("PulseAudio reported error: %s (%d)\n", pa_strerror(paerror), paerror); + LOG_E("audio/player/pulse") << "Stream connection failed: " << pa_strerror(paerror) << "(" << paerror << ")"; throw agi::AudioPlayerOpenError(std::string("PulseAudio reported error: ") + pa_strerror(paerror), 0); } while (true) { @@ -141,22 +133,14 @@ void PulseAudioPlayer::OpenStream() break; } else if (sstate == PA_STREAM_FAILED) { paerror = pa_context_errno(context); - printf("PulseAudio player: Stream connection failed: %s (%d)\n", pa_strerror(paerror), paerror); + LOG_E("audio/player/pulse") << "Stream connection failed: " << pa_strerror(paerror) << "(" << paerror << ")"; throw agi::AudioPlayerOpenError("PulseAudio player: Something went wrong connecting the stream", 0); } } - //printf("Connected playback stream, now playing\n\n"); - - // Hopefully this marks success - //printf("Finished opening PulseAudio\n\n"); - open = true; } -void PulseAudioPlayer::CloseStream() +PulseAudioPlayer::~PulseAudioPlayer() { - if (!open) return; - //printf("Closing PuseAudio\n"); - if (is_playing) Stop(); // Hope for the best and just do things as quickly as possible @@ -166,16 +150,10 @@ void PulseAudioPlayer::CloseStream() pa_context_unref(context); pa_threaded_mainloop_stop(mainloop); pa_threaded_mainloop_free(mainloop); - - //printf("Closed PulseAudio\n"); - open = false; } void PulseAudioPlayer::Play(int64_t start,int64_t count) { - //printf("Starting PulseAudio playback\n"); - if (!open) OpenStream(); - if (is_playing) { // If we're already playing, do a quick "reset" is_playing = false; @@ -187,14 +165,13 @@ void PulseAudioPlayer::Play(int64_t start,int64_t count) pa_operation_unref(op); if (!stream_success_val) { paerror = pa_context_errno(context); - printf("PulseAudio player: Error flushing stream: %s (%d)\n", pa_strerror(paerror), paerror); + LOG_E("audio/player/pulse") << "Error flushing stream: " << pa_strerror(paerror) << "(" << paerror << ")"; } } start_frame = start; cur_frame = start; end_frame = start + count; - //printf("start=%lu end=%lu\n", start_frame, end_frame); is_playing = true; @@ -202,9 +179,8 @@ void PulseAudioPlayer::Play(int64_t start,int64_t count) pa_threaded_mainloop_lock(mainloop); paerror = pa_stream_get_time(stream, (pa_usec_t*) &play_start_time); pa_threaded_mainloop_unlock(mainloop); - if (paerror) { - printf("PulseAudio player: Error getting stream time: %s (%d)\n", pa_strerror(paerror), paerror); - } + if (paerror) + LOG_E("audio/player/pulse") << "Error getting stream time: " << pa_strerror(paerror) << "(" << paerror << ")"; PulseAudioPlayer::pa_stream_write(stream, pa_stream_writable_size(stream), this); @@ -215,14 +191,13 @@ void PulseAudioPlayer::Play(int64_t start,int64_t count) pa_operation_unref(op); if (!stream_success_val) { paerror = pa_context_errno(context); - printf("PulseAudio player: Error triggering stream: %s (%d)\n", pa_strerror(paerror), paerror); + LOG_E("audio/player/pulse") << "Error triggering stream: " << pa_strerror(paerror) << "(" << paerror << ")"; } } void PulseAudioPlayer::Stop() { if (!is_playing) return; - //printf("Stopping PulseAudio\n"); is_playing = false; @@ -231,7 +206,6 @@ void PulseAudioPlayer::Stop() end_frame = 0; // Flush the stream of data - //printf("Flushing stream\n"); pa_threaded_mainloop_lock(mainloop); pa_operation *op = pa_stream_flush(stream, (pa_stream_success_cb_t)pa_stream_success, this); pa_threaded_mainloop_unlock(mainloop); @@ -239,16 +213,8 @@ void PulseAudioPlayer::Stop() pa_operation_unref(op); if (!stream_success_val) { paerror = pa_context_errno(context); - printf("PulseAudio player: Error flushing stream: %s (%d)\n", pa_strerror(paerror), paerror); + LOG_E("audio/player/pulse") << "Error flushing stream: " << pa_strerror(paerror) << "(" << paerror << ")"; } - - // And unref it - //printf("Stopped stream\n\n"); -} - -bool PulseAudioPlayer::IsPlaying() -{ - return is_playing; } void PulseAudioPlayer::SetEndPosition(int64_t pos) @@ -261,16 +227,6 @@ void PulseAudioPlayer::SetCurrentPosition(int64_t pos) cur_frame = pos; } -int64_t PulseAudioPlayer::GetStartPosition() -{ - return start_frame; -} - -int64_t PulseAudioPlayer::GetEndPosition() -{ - return end_frame; -} - int64_t PulseAudioPlayer::GetCurrentPosition() { if (!is_playing) return 0; @@ -317,7 +273,6 @@ void PulseAudioPlayer::pa_stream_write(pa_stream *p, size_t length, PulseAudioPl thread->is_playing = false; pa_operation *op = pa_stream_drain(p, NULL, NULL); pa_operation_unref(op); - //printf("PA requested more buffer, but no more to stream\n"); return; } else if (thread->cur_frame >= thread->end_frame) { @@ -328,12 +283,10 @@ void PulseAudioPlayer::pa_stream_write(pa_stream *p, size_t length, PulseAudioPl return; } - //printf("PA requested more buffer, %lu bytes\n", (unsigned long)length); unsigned long bpf = thread->bpf; unsigned long frames = length / thread->bpf; unsigned long maxframes = thread->end_frame - thread->cur_frame; if (frames > maxframes) frames = maxframes; - //printf("Handing it %lu frames\n", frames); void *buf = malloc(frames * bpf); thread->provider->GetAudioWithVolume(buf, thread->cur_frame, frames, thread->volume); ::pa_stream_write(p, buf, frames*bpf, free, 0, PA_SEEK_RELATIVE); diff --git a/aegisub/src/audio_player_pulse.h b/aegisub/src/audio_player_pulse.h index 07437ab46..4d1bad04d 100644 --- a/aegisub/src/audio_player_pulse.h +++ b/aegisub/src/audio_player_pulse.h @@ -47,14 +47,9 @@ class PulseAudioPlayer; /// /// DOCME class PulseAudioPlayer : public AudioPlayer { -private: - /// DOCME float volume; - /// DOCME - bool open; - /// DOCME bool is_playing; @@ -124,18 +119,15 @@ private: static void pa_stream_notify(pa_stream *p, PulseAudioPlayer *thread); public: - PulseAudioPlayer(); + PulseAudioPlayer(AudioProvider *provider); ~PulseAudioPlayer(); - void OpenStream(); - void CloseStream(); - void Play(int64_t start,int64_t count); void Stop(); - bool IsPlaying(); + bool IsPlaying() { return is_playing; } - int64_t GetStartPosition(); - int64_t GetEndPosition(); + int64_t GetStartPosition() { return start_frame; } + int64_t GetEndPosition() { return end_frame; } int64_t GetCurrentPosition(); void SetEndPosition(int64_t pos); void SetCurrentPosition(int64_t pos); diff --git a/aegisub/src/include/aegisub/audio_player.h b/aegisub/src/include/aegisub/audio_player.h index d2d818bfe..e39fdc918 100644 --- a/aegisub/src/include/aegisub/audio_player.h +++ b/aegisub/src/include/aegisub/audio_player.h @@ -50,12 +50,9 @@ protected: AudioProvider *provider; public: - AudioPlayer(); + AudioPlayer(AudioProvider *provider); virtual ~AudioPlayer() { } - virtual void OpenStream()=0; - virtual void CloseStream()=0; - virtual void Play(int64_t start,int64_t count)=0; // Play sample range virtual void Stop()=0; // Stop playing virtual bool IsPlaying()=0; @@ -68,12 +65,10 @@ public: virtual int64_t GetCurrentPosition()=0; virtual void SetEndPosition(int64_t pos)=0; virtual void SetCurrentPosition(int64_t pos)=0; - - virtual void SetProvider(AudioProvider *new_provider) { provider = new_provider; } }; -class AudioPlayerFactory : public Factory0 { +class AudioPlayerFactory : public Factory1 { public: static void RegisterProviders(); - static AudioPlayer *GetAudioPlayer(); + static AudioPlayer *GetAudioPlayer(AudioProvider *provider); };