Permalink
Browse files

Add play and pause commands

Add commands that always play and always pause, in addition to the
current toggle pause command.

Closes #342.
  • Loading branch information...
1 parent efd4f39 commit 847ca4193e3fbc5b27285979888ab364bbf1792e @simpkins simpkins committed with Jan 9, 2013
Showing with 99 additions and 41 deletions.
  1. +5 −1 contrib/config-example
  2. +11 −3 contrib/pianobar.1
  3. +2 −0 src/main.c
  4. +35 −19 src/player.c
  5. +4 −2 src/player.h
  6. +3 −1 src/settings.h
  7. +27 −9 src/ui_act.c
  8. +3 −1 src/ui_act.h
  9. +9 −5 src/ui_dispatch.h
@@ -24,10 +24,14 @@
#act_addshared = j
#act_songmove = m
#act_songnext = n
-#act_songpause = p
+#act_songpause = S
+#act_songpausetoggle = p
+#act_songpausetoggle2 =
+#act_songplay = P
#act_quit = q
#act_stationrename = r
#act_stationchange = s
+#act_stationcreatefromsong = v
#act_songtired = t
#act_upcoming = u
#act_stationselectquickmix = x
View
@@ -113,10 +113,18 @@ Move current song to another station
Skip current song.
.TP
-.B act_songpause = p
+.B act_songpause = S
+Pause playback
+
+.TP
+.B act_songpausetoggle = p
.TQ
-.B act_songpause2 = <Space>
-Pause/Continue
+.B act_songpausetoggle2 = <Space>
+Pause/resume playback
+
+.TP
+.B act_songplay = P
+Resume playback
.TP
.B act_quit = q
View
@@ -269,6 +269,7 @@ static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) {
app->player.audioFormat = app->playlist->audioFormat;
app->player.settings = &app->settings;
pthread_mutex_init (&app->player.pauseMutex, NULL);
+ pthread_cond_init (&app->player.pauseCond, NULL);
/* throw event */
BarUiStartEventCmd (&app->settings, "songstart",
@@ -296,6 +297,7 @@ 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);
/* don't continue playback if thread reports error */
View
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2008-2012
+Copyright (c) 2008-2013
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -38,20 +38,34 @@ THE SOFTWARE.
#define bigToHostEndian32(x) ntohl(x)
-/* wait while locked, but don't slow down main thread by keeping
- * locks too long */
-#define QUIT_PAUSE_CHECK \
- pthread_mutex_lock (&player->pauseMutex); \
- pthread_mutex_unlock (&player->pauseMutex); \
- if (player->doQuit) { \
- /* err => abort playback */ \
- return WAITRESS_CB_RET_ERR; \
- }
-
/* pandora uses float values with 2 digits precision. Scale them by 100 to get
* a "nice" integer */
#define RG_SCALE_FACTOR 100
+/* wait until the pause flag is cleared
+ * @param player structure
+ * @return true if the player should quit
+ */
+static bool BarPlayerCheckPauseQuit (struct audioPlayer *player) {
+ bool quit = false;
+
+ pthread_mutex_lock (&player->pauseMutex);
+ while (true) {
+ if (player->doQuit) {
+ quit = true;
+ break;
+ }
+ if (!player->doPause) {
+ break;
+ }
+ pthread_cond_wait(&player->pauseCond,
+ &player->pauseMutex);
+ }
+ pthread_mutex_unlock (&player->pauseMutex);
+
+ return quit;
+}
+
/* compute replaygain scale factor
* algo taken from here: http://www.dsprelated.com/showmessage/29246/1.php
* mpd does the same
@@ -125,9 +139,8 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size,
const char *data = ptr;
struct audioPlayer *player = stream;
- QUIT_PAUSE_CHECK;
-
- if (!BarPlayerBufferFill (player, data, size)) {
+ if (BarPlayerCheckPauseQuit (player) ||
+ !BarPlayerBufferFill (player, data, size)) {
return WAITRESS_CB_RET_ERR;
}
@@ -141,7 +154,9 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size,
player->sampleSize[player->sampleSizeCurr]) {
/* going through this loop can take up to a few seconds =>
* allow earlier thread abort */
- QUIT_PAUSE_CHECK;
+ if (BarPlayerCheckPauseQuit (player)) {
+ return WAITRESS_CB_RET_ERR;
+ }
/* decode frame */
aacDecoded = NeAACDecDecode(player->aacHandle, &frameInfo,
@@ -335,9 +350,8 @@ static WaitressCbReturn_t BarPlayerMp3Cb (void *ptr, size_t size,
struct audioPlayer *player = stream;
size_t i;
- QUIT_PAUSE_CHECK;
-
- if (!BarPlayerBufferFill (player, data, size)) {
+ if (BarPlayerCheckPauseQuit (player) ||
+ !BarPlayerBufferFill (player, data, size)) {
return WAITRESS_CB_RET_ERR;
}
@@ -417,7 +431,9 @@ static WaitressCbReturn_t BarPlayerMp3Cb (void *ptr, size_t size,
(unsigned long long int) player->samplerate;
}
- QUIT_PAUSE_CHECK;
+ if (BarPlayerCheckPauseQuit (player)) {
+ return WAITRESS_CB_RET_ERR;
+ }
} while (player->mp3Stream.error != MAD_ERROR_BUFLEN);
player->bufferRead += player->mp3Stream.next_frame - player->buffer;
View
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2008-2010
+Copyright (c) 2008-2013
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -49,7 +49,8 @@ THE SOFTWARE.
#define BAR_PLAYER_BUFSIZE (WAITRESS_BUFFER_SIZE*2)
struct audioPlayer {
- char doQuit;
+ bool doQuit; /* protected by pauseMutex */
+ bool doPause; /* protected by pauseMutex */
unsigned char channels;
unsigned char aoError;
@@ -102,6 +103,7 @@ struct audioPlayer {
unsigned char *buffer;
pthread_mutex_t pauseMutex;
+ pthread_cond_t pauseCond;
WaitressHandle_t waith;
};
View
@@ -57,8 +57,10 @@ typedef enum {
BAR_KS_MANAGESTATION = 23,
BAR_KS_PLAYPAUSE2 = 24,
BAR_KS_CREATESTATIONFROMSONG = 25,
+ BAR_KS_PLAY = 26,
+ BAR_KS_PAUSE = 27,
/* insert new shortcuts _before_ this element and increase its value */
- BAR_KS_COUNT = 26,
+ BAR_KS_COUNT = 28,
} BarKeyShortcutId_t;
#define BAR_KS_DISABLED '\x00'
View
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2008-2012
+Copyright (c) 2008-2013
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -49,9 +49,9 @@ THE SOFTWARE.
static inline void BarUiDoSkipSong (struct audioPlayer *player) {
assert (player != NULL);
- player->doQuit = 1;
- /* unlocking an unlocked mutex is forbidden by some implementations */
- pthread_mutex_trylock (&player->pauseMutex);
+ pthread_mutex_lock (&player->pauseMutex);
+ player->doQuit = true;
+ pthread_cond_broadcast (&player->pauseCond);
pthread_mutex_unlock (&player->pauseMutex);
}
@@ -335,13 +335,31 @@ BarUiActCallback(BarUiActSkipSong) {
BarUiDoSkipSong (&app->player);
}
+/* play
+ */
+BarUiActCallback(BarUiActPlay) {
+ pthread_mutex_lock (&app->player.pauseMutex);
+ app->player.doPause = false;
+ pthread_cond_broadcast (&app->player.pauseCond);
+ pthread_mutex_unlock (&app->player.pauseMutex);
+}
+
/* pause
*/
BarUiActCallback(BarUiActPause) {
- /* already locked => unlock/unpause */
- if (pthread_mutex_trylock (&app->player.pauseMutex) == EBUSY) {
- pthread_mutex_unlock (&app->player.pauseMutex);
- }
+ pthread_mutex_lock (&app->player.pauseMutex);
+ app->player.doPause = true;
+ pthread_cond_broadcast (&app->player.pauseCond);
+ pthread_mutex_unlock (&app->player.pauseMutex);
+}
+
+/* toggle pause
+ */
+BarUiActCallback(BarUiActTogglePause) {
+ pthread_mutex_lock (&app->player.pauseMutex);
+ app->player.doPause = !app->player.doPause;
+ pthread_cond_broadcast (&app->player.pauseCond);
+ pthread_mutex_unlock (&app->player.pauseMutex);
}
/* rename current station
@@ -483,7 +501,7 @@ BarUiActCallback(BarUiActSelectQuickMix) {
/* quit
*/
BarUiActCallback(BarUiActQuit) {
- app->doQuit = 1;
+ app->doQuit = true;
BarUiDoSkipSong (&app->player);
}
View
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2008-2011
+Copyright (c) 2008-2013
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -45,7 +45,9 @@ BarUiActCallback(BarUiActStationFromGenre);
BarUiActCallback(BarUiActSongInfo);
BarUiActCallback(BarUiActLoveSong);
BarUiActCallback(BarUiActSkipSong);
+BarUiActCallback(BarUiActPlay);
BarUiActCallback(BarUiActPause);
+BarUiActCallback(BarUiActTogglePause);
BarUiActCallback(BarUiActRenameStation);
BarUiActCallback(BarUiActSelectStation);
BarUiActCallback(BarUiActTempBanSong);
View
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2010-2012
+Copyright (c) 2010-2013
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -71,8 +71,8 @@ static const BarUiDispatchAction_t dispatchActions[BAR_KS_COUNT] = {
"act_addshared"},
{'n', BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActSkipSong, "next song",
"act_songnext"},
- {'p', BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActPause, "pause/continue",
- "act_songpause"},
+ {'p', BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActTogglePause, "pause/resume playback",
+ "act_songpausetoggle"},
{'q', BAR_DC_GLOBAL, BarUiActQuit, "quit", "act_quit"},
{'r', BAR_DC_STATION, BarUiActRenameStation, "rename station",
"act_stationrename"},
@@ -93,10 +93,14 @@ static const BarUiDispatchAction_t dispatchActions[BAR_KS_COUNT] = {
"act_volup"},
{'=', BAR_DC_STATION, BarUiActManageStation, "delete seeds/feedback",
"act_managestation"},
- {' ', BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActPause, NULL,
- "act_songpause2"},
+ {' ', BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActTogglePause, NULL,
+ "act_songpausetoggle2"},
{'v', BAR_DC_SONG, BarUiActCreateStationFromSong,
"create new station from song or artist", "act_stationcreatefromsong"},
+ {'P', BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActPlay, "resume playback",
+ "act_songplay"},
+ {'S', BAR_DC_GLOBAL | BAR_DC_STATION, BarUiActPause, "pause playback",
+ "act_songpause"},
};
#include <piano.h>

0 comments on commit 847ca41

Please sign in to comment.