aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/decode.c243
-rw-r--r--src/decode.h9
-rw-r--r--src/directory.c1
-rw-r--r--src/inputPlugins/aac_plugin.c2
-rw-r--r--src/inputPlugins/audiofile_plugin.c1
-rw-r--r--src/inputPlugins/flac_plugin.c1
-rw-r--r--src/inputPlugins/mod_plugin.c1
-rw-r--r--src/inputPlugins/mp3_plugin.c4
-rw-r--r--src/inputPlugins/mp4_plugin.c2
-rw-r--r--src/inputPlugins/mpc_plugin.c1
-rw-r--r--src/inputPlugins/oggflac_plugin.c1
-rw-r--r--src/inputPlugins/oggvorbis_plugin.c1
-rw-r--r--src/inputPlugins/wavpack_plugin.c1
-rw-r--r--src/main.c2
-rw-r--r--src/outputBuffer.c6
-rw-r--r--src/outputBuffer.h2
-rw-r--r--src/player.c275
-rw-r--r--src/player.h13
-rw-r--r--src/playerData.c2
-rw-r--r--src/sig_handlers.c19
-rw-r--r--src/sig_handlers.h2
21 files changed, 212 insertions, 377 deletions
diff --git a/src/decode.c b/src/decode.c
index c8e9fd9cf..caf29849a 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -30,63 +30,50 @@
#include "utf8.h"
#include "os_compat.h"
-static int decode_pid;
+static pthread_cond_t decoder_wakeup_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t decoder_wakeup_mutex = PTHREAD_MUTEX_INITIALIZER;
-void decodeSigHandler(int sig, siginfo_t * si, void *v)
+/* called inside decoder_task (inputPlugins) */
+void decoder_wakeup_player(void)
{
- if (sig == SIGCHLD) {
- int status;
- if (decode_pid == wait3(&status, WNOHANG, NULL)) {
- /*
- if (WIFSIGNALED(status)) {
- if (WTERMSIG(status) != SIGTERM) {
- ERROR("decode process died from "
- "signal: %i\n", WTERMSIG(status));
- }
- }
- */
- decode_pid = 0;
- getPlayerData()->playerControl.decode_pid = 0;
- }
- } else if (sig == SIGTERM) {
- int pid = decode_pid;
- if (pid > 0) {
- /* DEBUG("player (or child) got SIGTERM\n"); */
- kill(pid, SIGCONT);
- kill(pid, SIGTERM);
- } /* else
- DEBUG("decoder (or child) got SIGTERM\n"); */
- exit(EXIT_SUCCESS);
- }
+ wakeup_player_nb();
+}
+
+void decoder_sleep(void)
+{
+ pthread_cond_wait(&decoder_wakeup_cond, &decoder_wakeup_mutex);
+ wakeup_player_nb();
+}
+
+static void player_wakeup_decoder_nb(void)
+{
+ pthread_cond_signal(&decoder_wakeup_cond);
+}
+
+/* called from player_task */
+static void player_wakeup_decoder(void)
+{
+ pthread_cond_signal(&decoder_wakeup_cond);
+ player_sleep();
}
static void stopDecode(DecoderControl * dc)
{
- if (decode_pid > 0 && (dc->start || dc->state != DECODE_STATE_STOP)) {
+ if (dc->start || dc->state != DECODE_STATE_STOP) {
dc->stop = 1;
- kill(decode_pid, SIGCONT);
- signalNotify(&(getPlayerData()->buffer.notify));
- while (decode_pid > 0 && dc->stop)
- my_usleep(10000);
+ do { player_wakeup_decoder_nb(); } while (dc->stop);
}
}
static void quitDecode(PlayerControl * pc, DecoderControl * dc)
{
- int pid;
-
stopDecode(dc);
pc->state = PLAYER_STATE_STOP;
dc->seek = 0;
pc->play = 0;
pc->stop = 0;
pc->pause = 0;
-
- pid = decode_pid;
- if (pid > 0)
- kill(pid, SIGSTOP);
-
- kill(getppid(), SIGUSR1);
+ wakeup_main_task();
}
static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af)
@@ -111,7 +98,7 @@ static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af)
#define handleDecodeStart() \
if(decodeWaitedOn) { \
- if(dc->state!=DECODE_STATE_START && decode_pid > 0 && \
+ if(dc->state!=DECODE_STATE_START && \
dc->error==DECODE_ERROR_NOERROR) \
{ \
decodeWaitedOn = 0; \
@@ -121,8 +108,9 @@ static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af)
ERROR("problems opening audio device while playing \"%s\"\n", pc->utf8url); \
quitDecode(pc,dc); \
return; \
- } else if (decode_pid > 0) { \
- kill(decode_pid, SIGCONT); }\
+ } else { \
+ player_wakeup_decoder(); \
+ } \
if (pause) { \
dropBufferedAudio(); \
closeAudioDevice(); \
@@ -135,14 +123,14 @@ static int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af)
cb->audioFormat.channels/ \
cb->audioFormat.sampleRate; \
} \
- else if(dc->state!=DECODE_STATE_START || decode_pid <= 0) { \
+ else if(dc->state!=DECODE_STATE_START) { \
pathcpy_trunc(pc->erroredUrl, pc->utf8url); \
pc->error = PLAYER_ERROR_FILE; \
quitDecode(pc,dc); \
return; \
} \
else { \
- my_usleep(10000); \
+ player_sleep(); \
continue; \
} \
}
@@ -153,8 +141,8 @@ static int waitOnDecode(PlayerControl * pc, DecoderControl * dc,
MpdTag *tag = NULL;
pathcpy_trunc(pc->currentUrl, pc->utf8url);
- while (decode_pid > 0 && dc->start)
- my_usleep(10000);
+ while (dc->start)
+ player_wakeup_decoder();
if (dc->start || dc->error != DECODE_ERROR_NOERROR) {
pathcpy_trunc(pc->erroredUrl, pc->utf8url);
@@ -183,52 +171,45 @@ static int decodeSeek(PlayerControl * pc, DecoderControl * dc,
{
int ret = -1;
- if (decode_pid > 0) {
- if (dc->state == DECODE_STATE_STOP || dc->error ||
- strcmp(dc->utf8url, pc->utf8url) != 0) {
- stopDecode(dc);
- *next = -1;
- cb->begin = 0;
- cb->end = 0;
- dc->error = 0;
- dc->start = 1;
- waitOnDecode(pc, dc, cb, decodeWaitedOn);
- }
- if (decode_pid > 0 && dc->state != DECODE_STATE_STOP &&
- dc->seekable) {
- *next = -1;
- dc->seekWhere = pc->seekWhere > pc->totalTime - 0.1 ?
- pc->totalTime - 0.1 : pc->seekWhere;
- dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere;
- dc->seekError = 0;
- dc->seek = 1;
- kill(decode_pid, SIGCONT);
- signalNotify(&(getPlayerData()->buffer.notify));
- while (decode_pid > 0 && dc->seek)
- my_usleep(10000);
- if (!dc->seekError) {
- pc->elapsedTime = dc->seekWhere;
- ret = 0;
- }
+ if (dc->state == DECODE_STATE_STOP || dc->error ||
+ strcmp(dc->utf8url, pc->utf8url) != 0) {
+ stopDecode(dc);
+ *next = -1;
+ cb->begin = 0;
+ cb->end = 0;
+ dc->error = 0;
+ dc->start = 1;
+ waitOnDecode(pc, dc, cb, decodeWaitedOn);
+ }
+ if (dc->state != DECODE_STATE_STOP && dc->seekable) {
+ *next = -1;
+ dc->seekWhere = pc->seekWhere > pc->totalTime - 0.1 ?
+ pc->totalTime - 0.1 : pc->seekWhere;
+ dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere;
+ dc->seekError = 0;
+ dc->seek = 1;
+ do { player_wakeup_decoder(); } while (dc->seek);
+ if (!dc->seekError) {
+ pc->elapsedTime = dc->seekWhere;
+ ret = 0;
}
}
pc->seek = 0;
+ wakeup_main_task();
return ret;
}
#define processDecodeInput() \
- if(pc->cycleLogFiles) { \
- cycle_log_files(); \
- pc->cycleLogFiles = 0; \
- } \
if(pc->lockQueue) { \
pc->queueLockState = PLAYER_QUEUE_LOCKED; \
pc->lockQueue = 0; \
+ wakeup_main_task(); \
} \
if(pc->unlockQueue) { \
pc->queueLockState = PLAYER_QUEUE_UNLOCKED; \
pc->unlockQueue = 0; \
+ wakeup_main_task(); \
} \
if(pc->pause) { \
pause = !pause; \
@@ -236,8 +217,6 @@ static int decodeSeek(PlayerControl * pc, DecoderControl * dc,
pc->state = PLAYER_STATE_PAUSE; \
} else { \
if (openAudioDevice(NULL) >= 0) { \
- if (decode_pid > 0) \
- kill(decode_pid, SIGCONT); \
pc->state = PLAYER_STATE_PLAY; \
} else { \
pathcpy_trunc(pc->erroredUrl, pc->utf8url); \
@@ -247,7 +226,7 @@ static int decodeSeek(PlayerControl * pc, DecoderControl * dc,
} \
} \
pc->pause = 0; \
- kill(getppid(), SIGUSR1); \
+ wakeup_main_task(); \
if (pause == -1) { \
pause = 1; \
} else if (pause) { \
@@ -303,7 +282,7 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
while (!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0
&& !dc->stop) {
/* sleep so we don't consume 100% of the cpu */
- my_usleep(1000);
+ my_usleep(10000);
}
/* for http streams, seekable is determined in bufferInputStream */
@@ -353,8 +332,10 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
if (plugin == NULL) {
/* we already know our mp3Plugin supports streams, no
* need to check for stream{Types,DecodeFunc} */
- if ((plugin = getInputPluginFromName("mp3")))
- ret = plugin->streamDecodeFunc(cb, dc, &inStream);
+ if ((plugin = getInputPluginFromName("mp3"))) {
+ ret = plugin->streamDecodeFunc(cb, dc,
+ &inStream);
+ }
}
} else {
unsigned int next = 0;
@@ -397,51 +378,34 @@ stop_no_close:
dc->stop = 0;
}
-static int decoderInit(PlayerControl * pc, OutputBuffer * cb,
- DecoderControl * dc)
+static void * decoder_task(mpd_unused void *unused)
{
- int pid;
-
- pid = decode_pid;
- if (pid > 0) {
- kill(pid, SIGCONT);
- return 0;
- }
-
- blockSignals();
- getPlayerData()->playerControl.decode_pid = 0;
- decode_pid = fork();
-
- if (decode_pid == 0) {
- /* CHILD */
- unblockSignals();
-
- while (1) {
- if (dc->cycleLogFiles) {
- cycle_log_files();
- dc->cycleLogFiles = 0;
- } else if (dc->start || dc->seek)
- decodeStart(pc, cb, dc);
- else if (dc->stop) {
- dc->state = DECODE_STATE_STOP;
- dc->stop = 0;
- } else
- my_usleep(10000);
+ OutputBuffer *cb = &(getPlayerData()->buffer);
+ PlayerControl *pc = &(getPlayerData()->playerControl);
+ DecoderControl *dc = &(getPlayerData()->decoderControl);
+
+ while (1) {
+ if (dc->start || dc->seek) {
+ decodeStart(pc, cb, dc);
+ } else if (dc->stop) {
+ dc->state = DECODE_STATE_STOP;
+ dc->stop = 0;
+ decoder_wakeup_player();
+ } else {
+ decoder_sleep();
}
-
- exit(EXIT_SUCCESS);
- /* END OF CHILD */
- } else if (decode_pid < 0) {
- unblockSignals();
- pathcpy_trunc(pc->erroredUrl, pc->utf8url);
- pc->error = PLAYER_ERROR_SYSTEM;
- return -1;
}
- DEBUG("decoder PID: %d\n", decode_pid);
- getPlayerData()->playerControl.decode_pid = decode_pid;
- unblockSignals();
+}
- return 0;
+void decoderInit(void)
+{
+ pthread_attr_t attr;
+ pthread_t decoder_thread;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&decoder_thread, &attr, decoder_task, NULL))
+ FATAL("Failed to spawn decoder task: %s\n", strerror(errno));
}
static void handleMetadata(OutputBuffer * cb, PlayerControl * pc, int *previous,
@@ -519,14 +483,13 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
pc->elapsedTime = 0;
pc->state = PLAYER_STATE_PLAY;
pc->play = 0;
- kill(getppid(), SIGUSR1);
+ wakeup_main_task();
- while (decode_pid > 0 &&
- (unsigned)(cb->end - cb->begin) < bbp &&
+ while ((unsigned)cb->end - cb->begin < bbp &&
cb->end != buffered_chunks - 1 &&
dc->state != DECODE_STATE_STOP) {
processDecodeInput();
- my_usleep(1000);
+ player_sleep();
}
while (!quit) {
@@ -540,7 +503,8 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
next = cb->end;
dc->start = 1;
pc->queueState = PLAYER_QUEUE_DECODE;
- kill(getppid(), SIGUSR1);
+ wakeup_main_task();
+ player_wakeup_decoder_nb();
}
if (next >= 0 && doCrossFade == 0 && !dc->start &&
dc->state != DECODE_STATE_START) {
@@ -563,11 +527,9 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
race conditions and weirdness */
end = cb->end;
- if (pause) {
- if (decode_pid)
- kill(decode_pid, SIGSTOP);
- kill(getpid(), SIGSTOP);
- } else if (cb->begin != end && cb->begin != next) {
+ if (pause)
+ player_sleep();
+ else if (cb->begin != end && cb->begin != next) {
if (doCrossFade == 1 && next >= 0 &&
((next > cb->begin &&
(fadePosition = next - cb->begin)
@@ -625,7 +587,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
cb->begin = 0;
} else
cb->begin++;
- signalNotify(&cb->notify);
+ player_wakeup_decoder_nb();
} else if (cb->begin != end && cb->begin == next) {
if (doCrossFade == 1 && nextChunk >= 0) {
nextChunk = cb->begin + crossFadeChunks;
@@ -646,7 +608,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
while (pc->queueState == PLAYER_QUEUE_DECODE ||
pc->queueLockState == PLAYER_QUEUE_LOCKED) {
processDecodeInput();
- my_usleep(10000);
+ player_sleep();
}
if (pc->queueState != PLAYER_QUEUE_PLAY) {
quit = 1;
@@ -661,10 +623,9 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
doCrossFade = 0;
crossFadeChunks = 0;
pc->queueState = PLAYER_QUEUE_EMPTY;
- kill(getppid(), SIGUSR1);
+ wakeup_main_task();
}
- } else if (decode_pid <= 0 ||
- (dc->state == DECODE_STATE_STOP && !dc->start)) {
+ } else if (dc->state == DECODE_STATE_STOP && !dc->start) {
quit = 1;
break;
} else {
@@ -699,9 +660,7 @@ void decode(void)
dc->seek = 0;
dc->stop = 0;
dc->start = 1;
-
- if (decoderInit(pc, cb, dc) < 0)
- return;
+ do { player_wakeup_decoder(); } while (dc->start);
decodeParent(pc, dc, cb);
}
diff --git a/src/decode.h b/src/decode.h
index 14dc0e8ee..1d90dced4 100644
--- a/src/decode.h
+++ b/src/decode.h
@@ -47,15 +47,18 @@ typedef struct _DecoderControl {
volatile mpd_sint8 seek;
volatile mpd_sint8 seekError;
volatile mpd_sint8 seekable;
- volatile mpd_sint8 cycleLogFiles;
volatile double seekWhere;
AudioFormat audioFormat;
char utf8url[MPD_PATH_MAX];
volatile float totalTime;
} DecoderControl;
-void decodeSigHandler(int sig, siginfo_t * siginfo, void *v);
-
void decode(void);
+void decoder_wakeup_player(void);
+
+void decoder_sleep(void);
+
+void decoderInit(void);
+
#endif
diff --git a/src/directory.c b/src/directory.c
index 3bb18bf59..fa517cba6 100644
--- a/src/directory.c
+++ b/src/directory.c
@@ -175,7 +175,6 @@ int updateInit(int fd, List * pathList)
if (directory_updatePid == 0) {
/* child */
int dbUpdated = 0;
- clearPlayerPid();
unblockSignals();
diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c
index 0091b396e..de442acf7 100644
--- a/src/inputPlugins/aac_plugin.c
+++ b/src/inputPlugins/aac_plugin.c
@@ -400,6 +400,7 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
if (dc->seek) {
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
} else if (dc->stop) {
eof = 1;
break;
@@ -418,6 +419,7 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
if (dc->seek) {
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
}
return 0;
diff --git a/src/inputPlugins/audiofile_plugin.c b/src/inputPlugins/audiofile_plugin.c
index 1c94a8589..33ea54df9 100644
--- a/src/inputPlugins/audiofile_plugin.c
+++ b/src/inputPlugins/audiofile_plugin.c
@@ -102,6 +102,7 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
dc->audioFormat.sampleRate;
afSeekFrame(af_fp, AF_DEFAULT_TRACK, current);
dc->seek = 0;
+ decoder_wakeup_player();
}
ret =
diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c
index 7dab78922..23d61e805 100644
--- a/src/inputPlugins/flac_plugin.c
+++ b/src/inputPlugins/flac_plugin.c
@@ -394,6 +394,7 @@ static int flac_decode_internal(OutputBuffer * cb, DecoderControl * dc,
} else
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
}
}
if (!dc->stop) {
diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c
index 22c364d70..25cedf04b 100644
--- a/src/inputPlugins/mod_plugin.c
+++ b/src/inputPlugins/mod_plugin.c
@@ -194,6 +194,7 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
if (dc->seek) {
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
}
if (dc->stop)
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index b008a1dd9..76d226b00 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -857,6 +857,7 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
clearOutputBuffer(cb);
data->muteFrame = 0;
dc->seek = 0;
+ decoder_wakeup_player();
}
break;
default:
@@ -972,10 +973,12 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
dc->seekError = 1;
data->muteFrame = 0;
dc->seek = 0;
+ decoder_wakeup_player();
}
} else if (dc->seek && !data->inStream->seekable) {
dc->seek = 0;
dc->seekError = 1;
+ decoder_wakeup_player();
}
}
@@ -1082,6 +1085,7 @@ static int mp3_decode(OutputBuffer * cb, DecoderControl * dc,
if (dc->seek && data.muteFrame == MUTEFRAME_SEEK) {
clearOutputBuffer(cb);
dc->seek = 0;
+ decoder_wakeup_player();
}
flushOutputBuffer(cb);
diff --git a/src/inputPlugins/mp4_plugin.c b/src/inputPlugins/mp4_plugin.c
index 2e3dd18ae..0484e9993 100644
--- a/src/inputPlugins/mp4_plugin.c
+++ b/src/inputPlugins/mp4_plugin.c
@@ -221,6 +221,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc,
clearOutputBuffer(cb);
seeking = 0;
dc->seek = 0;
+ decoder_wakeup_player();
}
if (seeking)
@@ -296,6 +297,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc,
if (dc->seek && seeking) {
clearOutputBuffer(cb);
dc->seek = 0;
+ decoder_wakeup_player();
}
flushOutputBuffer(cb);
diff --git a/src/inputPlugins/mpc_plugin.c b/src/inputPlugins/mpc_plugin.c
index 49142aaed..9b6e862ff 100644
--- a/src/inputPlugins/mpc_plugin.c
+++ b/src/inputPlugins/mpc_plugin.c
@@ -194,6 +194,7 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
} else
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
}
vbrUpdateAcc = 0;
diff --git a/src/inputPlugins/oggflac_plugin.c b/src/inputPlugins/oggflac_plugin.c
index 4e56a554a..6638362b6 100644
--- a/src/inputPlugins/oggflac_plugin.c
+++ b/src/inputPlugins/oggflac_plugin.c
@@ -370,6 +370,7 @@ static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
} else
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
}
}
diff --git a/src/inputPlugins/oggvorbis_plugin.c b/src/inputPlugins/oggvorbis_plugin.c
index 539dc55b7..8eb075336 100644
--- a/src/inputPlugins/oggvorbis_plugin.c
+++ b/src/inputPlugins/oggvorbis_plugin.c
@@ -285,6 +285,7 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
} else
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
}
ret = ov_read(&vf, chunk + chunkpos,
OGG_CHUNK_SIZE - chunkpos,
diff --git a/src/inputPlugins/wavpack_plugin.c b/src/inputPlugins/wavpack_plugin.c
index e25b5099c..37dc4f3d0 100644
--- a/src/inputPlugins/wavpack_plugin.c
+++ b/src/inputPlugins/wavpack_plugin.c
@@ -192,6 +192,7 @@ static void wavpack_decode(OutputBuffer *cb, DecoderControl *dc,
}
dc->seek = 0;
+ decoder_wakeup_player();
}
if (dc->stop)
diff --git a/src/main.c b/src/main.c
index 671363b97..428ef2a91 100644
--- a/src/main.c
+++ b/src/main.c
@@ -429,6 +429,8 @@ int main(int argc, char *argv[])
initZeroconf();
openVolumeDevice();
+ decoderInit();
+ playerInit();
read_state_file();
while (COMMAND_RETURN_KILL != doIOForInterfaces() &&
diff --git a/src/outputBuffer.c b/src/outputBuffer.c
index dab233668..7a47a44e7 100644
--- a/src/outputBuffer.c
+++ b/src/outputBuffer.c
@@ -45,8 +45,6 @@ void initOutputBuffer(OutputBuffer * cb, char *chunks)
(float *)(((char *)cb->metaChunk) +
buffered_chunks * sizeof(mpd_sint8));
cb->acceptMetadata = 0;
-
- initNotify(&cb->notify);
}
void clearAllMetaChunkSets(OutputBuffer * cb)
@@ -129,11 +127,12 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
} else {
dc->seekError = 1;
dc->seek = 0;
+ decoder_wakeup_player();
}
}
if (!inStream ||
bufferInputStream(inStream) <= 0) {
- waitNotify(&cb->notify);
+ decoder_sleep();
}
}
if (dc->stop)
@@ -163,6 +162,7 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
flushOutputBuffer(cb);
}
}
+ decoder_wakeup_player();
return 0;
}
diff --git a/src/outputBuffer.h b/src/outputBuffer.h
index ab4ccc893..563c1904b 100644
--- a/src/outputBuffer.h
+++ b/src/outputBuffer.h
@@ -26,7 +26,6 @@
#include "inputStream.h"
#include "metadataChunk.h"
#include "replayGain.h"
-#include "notify.h"
#define OUTPUT_BUFFER_DC_STOP -1
#define OUTPUT_BUFFER_DC_SEEK -2
@@ -46,7 +45,6 @@ typedef struct _OutputBuffer {
mpd_sint8 metaChunkSet[BUFFERED_METACHUNKS];
mpd_sint8 *volatile metaChunk;
volatile mpd_sint8 acceptMetadata;
- Notify notify;
} OutputBuffer;
void initOutputBuffer(OutputBuffer * cb, char *chunks);
diff --git a/src/player.c b/src/player.c
index 3312a23e1..4071b5a57 100644
--- a/src/player.c
+++ b/src/player.c
@@ -33,167 +33,95 @@
#include "sig_handlers.h"
#include "os_compat.h"
+static pthread_cond_t player_wakeup = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t player_wakeup_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_cond_t main_wakeup = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t main_wakeup_mutex = PTHREAD_MUTEX_INITIALIZER;
+
static void playerCloseAudio(void);
-volatile int player_pid = 0;
+void wakeup_player_nb(void)
+{
+ pthread_cond_signal(&player_wakeup);
+}
-void clearPlayerPid(void)
+static void wakeup_player(void)
{
- player_pid = 0;
+ pthread_cond_signal(&player_wakeup);
+ pthread_cond_wait(&main_wakeup, &main_wakeup_mutex);
}
-static void resetPlayerMetadata(void)
+void wakeup_main_task(void)
{
- PlayerControl *pc = &(getPlayerData()->playerControl);
+ pthread_cond_signal(&main_wakeup);
+}
- if (pc->metadataState == PLAYER_METADATA_STATE_READ) {
- pc->metadataState = PLAYER_METADATA_STATE_WRITE;
- }
+void player_sleep(void)
+{
+ pthread_cond_wait(&player_wakeup, &player_wakeup_mutex);
}
-static void resetPlayer(void)
-{
- int pid;
-
- clearPlayerPid();
- getPlayerData()->playerControl.stop = 0;
- getPlayerData()->playerControl.play = 0;
- getPlayerData()->playerControl.pause = 0;
- getPlayerData()->playerControl.lockQueue = 0;
- getPlayerData()->playerControl.unlockQueue = 0;
- getPlayerData()->playerControl.state = PLAYER_STATE_STOP;
- getPlayerData()->playerControl.queueState = PLAYER_QUEUE_UNLOCKED;
- getPlayerData()->playerControl.seek = 0;
- getPlayerData()->playerControl.metadataState =
- PLAYER_METADATA_STATE_WRITE;
- pid = getPlayerData()->playerControl.decode_pid;
- if (pid > 0)
- kill(pid, SIGTERM);
- getPlayerData()->playerControl.decode_pid = 0;
-}
-
-void player_sigChldHandler(int pid, int status)
-{
- if (player_pid == pid)
- {
- /*
- DEBUG("SIGCHLD caused by player process\n");
- if (WIFSIGNALED(status) &&
- WTERMSIG(status) != SIGTERM &&
- WTERMSIG(status) != SIGINT)
- {
- ERROR("player process died from signal: %i\n",
- WTERMSIG(status));
- }
- */
- resetPlayer();
- }
- else if (pid == getPlayerData()->playerControl.decode_pid &&
- player_pid <= 0)
- {
- /*
- if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM)
- {
- ERROR("(caught by master parent) "
- "decode process died from a "
- "non-TERM signal: %i\n", WTERMSIG(status));
+static void * player_task(mpd_unused void *unused)
+{
+ PlayerControl *pc = &(getPlayerData()->playerControl);
+
+ while (1) {
+ if (pc->play) {
+ decode();
+ continue; /* decode() calls wakeup_main_task */
+ } else if (pc->stop) {
+ pc->stop = 0;
+ } else if (pc->seek) {
+ pc->seek = 0;
+ } else if (pc->pause) {
+ pc->pause = 0;
+ } else if (pc->closeAudio) {
+ closeAudioDevice();
+ pc->closeAudio = 0;
+ } else if (pc->lockQueue) {
+ pc->queueLockState = PLAYER_QUEUE_LOCKED;
+ pc->lockQueue = 0;
+ } else if (pc->unlockQueue) {
+ pc->queueLockState = PLAYER_QUEUE_UNLOCKED;
+ pc->unlockQueue = 0;
+ } else {
+ player_sleep();
+ continue;
}
- */
- getPlayerData()->playerControl.decode_pid = 0;
+ /* we did something, tell the main task about it */
+ wakeup_main_task();
}
+ return NULL;
}
-static int playerInit(void)
+static void resetPlayerMetadata(void)
{
PlayerControl *pc = &(getPlayerData()->playerControl);
- int pid;
-
- pid = player_pid;
- if (pid > 0) {
- kill(pid, SIGCONT);
- pc->wait = 0;
- return 0;
- }
- blockSignals();
- player_pid = fork();
- if (player_pid==0)
- {
- clock_t start = clock();
-
- unblockSignals();
-
- setSigHandlersForDecoder();
-
- closeAllListenSockets();
- freeAllInterfaces();
- finishPlaylist();
- closeMp3Directory();
- finishPermissions();
- finishCommands();
- finishVolume();
-
- DEBUG("took %f to init player\n",
- (float)(clock()-start)/CLOCKS_PER_SEC);
-
- while (1) {
- if (pc->play)
- decode();
- else if (pc->stop)
- pc->stop = 0;
- else if (pc->seek)
- pc->seek = 0;
- else if (pc->pause)
- pc->pause = 0;
- else if (pc->closeAudio) {
- closeAudioDevice();
- pc->closeAudio = 0;
- kill(getppid(), SIGUSR1);
- } else if (pc->lockQueue) {
- pc->queueLockState = PLAYER_QUEUE_LOCKED;
- pc->lockQueue = 0;
- } else if (pc->unlockQueue) {
- pc->queueLockState = PLAYER_QUEUE_UNLOCKED;
- pc->unlockQueue = 0;
- } else if (pc->cycleLogFiles) {
- cycle_log_files();
- pc->cycleLogFiles = 0;
- } else
- my_usleep(10000);
- }
- }
- else if (player_pid < 0)
- {
- unblockSignals();
- ERROR("player Problems fork()'ing\n");
- player_pid = 0;
- return -1;
+ if (pc->metadataState == PLAYER_METADATA_STATE_READ) {
+ pc->metadataState = PLAYER_METADATA_STATE_WRITE;
}
+}
- unblockSignals();
+void playerInit(void)
+{
+ pthread_attr_t attr;
+ pthread_t player_thread;
- return 0;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&player_thread, &attr, player_task, NULL))
+ FATAL("Failed to spawn player task: %s\n", strerror(errno));
}
int playerWait(int fd)
{
- PlayerControl *pc = &(getPlayerData()->playerControl);
- int pid;
-
- if (pc->wait)
- return 0;
-
if (playerStop(fd) < 0)
return -1;
playerCloseAudio();
- pid = player_pid;
- if (pid > 0) {
- pc->wait = 1;
- kill(pid, SIGSTOP);
- }
-
return 0;
}
@@ -215,17 +143,10 @@ int playerPlay(int fd, Song * song)
set_current_song(song);
- pc->play = 1;
- if (playerInit() < 0) {
- pc->play = 0;
- return -1;
- }
-
resetPlayerMetadata();
- if (player_pid > 0 && pc->state == PLAYER_STATE_PAUSE)
- kill(player_pid, SIGCONT);
- while (player_pid > 0 && pc->play)
- my_usleep(1000);
+ pc->play = 1;
+ /* FIXME: _nb() variant is probably wrong here, and everywhere... */
+ do { wakeup_player_nb(); } while (pc->play);
return 0;
}
@@ -234,12 +155,9 @@ int playerStop(int fd)
{
PlayerControl *pc = &(getPlayerData()->playerControl);
- if (player_pid > 0 && pc->state != PLAYER_STATE_STOP) {
+ if (pc->state != PLAYER_STATE_STOP) {
pc->stop = 1;
- if (pc->state == PLAYER_STATE_PAUSE)
- kill(player_pid, SIGCONT);
- while (player_pid > 0 && pc->stop)
- my_usleep(1000);
+ do { wakeup_player(); } while (pc->stop);
}
pc->queueState = PLAYER_QUEUE_BLANK;
@@ -248,27 +166,18 @@ int playerStop(int fd)
return 0;
}
-void playerKill(void)
+void playerKill(void) /* deprecated */
{
- int pid;
-
- pid = player_pid;
- if (pid > 0) {
- kill(pid, SIGCONT);
- kill(pid, SIGTERM);
- }
+ playerPause(STDERR_FILENO);
}
int playerPause(int fd)
{
PlayerControl *pc = &(getPlayerData()->playerControl);
- if (player_pid > 0 && pc->state != PLAYER_STATE_STOP) {
+ if (pc->state != PLAYER_STATE_STOP) {
pc->pause = 1;
- if (player_pid > 0 && pc->state == PLAYER_STATE_PAUSE)
- kill(player_pid, SIGCONT);
- while (player_pid > 0 && pc->pause)
- my_usleep(1000);
+ do { wakeup_player(); } while (pc->pause);
}
return 0;
@@ -278,9 +187,6 @@ int playerSetPause(int fd, int pause_flag)
{
PlayerControl *pc = &(getPlayerData()->playerControl);
- if (player_pid <= 0)
- return 0;
-
switch (pc->state) {
case PLAYER_STATE_PLAY:
if (pause_flag)
@@ -370,15 +276,10 @@ static void playerCloseAudio(void)
{
PlayerControl *pc = &(getPlayerData()->playerControl);
- if (player_pid > 0) {
- if (playerStop(STDERR_FILENO) < 0)
- return;
- pc->closeAudio = 1;
- if (pc->state == PLAYER_STATE_PAUSE)
- kill(player_pid, SIGCONT);
- while (player_pid > 0 && pc->closeAudio)
- my_usleep(1000);
- }
+ if (playerStop(STDERR_FILENO) < 0)
+ return;
+ pc->closeAudio = 1;
+ do { wakeup_player(); } while (pc->closeAudio);
}
int queueSong(Song * song)
@@ -412,12 +313,9 @@ void playerQueueLock(void)
{
PlayerControl *pc = &(getPlayerData()->playerControl);
- if (player_pid > 0 && pc->queueLockState == PLAYER_QUEUE_UNLOCKED) {
- if (pc->state == PLAYER_STATE_PAUSE)
- kill(player_pid, SIGCONT);
+ if (pc->queueLockState == PLAYER_QUEUE_UNLOCKED) {
pc->lockQueue = 1;
- while (player_pid > 0 && pc->lockQueue)
- my_usleep(1000);
+ do { wakeup_player(); } while (pc->lockQueue);
}
}
@@ -425,12 +323,9 @@ void playerQueueUnlock(void)
{
PlayerControl *pc = &(getPlayerData()->playerControl);
- if (player_pid > 0 && pc->queueLockState == PLAYER_QUEUE_LOCKED) {
- if (pc->state == PLAYER_STATE_PAUSE)
- kill(player_pid, SIGCONT);
+ if (pc->queueLockState == PLAYER_QUEUE_LOCKED) {
pc->unlockQueue = 1;
- while (player_pid > 0 && pc->unlockQueue)
- my_usleep(1000);
+ do { wakeup_player(); } while (pc->unlockQueue);
}
}
@@ -454,10 +349,8 @@ int playerSeek(int fd, Song * song, float seek_time)
resetPlayerMetadata();
pc->seekWhere = seek_time;
pc->seek = 1;
- if (player_pid > 0 && pc->state == PLAYER_STATE_PAUSE)
- kill(player_pid, SIGCONT);
- while (player_pid > 0 && pc->seek)
- my_usleep(1000);
+ /* FIXME: _nb() is probably wrong here, too */
+ do { wakeup_player_nb(); } while (pc->seek);
}
return 0;
@@ -519,15 +412,6 @@ int getPlayerChannels(void)
return pc->channels;
}
-void playerCycleLogFiles(void)
-{
- PlayerControl *pc = &(getPlayerData()->playerControl);
- DecoderControl *dc = &(getPlayerData()->decoderControl);
-
- pc->cycleLogFiles = 1;
- dc->cycleLogFiles = 1;
-}
-
/* this actually creates a dupe of the current metadata */
Song *playerCurrentDecodeSong(void)
{
@@ -537,7 +421,6 @@ Song *playerCurrentDecodeSong(void)
PlayerControl *pc = &(getPlayerData()->playerControl);
if (pc->metadataState == PLAYER_METADATA_STATE_READ) {
- DEBUG("playerCurrentDecodeSong: caught new metadata!\n");
if (prev)
free(prev);
prev = xmalloc(sizeof(MetadataChunk));
diff --git a/src/player.h b/src/player.h
index 48a87227f..71b0e9094 100644
--- a/src/player.h
+++ b/src/player.h
@@ -55,7 +55,6 @@
#define PLAYER_METADATA_STATE_WRITE 2
typedef struct _PlayerControl {
- volatile mpd_sint8 wait;
volatile mpd_sint8 stop;
volatile mpd_sint8 play;
volatile mpd_sint8 pause;
@@ -81,16 +80,16 @@ typedef struct _PlayerControl {
volatile float crossFade;
volatile mpd_uint16 softwareVolume;
volatile double totalPlayTime;
- volatile int decode_pid;
- volatile mpd_sint8 cycleLogFiles;
volatile mpd_sint8 metadataState;
MetadataChunk metadataChunk;
MetadataChunk fileMetadataChunk;
} PlayerControl;
-void clearPlayerPid(void);
+void wakeup_main_task(void);
-void player_sigChldHandler(int pid, int status);
+void wakeup_player_nb(void);
+
+void player_sleep(void);
int playerPlay(int fd, Song * song);
@@ -144,8 +143,8 @@ int getPlayerBits(void);
int getPlayerChannels(void);
-void playerCycleLogFiles(void);
-
Song *playerCurrentDecodeSong(void);
+void playerInit(void);
+
#endif
diff --git a/src/playerData.c b/src/playerData.c
index 3c92fde52..31a3bbd94 100644
--- a/src/playerData.c
+++ b/src/playerData.c
@@ -97,7 +97,6 @@ void initPlayerData(void)
initOutputBuffer(&(playerData_pd->buffer),
((char *)playerData_pd) + sizeof(PlayerData));
- playerData_pd->playerControl.wait = 0;
playerData_pd->playerControl.stop = 0;
playerData_pd->playerControl.pause = 0;
playerData_pd->playerControl.play = 0;
@@ -115,7 +114,6 @@ void initPlayerData(void)
playerData_pd->playerControl.crossFade = crossfade;
playerData_pd->playerControl.softwareVolume = 1000;
playerData_pd->playerControl.totalPlayTime = 0;
- playerData_pd->playerControl.decode_pid = 0;
playerData_pd->playerControl.metadataState =
PLAYER_METADATA_STATE_WRITE;
diff --git a/src/sig_handlers.c b/src/sig_handlers.c
index 111ce9775..af664f182 100644
--- a/src/sig_handlers.c
+++ b/src/sig_handlers.c
@@ -45,7 +45,6 @@ int handlePendingSignals(void)
}
if (cycle_log_files() < 0)
return COMMAND_RETURN_KILL;
- playerCycleLogFiles();
}
return 0;
@@ -63,7 +62,6 @@ static void chldSigHandler(int sig)
else
break;
}
- player_sigChldHandler(pid, status);
directory_sigChldHandler(pid, status);
}
}
@@ -92,23 +90,6 @@ void finishSigHandlers(void)
signal_unhandle(SIGHUP);
}
-void setSigHandlersForDecoder(void)
-{
- struct sigaction sa;
-
- finishSigHandlers();
-
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = SIG_IGN;
- while (sigaction(SIGHUP, &sa, NULL) < 0 && errno == EINTR) ;
- while (sigaction(SIGINT, &sa, NULL) < 0 && errno == EINTR) ;
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = decodeSigHandler;
- while (sigaction(SIGCHLD, &sa, NULL) < 0 && errno == EINTR) ;
- while (sigaction(SIGTERM, &sa, NULL) < 0 && errno == EINTR) ;
-}
-
void ignoreSignals(void)
{
struct sigaction sa;
diff --git a/src/sig_handlers.h b/src/sig_handlers.h
index 15fa181ee..a9438cac1 100644
--- a/src/sig_handlers.h
+++ b/src/sig_handlers.h
@@ -27,8 +27,6 @@ void initSigHandlers(void);
void finishSigHandlers(void);
-void setSigHandlersForDecoder(void);
-
void ignoreSignals(void);
void blockSignals(void);