Skip to content

Instantly share code, notes, and snippets.

Created March 2, 2018 15:42
Show Gist options
  • Save anonymous/f4bedb982de18683f2f70e0ecc403fc4 to your computer and use it in GitHub Desktop.
Save anonymous/f4bedb982de18683f2f70e0ecc403fc4 to your computer and use it in GitHub Desktop.
diff --git a/src/main.c b/src/main.c
index 229c606..41f1c44 100644
--- a/src/main.c
+++ b/src/main.c
@@ -259,8 +259,8 @@ static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) {
app->player.gain = curSong->fileGain;
app->player.settings = &app->settings;
app->player.songDuration = curSong->length;
- pthread_mutex_init (&app->player.pauseMutex, NULL);
- pthread_cond_init (&app->player.pauseCond, NULL);
+ pthread_mutex_init (&app->player.lock, NULL);
+ pthread_cond_init (&app->player.cond, NULL);
assert (interrupted == &app->doQuit);
interrupted = &app->player.interrupted;
@@ -291,8 +291,8 @@ static void BarMainPlayerCleanup (BarApp_t *app, pthread_t *playerThread) {
/* FIXME: pthread_join blocks everything if network connection
* is hung up e.g. */
pthread_join (*playerThread, &threadRet);
- pthread_cond_destroy (&app->player.pauseCond);
- pthread_mutex_destroy (&app->player.pauseMutex);
+ pthread_cond_destroy (&app->player.cond);
+ pthread_mutex_destroy (&app->player.lock);
if (threadRet == (void *) PLAYER_RET_OK) {
app->playerErrors = 0;
@@ -351,14 +351,15 @@ static void BarMainLoop (BarApp_t *app) {
BarMainGetInitialStation (app);
+ player_t * const player = &app->player;
/* little hack, needed to signal: hey! we need a playlist, but don't
* free anything (there is nothing to be freed yet) */
- memset (&app->player, 0, sizeof (app->player));
+ memset (player, 0, sizeof (*player));
while (!app->doQuit) {
/* song finished playing, clean up things/scrobble song */
- if (app->player.mode == PLAYER_FINISHED) {
- if (app->player.interrupted != 0) {
+ if (BarPlayerGetMode (player) == PLAYER_FINISHED) {
+ if (player->interrupted != 0) {
app->doQuit = 1;
}
BarMainPlayerCleanup (app, &playerThread);
@@ -366,7 +367,7 @@ static void BarMainLoop (BarApp_t *app) {
/* check whether player finished playing and start playing new
* song */
- if (app->player.mode == PLAYER_DEAD) {
+ if (BarPlayerGetMode (player) == PLAYER_DEAD) {
/* what's next? */
if (app->playlist != NULL) {
PianoSong_t *histsong = app->playlist;
@@ -389,12 +390,12 @@ static void BarMainLoop (BarApp_t *app) {
BarMainHandleUserInput (app);
/* show time */
- if (app->player.mode == PLAYER_PLAYING) {
+ if (BarPlayerGetMode (player) == PLAYER_PLAYING) {
BarMainPrintTime (app);
}
}
- if (app->player.mode != PLAYER_DEAD) {
+ if (BarPlayerGetMode (player) != PLAYER_DEAD) {
pthread_join (playerThread, NULL);
}
}
diff --git a/src/player.c b/src/player.c
index 9cbee69..b5c67c1 100644
--- a/src/player.c
+++ b/src/player.c
@@ -122,7 +122,9 @@ static int intCb (void * const data) {
assert (player != NULL);
if (player->interrupted > 1) {
/* got a sigint multiple times, quit pianobar (handled by main.c). */
+ pthread_mutex_lock (&player->lock);
player->doQuit = true;
+ pthread_mutex_unlock (&player->lock);
return 1;
} else if (player->interrupted != 0) {
/* the request is retried with the same player context */
@@ -190,9 +192,11 @@ static bool openStream (player_t * const player) {
av_seek_frame (player->fctx, player->streamIdx, player->lastTimestamp, 0);
}
+ pthread_mutex_lock (&player->lock);
player->songPlayed = 0;
player->songDuration = av_q2d (player->st->time_base) *
(double) player->st->duration;
+ pthread_mutex_unlock (&player->lock);
return true;
}
@@ -283,6 +287,29 @@ static bool openDevice (player_t * const player) {
return true;
}
+/* Operating on shared variables and must be protected by mutex
+ */
+
+static bool shouldQuit (player_t * const player) {
+ pthread_mutex_lock (&player->lock);
+ const bool ret = player->doQuit;
+ pthread_mutex_unlock (&player->lock);
+ return ret;
+}
+
+static void changeMode (player_t * const player, unsigned int mode) {
+ pthread_mutex_lock (&player->lock);
+ player->mode = mode;
+ pthread_mutex_unlock (&player->lock);
+}
+
+unsigned int BarPlayerGetMode (player_t * const player) {
+ pthread_mutex_lock (&player->lock);
+ const unsigned int ret = player->mode;
+ pthread_mutex_unlock (&player->lock);
+ return ret;
+}
+
/* decode and play stream. returns 0 or av error code.
*/
static int play (player_t * const player) {
@@ -302,7 +329,7 @@ static int play (player_t * const player) {
enum { FILL, DRAIN, DONE } drainMode = FILL;
int ret = 0;
- while (!player->doQuit && drainMode != DONE) {
+ while (!shouldQuit (player) && drainMode != DONE) {
if (drainMode == FILL) {
ret = av_read_frame (player->fctx, &pkt);
if (ret == AVERROR_EOF) {
@@ -323,17 +350,17 @@ static int play (player_t * const player) {
}
/* pausing */
- pthread_mutex_lock (&player->pauseMutex);
+ pthread_mutex_lock (&player->lock);
if (player->doPause) {
av_read_pause (player->fctx);
do {
- pthread_cond_wait (&player->pauseCond, &player->pauseMutex);
+ pthread_cond_wait (&player->cond, &player->lock);
} while (player->doPause);
av_read_play (player->fctx);
}
- pthread_mutex_unlock (&player->pauseMutex);
+ pthread_mutex_unlock (&player->lock);
- while (!player->doQuit) {
+ while (!shouldQuit (player)) {
ret = avcodec_receive_frame (cctx, frame);
if (ret == AVERROR_EOF) {
/* done draining */
@@ -367,7 +394,9 @@ static int play (player_t * const player) {
}
}
+ pthread_mutex_lock (&player->lock);
player->songPlayed = av_q2d (player->st->time_base) * (double) pkt.pts;
+ pthread_mutex_unlock (&player->lock);
player->lastTimestamp = pkt.pts;
av_packet_unref (&pkt);
@@ -410,7 +439,7 @@ void *BarPlayerThread (void *data) {
retry = false;
if (openStream (player)) {
if (openFilter (player) && openDevice (player)) {
- player->mode = PLAYER_PLAYING;
+ changeMode (player, PLAYER_PLAYING);
BarPlayerSetVolume (player);
retry = play (player) == AVERROR_INVALIDDATA &&
!player->interrupted;
@@ -422,11 +451,11 @@ void *BarPlayerThread (void *data) {
/* stream not found */
pret = PLAYER_RET_SOFTFAIL;
}
- player->mode = PLAYER_WAITING;
+ changeMode (player, PLAYER_WAITING);
finish (player);
} while (retry);
- player->mode = PLAYER_FINISHED;
+ changeMode (player, PLAYER_FINISHED);
return (void *) pret;
}
diff --git a/src/player.h b/src/player.h
index 0213fde..570038f 100644
--- a/src/player.h
+++ b/src/player.h
@@ -40,11 +40,15 @@ THE SOFTWARE.
#include "settings.h"
typedef struct {
- /* protected by pauseMutex */
- volatile bool doQuit;
- volatile bool doPause;
- pthread_mutex_t pauseMutex;
- pthread_cond_t pauseCond;
+ /* public attributes protected by mutex */
+ pthread_mutex_t lock;
+ pthread_cond_t cond; /* broadcast changes to doPause */
+
+ bool doQuit, doPause;
+
+ /* measured in seconds */
+ unsigned int songDuration;
+ unsigned int songPlayed;
enum {
/* not running */
@@ -57,6 +61,8 @@ typedef struct {
PLAYER_FINISHED,
} mode;
+ /* private attributes _not_ protected by mutex */
+
/* libav */
AVFilterContext *fvolume;
AVFilterGraph *fgraph;
@@ -70,14 +76,10 @@ typedef struct {
ao_device *aoDev;
- /* settings */
+ /* settings (must be set before starting the thread) */
double gain;
char *url;
const BarSettings_t *settings;
-
- /* measured in seconds */
- volatile unsigned int songDuration;
- volatile unsigned int songPlayed;
} player_t;
enum {PLAYER_RET_OK = 0, PLAYER_RET_HARDFAIL = 1, PLAYER_RET_SOFTFAIL = 2};
@@ -86,4 +88,5 @@ void *BarPlayerThread (void *data);
void BarPlayerSetVolume (player_t * const player);
void BarPlayerInit ();
void BarPlayerDestroy ();
+unsigned int BarPlayerGetMode (player_t * const player);
diff --git a/src/ui_act.c b/src/ui_act.c
index 2c5f264..8600f6e 100644
--- a/src/ui_act.c
+++ b/src/ui_act.c
@@ -52,11 +52,11 @@ THE SOFTWARE.
static inline void BarUiDoSkipSong (player_t * const player) {
assert (player != NULL);
- pthread_mutex_lock (&player->pauseMutex);
+ pthread_mutex_lock (&player->lock);
player->doQuit = true;
player->doPause = false;
- pthread_cond_broadcast (&player->pauseCond);
- pthread_mutex_unlock (&player->pauseMutex);
+ pthread_cond_broadcast (&player->cond);
+ pthread_mutex_unlock (&player->lock);
}
/* transform station if necessary to allow changes like rename, rate, ...
@@ -419,28 +419,28 @@ BarUiActCallback(BarUiActSkipSong) {
/* play
*/
BarUiActCallback(BarUiActPlay) {
- pthread_mutex_lock (&app->player.pauseMutex);
+ pthread_mutex_lock (&app->player.lock);
app->player.doPause = false;
- pthread_cond_broadcast (&app->player.pauseCond);
- pthread_mutex_unlock (&app->player.pauseMutex);
+ pthread_cond_broadcast (&app->player.cond);
+ pthread_mutex_unlock (&app->player.lock);
}
/* pause
*/
BarUiActCallback(BarUiActPause) {
- pthread_mutex_lock (&app->player.pauseMutex);
+ pthread_mutex_lock (&app->player.lock);
app->player.doPause = true;
- pthread_cond_broadcast (&app->player.pauseCond);
- pthread_mutex_unlock (&app->player.pauseMutex);
+ pthread_cond_broadcast (&app->player.cond);
+ pthread_mutex_unlock (&app->player.lock);
}
/* toggle pause
*/
BarUiActCallback(BarUiActTogglePause) {
- pthread_mutex_lock (&app->player.pauseMutex);
+ pthread_mutex_lock (&app->player.lock);
app->player.doPause = !app->player.doPause;
- pthread_cond_broadcast (&app->player.pauseCond);
- pthread_mutex_unlock (&app->player.pauseMutex);
+ pthread_cond_broadcast (&app->player.cond);
+ pthread_mutex_unlock (&app->player.lock);
}
/* rename current station
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment