Eliminate all uses of volatile in the alsa player and just lock reads instead

Originally committed to SVN as r6496.
This commit is contained in:
Thomas Goyne 2012-02-20 18:22:37 +00:00
parent df73e15f0f
commit fb6d3daf8b
1 changed files with 41 additions and 38 deletions

View File

@ -57,6 +57,7 @@ class PthreadMutexLocker {
PthreadMutexLocker(const PthreadMutexLocker &); // uncopyable PthreadMutexLocker(const PthreadMutexLocker &); // uncopyable
PthreadMutexLocker(); // no default PthreadMutexLocker(); // no default
PthreadMutexLocker& operator=(PthreadMutexLocker const&);
public: public:
explicit PthreadMutexLocker(pthread_mutex_t &mutex) : mutex(mutex) explicit PthreadMutexLocker(pthread_mutex_t &mutex) : mutex(mutex)
@ -85,13 +86,14 @@ public:
class ScopedAliveFlag { class ScopedAliveFlag {
volatile bool &flag; bool &flag;
ScopedAliveFlag(const ScopedAliveFlag &); // uncopyable ScopedAliveFlag(const ScopedAliveFlag &); // uncopyable
ScopedAliveFlag(); // no default ScopedAliveFlag(); // no default
ScopedAliveFlag& operator=(ScopedAliveFlag const&);
public: public:
explicit ScopedAliveFlag(volatile bool &var) : flag(var) { flag = true; } explicit ScopedAliveFlag(bool &var) : flag(var) { flag = true; }
~ScopedAliveFlag() { flag = false; } ~ScopedAliveFlag() { flag = false; }
}; };
@ -100,17 +102,17 @@ struct PlaybackState {
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t cond; pthread_cond_t cond;
volatile bool playing; bool playing;
volatile bool alive; bool alive;
volatile bool signal_start; bool signal_start;
volatile bool signal_stop; bool signal_stop;
volatile bool signal_close; bool signal_close;
volatile bool signal_volume; bool signal_volume;
volatile double volume; double volume;
volatile int64_t start_position; int64_t start_position;
volatile int64_t end_position; int64_t end_position;
AudioProvider *provider; AudioProvider *provider;
std::string device_name; std::string device_name;
@ -160,18 +162,18 @@ void *playback_thread(void *arg)
snd_pcm_t *pcm = 0; snd_pcm_t *pcm = 0;
if (snd_pcm_open(&pcm, ps.device_name.c_str(), SND_PCM_STREAM_PLAYBACK, 0) != 0) if (snd_pcm_open(&pcm, ps.device_name.c_str(), SND_PCM_STREAM_PLAYBACK, 0) != 0)
return (void*)"snd_pcm_open"; return (void*)"snd_pcm_open";
printf("alsa_player: opened pcm\n"); LOG_D("audio/player/alsa") << "opened pcm";
do_setup: do_setup:
snd_pcm_format_t pcm_format; snd_pcm_format_t pcm_format;
switch (ps.provider->GetBytesPerSample()) switch (ps.provider->GetBytesPerSample())
{ {
case 1: case 1:
printf("alsa_player: format U8\n"); LOG_D("audio/player/alsa") << "format U8";
pcm_format = SND_PCM_FORMAT_U8; pcm_format = SND_PCM_FORMAT_U8;
break; break;
case 2: case 2:
printf("alsa_player: format S16_LE\n"); LOG_D("audio/player/alsa") << "format S16_LE";
pcm_format = SND_PCM_FORMAT_S16_LE; pcm_format = SND_PCM_FORMAT_S16_LE;
break; break;
default: default:
@ -187,7 +189,7 @@ do_setup:
100*1000 // 100 milliseconds latency 100*1000 // 100 milliseconds latency
) != 0) ) != 0)
return (void*)"snd_pcm_set_params"; return (void*)"snd_pcm_set_params";
printf("alsa_player: set pcm params\n"); LOG_D("audio/player/alsa") << "set pcm params";
size_t framesize = ps.provider->GetChannels() * ps.provider->GetBytesPerSample(); size_t framesize = ps.provider->GetChannels() * ps.provider->GetBytesPerSample();
@ -197,16 +199,16 @@ do_setup:
// Wait for condition to trigger // Wait for condition to trigger
if (!ps.signal_start) if (!ps.signal_start)
ml.WaitCondition(ps.cond); ml.WaitCondition(ps.cond);
printf("alsa_player: outer loop, condition happened\n"); LOG_D("audio/player/alsa") << "outer loop, condition happened";
if (ps.signal_start == false || ps.end_position <= ps.start_position) if (ps.signal_start == false || ps.end_position <= ps.start_position)
{ {
printf("alsa_player: nothing to play, rewaiting\n"); LOG_D("audio/player/alsa") << "nothing to play, rewaiting";
ps.signal_start = false; ps.signal_start = false;
continue; continue;
} }
printf("alsa_player: starting playback\n"); LOG_D("audio/player/alsa") << "starting playback";
int64_t position = ps.start_position; int64_t position = ps.start_position;
// Playback position // Playback position
@ -229,7 +231,7 @@ do_setup:
{ {
delete[] buf; delete[] buf;
snd_pcm_close(pcm); snd_pcm_close(pcm);
printf("alsa_player: error filling buffer\n"); LOG_D("audio/player/alsa") << "error filling buffer";
return (void*)"snd_pcm_writei"; return (void*)"snd_pcm_writei";
} }
} }
@ -237,7 +239,7 @@ do_setup:
position += written; position += written;
// Start playback // Start playback
printf("alsa_player: initial buffer filled, hitting start\n"); LOG_D("audio/player/alsa") << "initial buffer filled, hitting start";
snd_pcm_start(pcm); snd_pcm_start(pcm);
ps.signal_start = false; ps.signal_start = false;
@ -249,12 +251,12 @@ do_setup:
// Sleep a bit, or until an event // Sleep a bit, or until an event
ml.WaitConditionTimeout(ps.cond, 50); ml.WaitConditionTimeout(ps.cond, 50);
//printf("alsa_player: playback loop, out of wait\n"); //LOG_D("audio/player/alsa") << "playback loop, out of wait";
// Check for stop signal // Check for stop signal
if (ps.signal_stop == true) if (ps.signal_stop == true)
{ {
printf("alsa_player: playback loop, stop signal\n"); LOG_D("audio/player/alsa") << "playback loop, stop signal";
snd_pcm_drop(pcm); snd_pcm_drop(pcm);
break; break;
} }
@ -287,24 +289,24 @@ do_setup:
{ {
delete[] buf; delete[] buf;
snd_pcm_close(pcm); snd_pcm_close(pcm);
printf("alsa_player: error filling buffer, written=%d\n", (int)written); LOG_D("audio/player/alsa") << "error filling buffer, written=" << written;
return (void*)"snd_pcm_writei"; return (void*)"snd_pcm_writei";
} }
} }
delete[] buf; delete[] buf;
position += written; position += written;
//printf("alsa_player: playback loop, filled buffer\n"); //LOG_D("audio/player/alsa") << "playback loop, filled buffer";
// Check for end of playback // Check for end of playback
if (position >= ps.end_position) if (position >= ps.end_position)
{ {
printf("alsa_player: playback loop, past end, draining\n"); LOG_D("audio/player/alsa") << "playback loop, past end, draining";
snd_pcm_drain(pcm); snd_pcm_drain(pcm);
break; break;
} }
} }
ps.signal_stop = false; ps.signal_stop = false;
printf("alsa_player: out of playback loop\n"); LOG_D("audio/player/alsa") << "out of playback loop";
switch (snd_pcm_state(pcm)) switch (snd_pcm_state(pcm))
{ {
@ -330,7 +332,7 @@ do_setup:
} }
} }
ps.signal_close = false; ps.signal_close = false;
printf("alsa_player: out of outer loop\n"); LOG_D("audio/player/alsa") << "out of outer loop";
snd_pcm_close(pcm); snd_pcm_close(pcm);
@ -364,13 +366,9 @@ void AlsaPlayer::OpenStream()
ps->device_name = std::string(device_name.utf8_str()); ps->device_name = std::string(device_name.utf8_str());
if (pthread_create(&thread, 0, &playback_thread, ps.get()) == 0) if (pthread_create(&thread, 0, &playback_thread, ps.get()) == 0)
{
open = true; open = true;
}
else else
{
throw agi::AudioPlayerOpenError("AlsaPlayer: Creating the playback thread failed", 0); throw agi::AudioPlayerOpenError("AlsaPlayer: Creating the playback thread failed", 0);
}
} }
@ -382,7 +380,7 @@ void AlsaPlayer::CloseStream()
PthreadMutexLocker ml(ps->mutex); PthreadMutexLocker ml(ps->mutex);
ps->signal_stop = true; ps->signal_stop = true;
ps->signal_close = true; ps->signal_close = true;
printf("AlsaPlayer: close stream, stop+close signal\n"); LOG_D("audio/player/alsa") << "close stream, stop+close signal";
pthread_cond_signal(&ps->cond); pthread_cond_signal(&ps->cond);
} }
@ -405,7 +403,8 @@ void AlsaPlayer::Play(int64_t start, int64_t count)
pthread_cond_signal(&ps->cond); pthread_cond_signal(&ps->cond);
} }
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15); if (displayTimer && !displayTimer->IsRunning())
displayTimer->Start(15);
} }
@ -416,17 +415,17 @@ void AlsaPlayer::Stop(bool timerToo)
{ {
PthreadMutexLocker ml(ps->mutex); PthreadMutexLocker ml(ps->mutex);
ps->signal_stop = true; ps->signal_stop = true;
printf("AlsaPlayer: stop stream, stop signal\n"); LOG_D("audio/player/alsa") << "stop stream, stop signal";
pthread_cond_signal(&ps->cond); pthread_cond_signal(&ps->cond);
} }
if (timerToo && displayTimer) { if (timerToo && displayTimer)
displayTimer->Stop(); displayTimer->Stop();
}
} }
bool AlsaPlayer::IsPlaying() bool AlsaPlayer::IsPlaying()
{ {
PthreadMutexLocker ml(ps->mutex);
return open && ps->playing; return open && ps->playing;
} }
@ -450,19 +449,21 @@ void AlsaPlayer::SetCurrentPosition(int64_t pos)
ps->start_position = pos; ps->start_position = pos;
ps->signal_start = true; ps->signal_start = true;
ps->signal_stop = true; ps->signal_stop = true;
printf("AlsaPlayer: set position, stop+start signal\n"); LOG_D("audio/player/alsa") << "set position, stop+start signal";
pthread_cond_signal(&ps->cond); pthread_cond_signal(&ps->cond);
} }
int64_t AlsaPlayer::GetStartPosition() int64_t AlsaPlayer::GetStartPosition()
{ {
if (!open) return 0; if (!open) return 0;
PthreadMutexLocker ml(ps->mutex);
return ps->start_position; return ps->start_position;
} }
int64_t AlsaPlayer::GetEndPosition() int64_t AlsaPlayer::GetEndPosition()
{ {
if (!open) return 0; if (!open) return 0;
PthreadMutexLocker ml(ps->mutex);
return ps->end_position; return ps->end_position;
} }
@ -476,7 +477,7 @@ int64_t AlsaPlayer::GetCurrentPosition()
int64_t samplerate; int64_t samplerate;
{ {
//PthreadMutexLocker ml(ps->mutex); PthreadMutexLocker ml(ps->mutex);
lastpos = ps->last_position; lastpos = ps->last_position;
lasttime = ps->last_position_time; lasttime = ps->last_position_time;
samplerate = ps->provider->GetSampleRate(); samplerate = ps->provider->GetSampleRate();
@ -500,6 +501,7 @@ int64_t AlsaPlayer::GetCurrentPosition()
void AlsaPlayer::SetVolume(double vol) void AlsaPlayer::SetVolume(double vol)
{ {
if (!open) return; if (!open) return;
PthreadMutexLocker ml(ps->mutex); PthreadMutexLocker ml(ps->mutex);
ps->volume = vol; ps->volume = vol;
ps->signal_volume = true; ps->signal_volume = true;
@ -510,6 +512,7 @@ void AlsaPlayer::SetVolume(double vol)
double AlsaPlayer::GetVolume() double AlsaPlayer::GetVolume()
{ {
if (!open) return 1.0; if (!open) return 1.0;
PthreadMutexLocker ml(ps->mutex); PthreadMutexLocker ml(ps->mutex);
return ps->volume; return ps->volume;
} }