aboutsummaryrefslogtreecommitdiffstats
path: root/src/decode.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/decode.c413
1 files changed, 222 insertions, 191 deletions
diff --git a/src/decode.c b/src/decode.c
index 5a04c780f..f77a9b999 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -79,7 +79,7 @@ void decodeSigHandler(int sig) {
void stopDecode(DecoderControl * dc) {
if(decode_pid && *decode_pid>0 &&
- (dc->start || dc->state==DECODE_STATE_DECODE))
+ (dc->start || dc->state!=DECODE_STATE_STOP))
{
dc->stop = 1;
while(decode_pid && *decode_pid>0 && dc->stop) my_usleep(1000);
@@ -112,7 +112,29 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
return (int)chunks;
}
-int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
+#define handleDecodeStart() \
+ if(decodeWaitedOn && dc->state==DECODE_STATE_DECODE) { \
+ decodeWaitedOn = 1; \
+ if(openAudioDevice(&(cb->audioFormat))<0) { \
+ strncpy(pc->erroredFile,pc->file,MAXPATHLEN); \
+ pc->erroredFile[MAXPATHLEN] = '\0'; \
+ pc->error = PLAYER_ERROR_AUDIO; \
+ quitDecode(pc,dc); \
+ return; \
+ } \
+ pc->totalTime = dc->totalTime; \
+ pc->sampleRate = dc->audioFormat.sampleRate; \
+ pc->bits = dc->audioFormat.bits; \
+ pc->channels = dc->audioFormat.channels; \
+ } \
+ else { \
+ my_usleep(10); \
+ continue; \
+ }
+
+int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
+ int * decodeWaitedOn)
+{
while(decode_pid && *decode_pid>0 && dc->start) my_usleep(1000);
if(dc->start || dc->error!=DECODE_ERROR_NOERROR) {
@@ -123,28 +145,25 @@ int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
return -1;
}
- if(openAudioDevice(&(cb->audioFormat))<0) {
- strncpy(pc->erroredFile,pc->file,MAXPATHLEN);
- pc->erroredFile[MAXPATHLEN] = '\0';
- pc->error = PLAYER_ERROR_AUDIO;
- quitDecode(pc,dc);
- return -1;
- }
-
- pc->totalTime = dc->totalTime;
- pc->elapsedTime = 0;
- pc->bitRate = 0;
- pc->sampleRate = dc->audioFormat.sampleRate;
- pc->bits = dc->audioFormat.bits;
- pc->channels = dc->audioFormat.channels;
+ pc->totalTime = pc->fileTime;
+ pc->elapsedTime = 0;
+ pc->bitRate = 0;
+ pc->sampleRate = 0;
+ pc->bits = 0;
+ pc->channels = 0;
+ *decodeWaitedOn = 1;
return 0;
}
-void decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
+int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
+ int * decodeWaitedOn)
+{
+ int ret = -1;
+
if(decode_pid && *decode_pid>0) {
cb->next = -1;
- if(dc->state!=DECODE_STATE_DECODE || dc->error ||
+ if(dc->state==DECODE_STATE_STOP || dc->error ||
strcmp(dc->file,pc->file)!=0)
{
stopDecode(dc);
@@ -153,9 +172,9 @@ void decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
cb->wrap = 0;
dc->error = 0;
dc->start = 1;
- waitOnDecode(pc,dc,cb);
+ waitOnDecode(pc,dc,cb,decodeWaitedOn);
}
- if(*decode_pid>0 && dc->state==DECODE_STATE_DECODE) {
+ if(*decode_pid>0 && dc->state!=DECODE_STATE_STOP) {
dc->seekWhere = pc->seekWhere > pc->totalTime-0.1 ?
pc->totalTime-0.1 :
pc->seekWhere;
@@ -164,10 +183,15 @@ void decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
dc->seek = 1;
pc->bitRate = 0;
while(*decode_pid>0 && dc->seek) my_usleep(1000);
- if(!dc->seekError) pc->elapsedTime = dc->seekWhere;
+ if(!dc->seekError) {
+ ret = 0;
+ pc->elapsedTime = dc->seekWhere;
+ }
}
}
pc->seek = 0;
+
+ return ret;
}
#define processDecodeInput() \
@@ -202,11 +226,12 @@ void decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
} \
if(pc->seek) { \
pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
- decodeSeek(pc,dc,cb); \
- pc->beginTime = pc->elapsedTime; \
- doCrossFade = 0; \
- nextChunk = -1; \
- bbp = 0; \
+ if(decodeSeek(pc,dc,cb,&decodeWaitedOn) == 0) { \
+ pc->beginTime = pc->elapsedTime; \
+ doCrossFade = 0; \
+ nextChunk = -1; \
+ bbp = 0; \
+ } \
} \
if(pc->stop) { \
pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
@@ -229,7 +254,17 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return;
}
- while(!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0);
+ dc->state = DECODE_STATE_START;
+ dc->start = 0;
+
+ while(!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0
+ && !dc->stop);
+
+ if(dc->stop) {
+ dc->state = DECODE_STATE_STOP;
+ dc->stop = 0;
+ return;
+ }
switch(pc->decodeType) {
case DECODE_TYPE_URL:
@@ -339,112 +374,86 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return 0;
}
-/* decode w/ buffering
- * this will fork another process
- * child process does decoding
- * parent process does playing audio
- */
-void decode() {
- OutputBuffer * cb;
- PlayerControl * pc;
- DecoderControl * dc;
+void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
+ int pause = 0;
+ int quit = 0;
+ int bbp = buffered_before_play;
+ int doCrossFade = 0;
+ int crossFadeChunks = 0;
+ int fadePosition;
+ int nextChunk = -1;
+ int test;
+ int decodeWaitedOn = 0;
+ char silence[CHUNK_SIZE];
- cb = &(getPlayerData()->buffer);
+ memset(silence,0,CHUNK_SIZE);
- cb->begin = 0;
- cb->end = 0;
- cb->wrap = 0;
- pc = &(getPlayerData()->playerControl);
- dc = &(getPlayerData()->decoderControl);
- dc->error = 0;
- dc->start = 1;
- cb->next = -1;
+ if(waitOnDecode(pc,dc,cb,&decodeWaitedOn)<0) return;
- if(decode_pid==NULL || *decode_pid<=0) {
- if(decoderInit(pc,cb,dc)<0) return;
+ pc->state = PLAYER_STATE_PLAY;
+ pc->play = 0;
+ pc->beginTime = pc->elapsedTime;
+ kill(getppid(),SIGUSR1);
+
+ while(*decode_pid>0 && !cb->wrap && cb->end-cb->begin<bbp &&
+ dc->state!=DECODE_STATE_STOP)
+ {
+ processDecodeInput();
+ if(quit) return;
+ my_usleep(10000);
}
- {
- /* PARENT */
- int pause = 0;
- int quit = 0;
- int bbp = buffered_before_play;
- int doCrossFade = 0;
- int crossFadeChunks = 0;
- int fadePosition;
- int nextChunk = -1;
- int test;
- char silence[CHUNK_SIZE];
-
- memset(silence,0,CHUNK_SIZE);
-
- if(waitOnDecode(pc,dc,cb)<0) return;
-
- pc->state = PLAYER_STATE_PLAY;
- pc->play = 0;
- pc->beginTime = pc->elapsedTime;
- kill(getppid(),SIGUSR1);
-
- while(*decode_pid>0 && !cb->wrap && cb->end-cb->begin<bbp &&
- dc->state==DECODE_STATE_DECODE)
+ while(!quit) {
+ processDecodeInput();
+ handleDecodeStart();
+ if(dc->state==DECODE_STATE_STOP &&
+ pc->queueState==PLAYER_QUEUE_FULL &&
+ pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
{
- processDecodeInput();
- if(quit) return;
- my_usleep(1000);
+ cb->next = cb->end;
+ dc->start = 1;
+ pc->queueState = PLAYER_QUEUE_DECODE;
+ kill(getppid(),SIGUSR1);
}
-
- while(!quit) {
- processDecodeInput();
- if(dc->state==DECODE_STATE_STOP &&
- pc->queueState==PLAYER_QUEUE_FULL &&
- pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
- {
- cb->next = cb->end;
- dc->start = 1;
- pc->queueState = PLAYER_QUEUE_DECODE;
- kill(getppid(),SIGUSR1);
- }
- if(cb->next>=0 && doCrossFade==0 && !dc->start) {
- nextChunk = -1;
- if(isCurrentAudioFormat(&(cb->audioFormat))) {
- doCrossFade = 1;
- crossFadeChunks =
- calculateCrossFadeChunks(pc,
- &(cb->audioFormat));
- if(!crossFadeChunks ||
+ if(cb->next>=0 && doCrossFade==0 && !dc->start) {
+ nextChunk = -1;
+ if(isCurrentAudioFormat(&(cb->audioFormat))) {
+ doCrossFade = 1;
+ crossFadeChunks =
+ calculateCrossFadeChunks(pc,
+ &(cb->audioFormat));
+ if(!crossFadeChunks ||
pc->crossFade>=dc->totalTime)
- {
- doCrossFade = -1;
- }
+ {
+ doCrossFade = -1;
}
- else doCrossFade = -1;
}
- if(pause) my_usleep(10000);
- else if((cb->begin!=cb->end || cb->wrap) &&
+ else doCrossFade = -1;
+ }
+ if(pause) my_usleep(10000);
+ else if((cb->begin!=cb->end || cb->wrap) &&
cb->begin!=cb->next)
- {
- if(doCrossFade==1 && cb->next>=0 &&
+ {
+ if(doCrossFade==1 && cb->next>=0 &&
((cb->next>cb->begin &&
(fadePosition=cb->next-cb->begin)
<=crossFadeChunks) ||
(cb->begin>cb->next &&
(fadePosition=cb->next-cb->begin+
buffered_chunks)<=crossFadeChunks)))
- {
- if(nextChunk<0) {
- crossFadeChunks = fadePosition;
+ {
+ if(nextChunk<0) {
+ crossFadeChunks = fadePosition;
+ }
+ test = cb->end;
+ if(cb->wrap) test+=buffered_chunks;
+ nextChunk = cb->begin+crossFadeChunks;
+ if(nextChunk<test) {
+ if(nextChunk>=buffered_chunks)
+ {
+ nextChunk -= buffered_chunks;
}
- test = cb->end;
- if(cb->wrap) test+=buffered_chunks;
- nextChunk = cb->begin+crossFadeChunks;
- if(nextChunk<test) {
- if(nextChunk>=buffered_chunks)
- {
- nextChunk-=
- buffered_chunks;
- }
- pcm_mix(cb->chunks+cb->begin*
- CHUNK_SIZE,
+ pcm_mix(cb->chunks+cb->begin*CHUNK_SIZE,
cb->chunks+nextChunk*
CHUNK_SIZE,
cb->chunkSize[
@@ -454,101 +463,123 @@ void decode() {
&(cb->audioFormat),
((float)fadePosition)/
crossFadeChunks);
- if(cb->chunkSize[nextChunk]>
+ if(cb->chunkSize[nextChunk]>
cb->chunkSize[cb->begin]
)
- {
- cb->chunkSize[cb->begin]
+ {
+ cb->chunkSize[cb->begin]
= cb->chunkSize
[nextChunk];
- }
}
- else {
- if(dc->state==DECODE_STATE_STOP)
- {
- doCrossFade = -1;
- }
- else continue;
- }
- }
- pc->elapsedTime = cb->times[cb->begin];
- pc->bitRate = cb->bitRate[cb->begin];
- pcm_volumeChange(cb->chunks+cb->begin*
- CHUNK_SIZE,
- cb->chunkSize[cb->begin],
- &(cb->audioFormat),
- pc->softwareVolume);
- if(playAudio(cb->chunks+cb->begin*CHUNK_SIZE,
- cb->chunkSize[cb->begin])<0)
- {
- quit = 1;
}
- cb->begin++;
- if(cb->begin>=buffered_chunks) {
- cb->begin = 0;
- cb->wrap = 0;
+ else {
+ if(dc->state==DECODE_STATE_STOP)
+ {
+ doCrossFade = -1;
+ }
+ else continue;
}
}
- else if(cb->next==cb->begin) {
- pc->totalPlayTime+= pc->elapsedTime-
- pc->beginTime;
- if(doCrossFade==1 && nextChunk>=0) {
- nextChunk = cb->begin+crossFadeChunks;
- test = cb->end;
- if(cb->wrap) test+=buffered_chunks;
- if(nextChunk<test) {
- if(nextChunk>=buffered_chunks)
- {
- nextChunk-=
- buffered_chunks;
- }
- cb->begin = nextChunk;
- }
- }
- while(pc->queueState==PLAYER_QUEUE_DECODE ||
- pc->queueLockState==PLAYER_QUEUE_LOCKED)
- {
- processDecodeInput();
- if(quit) {
- quitDecode(pc,dc);
- return;
+ pc->elapsedTime = cb->times[cb->begin];
+ pc->bitRate = cb->bitRate[cb->begin];
+ pcm_volumeChange(cb->chunks+cb->begin*
+ CHUNK_SIZE,
+ cb->chunkSize[cb->begin],
+ &(cb->audioFormat),
+ pc->softwareVolume);
+ if(playAudio(cb->chunks+cb->begin*CHUNK_SIZE,
+ cb->chunkSize[cb->begin])<0)
+ {
+ quit = 1;
+ }
+ cb->begin++;
+ if(cb->begin>=buffered_chunks) {
+ cb->begin = 0;
+ cb->wrap = 0;
+ }
+ }
+ else if(cb->next==cb->begin) {
+ pc->totalPlayTime+= pc->elapsedTime-
+ pc->beginTime;
+ if(doCrossFade==1 && nextChunk>=0) {
+ nextChunk = cb->begin+crossFadeChunks;
+ test = cb->end;
+ if(cb->wrap) test+=buffered_chunks;
+ if(nextChunk<test) {
+ if(nextChunk>=buffered_chunks)
+ {
+ nextChunk -= buffered_chunks;
}
- my_usleep(1000);
- }
- if(pc->queueState!=PLAYER_QUEUE_PLAY) {
- quit = 1;
- break;
- }
- else {
- cb->next = -1;
- if(waitOnDecode(pc,dc,cb)<0) return;
- nextChunk = -1;
- doCrossFade = 0;
- crossFadeChunks = 0;
- pc->queueState = PLAYER_QUEUE_EMPTY;
- kill(getppid(),SIGUSR1);
- }
- pc->beginTime = cb->times[cb->begin];
+ cb->begin = nextChunk;
+ }
}
- else if(*decode_pid<=0 ||
- (dc->state==DECODE_STATE_STOP && !dc->start))
+ while(pc->queueState==PLAYER_QUEUE_DECODE ||
+ pc->queueLockState==PLAYER_QUEUE_LOCKED)
{
+ processDecodeInput();
+ if(quit) {
+ quitDecode(pc,dc);
+ return;
+ }
+ my_usleep(1000);
+ }
+ if(pc->queueState!=PLAYER_QUEUE_PLAY) {
quit = 1;
break;
}
else {
- if(playAudio(silence, CHUNK_SIZE) < 0) {
- quit = 1;
- }
+ cb->next = -1;
+ if(waitOnDecode(pc,dc,cb,&decodeWaitedOn)<0) {
+ return;
+ }
+ nextChunk = -1;
+ doCrossFade = 0;
+ crossFadeChunks = 0;
+ pc->queueState = PLAYER_QUEUE_EMPTY;
+ kill(getppid(),SIGUSR1);
}
+ pc->beginTime = cb->times[cb->begin];
+ }
+ else if(*decode_pid<=0 ||
+ (dc->state==DECODE_STATE_STOP && !dc->start))
+ {
+ quit = 1;
+ break;
}
+ else {
+ if(playAudio(silence, CHUNK_SIZE) < 0) quit = 1;
+ }
+ }
- pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
- quitDecode(pc,dc);
+ pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
+ quitDecode(pc,dc);
+}
+
+/* decode w/ buffering
+ * this will fork another process
+ * child process does decoding
+ * parent process does playing audio
+ */
+void decode() {
+ OutputBuffer * cb;
+ PlayerControl * pc;
+ DecoderControl * dc;
+
+ cb = &(getPlayerData()->buffer);
- /* END OF PARENT */
+ cb->begin = 0;
+ cb->end = 0;
+ cb->wrap = 0;
+ pc = &(getPlayerData()->playerControl);
+ dc = &(getPlayerData()->decoderControl);
+ dc->error = 0;
+ dc->start = 1;
+ cb->next = -1;
+
+ if(decode_pid==NULL || *decode_pid<=0) {
+ if(decoderInit(pc,cb,dc)<0) return;
}
- return;
+ decodeParent(pc, dc, cb);
}
-/* vim:set shiftwidth=4 tabstop=8 expandtab: */
+/* vim:set shiftwidth=8 tabstop=8 expandtab: */