diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | e2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch) | |
tree | 9047cf9e6b5c43878d5bf82660adae77ceee097a /mpg123_artsplugin/mpg123/buffer.c | |
download | tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'mpg123_artsplugin/mpg123/buffer.c')
-rw-r--r-- | mpg123_artsplugin/mpg123/buffer.c | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/mpg123_artsplugin/mpg123/buffer.c b/mpg123_artsplugin/mpg123/buffer.c new file mode 100644 index 00000000..3c85b654 --- /dev/null +++ b/mpg123_artsplugin/mpg123/buffer.c @@ -0,0 +1,245 @@ +/* + * buffer.c + * + * Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de> + * Mon Apr 14 03:53:18 MET DST 1997 + */ + +#include <stdlib.h> +#include <errno.h> + +#include "mpg123.h" + +int outburst = MAXOUTBURST; +int preload; + +static int intflag = FALSE; +static int usr1flag = FALSE; + +static void catch_interrupt (void) +{ + intflag = TRUE; +} + +static void catch_usr1 (void) +{ + usr1flag = TRUE; +} + +/* Interfaces to writer process */ + +extern void buffer_sig(int signal, int block); + +void buffer_ignore_lowmem(void) +{ +#ifndef NOXFERMEM + if(buffermem->wakeme[XF_READER]) + xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_WAKEUP); +#endif +} + +void buffer_end(void) +{ +#ifndef NOXFERMEM + xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_TERMINATE); +#endif +} + +void buffer_resync(void) +{ + buffer_sig(SIGINT, TRUE); +} + +void buffer_reset(void) +{ + buffer_sig(SIGUSR1, TRUE); +} + +void buffer_start(void) +{ + buffer_sig(SIGCONT, FALSE); +} + +void buffer_stop(void) +{ + buffer_sig(SIGSTOP, FALSE); +} + +extern int buffer_pid; + +void buffer_sig(int signal, int block) +{ + +#ifndef NOXFERMEM + + kill(buffer_pid, signal); + + if (!buffermem || !block) + return; + + if(xfermem_block(XF_WRITER, buffermem) != XF_CMD_WAKEUP) + perror("Could not resync/reset buffers"); +#endif + + return; +} + +#ifndef NOXFERMEM + +void buffer_loop(struct audio_info_struct *ai, sigset_t *oldsigset) +{ + int bytes; + int my_fd = buffermem->fd[XF_READER]; + txfermem *xf = buffermem; + int done = FALSE; + + catchsignal (SIGINT, catch_interrupt); + catchsignal (SIGUSR1, catch_usr1); + sigprocmask (SIG_SETMASK, oldsigset, NULL); +#ifndef NO_DECODE_AUDIO + if (param.outmode == DECODE_AUDIO) { + if (audio_open(ai) < 0) { + perror("audio"); + exit(1); + } + } +#endif + + for (;;) { + if (intflag) { + intflag = FALSE; +#ifndef NO_DECODE_AUDIO + if (param.outmode == DECODE_AUDIO) + audio_queueflush (ai); +#endif + xf->readindex = xf->freeindex; + if (xf->wakeme[XF_WRITER]) + xfermem_putcmd(my_fd, XF_CMD_WAKEUP); + } + if (usr1flag) { + usr1flag = FALSE; + /* close and re-open in order to flush + * the device's internal buffer before + * changing the sample rate. [OF] + */ + /* writer must block when sending SIGUSR1 + * or we will lose all data processed + * in the meantime! [dk] + */ + xf->readindex = xf->freeindex; + /* We've nailed down the new starting location - + * writer is now safe to go on. [dk] + */ + if (xf->wakeme[XF_WRITER]) + xfermem_putcmd(my_fd, XF_CMD_WAKEUP); +#ifndef NO_DECODE_AUDIO + if (param.outmode == DECODE_AUDIO) { + audio_close (ai); + ai->rate = xf->buf[0]; + ai->channels = xf->buf[1]; + ai->format = xf->buf[2]; + if (audio_open(ai) < 0) { + sleep(1); + /* give em a 2. try */ + if (audio_open(ai) < 0) { + perror("audio"); + exit(1); + } + } + } +#endif + } + if ( (bytes = xfermem_get_usedspace(xf)) < outburst ) { + /* if we got a buffer underrun we first + * fill 1/8 of the buffer before continue/start + * playing */ + preload = xf->size>>3; + if(preload < outburst) + preload = outburst; + } + if(bytes < preload) { + int cmd; + if (done && !bytes) { + break; + } + + if(!done) { + + cmd = xfermem_block(XF_READER, xf); + + switch(cmd) { + + /* More input pending. */ + case XF_CMD_WAKEUP_INFO: + continue; + /* Yes, we know buffer is low but + * know we don't care. + */ + case XF_CMD_WAKEUP: + break; /* Proceed playing. */ + case XF_CMD_TERMINATE: + /* Proceed playing without + * blocking any further. + */ + done=TRUE; + break; + case -1: + if(errno==EINTR) + continue; + perror("Yuck! Error in buffer handling..."); + done = TRUE; + xf->readindex = xf->freeindex; + xfermem_putcmd(xf->fd[XF_READER], XF_CMD_TERMINATE); + break; + default: + fprintf(stderr, "\nEh!? Received unknown command 0x%x in buffer process. Tell Daniel!\n", cmd); + } + } + } + preload = outburst; /* set preload to lower mark */ + if (bytes > xf->size - xf->readindex) + bytes = xf->size - xf->readindex; + if (bytes > outburst) + bytes = outburst; + + if (param.outmode == DECODE_FILE) + bytes = write(OutputDescriptor, xf->data + xf->readindex, bytes); +#ifndef NO_DECODE_AUDIO + else if (param.outmode == DECODE_AUDIO) + bytes = audio_play_samples(ai, + (unsigned char *) (xf->data + xf->readindex), bytes); +#endif + + if(bytes < 0) { + bytes = 0; + if(errno != EINTR) { + perror("Ouch ... error while writing audio data: "); + /* + * done==TRUE tells writer process to stop + * sending data. There might be some latency + * involved when resetting readindex to + * freeindex so we might need more than one + * cycle to terminate. (The number of cycles + * should be finite unless I managed to mess + * up something. ;-) [dk] + */ + done = TRUE; + xf->readindex = xf->freeindex; + xfermem_putcmd(xf->fd[XF_READER], XF_CMD_TERMINATE); + } + } + + xf->readindex = (xf->readindex + bytes) % xf->size; + if (xf->wakeme[XF_WRITER]) + xfermem_putcmd(my_fd, XF_CMD_WAKEUP); + } + +#ifndef NO_DECODE_AUDIO + if (param.outmode == DECODE_AUDIO) + audio_close (ai); +#endif +} + +#endif + +/* EOF */ |