Get rid of PlayerControl inside the PlayerData struct

It actually increases our image size a small bit and may even
hurt performance a very small bit, but makes the code less
verbose and easier to manage.

I don't see a reason for mpd to ever support playing multiple
files at the same time (users can run multiple instances of mpd
if they really want to play Zaireeka, but that's such an edge
case it's not worth ever supporting in our code).

git-svn-id: https://svn.musicpd.org/mpd/trunk@7352 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
Eric Wong 2008-04-13 01:15:50 +00:00
parent ae1335753a
commit 98acfa8ac5
7 changed files with 184 additions and 246 deletions

View File

@ -29,15 +29,13 @@
/* called inside decoder_task (inputPlugins) */ /* called inside decoder_task (inputPlugins) */
void decoder_wakeup_player(void) void decoder_wakeup_player(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); wakeup_player_nb();
wakeup_player_nb(pc);
} }
void decoder_sleep(DecoderControl * dc) void decoder_sleep(DecoderControl * dc)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl);
notifyWait(&dc->notify); notifyWait(&dc->notify);
wakeup_player_nb(pc); wakeup_player_nb();
} }
static void player_wakeup_decoder_nb(DecoderControl * dc) static void player_wakeup_decoder_nb(DecoderControl * dc)
@ -46,10 +44,10 @@ static void player_wakeup_decoder_nb(DecoderControl * dc)
} }
/* called from player_task */ /* called from player_task */
static void player_wakeup_decoder(PlayerControl * pc, DecoderControl * dc) static void player_wakeup_decoder(DecoderControl * dc)
{ {
notifySignal(&dc->notify); notifySignal(&dc->notify);
player_sleep(pc); player_sleep();
} }
static void stopDecode(DecoderControl * dc) static void stopDecode(DecoderControl * dc)
@ -60,33 +58,32 @@ static void stopDecode(DecoderControl * dc)
} }
} }
static void quitDecode(PlayerControl * pc, DecoderControl * dc) static void quitDecode(DecoderControl * dc)
{ {
stopDecode(dc); stopDecode(dc);
pc->state = PLAYER_STATE_STOP; pc.state = PLAYER_STATE_STOP;
dc->seek = 0; dc->seek = 0;
pc->play = 0; pc.play = 0;
pc->stop = 0; pc.stop = 0;
pc->pause = 0; pc.pause = 0;
wakeup_main_task(); wakeup_main_task();
} }
static unsigned calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af, static unsigned calculateCrossFadeChunks(AudioFormat * af, float totalTime)
float totalTime)
{ {
unsigned int buffered_chunks, chunks; unsigned int buffered_chunks, chunks;
if (pc->crossFade == 0 || pc->crossFade >= totalTime || if (pc.crossFade == 0 || pc.crossFade >= totalTime ||
!isCurrentAudioFormat(af)) !isCurrentAudioFormat(af))
return 0; return 0;
assert(pc->crossFade > 0); assert(pc.crossFade > 0);
assert(af->bits > 0); assert(af->bits > 0);
assert(af->channels > 0); assert(af->channels > 0);
assert(af->sampleRate > 0); assert(af->sampleRate > 0);
chunks = (af->sampleRate * af->bits * af->channels / 8.0 / CHUNK_SIZE); chunks = (af->sampleRate * af->bits * af->channels / 8.0 / CHUNK_SIZE);
chunks = (chunks * pc->crossFade + 0.5); chunks = (chunks * pc.crossFade + 0.5);
buffered_chunks = getPlayerData()->buffer.size; buffered_chunks = getPlayerData()->buffer.size;
assert(buffered_chunks >= buffered_before_play); assert(buffered_chunks >= buffered_before_play);
@ -96,98 +93,98 @@ static unsigned calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af,
return chunks; return chunks;
} }
static int waitOnDecode(PlayerControl * pc, DecoderControl * dc, static int waitOnDecode(DecoderControl * dc,
OutputBuffer * cb, int *decodeWaitedOn) OutputBuffer * cb, int *decodeWaitedOn)
{ {
while (dc->start) while (dc->start)
player_wakeup_decoder(pc, dc); player_wakeup_decoder(dc);
if (dc->error != DECODE_ERROR_NOERROR) { if (dc->error != DECODE_ERROR_NOERROR) {
pc->errored_song = pc->current_song; pc.errored_song = pc.current_song;
pc->error = PLAYER_ERROR_FILE; pc.error = PLAYER_ERROR_FILE;
quitDecode(pc, dc); quitDecode(dc);
return -1; return -1;
} }
pc->totalTime = pc->fileTime; pc.totalTime = pc.fileTime;
pc->bitRate = 0; pc.bitRate = 0;
pc->sampleRate = 0; pc.sampleRate = 0;
pc->bits = 0; pc.bits = 0;
pc->channels = 0; pc.channels = 0;
*decodeWaitedOn = 1; *decodeWaitedOn = 1;
return 0; return 0;
} }
static int decodeSeek(PlayerControl * pc, DecoderControl * dc, static int decodeSeek(DecoderControl * dc,
OutputBuffer * cb, int *decodeWaitedOn, int *next) OutputBuffer * cb, int *decodeWaitedOn, int *next)
{ {
int ret = -1; int ret = -1;
if (dc->state == DECODE_STATE_STOP || if (dc->state == DECODE_STATE_STOP ||
dc->error != DECODE_ERROR_NOERROR || dc->error != DECODE_ERROR_NOERROR ||
dc->current_song != pc->current_song) { dc->current_song != pc.current_song) {
stopDecode(dc); stopDecode(dc);
*next = -1; *next = -1;
clearOutputBuffer(cb); clearOutputBuffer(cb);
dc->error = DECODE_ERROR_NOERROR; dc->error = DECODE_ERROR_NOERROR;
dc->start = 1; dc->start = 1;
waitOnDecode(pc, dc, cb, decodeWaitedOn); waitOnDecode(dc, cb, decodeWaitedOn);
} }
if (dc->state != DECODE_STATE_STOP && dc->seekable) { if (dc->state != DECODE_STATE_STOP && dc->seekable) {
*next = -1; *next = -1;
dc->seekWhere = pc->seekWhere > pc->totalTime - 0.1 ? dc->seekWhere = pc.seekWhere > pc.totalTime - 0.1 ?
pc->totalTime - 0.1 : pc->seekWhere; pc.totalTime - 0.1 : pc.seekWhere;
dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere; dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere;
dc->seekError = 0; dc->seekError = 0;
dc->seek = 1; dc->seek = 1;
do { player_wakeup_decoder(pc, dc); } while (dc->seek); do { player_wakeup_decoder(dc); } while (dc->seek);
if (!dc->seekError) { if (!dc->seekError) {
pc->elapsedTime = dc->seekWhere; pc.elapsedTime = dc->seekWhere;
ret = 0; ret = 0;
} }
} }
pc->seek = 0; pc.seek = 0;
wakeup_main_task(); wakeup_main_task();
return ret; return ret;
} }
static void processDecodeInput(PlayerControl * pc, DecoderControl * dc, static void processDecodeInput(DecoderControl * dc,
OutputBuffer * cb, OutputBuffer * cb,
int *pause_r, unsigned int *bbp_r, int *pause_r, unsigned int *bbp_r,
int *doCrossFade_r, int *doCrossFade_r,
int *decodeWaitedOn_r, int *decodeWaitedOn_r,
int *next_r) int *next_r)
{ {
if(pc->lockQueue) { if(pc.lockQueue) {
pc->queueLockState = PLAYER_QUEUE_LOCKED; pc.queueLockState = PLAYER_QUEUE_LOCKED;
pc->lockQueue = 0; pc.lockQueue = 0;
wakeup_main_task(); wakeup_main_task();
} }
if(pc->unlockQueue) { if(pc.unlockQueue) {
pc->queueLockState = PLAYER_QUEUE_UNLOCKED; pc.queueLockState = PLAYER_QUEUE_UNLOCKED;
pc->unlockQueue = 0; pc.unlockQueue = 0;
wakeup_main_task(); wakeup_main_task();
} }
if(pc->pause) { if(pc.pause) {
*pause_r = !*pause_r; *pause_r = !*pause_r;
if (*pause_r) { if (*pause_r) {
pc->state = PLAYER_STATE_PAUSE; pc.state = PLAYER_STATE_PAUSE;
} else { } else {
if (openAudioDevice(NULL) >= 0) { if (openAudioDevice(NULL) >= 0) {
pc->state = PLAYER_STATE_PLAY; pc.state = PLAYER_STATE_PLAY;
} else { } else {
char tmp[MPD_PATH_MAX]; char tmp[MPD_PATH_MAX];
pc->errored_song = pc->current_song; pc.errored_song = pc.current_song;
pc->error = PLAYER_ERROR_AUDIO; pc.error = PLAYER_ERROR_AUDIO;
ERROR("problems opening audio device " ERROR("problems opening audio device "
"while playing \"%s\"\n", "while playing \"%s\"\n",
get_song_url(tmp, pc->current_song)); get_song_url(tmp, pc.current_song));
*pause_r = -1; *pause_r = -1;
} }
} }
pc->pause = 0; pc.pause = 0;
wakeup_main_task(); wakeup_main_task();
if (*pause_r == -1) { if (*pause_r == -1) {
*pause_r = 1; *pause_r = 1;
@ -196,17 +193,16 @@ static void processDecodeInput(PlayerControl * pc, DecoderControl * dc,
closeAudioDevice(); closeAudioDevice();
} }
} }
if(pc->seek) { if(pc.seek) {
dropBufferedAudio(); dropBufferedAudio();
if(decodeSeek(pc,dc,cb,decodeWaitedOn_r,next_r) == 0) { if(decodeSeek(dc,cb,decodeWaitedOn_r,next_r) == 0) {
*doCrossFade_r = 0; *doCrossFade_r = 0;
*bbp_r = 0; *bbp_r = 0;
} }
} }
} }
static void decodeStart(PlayerControl * pc, OutputBuffer * cb, static void decodeStart(OutputBuffer * cb, DecoderControl * dc)
DecoderControl * dc)
{ {
int ret; int ret;
int close_instream = 1; int close_instream = 1;
@ -215,7 +211,7 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
char path_max_fs[MPD_PATH_MAX]; char path_max_fs[MPD_PATH_MAX];
char path_max_utf8[MPD_PATH_MAX]; char path_max_utf8[MPD_PATH_MAX];
if (!get_song_url(path_max_utf8, pc->current_song)) { if (!get_song_url(path_max_utf8, pc.current_song)) {
dc->error = DECODE_ERROR_FILE; dc->error = DECODE_ERROR_FILE;
goto stop_no_close; goto stop_no_close;
} }
@ -224,7 +220,7 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
utf8_to_fs_charset(path_max_fs, path_max_utf8)); utf8_to_fs_charset(path_max_fs, path_max_utf8));
} }
dc->current_song = pc->current_song; /* NEED LOCK */ dc->current_song = pc.current_song; /* NEED LOCK */
if (openInputStream(&inStream, path_max_fs) < 0) { if (openInputStream(&inStream, path_max_fs) < 0) {
dc->error = DECODE_ERROR_FILE; dc->error = DECODE_ERROR_FILE;
goto stop_no_close; goto stop_no_close;
@ -309,7 +305,7 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
} }
if (ret < 0 || ret == DECODE_ERROR_UNKTYPE) { if (ret < 0 || ret == DECODE_ERROR_UNKTYPE) {
pc->errored_song = pc->current_song; pc.errored_song = pc.current_song;
if (ret != DECODE_ERROR_UNKTYPE) if (ret != DECODE_ERROR_UNKTYPE)
dc->error = DECODE_ERROR_FILE; dc->error = DECODE_ERROR_FILE;
else else
@ -328,13 +324,12 @@ static void * decoder_task(void *arg)
{ {
DecoderControl *dc = arg; DecoderControl *dc = arg;
OutputBuffer *cb = &(getPlayerData()->buffer); OutputBuffer *cb = &(getPlayerData()->buffer);
PlayerControl *pc = &(getPlayerData()->playerControl);
notifyEnter(&dc->notify); notifyEnter(&dc->notify);
while (1) { while (1) {
if (dc->start || dc->seek) { if (dc->start || dc->seek) {
decodeStart(pc, cb, dc); decodeStart(cb, dc);
} else if (dc->stop) { } else if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
@ -375,25 +370,24 @@ static void crossFade(OutputBufferChunk * a, OutputBufferChunk * b,
a->chunkSize = b->chunkSize; a->chunkSize = b->chunkSize;
} }
static int playChunk(PlayerControl * pc, OutputBufferChunk * chunk, static int playChunk(OutputBufferChunk * chunk,
AudioFormat * format, double sizeToTime) AudioFormat * format, double sizeToTime)
{ {
pc->elapsedTime = chunk->times; pc.elapsedTime = chunk->times;
pc->bitRate = chunk->bitRate; pc.bitRate = chunk->bitRate;
pcm_volumeChange(chunk->data, chunk->chunkSize, pcm_volumeChange(chunk->data, chunk->chunkSize,
format, pc->softwareVolume); format, pc.softwareVolume);
if (playAudio(chunk->data, if (playAudio(chunk->data,
chunk->chunkSize) < 0) chunk->chunkSize) < 0)
return -1; return -1;
pc->totalPlayTime += pc.totalPlayTime += sizeToTime * chunk->chunkSize;
sizeToTime * chunk->chunkSize;
return 0; return 0;
} }
static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) static void decodeParent(DecoderControl * dc, OutputBuffer * cb)
{ {
int do_pause = 0; int do_pause = 0;
int buffering = 1; int buffering = 1;
@ -411,19 +405,19 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
/** the position of the first chunk in the next song */ /** the position of the first chunk in the next song */
int next = -1; int next = -1;
if (waitOnDecode(pc, dc, cb, &decodeWaitedOn) < 0) if (waitOnDecode(dc, cb, &decodeWaitedOn) < 0)
return; return;
pc->elapsedTime = 0; pc.elapsedTime = 0;
pc->state = PLAYER_STATE_PLAY; pc.state = PLAYER_STATE_PLAY;
pc->play = 0; pc.play = 0;
wakeup_main_task(); wakeup_main_task();
while (1) { while (1) {
processDecodeInput(pc, dc, cb, processDecodeInput(dc, cb,
&do_pause, &bbp, &doCrossFade, &do_pause, &bbp, &doCrossFade,
&decodeWaitedOn, &next); &decodeWaitedOn, &next);
if (pc->stop) { if (pc.stop) {
dropBufferedAudio(); dropBufferedAudio();
break; break;
} }
@ -431,7 +425,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
if (buffering) { if (buffering) {
if (availableOutputBuffer(cb) < bbp) { if (availableOutputBuffer(cb) < bbp) {
/* not enough decoded buffer space yet */ /* not enough decoded buffer space yet */
player_sleep(pc); player_sleep();
continue; continue;
} else } else
/* buffering is complete */ /* buffering is complete */
@ -445,47 +439,47 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
decodeWaitedOn = 0; decodeWaitedOn = 0;
if(openAudioDevice(&(cb->audioFormat))<0) { if(openAudioDevice(&(cb->audioFormat))<0) {
char tmp[MPD_PATH_MAX]; char tmp[MPD_PATH_MAX];
pc->errored_song = pc->current_song; pc.errored_song = pc.current_song;
pc->error = PLAYER_ERROR_AUDIO; pc.error = PLAYER_ERROR_AUDIO;
ERROR("problems opening audio device " ERROR("problems opening audio device "
"while playing \"%s\"\n", "while playing \"%s\"\n",
get_song_url(tmp, pc->current_song)); get_song_url(tmp, pc.current_song));
break; break;
} else { } else {
player_wakeup_decoder(pc, dc); player_wakeup_decoder(dc);
} }
if (do_pause) { if (do_pause) {
dropBufferedAudio(); dropBufferedAudio();
closeAudioDevice(); closeAudioDevice();
} }
pc->totalTime = dc->totalTime; pc.totalTime = dc->totalTime;
pc->sampleRate = dc->audioFormat.sampleRate; pc.sampleRate = dc->audioFormat.sampleRate;
pc->bits = dc->audioFormat.bits; pc.bits = dc->audioFormat.bits;
pc->channels = dc->audioFormat.channels; pc.channels = dc->audioFormat.channels;
sizeToTime = audioFormatSizeToTime(&cb->audioFormat); sizeToTime = audioFormatSizeToTime(&cb->audioFormat);
} }
else if(dc->state!=DECODE_STATE_START) { else if(dc->state!=DECODE_STATE_START) {
/* the decoder failed */ /* the decoder failed */
pc->errored_song = pc->current_song; pc.errored_song = pc.current_song;
pc->error = PLAYER_ERROR_FILE; pc.error = PLAYER_ERROR_FILE;
break; break;
} }
else { else {
/* the decoder is not yet ready; wait /* the decoder is not yet ready; wait
some more */ some more */
player_sleep(pc); player_sleep();
continue; continue;
} }
} }
if (dc->state == DECODE_STATE_STOP && if (dc->state == DECODE_STATE_STOP &&
pc->queueState == PLAYER_QUEUE_FULL && pc.queueState == PLAYER_QUEUE_FULL &&
pc->queueLockState == PLAYER_QUEUE_UNLOCKED) { pc.queueLockState == PLAYER_QUEUE_UNLOCKED) {
/* the decoder has finished the current song; /* the decoder has finished the current song;
make it decode the next song */ make it decode the next song */
next = cb->end; next = cb->end;
dc->start = 1; dc->start = 1;
pc->queueState = PLAYER_QUEUE_DECODE; pc.queueState = PLAYER_QUEUE_DECODE;
wakeup_main_task(); wakeup_main_task();
player_wakeup_decoder_nb(dc); player_wakeup_decoder_nb(dc);
} }
@ -495,9 +489,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
calculate how many chunks will be required calculate how many chunks will be required
for it */ for it */
crossFadeChunks = crossFadeChunks =
calculateCrossFadeChunks(pc, calculateCrossFadeChunks(&(cb->audioFormat),
&(cb->
audioFormat),
dc->totalTime); dc->totalTime);
if (crossFadeChunks > 0) { if (crossFadeChunks > 0) {
doCrossFade = 1; doCrossFade = 1;
@ -509,7 +501,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
} }
if (do_pause) if (do_pause)
player_sleep(pc); player_sleep();
else if (!outputBufferEmpty(cb) && (int)cb->begin != next) { else if (!outputBufferEmpty(cb) && (int)cb->begin != next) {
OutputBufferChunk *beginChunk = OutputBufferChunk *beginChunk =
outputBufferGetChunk(cb, cb->begin); outputBufferGetChunk(cb, cb->begin);
@ -544,14 +536,14 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
} else { } else {
/* wait for the /* wait for the
decoder */ decoder */
player_sleep(pc); player_sleep();
continue; continue;
} }
} }
} }
/* play the current chunk */ /* play the current chunk */
if (playChunk(pc, beginChunk, &(cb->audioFormat), if (playChunk(beginChunk, &(cb->audioFormat),
sizeToTime) < 0) sizeToTime) < 0)
break; break;
outputBufferShift(cb); outputBufferShift(cb);
@ -569,19 +561,19 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
doCrossFade = 0; doCrossFade = 0;
/* wait for the decoder to work on the new song */ /* wait for the decoder to work on the new song */
if (pc->queueState == PLAYER_QUEUE_DECODE || if (pc.queueState == PLAYER_QUEUE_DECODE ||
pc->queueLockState == PLAYER_QUEUE_LOCKED) { pc.queueLockState == PLAYER_QUEUE_LOCKED) {
player_sleep(pc); player_sleep();
continue; continue;
} }
if (pc->queueState != PLAYER_QUEUE_PLAY) if (pc.queueState != PLAYER_QUEUE_PLAY)
break; break;
next = -1; next = -1;
if (waitOnDecode(pc, dc, cb, &decodeWaitedOn) < 0) if (waitOnDecode(dc, cb, &decodeWaitedOn) < 0)
return; return;
pc->queueState = PLAYER_QUEUE_EMPTY; pc.queueState = PLAYER_QUEUE_EMPTY;
wakeup_main_task(); wakeup_main_task();
} else if (dc->state == DECODE_STATE_STOP && !dc->start) { } else if (dc->state == DECODE_STATE_STOP && !dc->start) {
break; break;
@ -592,7 +584,7 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
} }
} }
quitDecode(pc, dc); quitDecode(dc);
} }
/* decode w/ buffering /* decode w/ buffering
@ -603,19 +595,17 @@ static void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer *
void decode(void) void decode(void)
{ {
OutputBuffer *cb; OutputBuffer *cb;
PlayerControl *pc;
DecoderControl *dc; DecoderControl *dc;
cb = &(getPlayerData()->buffer); cb = &(getPlayerData()->buffer);
clearOutputBuffer(cb); clearOutputBuffer(cb);
pc = &(getPlayerData()->playerControl);
dc = &(getPlayerData()->decoderControl); dc = &(getPlayerData()->decoderControl);
dc->error = DECODE_ERROR_NOERROR; dc->error = DECODE_ERROR_NOERROR;
dc->seek = 0; dc->seek = 0;
dc->stop = 0; dc->stop = 0;
dc->start = 1; dc->start = 1;
do { player_wakeup_decoder(pc, dc); } while (dc->start); do { player_wakeup_decoder(dc); } while (dc->start);
decodeParent(pc, dc, cb); decodeParent(dc, cb);
} }

View File

@ -465,7 +465,7 @@ static int wavpack_streamdecode(OutputBuffer *cb, DecoderControl *dc,
* As we use dc->utf8url, this function will be bad for * As we use dc->utf8url, this function will be bad for
* single files. utf8url is not absolute file path :/ * single files. utf8url is not absolute file path :/
*/ */
utf8url = get_song_url(tmp, getPlayerData()->playerControl.current_song); utf8url = get_song_url(tmp, pc.current_song);
if (utf8url == NULL) { if (utf8url == NULL) {
break; break;
} }

