Mercurial > audlegacy
changeset 890:ed26947bbf57 trunk
[svn] Gapless support. This comes with a few caveats, that I will mention here:
1) It is not really gapless, it just removes any delays caused by
resetting the output device. Mileage depends on source performance.
However, this commit reduces any gaps I have to a period of time that is
unnoticable to me. (Of course, I have a 15k RPM SATA drive too.)
author | nenolod |
---|---|
date | Mon, 27 Mar 2006 13:05:09 -0800 |
parents | 21e0ef28e318 |
children | 08b940c25a9a |
files | audacious/input.c audacious/input.h audacious/mainwin.c audacious/output.c audacious/output.h audacious/playback.c |
diffstat | 6 files changed, 157 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/audacious/input.c Mon Mar 27 11:02:35 2006 -0800 +++ b/audacious/input.c Mon Mar 27 13:05:09 2006 -0800 @@ -60,6 +60,7 @@ NULL, FALSE, FALSE, + FALSE, NULL };
--- a/audacious/input.h Mon Mar 27 11:02:35 2006 -0800 +++ b/audacious/input.h Mon Mar 27 13:05:09 2006 -0800 @@ -31,6 +31,7 @@ InputPlugin *current_input_plugin; gboolean playing; gboolean paused; + gboolean stop; GMutex *playback_mutex; };
--- a/audacious/mainwin.c Mon Mar 27 11:02:35 2006 -0800 +++ b/audacious/mainwin.c Mon Mar 27 13:05:09 2006 -0800 @@ -2088,8 +2088,10 @@ void mainwin_stop_pushed(void) { + ip_data.stop = TRUE; mainwin_clear_song_info(); bmp_playback_stop(); + ip_data.stop = FALSE; } void
--- a/audacious/output.c Mon Mar 27 11:02:35 2006 -0800 +++ b/audacious/output.c Mon Mar 27 13:05:09 2006 -0800 @@ -36,6 +36,12 @@ NULL }; +OutputPluginState op_state = { + 0, + 0, + 0 +}; + OutputPlugin psuedo_output_plugin = { NULL, NULL, @@ -46,17 +52,16 @@ NULL, output_get_volume, output_set_volume, - NULL, /* XXX we need noop code for this */ - NULL, - NULL, + output_open_audio, + output_write_audio, + output_close_audio, - NULL, - NULL, - NULL, - NULL, + output_flush, + output_pause, + output_buffer_free, + output_buffer_playing, get_output_time, get_written_time, - NULL }; @@ -215,6 +220,127 @@ return op->output_time(); } +gint +output_open_audio(AFormat fmt, gint rate, gint nch) +{ + gint ret; + OutputPlugin *op; + + op = get_current_output_plugin(); + + if (op == NULL) + return -1; + + /* Is our output port already open? */ + if ((op_state.rate != 0 && op_state.nch != 0) && + (op_state.rate == rate && op_state.nch == nch)) + { + /* Yes, and it's the correct sampling rate. Reset the counter and go. */ + op->flush(0); + return 1; + } + else if (op_state.rate != 0 && op_state.nch != 0) + op->close_audio(); + + ret = op->open_audio(fmt, rate, nch); + + if (ret == 1) /* Success? */ + { + op_state.fmt = fmt; + op_state.rate = rate; + op_state.nch = nch; + } + + return ret; +} + +void +output_write_audio(gpointer ptr, gint length) +{ + OutputPlugin *op = get_current_output_plugin(); + + /* Sanity check. */ + if (op == NULL) + return; + + op->write_audio(ptr, length); +} + +void +output_close_audio(void) +{ + OutputPlugin *op = get_current_output_plugin(); + + /* Do not close if there are still songs to play and the user has + * not requested a stop. --nenolod + */ + if (ip_data.stop == FALSE && + (playlist_get_position_nolock() < playlist_get_length_nolock() - 1)) + return; + + /* Sanity check. */ + if (op == NULL) + return; + +#if 0 + g_print("Requirements to close audio output have been met:\n" + "ip_data.stop = %d\n" + "playlist_get_position_nolock() = %d\n" + "playlist_get_length_nolock() - 1 = %d\n", + ip_data.stop, playlist_get_position_nolock(), + playlist_get_length_nolock() - 1); +#endif + + op->close_audio(); + + /* Reset the op_state. */ + op_state.fmt = op_state.rate = op_state.nch = 0; +} + +void +output_flush(gint time) +{ + OutputPlugin *op = get_current_output_plugin(); + + if (op == NULL) + return; + + op->flush(time); +} + +void +output_pause(gshort paused) +{ + OutputPlugin *op = get_current_output_plugin(); + + if (op == NULL) + return; + + op->pause(paused); +} + +gint +output_buffer_free(void) +{ + OutputPlugin *op = get_current_output_plugin(); + + if (op == NULL) + return 0; + + return op->buffer_free(); +} + +gint +output_buffer_playing(void) +{ + OutputPlugin *op = get_current_output_plugin(); + + if (op == NULL) + return 0; + + return op->buffer_playing(); +} + /* called by input plugin when data is ready */ void produce_audio(gint time, /* position */ @@ -261,5 +387,5 @@ g_usleep(10000); /* else sleep for retry */ } - op->write_audio(ptr, length); /* do output */ + op->write_audio(ptr, length); /* do output */ }
--- a/audacious/output.h Mon Mar 27 11:02:35 2006 -0800 +++ b/audacious/output.h Mon Mar 27 13:05:09 2006 -0800 @@ -33,6 +33,14 @@ OutputPlugin *current_output_plugin; }; +typedef struct _OutputPluginState OutputPluginState; + +struct _OutputPluginState { + AFormat fmt; + gint rate; + gint nch; +}; + GList *get_output_list(void); OutputPlugin *get_current_output_plugin(void); void set_current_output_plugin(gint i); @@ -41,6 +49,15 @@ void output_get_volume(gint * l, gint * r); void output_set_volume(gint l, gint r); void output_set_eq(gboolean, gfloat, gfloat *); +gint output_open_audio(AFormat, gint, gint); +void output_write_audio(gpointer ptr, gint length); +void output_close_audio(void); + +void output_flush(gint); +void output_pause(gshort); +gint output_buffer_free(void); +gint output_buffer_playing(void); + void produce_audio(gint, AFormat, gint, gint, gpointer, int *); gint get_written_time(void);
--- a/audacious/playback.c Mon Mar 27 11:02:35 2006 -0800 +++ b/audacious/playback.c Mon Mar 27 13:05:09 2006 -0800 @@ -231,7 +231,7 @@ } set_current_input_plugin(entry->decoder); - entry->decoder->output = get_current_output_plugin(); + entry->decoder->output = &psuedo_output_plugin; entry->decoder->play_file(entry->filename); ip_data.playing = TRUE;