aboutsummaryrefslogtreecommitdiffstats
path: root/src/decode.c
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-08-26 08:27:09 +0200
committerMax Kellermann <max@duempel.org>2008-08-26 08:27:09 +0200
commite8bd9ddc9fc99d31659db1121622bef0f3303fc1 (patch)
treea9fea2466a207ca957fe47c6a0881e957ba2aad5 /src/decode.c
parent6104e9690e75046b793c0abe6fc20576fb3da19b (diff)
downloadmpd-e8bd9ddc9fc99d31659db1121622bef0f3303fc1.tar.gz
mpd-e8bd9ddc9fc99d31659db1121622bef0f3303fc1.tar.xz
mpd-e8bd9ddc9fc99d31659db1121622bef0f3303fc1.zip
moved code to player_thread.c
Move code which runs in the player thread to player_thread.c. Having a lot of player thread code in decode.c isn't easy to understand.
Diffstat (limited to 'src/decode.c')
-rw-r--r--src/decode.c394
1 files changed, 0 insertions, 394 deletions
diff --git a/src/decode.c b/src/decode.c
index 8d929d0fb..92f01a393 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -19,166 +19,10 @@
#include "decode.h"
#include "decoder_internal.h"
-#include "player.h"
#include "playerData.h"
-#include "pcm_utils.h"
#include "path.h"
#include "log.h"
#include "ls.h"
-#include "main_notify.h"
-#include "audio.h"
-#include "crossfade.h"
-
-enum xfade_state {
- XFADE_DISABLED = -1,
- XFADE_UNKNOWN = 0,
- XFADE_ENABLED = 1
-};
-
-static void dc_command_wait(void)
-{
- while (dc.command != DECODE_COMMAND_NONE) {
- notify_signal(&dc.notify);
- notify_wait(&pc.notify);
- }
-}
-
-static void dc_command(enum decoder_command cmd)
-{
- dc.command = cmd;
- dc_command_wait();
-}
-
-static void stopDecode(void)
-{
- if (dc.command == DECODE_COMMAND_START ||
- dc.state != DECODE_STATE_STOP)
- dc_command(DECODE_COMMAND_STOP);
-}
-
-static void quitDecode(void)
-{
- stopDecode();
- pc.state = PLAYER_STATE_STOP;
- dc.command = DECODE_COMMAND_NONE;
- pc.command = PLAYER_COMMAND_NONE;
- wakeup_main_task();
-}
-
-static int waitOnDecode(int *decodeWaitedOn)
-{
- while (dc.command == DECODE_COMMAND_START) {
- notify_signal(&dc.notify);
- notify_wait(&pc.notify);
- }
-
- if (dc.error != DECODE_ERROR_NOERROR) {
- pc.errored_song = dc.next_song;
- pc.error = PLAYER_ERROR_FILE;
- quitDecode();
- return -1;
- }
-
- pc.totalTime = pc.fileTime;
- pc.bitRate = 0;
- pc.sampleRate = 0;
- pc.bits = 0;
- pc.channels = 0;
- *decodeWaitedOn = 1;
-
- return 0;
-}
-
-static int decodeSeek(int *decodeWaitedOn, int *next)
-{
- int ret = -1;
-
- if (dc.state == DECODE_STATE_STOP ||
- dc.error != DECODE_ERROR_NOERROR ||
- dc.current_song != pc.next_song) {
- stopDecode();
- *next = -1;
- ob_clear();
- dc.next_song = pc.next_song;
- dc.error = DECODE_ERROR_NOERROR;
- dc.command = DECODE_COMMAND_START;
- waitOnDecode(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_command(DECODE_COMMAND_SEEK);
- if (!dc.seekError) {
- pc.elapsedTime = dc.seekWhere;
- ret = 0;
- }
- }
-
- player_command_finished();
-
- return ret;
-}
-
-static void processDecodeInput(int *pause_r, unsigned int *bbp_r,
- enum xfade_state *do_xfade_r,
- int *decodeWaitedOn_r,
- int *next_r)
-{
- switch (pc.command) {
- case PLAYER_COMMAND_NONE:
- case PLAYER_COMMAND_PLAY:
- case PLAYER_COMMAND_STOP:
- case PLAYER_COMMAND_CLOSE_AUDIO:
- break;
-
- case PLAYER_COMMAND_LOCK_QUEUE:
- pc.queueLockState = PLAYER_QUEUE_LOCKED;
- player_command_finished();
- break;
-
- case PLAYER_COMMAND_UNLOCK_QUEUE:
- pc.queueLockState = PLAYER_QUEUE_UNLOCKED;
- player_command_finished();
- break;
-
- case PLAYER_COMMAND_PAUSE:
- *pause_r = !*pause_r;
- if (*pause_r) {
- pc.state = PLAYER_STATE_PAUSE;
- } else {
- if (openAudioDevice(NULL) >= 0) {
- pc.state = PLAYER_STATE_PLAY;
- } else {
- char tmp[MPD_PATH_MAX];
- pc.errored_song = dc.next_song;
- pc.error = PLAYER_ERROR_AUDIO;
- ERROR("problems opening audio device "
- "while playing \"%s\"\n",
- get_song_url(tmp, dc.next_song));
- *pause_r = -1;
- }
- }
- player_command_finished();
- if (*pause_r == -1) {
- *pause_r = 1;
- } else if (*pause_r) {
- dropBufferedAudio();
- closeAudioDevice();
- }
- break;
-
- case PLAYER_COMMAND_SEEK:
- dropBufferedAudio();
- if (decodeSeek(decodeWaitedOn_r, next_r) == 0) {
- *do_xfade_r = XFADE_UNKNOWN;
- *bbp_r = 0;
- }
- break;
- }
-}
static void decodeStart(void)
{
@@ -337,241 +181,3 @@ void decoderInit(void)
if (pthread_create(&decoder_thread, &attr, decoder_task, NULL))
FATAL("Failed to spawn decoder task: %s\n", strerror(errno));
}
-
-static int playChunk(ob_chunk * chunk,
- const AudioFormat * format, double sizeToTime)
-{
- pc.elapsedTime = chunk->times;
- pc.bitRate = chunk->bitRate;
-
- pcm_volumeChange(chunk->data, chunk->chunkSize,
- format, pc.softwareVolume);
-
- if (playAudio(chunk->data,
- chunk->chunkSize) < 0)
- return -1;
-
- pc.totalPlayTime += sizeToTime * chunk->chunkSize;
- return 0;
-}
-
-static void decodeParent(void)
-{
- int do_pause = 0;
- int buffering = 1;
- unsigned int bbp = buffered_before_play;
- enum xfade_state do_xfade = XFADE_UNKNOWN;
- unsigned int crossFadeChunks = 0;
- /** the position of the next cross-faded chunk in the next
- song */
- int nextChunk = 0;
- int decodeWaitedOn = 0;
- static const char silence[CHUNK_SIZE];
- double sizeToTime = 0.0;
- /** the position of the first chunk in the next song */
- int next = -1;
-
- ob_set_lazy(0);
-
- if (waitOnDecode(&decodeWaitedOn) < 0)
- return;
-
- pc.elapsedTime = 0;
- pc.state = PLAYER_STATE_PLAY;
- player_command_finished();
-
- while (1) {
- processDecodeInput(&do_pause, &bbp, &do_xfade,
- &decodeWaitedOn, &next);
- if (pc.command == PLAYER_COMMAND_STOP) {
- dropBufferedAudio();
- break;
- }
-
- if (buffering) {
- if (ob_available() < bbp) {
- /* not enough decoded buffer space yet */
- notify_wait(&pc.notify);
- continue;
- } else {
- /* buffering is complete */
- buffering = 0;
- ob_set_lazy(1);
- }
- }
-
- if (decodeWaitedOn) {
- if(dc.state!=DECODE_STATE_START &&
- dc.error==DECODE_ERROR_NOERROR) {
- /* the decoder is ready and ok */
- decodeWaitedOn = 0;
- if(openAudioDevice(&(ob.audioFormat))<0) {
- char tmp[MPD_PATH_MAX];
- pc.errored_song = dc.next_song;
- pc.error = PLAYER_ERROR_AUDIO;
- ERROR("problems opening audio device "
- "while playing \"%s\"\n",
- get_song_url(tmp, dc.next_song));
- break;
- }
-
- if (do_pause) {
- dropBufferedAudio();
- closeAudioDevice();
- }
- pc.totalTime = dc.totalTime;
- pc.sampleRate = dc.audioFormat.sampleRate;
- pc.bits = dc.audioFormat.bits;
- pc.channels = dc.audioFormat.channels;
- sizeToTime = audioFormatSizeToTime(&ob.audioFormat);
- }
- else if(dc.state!=DECODE_STATE_START) {
- /* the decoder failed */
- pc.errored_song = dc.next_song;
- pc.error = PLAYER_ERROR_FILE;
- break;
- }
- else {
- /* the decoder is not yet ready; wait
- some more */
- notify_wait(&pc.notify);
- continue;
- }
- }
-
- if (dc.state == DECODE_STATE_STOP &&
- pc.queueState == PLAYER_QUEUE_FULL &&
- pc.queueLockState == PLAYER_QUEUE_UNLOCKED) {
- /* the decoder has finished the current song;
- make it decode the next song */
- next = ob.end;
- dc.next_song = pc.next_song;
- dc.error = DECODE_ERROR_NOERROR;
- dc.command = DECODE_COMMAND_START;
- pc.queueState = PLAYER_QUEUE_DECODE;
- wakeup_main_task();
- notify_signal(&dc.notify);
- }
- if (next >= 0 && do_xfade == XFADE_UNKNOWN &&
- dc.command != DECODE_COMMAND_START &&
- dc.state != DECODE_STATE_START) {
- /* enable cross fading in this song? if yes,
- calculate how many chunks will be required
- for it */
- crossFadeChunks =
- cross_fade_calc(pc.crossFade, dc.totalTime,
- &(ob.audioFormat),
- ob.size -
- buffered_before_play);
- if (crossFadeChunks > 0) {
- do_xfade = XFADE_ENABLED;
- nextChunk = -1;
- } else
- /* cross fading is disabled or the
- next song is too short */
- do_xfade = XFADE_DISABLED;
- }
-
- if (do_pause)
- notify_wait(&pc.notify);
- else if (!ob_is_empty() && (int)ob.begin != next) {
- ob_chunk *beginChunk = ob_get_chunk(ob.begin);
- unsigned int fadePosition;
- if (do_xfade == XFADE_ENABLED && next >= 0 &&
- (fadePosition = ob_relative(next))
- <= crossFadeChunks) {
- /* perform cross fade */
- if (nextChunk < 0) {
- /* beginning of the cross fade
- - adjust crossFadeChunks
- which might be bigger than
- the remaining number of
- chunks in the old song */
- crossFadeChunks = fadePosition;
- }
- nextChunk = ob_absolute(crossFadeChunks);
- if (nextChunk >= 0) {
- ob_set_lazy(1);
- cross_fade_apply(beginChunk,
- ob_get_chunk(nextChunk),
- &(ob.audioFormat),
- fadePosition,
- crossFadeChunks);
- } else {
- /* there are not enough
- decoded chunks yet */
- if (dc.state == DECODE_STATE_STOP) {
- /* the decoder isn't
- running, abort
- cross fading */
- do_xfade = XFADE_DISABLED;
- } else {
- /* wait for the
- decoder */
- ob_set_lazy(0);
- notify_wait(&pc.notify);
- continue;
- }
- }
- }
-
- /* play the current chunk */
- if (playChunk(beginChunk, &(ob.audioFormat),
- sizeToTime) < 0)
- break;
- ob_shift();
- notify_signal(&dc.notify);
- } else if (!ob_is_empty() && (int)ob.begin == next) {
- /* at the beginning of a new song */
-
- if (do_xfade == XFADE_ENABLED && nextChunk >= 0) {
- /* the cross-fade is finished; skip
- the section which was cross-faded
- (and thus already played) */
- ob_skip(crossFadeChunks);
- }
-
- do_xfade = XFADE_UNKNOWN;
-
- /* wait for the decoder to work on the new song */
- if (pc.queueState == PLAYER_QUEUE_DECODE ||
- pc.queueLockState == PLAYER_QUEUE_LOCKED) {
- notify_wait(&pc.notify);
- continue;
- }
- if (pc.queueState != PLAYER_QUEUE_PLAY)
- break;
-
- next = -1;
- if (waitOnDecode(&decodeWaitedOn) < 0)
- return;
-
- pc.queueState = PLAYER_QUEUE_EMPTY;
- wakeup_main_task();
- } else if (dc.state == DECODE_STATE_STOP &&
- dc.command != DECODE_COMMAND_START) {
- break;
- } else {
- /*DEBUG("waiting for decoded audio, play silence\n");*/
- if (playAudio(silence, CHUNK_SIZE) < 0)
- break;
- }
- }
-
- quitDecode();
-}
-
-/* decode w/ buffering
- * this will fork another process
- * child process does decoding
- * parent process does playing audio
- */
-void decode(void)
-{
- ob_clear();
- dc.next_song = pc.next_song;
- dc.error = DECODE_ERROR_NOERROR;
- dc_command(DECODE_COMMAND_START);
-
- decodeParent();
-}