View File

@ -432,7 +432,7 @@ int main(int argc, char *argv[])
openVolumeDevice(); openVolumeDevice();
decoderInit(&getPlayerData()->decoderControl); decoderInit(&getPlayerData()->decoderControl);
playerInit(&getPlayerData()->playerControl); playerInit();
read_state_file(); read_state_file();
while (COMMAND_RETURN_KILL != doIOForInterfaces() && while (COMMAND_RETURN_KILL != doIOForInterfaces() &&

View File

@ -36,49 +36,47 @@
static void playerCloseAudio(void); static void playerCloseAudio(void);
void wakeup_player_nb(PlayerControl *pc) void wakeup_player_nb(void)
{ {
notifySignal(&pc->notify); notifySignal(&pc.notify);
} }
static void wakeup_player(PlayerControl *pc) static void wakeup_player(void)
{ {
notifySignal(&pc->notify); notifySignal(&pc.notify);
wait_main_task(); wait_main_task();
} }
void player_sleep(PlayerControl *pc) void player_sleep(void)
{ {
notifyWait(&pc->notify); notifyWait(&pc.notify);
} }
static void * player_task(void *arg) static void * player_task(mpd_unused void *arg)
{ {
PlayerControl *pc = arg; notifyEnter(&pc.notify);
notifyEnter(&pc->notify);
while (1) { while (1) {
if (pc->play) { if (pc.play) {
decode(); decode();
continue; /* decode() calls wakeup_main_task */ continue; /* decode() calls wakeup_main_task */
} else if (pc->stop) { } else if (pc.stop) {
pc->stop = 0; pc.stop = 0;
} else if (pc->seek) { } else if (pc.seek) {
pc->seek = 0; pc.seek = 0;
} else if (pc->pause) { } else if (pc.pause) {
pc->pause = 0; pc.pause = 0;
} else if (pc->closeAudio) { } else if (pc.closeAudio) {
closeAudioDevice(); closeAudioDevice();
pc->closeAudio = 0; pc.closeAudio = 0;
} else if (pc->lockQueue) { } else if (pc.lockQueue) {
pc->queueLockState = PLAYER_QUEUE_LOCKED; pc.queueLockState = PLAYER_QUEUE_LOCKED;
pc->lockQueue = 0; pc.lockQueue = 0;
} else if (pc->unlockQueue) { } else if (pc.unlockQueue) {
pc->queueLockState = PLAYER_QUEUE_UNLOCKED; pc.queueLockState = PLAYER_QUEUE_UNLOCKED;
pc->unlockQueue = 0; pc.unlockQueue = 0;
} else { } else {
player_sleep(pc); player_sleep();
continue; continue;
} }
/* we did something, tell the main task about it */ /* we did something, tell the main task about it */
@ -87,14 +85,14 @@ static void * player_task(void *arg)
return NULL; return NULL;
} }
void playerInit(PlayerControl * pc) void playerInit(void)
{ {
pthread_attr_t attr; pthread_attr_t attr;
pthread_t player_thread; pthread_t player_thread;
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&player_thread, &attr, player_task, pc)) if (pthread_create(&player_thread, &attr, player_task, NULL))
FATAL("Failed to spawn player task: %s\n", strerror(errno)); FATAL("Failed to spawn player task: %s\n", strerror(errno));
} }
@ -108,38 +106,34 @@ int playerWait(int fd)
return 0; return 0;
} }
static void set_current_song(PlayerControl * pc, Song *song) static void set_current_song(Song *song)
{ {
pc->fileTime = song->tag ? song->tag->time : 0; pc.fileTime = song->tag ? song->tag->time : 0;
pc->current_song = song; pc.current_song = song;
} }
int playerPlay(int fd, Song * song) int playerPlay(int fd, Song * song)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl);
if (playerStop(fd) < 0) if (playerStop(fd) < 0)
return -1; return -1;
set_current_song(pc, song); set_current_song(song);
pc->play = 1; pc.play = 1;
/* FIXME: _nb() variant is probably wrong here, and everywhere... */ /* FIXME: _nb() variant is probably wrong here, and everywhere... */
do { wakeup_player_nb(pc); } while (pc->play); do { wakeup_player_nb(); } while (pc.play);
return 0; return 0;
} }
int playerStop(int fd) int playerStop(int fd)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); if (pc.state != PLAYER_STATE_STOP) {
pc.stop = 1;
if (pc->state != PLAYER_STATE_STOP) { do { wakeup_player(); } while (pc.stop);
pc->stop = 1;
do { wakeup_player(pc); } while (pc->stop);
} }
pc->queueState = PLAYER_QUEUE_BLANK; pc.queueState = PLAYER_QUEUE_BLANK;
playerQueueUnlock(); playerQueueUnlock();
return 0; return 0;
@ -152,11 +146,9 @@ void playerKill(void) /* deprecated */
int playerPause(int fd) int playerPause(int fd)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); if (pc.state != PLAYER_STATE_STOP) {
pc.pause = 1;
if (pc->state != PLAYER_STATE_STOP) { do { wakeup_player(); } while (pc.pause);
pc->pause = 1;
do { wakeup_player(pc); } while (pc->pause);
} }
return 0; return 0;
@ -164,9 +156,7 @@ int playerPause(int fd)
int playerSetPause(int fd, int pause_flag) int playerSetPause(int fd, int pause_flag)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); switch (pc.state) {
switch (pc->state) {
case PLAYER_STATE_PLAY: case PLAYER_STATE_PLAY:
if (pause_flag) if (pause_flag)
playerPause(fd); playerPause(fd);
@ -182,32 +172,32 @@ int playerSetPause(int fd, int pause_flag)
int getPlayerElapsedTime(void) int getPlayerElapsedTime(void)
{ {
return (int)(getPlayerData()->playerControl.elapsedTime + 0.5); return (int)(pc.elapsedTime + 0.5);
} }
unsigned long getPlayerBitRate(void) unsigned long getPlayerBitRate(void)
{ {
return getPlayerData()->playerControl.bitRate; return pc.bitRate;
} }
int getPlayerTotalTime(void) int getPlayerTotalTime(void)
{ {
return (int)(getPlayerData()->playerControl.totalTime + 0.5); return (int)(pc.totalTime + 0.5);
} }
int getPlayerState(void) int getPlayerState(void)
{ {
return getPlayerData()->playerControl.state; return pc.state;
} }
void clearPlayerError(void) void clearPlayerError(void)
{ {
getPlayerData()->playerControl.error = 0; pc.error = 0;
} }
int getPlayerError(void) int getPlayerError(void)
{ {
return getPlayerData()->playerControl.error; return pc.error;
} }
char *getPlayerErrorStr(void) char *getPlayerErrorStr(void)
@ -216,18 +206,17 @@ char *getPlayerErrorStr(void)
static char error[MPD_PATH_MAX + 64]; /* still too much */ static char error[MPD_PATH_MAX + 64]; /* still too much */
static const size_t errorlen = sizeof(error); static const size_t errorlen = sizeof(error);
char path_max_tmp[MPD_PATH_MAX]; char path_max_tmp[MPD_PATH_MAX];
PlayerControl *pc = &(getPlayerData()->playerControl);
*error = '\0'; /* likely */ *error = '\0'; /* likely */
switch (pc->error) { switch (pc.error) {
case PLAYER_ERROR_FILENOTFOUND: case PLAYER_ERROR_FILENOTFOUND:
snprintf(error, errorlen, snprintf(error, errorlen,
"file \"%s\" does not exist or is inaccessible", "file \"%s\" does not exist or is inaccessible",
get_song_url(path_max_tmp, pc->errored_song)); get_song_url(path_max_tmp, pc.errored_song));
break; break;
case PLAYER_ERROR_FILE: case PLAYER_ERROR_FILE:
snprintf(error, errorlen, "problems decoding \"%s\"", snprintf(error, errorlen, "problems decoding \"%s\"",
get_song_url(path_max_tmp, pc->errored_song)); get_song_url(path_max_tmp, pc.errored_song));
break; break;
case PLAYER_ERROR_AUDIO: case PLAYER_ERROR_AUDIO:
strcpy(error, "problems opening audio device"); strcpy(error, "problems opening audio device");
@ -237,28 +226,24 @@ char *getPlayerErrorStr(void)
break; break;
case PLAYER_ERROR_UNKTYPE: case PLAYER_ERROR_UNKTYPE:
snprintf(error, errorlen, "file type of \"%s\" is unknown", snprintf(error, errorlen, "file type of \"%s\" is unknown",
get_song_url(path_max_tmp, pc->errored_song)); get_song_url(path_max_tmp, pc.errored_song));
} }
return *error ? error : NULL; return *error ? error : NULL;
} }
static void playerCloseAudio(void) static void playerCloseAudio(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl);
if (playerStop(STDERR_FILENO) < 0) if (playerStop(STDERR_FILENO) < 0)
return; return;
pc->closeAudio = 1; pc.closeAudio = 1;
do { wakeup_player(pc); } while (pc->closeAudio); do { wakeup_player(); } while (pc.closeAudio);
} }
int queueSong(Song * song) int queueSong(Song * song)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); if (pc.queueState == PLAYER_QUEUE_BLANK) {
set_current_song(song);
if (pc->queueState == PLAYER_QUEUE_BLANK) { pc.queueState = PLAYER_QUEUE_FULL;
set_current_song(pc, song);
pc->queueState = PLAYER_QUEUE_FULL;
return 0; return 0;
} }
@ -267,59 +252,49 @@ int queueSong(Song * song)
int getPlayerQueueState(void) int getPlayerQueueState(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); return pc.queueState;
return pc->queueState;
} }
void setQueueState(int queueState) void setQueueState(int queueState)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); pc.queueState = queueState;
wakeup_player_nb();
pc->queueState = queueState;
wakeup_player_nb(pc);
} }
void playerQueueLock(void) void playerQueueLock(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); if (pc.queueLockState == PLAYER_QUEUE_UNLOCKED) {
pc.lockQueue = 1;
if (pc->queueLockState == PLAYER_QUEUE_UNLOCKED) { do { wakeup_player(); } while (pc.lockQueue);
pc->lockQueue = 1;
do { wakeup_player(pc); } while (pc->lockQueue);
} }
} }
void playerQueueUnlock(void) void playerQueueUnlock(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); if (pc.queueLockState == PLAYER_QUEUE_LOCKED) {
pc.unlockQueue = 1;
if (pc->queueLockState == PLAYER_QUEUE_LOCKED) { do { wakeup_player(); } while (pc.unlockQueue);
pc->unlockQueue = 1;
do { wakeup_player(pc); } while (pc->unlockQueue);
} }
} }
int playerSeek(int fd, Song * song, float seek_time) int playerSeek(int fd, Song * song, float seek_time)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl);
assert(song != NULL); assert(song != NULL);
if (pc->state == PLAYER_STATE_STOP) { if (pc.state == PLAYER_STATE_STOP) {
commandError(fd, ACK_ERROR_PLAYER_SYNC, commandError(fd, ACK_ERROR_PLAYER_SYNC,
"player not currently playing"); "player not currently playing");
return -1; return -1;
} }
if (pc->current_song != song) if (pc.current_song != song)
set_current_song(pc, song); set_current_song(song);
if (pc->error == PLAYER_ERROR_NOERROR) { if (pc.error == PLAYER_ERROR_NOERROR) {
pc->seekWhere = seek_time; pc.seekWhere = seek_time;
pc->seek = 1; pc.seek = 1;
/* FIXME: _nb() is probably wrong here, too */ /* FIXME: _nb() is probably wrong here, too */
do { wakeup_player_nb(pc); } while (pc->seek); do { wakeup_player_nb(); } while (pc.seek);
} }
return 0; return 0;
@ -327,58 +302,40 @@ int playerSeek(int fd, Song * song, float seek_time)
float getPlayerCrossFade(void) float getPlayerCrossFade(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); return pc.crossFade;
return pc->crossFade;
} }
void setPlayerCrossFade(float crossFadeInSeconds) void setPlayerCrossFade(float crossFadeInSeconds)
{ {
PlayerControl *pc;
if (crossFadeInSeconds < 0) if (crossFadeInSeconds < 0)
crossFadeInSeconds = 0; crossFadeInSeconds = 0;
pc.crossFade = crossFadeInSeconds;
pc = &(getPlayerData()->playerControl);
pc->crossFade = crossFadeInSeconds;
} }
void setPlayerSoftwareVolume(int volume) void setPlayerSoftwareVolume(int volume)
{ {
PlayerControl *pc;
volume = (volume > 1000) ? 1000 : (volume < 0 ? 0 : volume); volume = (volume > 1000) ? 1000 : (volume < 0 ? 0 : volume);
pc.softwareVolume = volume;
pc = &(getPlayerData()->playerControl);
pc->softwareVolume = volume;
} }
double getPlayerTotalPlayTime(void) double getPlayerTotalPlayTime(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); return pc.totalPlayTime;
return pc->totalPlayTime;
} }
unsigned int getPlayerSampleRate(void) unsigned int getPlayerSampleRate(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); return pc.sampleRate;
return pc->sampleRate;
} }
int getPlayerBits(void) int getPlayerBits(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); return pc.bits;
return pc->bits;
} }
int getPlayerChannels(void) int getPlayerChannels(void)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); return pc.channels;
return pc->channels;
} }
/* this actually creates a dupe of the current metadata */ /* this actually creates a dupe of the current metadata */

