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.
This commit is contained in:
Thomas Goyne 2012-03-19 16:31:33 -07:00
parent 6e90d9498d
commit 95a1b7e9b5
17 changed files with 131 additions and 339 deletions

View File

@ -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;
}

View File

@ -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<std::string> 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<AudioPlayer *(*)()>::classes = NULL;
template<> AudioPlayerFactory::map *FactoryBase<AudioPlayer *(*)(AudioProvider*)>::classes = NULL;

View File

@ -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;
}

View File

@ -47,15 +47,11 @@ struct PlaybackState;
class AlsaPlayer : public AudioPlayer {
agi::scoped_ptr<PlaybackState> 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();

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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; }

View File

@ -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

View File

@ -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();

View File

@ -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<std::string, DeviceVec>::iterator it = player.devices.begin(); it != player.devices.end(); ++it)
list.push_back(lagi_wxString(it->first));

View File

@ -48,6 +48,8 @@ extern "C" {
#include <vector>
#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

View File

@ -39,7 +39,9 @@
#ifdef WITH_LIBPULSE
#ifndef AGI_PRE
#include <stdio.h>
#include <cstdio>
#include <wx/thread.h>
#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 <libaegisub/log.h>
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);

View File

@ -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);

View File

@ -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<AudioPlayer> {
class AudioPlayerFactory : public Factory1<AudioPlayer, AudioProvider*> {
public:
static void RegisterProviders();
static AudioPlayer *GetAudioPlayer();
static AudioPlayer *GetAudioPlayer(AudioProvider *provider);
};