From 8c06a59a34b5d9bba277a50198fe2dd50d832da3 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sat, 5 Mar 2016 13:13:47 +0100 Subject: Quit upon reception of two SIGINT If player is running one SIGINT restarts current track request, two SIGINT (or more) quit pianobar. Idle main loop (i.e. no player or submenu) quits on SIGINT. Fixes issue #564. --- src/main.c | 15 ++++++++++----- src/main.h | 2 +- src/player.c | 13 +++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main.c b/src/main.c index 5d0e91b..c0388e2 100644 --- a/src/main.c +++ b/src/main.c @@ -259,7 +259,7 @@ static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) { pthread_mutex_init (&app->player.pauseMutex, NULL); pthread_cond_init (&app->player.pauseCond, NULL); - assert (interrupted == NULL); + assert (interrupted == &app->doQuit); interrupted = &app->player.interrupted; /* throw event */ @@ -306,7 +306,7 @@ static void BarMainPlayerCleanup (BarApp_t *app, pthread_t *playerThread) { memset (&app->player, 0, sizeof (app->player)); assert (interrupted == &app->player.interrupted); - interrupted = NULL; + interrupted = &app->doQuit; } /* print song duration @@ -355,12 +355,16 @@ static void BarMainLoop (BarApp_t *app) { while (!app->doQuit) { /* song finished playing, clean up things/scrobble song */ if (app->player.mode == PLAYER_FINISHED) { + if (app->player.interrupted != 0) { + app->doQuit = 1; + } BarMainPlayerCleanup (app, &playerThread); } /* check whether player finished playing and start playing new * song */ - if (app->player.mode == PLAYER_DEAD && app->curStation != NULL) { + if (app->player.mode == PLAYER_DEAD && app->curStation != NULL && + !app->doQuit) { /* what's next? */ if (app->playlist != NULL) { PianoSong_t *histsong = app->playlist; @@ -394,7 +398,7 @@ sig_atomic_t *interrupted = NULL; static void intHandler (int signal) { if (interrupted != NULL) { - *interrupted = 1; + *interrupted += 1; } } @@ -414,10 +418,11 @@ int main (int argc, char **argv) { /* save terminal attributes, before disabling echoing */ BarTermInit (); - BarMainSetupSigaction (); /* signals */ signal (SIGPIPE, SIG_IGN); + BarMainSetupSigaction (); + interrupted = &app.doQuit; /* init some things */ gcry_check_version (NULL); diff --git a/src/main.h b/src/main.h index d1e71ec..0dd2647 100644 --- a/src/main.h +++ b/src/main.h @@ -40,7 +40,7 @@ typedef struct { PianoSong_t *playlist; PianoSong_t *songHistory; PianoStation_t *curStation; - char doQuit; + sig_atomic_t doQuit; BarReadlineFds_t input; unsigned int playerErrors; } BarApp_t; diff --git a/src/player.c b/src/player.c index cd666fc..04b9d4a 100644 --- a/src/player.c +++ b/src/player.c @@ -114,12 +114,16 @@ void BarPlayerSetVolume (player_t * const player) { printError (player->settings, msg, ret); \ return false; -/* interrupt callback for blocking setup functions from openStream +/* ffmpeg callback for blocking functions, returns 1 to abort function */ static int intCb (void * const data) { player_t * const player = data; assert (player != NULL); - if (player->interrupted != 0) { + if (player->interrupted > 1) { + /* got a sigint multiple times, quit pianobar (handled by main.c). */ + player->doQuit = true; + return 1; + } else if (player->interrupted != 0) { /* the request is retried with the same player context */ player->interrupted = 0; return 1; @@ -390,7 +394,7 @@ void *BarPlayerThread (void *data) { assert (data != NULL); player_t * const player = data; - intptr_t pret = PLAYER_RET_OK; + uintptr_t pret = PLAYER_RET_OK; bool retry; do { @@ -399,7 +403,8 @@ void *BarPlayerThread (void *data) { if (openFilter (player) && openDevice (player)) { player->mode = PLAYER_PLAYING; BarPlayerSetVolume (player); - retry = play (player) == AVERROR_INVALIDDATA; + retry = play (player) == AVERROR_INVALIDDATA && + !player->interrupted; } else { /* filter missing or audio device busy */ pret = PLAYER_RET_HARDFAIL; -- cgit v1.2.3