View File

@ -76,9 +76,9 @@ typedef struct _PlayerControl {
volatile double totalPlayTime; volatile double totalPlayTime;
} PlayerControl; } PlayerControl;
void wakeup_player_nb(PlayerControl *pc); void wakeup_player_nb(void);
void player_sleep(PlayerControl *pc); void player_sleep(void);
int playerPlay(int fd, Song * song); int playerPlay(int fd, Song * song);
@ -134,6 +134,6 @@ int getPlayerChannels(void);
Song *playerCurrentDecodeSong(void); Song *playerCurrentDecodeSong(void);
void playerInit(PlayerControl * pc); void playerInit(void);
#endif #endif

View File

@ -27,6 +27,7 @@ unsigned int buffered_before_play;
#define DEFAULT_BUFFER_BEFORE_PLAY 10 #define DEFAULT_BUFFER_BEFORE_PLAY 10
static PlayerData playerData_pd; static PlayerData playerData_pd;
PlayerControl pc;
void initPlayerData(void) void initPlayerData(void)
{ {
@ -76,23 +77,13 @@ void initPlayerData(void)
initOutputBuffer(&(playerData_pd.buffer), buffered_chunks); initOutputBuffer(&(playerData_pd.buffer), buffered_chunks);
notifyInit(&playerData_pd.playerControl.notify); notifyInit(&pc.notify);
playerData_pd.playerControl.stop = 0; pc.error = PLAYER_ERROR_NOERROR;
playerData_pd.playerControl.pause = 0; pc.state = PLAYER_STATE_STOP;
playerData_pd.playerControl.play = 0; pc.queueState = PLAYER_QUEUE_BLANK;
playerData_pd.playerControl.error = PLAYER_ERROR_NOERROR; pc.queueLockState = PLAYER_QUEUE_UNLOCKED;
playerData_pd.playerControl.lockQueue = 0; pc.crossFade = crossfade;
playerData_pd.playerControl.unlockQueue = 0; pc.softwareVolume = 1000;
playerData_pd.playerControl.state = PLAYER_STATE_STOP;
playerData_pd.playerControl.queueState = PLAYER_QUEUE_BLANK;
playerData_pd.playerControl.queueLockState = PLAYER_QUEUE_UNLOCKED;
playerData_pd.playerControl.seek = 0;
playerData_pd.playerControl.closeAudio = 0;
playerData_pd.playerControl.current_song = NULL;
playerData_pd.playerControl.errored_song = NULL;
playerData_pd.playerControl.crossFade = crossfade;
playerData_pd.playerControl.softwareVolume = 1000;
playerData_pd.playerControl.totalPlayTime = 0;
notifyInit(&playerData_pd.decoderControl.notify); notifyInit(&playerData_pd.decoderControl.notify);
playerData_pd.decoderControl.stop = 0; playerData_pd.decoderControl.stop = 0;

View File

@ -26,10 +26,10 @@
#include "outputBuffer.h" #include "outputBuffer.h"
extern unsigned int buffered_before_play; extern unsigned int buffered_before_play;
extern PlayerControl pc;
typedef struct _PlayerData { typedef struct _PlayerData {
OutputBuffer buffer; OutputBuffer buffer;
PlayerControl playerControl;
DecoderControl decoderControl; DecoderControl decoderControl;
mpd_uint8 *audioDeviceStates; mpd_uint8 *audioDeviceStates;
} PlayerData; } PlayerData;