mirror of
http://mpg123.de/trunk/.git
synced 2025-10-28 02:55:29 +03:00
More communicative buffer and normalized usage of which.
No nastly killing or SIGSTOP anymore; buffer either plays or waits for commands, including termination. This fixes the terminal behaviour with track skip and seek when stopped: The buffer can be resynced while being stopped, so no forced restart of playback on track skip anymore. The only nagging usability issue remaining with the buffer is the inability to seek while playing. Refilling of the buffer effects in fast-forward only. git-svn-id: svn://scm.orgis.org/mpg123/trunk@1251 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
@@ -385,7 +385,6 @@ int open_output(audio_output_t *ao)
|
|||||||
error("ao should not be NULL here!");
|
error("ao should not be NULL here!");
|
||||||
exit(110);
|
exit(110);
|
||||||
}
|
}
|
||||||
debug3("ao=%p, ao->is_open=%i, ao->open=%p", ao, ao->is_open, ao->open);
|
|
||||||
ao->is_open = ao->open(ao) < 0 ? FALSE : TRUE;
|
ao->is_open = ao->open(ao) < 0 ? FALSE : TRUE;
|
||||||
if(!ao->is_open)
|
if(!ao->is_open)
|
||||||
{
|
{
|
||||||
|
|||||||
86
src/buffer.c
86
src/buffer.c
@@ -44,16 +44,22 @@ void real_buffer_ignore_lowmem(void)
|
|||||||
xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_WAKEUP);
|
xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_WAKEUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void real_buffer_end(void)
|
void real_buffer_end(int rude)
|
||||||
{
|
{
|
||||||
if (!buffermem)
|
if (!buffermem)
|
||||||
return;
|
return;
|
||||||
xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_TERMINATE);
|
xfermem_putcmd(buffermem->fd[XF_WRITER], rude ? XF_CMD_ABORT : XF_CMD_TERMINATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void real_buffer_resync(void)
|
void real_buffer_resync(void)
|
||||||
{
|
{
|
||||||
buffer_sig(SIGINT, TRUE);
|
if(buffermem->justwait)
|
||||||
|
{
|
||||||
|
buffermem->wakeme[XF_WRITER] = TRUE;
|
||||||
|
xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_RESYNC);
|
||||||
|
xfermem_getcmd(buffermem->fd[XF_WRITER], TRUE);
|
||||||
|
}
|
||||||
|
else buffer_sig(SIGINT, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void real_plain_buffer_resync(void)
|
void real_plain_buffer_resync(void)
|
||||||
@@ -68,12 +74,18 @@ void real_buffer_reset(void)
|
|||||||
|
|
||||||
void real_buffer_start(void)
|
void real_buffer_start(void)
|
||||||
{
|
{
|
||||||
buffer_sig(SIGCONT, FALSE);
|
if(buffermem->justwait)
|
||||||
|
{
|
||||||
|
debug("ending buffer's waiting");
|
||||||
|
buffermem->justwait = FALSE;
|
||||||
|
xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_WAKEUP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void real_buffer_stop(void)
|
void real_buffer_stop()
|
||||||
{
|
{
|
||||||
buffer_sig(SIGSTOP, FALSE);
|
buffermem->justwait = TRUE;
|
||||||
|
buffer_sig(SIGINT, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int buffer_pid;
|
extern int buffer_pid;
|
||||||
@@ -142,14 +154,25 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (intflag) {
|
if (intflag) {
|
||||||
|
debug("handle intflag... flushing");
|
||||||
intflag = FALSE;
|
intflag = FALSE;
|
||||||
if (param.outmode == DECODE_AUDIO)
|
if (param.outmode == DECODE_AUDIO) ao->flush(ao);
|
||||||
ao->flush(ao);
|
/* Either prepare for waiting or empty buffer now. */
|
||||||
xf->readindex = xf->freeindex;
|
if(!xf->justwait) xf->readindex = xf->freeindex;
|
||||||
if (xf->wakeme[XF_WRITER])
|
else
|
||||||
xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
|
{
|
||||||
|
int cmd;
|
||||||
|
debug("Prepare for waiting; draining command queue. (There's a lot of wakeup commands pending, usually.)");
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cmd = xfermem_getcmd(my_fd, FALSE);
|
||||||
|
/* debug1("drain: %i", cmd); */
|
||||||
|
} while(cmd > 0);
|
||||||
|
}
|
||||||
|
if(xf->wakeme[XF_WRITER]) xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
|
||||||
}
|
}
|
||||||
if (usr1flag) {
|
if (usr1flag) {
|
||||||
|
debug("handling usr1flag");
|
||||||
usr1flag = FALSE;
|
usr1flag = FALSE;
|
||||||
/* close and re-open in order to flush
|
/* close and re-open in order to flush
|
||||||
* the device's internal buffer before
|
* the device's internal buffer before
|
||||||
@@ -182,19 +205,19 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
|||||||
if(preload < outburst)
|
if(preload < outburst)
|
||||||
preload = outburst;
|
preload = outburst;
|
||||||
}
|
}
|
||||||
if(bytes < preload) {
|
debug1("bytes: %i", bytes);
|
||||||
|
if(xf->justwait || bytes < preload) {
|
||||||
int cmd;
|
int cmd;
|
||||||
if (done && !bytes) {
|
if (done && !bytes) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!done) {
|
if(xf->justwait || !done) {
|
||||||
|
|
||||||
/* Don't spill into errno check below. */
|
/* Don't spill into errno check below. */
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
cmd = xfermem_block(XF_READER, xf);
|
cmd = xfermem_block(XF_READER, xf);
|
||||||
|
debug1("got %i", cmd);
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
|
|
||||||
/* More input pending. */
|
/* More input pending. */
|
||||||
@@ -205,23 +228,34 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
|||||||
*/
|
*/
|
||||||
case XF_CMD_WAKEUP:
|
case XF_CMD_WAKEUP:
|
||||||
break; /* Proceed playing. */
|
break; /* Proceed playing. */
|
||||||
case XF_CMD_TERMINATE:
|
case XF_CMD_ABORT: /* Immediate end, discard buffer contents. */
|
||||||
/* Proceed playing without
|
return; /* Cleanup happens outside of buffer_loop()*/
|
||||||
* blocking any further.
|
case XF_CMD_TERMINATE: /* Graceful end, playing stuff in buffer and then return. */
|
||||||
*/
|
debug("going to terminate");
|
||||||
done=TRUE;
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
case XF_CMD_RESYNC:
|
||||||
|
debug("ordered resync");
|
||||||
|
if (param.outmode == DECODE_AUDIO) ao->flush(ao);
|
||||||
|
|
||||||
|
xf->readindex = xf->freeindex;
|
||||||
|
if (xf->wakeme[XF_WRITER]) xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
|
||||||
|
continue;
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
if(errno==EINTR) /* Got signal, handle it at top of loop... */
|
if(intflag || usr1flag) /* Got signal, handle it at top of loop... */
|
||||||
|
{
|
||||||
|
debug("buffer interrupted");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if(errno)
|
if(errno)
|
||||||
perror("Yuck! Error in buffer handling... or somewhere unexpected.");
|
error1("Yuck! Error in buffer handling... or somewhere unexpected: %s", strerror(errno));
|
||||||
done = TRUE;
|
done = TRUE;
|
||||||
xf->readindex = xf->freeindex;
|
xf->readindex = xf->freeindex;
|
||||||
xfermem_putcmd(xf->fd[XF_READER], XF_CMD_TERMINATE);
|
xfermem_putcmd(xf->fd[XF_READER], XF_CMD_TERMINATE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "\nEh!? Received unknown command 0x%x in buffer process. Tell Daniel!\n", cmd);
|
fprintf(stderr, "\nEh!? Received unknown command 0x%x in buffer process.\n", cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +263,7 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
|||||||
* audio settings. We do not want to lower the preload mark
|
* audio settings. We do not want to lower the preload mark
|
||||||
* just yet!
|
* just yet!
|
||||||
*/
|
*/
|
||||||
if (!bytes)
|
if (xf->justwait || !bytes)
|
||||||
continue;
|
continue;
|
||||||
preload = outburst; /* set preload to lower mark */
|
preload = outburst; /* set preload to lower mark */
|
||||||
if (bytes > xf->size - xf->readindex)
|
if (bytes > xf->size - xf->readindex)
|
||||||
@@ -238,6 +272,7 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
|||||||
bytes = outburst;
|
bytes = outburst;
|
||||||
|
|
||||||
/* Could change that to use flush_output.... need to capture return value, then. */
|
/* Could change that to use flush_output.... need to capture return value, then. */
|
||||||
|
debug("write");
|
||||||
if (param.outmode == DECODE_FILE)
|
if (param.outmode == DECODE_FILE)
|
||||||
bytes = write(OutputDescriptor, xf->data + xf->readindex, bytes);
|
bytes = write(OutputDescriptor, xf->data + xf->readindex, bytes);
|
||||||
else if (param.outmode == DECODE_AUDIO)
|
else if (param.outmode == DECODE_AUDIO)
|
||||||
@@ -246,7 +281,7 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
|||||||
|
|
||||||
if(bytes < 0) {
|
if(bytes < 0) {
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
if(errno != EINTR) {
|
if(!intflag && !usr1flag) {
|
||||||
perror("Ouch ... error while writing audio data: ");
|
perror("Ouch ... error while writing audio data: ");
|
||||||
/*
|
/*
|
||||||
* done==TRUE tells writer process to stop
|
* done==TRUE tells writer process to stop
|
||||||
@@ -261,6 +296,7 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
|||||||
xf->readindex = xf->freeindex;
|
xf->readindex = xf->freeindex;
|
||||||
xfermem_putcmd(xf->fd[XF_READER], XF_CMD_TERMINATE);
|
xfermem_putcmd(xf->fd[XF_READER], XF_CMD_TERMINATE);
|
||||||
}
|
}
|
||||||
|
else debug("buffer interrupted");
|
||||||
}
|
}
|
||||||
|
|
||||||
xf->readindex = (xf->readindex + bytes) % xf->size;
|
xf->readindex = (xf->readindex + bytes) % xf->size;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
void real_buffer_ignore_lowmem(void);
|
void real_buffer_ignore_lowmem(void);
|
||||||
void real_buffer_end(void);
|
void real_buffer_end(int rude);
|
||||||
void real_buffer_resync(void);
|
void real_buffer_resync(void);
|
||||||
void real_plain_buffer_resync(void);
|
void real_plain_buffer_resync(void);
|
||||||
void real_buffer_reset(void);
|
void real_buffer_reset(void);
|
||||||
@@ -30,7 +30,7 @@ void real_buffer_stop(void);
|
|||||||
#define buffer_reset() (param.usebuffer ? real_buffer_reset(),0 : 0)
|
#define buffer_reset() (param.usebuffer ? real_buffer_reset(),0 : 0)
|
||||||
#define buffer_resync() (param.usebuffer ? real_buffer_resync(),0 : 0)
|
#define buffer_resync() (param.usebuffer ? real_buffer_resync(),0 : 0)
|
||||||
#define plain_buffer_resync() (param.usebuffer ? real_plain_buffer_resync(),0 : 0)
|
#define plain_buffer_resync() (param.usebuffer ? real_plain_buffer_resync(),0 : 0)
|
||||||
#define buffer_end() (param.usebuffer ? real_buffer_end(),0 : 0)
|
#define buffer_end(a) (param.usebuffer ? real_buffer_end(a),0 : 0)
|
||||||
#define buffer_ignore_lowmem() (param.usebuffer ? real_buffer_ignore_lowmem(),0 : 0)
|
#define buffer_ignore_lowmem() (param.usebuffer ? real_buffer_ignore_lowmem(),0 : 0)
|
||||||
#else
|
#else
|
||||||
#define buffer_start()
|
#define buffer_start()
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ void generic_sendinfo (char *filename)
|
|||||||
|
|
||||||
static void generic_load(mpg123_handle *fr, char *arg, int state)
|
static void generic_load(mpg123_handle *fr, char *arg, int state)
|
||||||
{
|
{
|
||||||
|
if(param.usebuffer)
|
||||||
|
{
|
||||||
|
buffer_resync();
|
||||||
|
if(mode == MODE_PAUSED && state != MODE_PAUSED) buffer_start();
|
||||||
|
}
|
||||||
if(mode != MODE_STOPPED)
|
if(mode != MODE_STOPPED)
|
||||||
{
|
{
|
||||||
close_track();
|
close_track();
|
||||||
@@ -110,6 +115,7 @@ static void generic_load(mpg123_handle *fr, char *arg, int state)
|
|||||||
|
|
||||||
if(htd.icy_name.fill) generic_sendmsg("I ICY-NAME: %s", htd.icy_name.p);
|
if(htd.icy_name.fill) generic_sendmsg("I ICY-NAME: %s", htd.icy_name.p);
|
||||||
if(htd.icy_url.fill) generic_sendmsg("I ICY-URL: %s", htd.icy_url.p);
|
if(htd.icy_url.fill) generic_sendmsg("I ICY-URL: %s", htd.icy_url.p);
|
||||||
|
|
||||||
mode = state;
|
mode = state;
|
||||||
init = 1;
|
init = 1;
|
||||||
generic_sendmsg(mode == MODE_PAUSED ? "P 1" : "P 2");
|
generic_sendmsg(mode == MODE_PAUSED ? "P 1" : "P 2");
|
||||||
@@ -264,11 +270,11 @@ int control_generic (mpg123_handle *fr)
|
|||||||
{
|
{
|
||||||
if (mode == MODE_PLAYING) {
|
if (mode == MODE_PLAYING) {
|
||||||
mode = MODE_PAUSED;
|
mode = MODE_PAUSED;
|
||||||
buffer_stop();
|
if(param.usebuffer) buffer_stop();
|
||||||
generic_sendmsg("P 1");
|
generic_sendmsg("P 1");
|
||||||
} else {
|
} else {
|
||||||
mode = MODE_PLAYING;
|
mode = MODE_PLAYING;
|
||||||
buffer_start();
|
if(param.usebuffer) buffer_start();
|
||||||
generic_sendmsg("P 2");
|
generic_sendmsg("P 2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,6 +284,11 @@ int control_generic (mpg123_handle *fr)
|
|||||||
/* STOP */
|
/* STOP */
|
||||||
if (!strcasecmp(comstr, "S") || !strcasecmp(comstr, "STOP")) {
|
if (!strcasecmp(comstr, "S") || !strcasecmp(comstr, "STOP")) {
|
||||||
if (mode != MODE_STOPPED) {
|
if (mode != MODE_STOPPED) {
|
||||||
|
if(param.usebuffer)
|
||||||
|
{
|
||||||
|
buffer_stop();
|
||||||
|
buffer_resync();
|
||||||
|
}
|
||||||
close_track();
|
close_track();
|
||||||
mode = MODE_STOPPED;
|
mode = MODE_STOPPED;
|
||||||
generic_sendmsg("P 0");
|
generic_sendmsg("P 0");
|
||||||
@@ -375,6 +386,8 @@ int control_generic (mpg123_handle *fr)
|
|||||||
generic_sendmsg("E Error while seeking: %s", mpg123_strerror(fr));
|
generic_sendmsg("E Error while seeking: %s", mpg123_strerror(fr));
|
||||||
mpg123_seek(fr, 0, SEEK_SET);
|
mpg123_seek(fr, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
if(param.usebuffer) buffer_resync();
|
||||||
|
|
||||||
generic_sendmsg("K %li", (long)mpg123_tell(fr));
|
generic_sendmsg("K %li", (long)mpg123_tell(fr));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
51
src/mpg123.c
51
src/mpg123.c
@@ -118,10 +118,18 @@ int buffer_pid;
|
|||||||
size_t bufferblock = 0;
|
size_t bufferblock = 0;
|
||||||
|
|
||||||
static int intflag = FALSE;
|
static int intflag = FALSE;
|
||||||
|
static int skip_tracks = 0;
|
||||||
int OutputDescriptor;
|
int OutputDescriptor;
|
||||||
static int filept = -1;
|
static int filept = -1;
|
||||||
char *binpath; /* Path to myself. */
|
char *binpath; /* Path to myself. */
|
||||||
|
|
||||||
|
void set_intflag()
|
||||||
|
{
|
||||||
|
debug("set_intflag TRUE");
|
||||||
|
intflag = TRUE;
|
||||||
|
skip_tracks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(WIN32) && !defined(GENERIC)
|
#if !defined(WIN32) && !defined(GENERIC)
|
||||||
static void catch_interrupt(void)
|
static void catch_interrupt(void)
|
||||||
{
|
{
|
||||||
@@ -133,6 +141,7 @@ static void catch_interrupt(void)
|
|||||||
void next_track(void)
|
void next_track(void)
|
||||||
{
|
{
|
||||||
intflag = TRUE;
|
intflag = TRUE;
|
||||||
|
++skip_tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void safe_exit(int code)
|
void safe_exit(int code)
|
||||||
@@ -758,15 +767,10 @@ int main(int argc, char *argv[])
|
|||||||
if(!param.remote) prepare_playlist(argc, argv);
|
if(!param.remote) prepare_playlist(argc, argv);
|
||||||
|
|
||||||
#if !defined(WIN32) && !defined(GENERIC)
|
#if !defined(WIN32) && !defined(GENERIC)
|
||||||
/* This ctrl+c for title skip only when not in some control mode */
|
/* Remote mode is special... but normal console and terminal-controlled operation needs to catch the SIGINT.
|
||||||
if
|
For one it serves for track skip when not in terminal control mode.
|
||||||
(
|
The more important use being a graceful exit, including telling the buffer process what's going on. */
|
||||||
!param.remote
|
if(!param.remote) catchsignal (SIGINT, catch_interrupt);
|
||||||
#ifdef HAVE_TERMIOS
|
|
||||||
&& !param.term_ctrl
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
catchsignal (SIGINT, catch_interrupt);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(param.remote) {
|
if(param.remote) {
|
||||||
@@ -780,6 +784,13 @@ int main(int argc, char *argv[])
|
|||||||
while ((fname = get_next_file()))
|
while ((fname = get_next_file()))
|
||||||
{
|
{
|
||||||
char *dirname, *filename;
|
char *dirname, *filename;
|
||||||
|
/* skip_tracks includes the previous one. */
|
||||||
|
if(skip_tracks) --skip_tracks;
|
||||||
|
if(skip_tracks)
|
||||||
|
{
|
||||||
|
debug("Skipping this track.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
frames_left = param.frame_number;
|
frames_left = param.frame_number;
|
||||||
debug1("Going to play %s", strcmp(fname, "-") ? fname : "standard input");
|
debug1("Going to play %s", strcmp(fname, "-") ? fname : "standard input");
|
||||||
|
|
||||||
@@ -886,6 +897,7 @@ tc_hack:
|
|||||||
while ((s = xfermem_get_usedspace(buffermem)))
|
while ((s = xfermem_get_usedspace(buffermem)))
|
||||||
{
|
{
|
||||||
struct timeval wait170 = {0, 170000};
|
struct timeval wait170 = {0, 170000};
|
||||||
|
if(intflag) break;
|
||||||
buffer_ignore_lowmem();
|
buffer_ignore_lowmem();
|
||||||
if(param.verbose) print_stat(mh,0,s);
|
if(param.verbose) print_stat(mh,0,s);
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
@@ -929,6 +941,7 @@ tc_hack:
|
|||||||
* no pressing need to keep up this first second SIGINT hack that was too
|
* no pressing need to keep up this first second SIGINT hack that was too
|
||||||
* often mistaken as a bug. [dk]
|
* often mistaken as a bug. [dk]
|
||||||
* ThOr: Yep, I deactivated the Ctrl+C hack for active control modes.
|
* ThOr: Yep, I deactivated the Ctrl+C hack for active control modes.
|
||||||
|
* Though, some sort of hack remains, still using intflag for track skip.
|
||||||
*/
|
*/
|
||||||
#if !defined(WIN32) && !defined(GENERIC)
|
#if !defined(WIN32) && !defined(GENERIC)
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
@@ -942,8 +955,23 @@ tc_hack:
|
|||||||
else
|
else
|
||||||
secdiff -= (start_time.tv_usec - now.tv_usec) / 1000;
|
secdiff -= (start_time.tv_usec - now.tv_usec) / 1000;
|
||||||
if (secdiff < 1000)
|
if (secdiff < 1000)
|
||||||
|
{
|
||||||
|
debug("got the second interrupt: out of here!");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug("It's a track advancement message.");
|
||||||
|
++skip_tracks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_TERMIOS
|
||||||
|
else if(skip_tracks == 0)
|
||||||
|
{
|
||||||
|
debug("breaking up");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
intflag = FALSE;
|
intflag = FALSE;
|
||||||
|
|
||||||
@@ -954,12 +982,15 @@ tc_hack:
|
|||||||
} /* end of loop over input files */
|
} /* end of loop over input files */
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
if (param.usebuffer) {
|
if (param.usebuffer) {
|
||||||
buffer_end();
|
debug("ending buffer");
|
||||||
|
buffer_stop(); /* Puts buffer into waiting-for-command mode. */
|
||||||
|
buffer_end(intflag); /* Gives command to end operation. */
|
||||||
xfermem_done_writer (buffermem);
|
xfermem_done_writer (buffermem);
|
||||||
waitpid (buffer_pid, NULL, 0);
|
waitpid (buffer_pid, NULL, 0);
|
||||||
xfermem_done (buffermem);
|
xfermem_done (buffermem);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
debug("close output");
|
||||||
/* Close the output... doesn't matter if buffer handled it, that's taken care of. */
|
/* Close the output... doesn't matter if buffer handled it, that's taken care of. */
|
||||||
close_output(ao);
|
close_output(ao);
|
||||||
close_output_module(ao);
|
close_output_module(ao);
|
||||||
|
|||||||
@@ -188,4 +188,5 @@ extern struct parameter param;
|
|||||||
void next_track(void);
|
void next_track(void);
|
||||||
int open_track(char *fname);
|
int open_track(char *fname);
|
||||||
void close_track(void);
|
void close_track(void);
|
||||||
|
void set_intflag(void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
49
src/term.c
49
src/term.c
@@ -156,24 +156,11 @@ static long term_handle_input(mpg123_handle *fr, int do_delay)
|
|||||||
switch(tolower(val)) {
|
switch(tolower(val)) {
|
||||||
case BACK_KEY:
|
case BACK_KEY:
|
||||||
if(!param.usebuffer) ao->flush(ao);
|
if(!param.usebuffer) ao->flush(ao);
|
||||||
/*
|
else buffer_resync();
|
||||||
* NOTE: rd->rewind() calls buffer_resync() that blocks until
|
|
||||||
* buffer process returns ACK. If buffer process is stopped, we
|
|
||||||
* end up in a deadlock. The only acceptable workaround was to
|
|
||||||
* resume playing as soon as BACK_KEY is pressed. This is not
|
|
||||||
* necessary when running non-buffered but I chose to remain
|
|
||||||
* compatible. [dk] -- now the resync is explicitly here... [ThOr]
|
|
||||||
*/
|
|
||||||
if(stopped) {
|
|
||||||
stopped = 0;
|
|
||||||
if(param.usebuffer)
|
|
||||||
buffer_start();
|
|
||||||
fprintf(stderr, "%s", EMPTY_STRING);
|
|
||||||
}
|
|
||||||
if(paused) pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr));
|
if(paused) pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr));
|
||||||
|
|
||||||
mpg123_seek_frame(fr, 0, SEEK_SET);
|
if(mpg123_seek_frame(fr, 0, SEEK_SET) < 0)
|
||||||
if(param.usebuffer) buffer_resync();
|
error1("Seek to begin failed: %s", mpg123_strerror(fr));
|
||||||
|
|
||||||
framenum=0;
|
framenum=0;
|
||||||
break;
|
break;
|
||||||
@@ -183,9 +170,18 @@ static long term_handle_input(mpg123_handle *fr, int do_delay)
|
|||||||
next_track();
|
next_track();
|
||||||
break;
|
break;
|
||||||
case QUIT_KEY:
|
case QUIT_KEY:
|
||||||
if (buffer_pid)
|
debug("QUIT");
|
||||||
kill(buffer_pid, SIGTERM);
|
if(stopped)
|
||||||
kill(getpid(), SIGTERM);
|
{
|
||||||
|
stopped = 0;
|
||||||
|
if(param.usebuffer)
|
||||||
|
{
|
||||||
|
buffer_resync();
|
||||||
|
buffer_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_intflag();
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
case PAUSE_KEY:
|
case PAUSE_KEY:
|
||||||
paused=1-paused;
|
paused=1-paused;
|
||||||
@@ -193,10 +189,11 @@ static long term_handle_input(mpg123_handle *fr, int do_delay)
|
|||||||
pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr));
|
pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr));
|
||||||
offset -= pause_cycle;
|
offset -= pause_cycle;
|
||||||
}
|
}
|
||||||
if(stopped) {
|
if(stopped)
|
||||||
stopped=0;
|
{
|
||||||
buffer_start();
|
stopped=0;
|
||||||
}
|
if(param.usebuffer) buffer_start();
|
||||||
|
}
|
||||||
fprintf(stderr, "%s", (paused) ? PAUSED_STRING : EMPTY_STRING);
|
fprintf(stderr, "%s", (paused) ? PAUSED_STRING : EMPTY_STRING);
|
||||||
break;
|
break;
|
||||||
case STOP_KEY:
|
case STOP_KEY:
|
||||||
@@ -208,7 +205,11 @@ static long term_handle_input(mpg123_handle *fr, int do_delay)
|
|||||||
paused=0;
|
paused=0;
|
||||||
offset -= pause_cycle;
|
offset -= pause_cycle;
|
||||||
}
|
}
|
||||||
if(stopped) buffer_stop(); else buffer_start();
|
if(param.usebuffer)
|
||||||
|
{
|
||||||
|
if(stopped) buffer_stop();
|
||||||
|
else buffer_start();
|
||||||
|
}
|
||||||
fprintf(stderr, "%s", (stopped) ? STOPPED_STRING : EMPTY_STRING);
|
fprintf(stderr, "%s", (stopped) ? STOPPED_STRING : EMPTY_STRING);
|
||||||
break;
|
break;
|
||||||
case FINE_REWIND_KEY:
|
case FINE_REWIND_KEY:
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ void xfermem_init (txfermem **xf, size_t bufsize, size_t msize, size_t skipbuf)
|
|||||||
(*xf)->metadata = ((byte *) *xf) + sizeof(txfermem);
|
(*xf)->metadata = ((byte *) *xf) + sizeof(txfermem);
|
||||||
(*xf)->size = bufsize;
|
(*xf)->size = bufsize;
|
||||||
(*xf)->metasize = msize + skipbuf;
|
(*xf)->metasize = msize + skipbuf;
|
||||||
|
(*xf)->justwait = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xfermem_done (txfermem *xf)
|
void xfermem_done (txfermem *xf)
|
||||||
@@ -242,6 +243,7 @@ int xfermem_write(txfermem *xf, byte *buffer, size_t bytes)
|
|||||||
/* Advance the free space pointer, including the wrap. */
|
/* Advance the free space pointer, including the wrap. */
|
||||||
xf->freeindex = (xf->freeindex + bytes) % xf->size;
|
xf->freeindex = (xf->freeindex + bytes) % xf->size;
|
||||||
/* Wake up the buffer process if necessary. */
|
/* Wake up the buffer process if necessary. */
|
||||||
|
debug("write waking");
|
||||||
if(xf->wakeme[XF_READER]) xfermem_putcmd(xf->fd[XF_WRITER], XF_CMD_WAKEUP_INFO);
|
if(xf->wakeme[XF_READER]) xfermem_putcmd(xf->fd[XF_WRITER], XF_CMD_WAKEUP_INFO);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ typedef struct {
|
|||||||
long rate;
|
long rate;
|
||||||
int channels;
|
int channels;
|
||||||
int format;
|
int format;
|
||||||
|
int justwait;
|
||||||
} txfermem;
|
} txfermem;
|
||||||
/*
|
/*
|
||||||
* [W] -- May be written to by the writing process only!
|
* [W] -- May be written to by the writing process only!
|
||||||
@@ -54,6 +55,8 @@ size_t xfermem_get_usedspace (txfermem *xf);
|
|||||||
#define XF_CMD_WAKEUP 0x02
|
#define XF_CMD_WAKEUP 0x02
|
||||||
#define XF_CMD_TERMINATE 0x03
|
#define XF_CMD_TERMINATE 0x03
|
||||||
#define XF_CMD_AUDIOCAP 0x05
|
#define XF_CMD_AUDIOCAP 0x05
|
||||||
|
#define XF_CMD_RESYNC 0x06
|
||||||
|
#define XF_CMD_ABORT 0x07
|
||||||
#define XF_WRITER 0
|
#define XF_WRITER 0
|
||||||
#define XF_READER 1
|
#define XF_READER 1
|
||||||
int xfermem_getcmd (int fd, int block);
|
int xfermem_getcmd (int fd, int block);
|
||||||
|
|||||||
Reference in New Issue
Block a user