summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2009-02-10 18:25:09 +0000
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2009-02-10 18:25:09 +0000
commit1c19b8e8e3cfb32e341332b751686e86d7389569 (patch)
tree64d9edcf312915b3d9ae524d55b6508b61bf361f
parentc62b455944c8c91bd4d9ae5e8000ec33190174c5 (diff)
parent6002a9a87b3f591832c2b91ca1b2b1b67be008f5 (diff)
downloadxine-lib-1c19b8e8e3cfb32e341332b751686e86d7389569.tar.gz
xine-lib-1c19b8e8e3cfb32e341332b751686e86d7389569.tar.bz2
Merge from 1.1.
--HG-- rename : doc/faq/faq.sgml => doc/faq/faq.docbook rename : src/xine-engine/buffer.h => include/xine/buffer.h rename : src/xine-engine/xine_internal.h => include/xine/xine_internal.h
-rw-r--r--.hgtags1
-rw-r--r--ChangeLog12
-rw-r--r--doc/faq/faq.docbook13
-rw-r--r--include/xine/buffer.h3
-rw-r--r--include/xine/xine_internal.h1
-rw-r--r--src/combined/ffmpeg/ff_audio_decoder.c4
-rw-r--r--src/demuxers/demux_4xm.c4
-rw-r--r--src/input/input_dvb.c4
-rw-r--r--src/input/input_file.c4
-rw-r--r--src/input/input_gnome_vfs.c4
-rw-r--r--src/input/input_http.c4
-rw-r--r--src/input/input_mms.c4
-rw-r--r--src/input/input_net.c4
-rw-r--r--src/input/input_pnm.c4
-rw-r--r--src/input/input_pvr.c4
-rw-r--r--src/input/input_rtp.c4
-rw-r--r--src/input/input_rtsp.c4
-rw-r--r--src/input/input_smb.c4
-rw-r--r--src/input/input_stdin_fifo.c4
-rw-r--r--src/xine-engine/audio_decoder.c6
-rw-r--r--src/xine-engine/audio_out.c2
-rw-r--r--src/xine-engine/demux.c53
-rw-r--r--src/xine-engine/video_decoder.c2
-rw-r--r--src/xine-engine/xine.c6
-rw-r--r--src/xine-engine/xine_interface.c3
25 files changed, 122 insertions, 36 deletions
diff --git a/.hgtags b/.hgtags
index dd2255f7d..fedfb0905 100644
--- a/.hgtags
+++ b/.hgtags
@@ -79,3 +79,4 @@ ffe7962edb79c2ed967b82a82ccfb2ac7eb148a2 vdr-xine-version-802
17f8ed16524ba779af42913e51667e89b83a1887 xine-lib-1_1_15-release
e33280bcaa3b1f3f5b93e633e2225e2440ecfd7c xine-lib-1_1_16-release
01fac0a015581bbdf7e38561ad2a95405e2ca785 xine-lib-1_1_16_1-release
+ff19463729d8f9bbea35171d641c5f28cdacc7c8 xine-lib-1_1_16_2-release
diff --git a/ChangeLog b/ChangeLog
index 63f8f8bfe..7e250d002 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -69,12 +69,18 @@ xine-lib (1.1.90) (Unreleased)
colour controls, zooming, colour keying.
xine-lib (1.1.17) 2009-??-??
- * Build fixes related to ImageMagick 6.4 & later.
- * Fix an error in Matroska PTS calculation.
* Enable libmpeg2new. This is not yet production code; the old mpeg2
decoder remains the default.
- * Fix a broken size check in the pvr input plugin (ref. CVE-2008-5239).
+
+xine-lib (1.1.16.2) 2009-02-10
+ * Build fixes related to ImageMagick 6.4 & later.
+ * Fix an error in Matroska PTS calculation.
+ * Some front ends hang due to the hang fixes in 1.1.16. Fix this by
+ removing a break statement.
+ * Fix broken size checks in various input plugins (ref. CVE-2008-5239).
* More malloc checking (ref. CVE-2008-5240).
+ * Fix race conditions in gapless_switch (ref. kde bug #180339)
+ * Fix a possible integer overflow in the 4XM demuxer. (TKADV2009-004.txt)
xine-lib (1.1.16.1) 2009-01-11
* Fix build with older ffmpeg, both internal and in Debian 5.0.
diff --git a/doc/faq/faq.docbook b/doc/faq/faq.docbook
index 7b8acd7a9..4eb947e06 100644
--- a/doc/faq/faq.docbook
+++ b/doc/faq/faq.docbook
@@ -876,6 +876,19 @@
<filename>/opt/real/RealPlayer/codecs/</filename>. Restart xine then
and you should be able to watch Real files/streams.
</para>
+ <para>
+ Another way to get the Real codecs is to download them from the MPlayer website
+ <ulink url="http://www.mplayerhq.hu/design7/dload.html">
+ http://www.mplayerhq.hu/design7/dload.html
+ </ulink>.
+ The package is called "essential". Unpack it and move everything you
+ find inside to <filename>/usr/lib/codecs</filename> and set the
+ <parameter>decoder.external.real_codecs_path</parameter> in your xine config file
+ to <filename>/usr/lib/codecs</filename> (actually you can place them
+ anywhere you want, e.g. someplace in your home directory, but then you'll
+ have to set <parameter>decoder.external.real_codecs_path</parameter> accordingly).
+ Restart xine then and you should be able to watch Real files/streams.
+ </para>
</sect3>
<sect3 id="realnetworkstreams">
<title>What about (live) network streams (pnm://, rtsp:// style urls)?</title>
diff --git a/include/xine/buffer.h b/include/xine/buffer.h
index 76302dd93..6959b1de0 100644
--- a/include/xine/buffer.h
+++ b/include/xine/buffer.h
@@ -391,6 +391,9 @@ struct buf_element_s {
* decoder_info[2] carries denominator for display aspect ratio */
#define BUF_FLAG_ASPECT 0x0800
+/* represent the state of gapless_switch at the time buf was enqueued */
+#define BUF_FLAG_GAPLESS_SW 0x1000
+
/**
* \defgroup buffer_special Special buffer types:
diff --git a/include/xine/xine_internal.h b/include/xine/xine_internal.h
index b876030ee..c6e2b50b2 100644
--- a/include/xine/xine_internal.h
+++ b/include/xine/xine_internal.h
@@ -260,6 +260,7 @@ struct xine_stream_s {
* layers as they cannot call xine_stop. */
uint32_t early_finish_event:1; /*< do not wait fifos get empty before sending event */
uint32_t gapless_switch:1; /*< next stream switch will be gapless */
+ uint32_t keep_ao_driver_open:1;
input_class_t *eject_class;
demux_plugin_t *demux_plugin;
diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c
index 893e405b1..bae0f92a4 100644
--- a/src/combined/ffmpeg/ff_audio_decoder.c
+++ b/src/combined/ffmpeg/ff_audio_decoder.c
@@ -332,8 +332,10 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
while (out < decode_buffer_size) {
int stream_status = xine_get_status(this->stream);
- if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP)
+ if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP) {
+ this->size = 0;
return;
+ }
audio_buffer =
this->stream->audio_out->get_buffer (this->stream->audio_out);
diff --git a/src/demuxers/demux_4xm.c b/src/demuxers/demux_4xm.c
index 62146cffc..0870179fe 100644
--- a/src/demuxers/demux_4xm.c
+++ b/src/demuxers/demux_4xm.c
@@ -192,6 +192,10 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) {
const uint32_t current_track = _X_LE_32(&header[i + 8]);
if (current_track + 1 > fourxm->track_count) {
fourxm->track_count = current_track + 1;
+ if (fourxm->track_count >= UINT_MAX / sizeof(audio_track_t)) {
+ free(header);
+ return 0;
+ }
fourxm->tracks = realloc(fourxm->tracks,
fourxm->track_count * sizeof(audio_track_t));
if (!fourxm->tracks) {
diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c
index 2c25b9863..065a57b47 100644
--- a/src/input/input_dvb.c
+++ b/src/input/input_dvb.c
@@ -2590,7 +2590,9 @@ static buf_element_t *dvb_plugin_read_block (input_plugin_t *this_gen,
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
int total_bytes;
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_file.c b/src/input/input_file.c
index 387b8c4ea..26874db7c 100644
--- a/src/input/input_file.c
+++ b/src/input/input_file.c
@@ -169,7 +169,9 @@ static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buf
file_input_plugin_t *this = (file_input_plugin_t *) this_gen;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_gnome_vfs.c b/src/input/input_gnome_vfs.c
index cb0c88877..acb63dcf6 100644
--- a/src/input/input_gnome_vfs.c
+++ b/src/input/input_gnome_vfs.c
@@ -122,7 +122,9 @@ gnomevfs_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo,
off_t total_bytes;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_http.c b/src/input/input_http.c
index 3b87e003d..a4a37c501 100644
--- a/src/input/input_http.c
+++ b/src/input/input_http.c
@@ -474,7 +474,9 @@ static buf_element_t *http_plugin_read_block (input_plugin_t *this_gen, fifo_buf
off_t total_bytes;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_mms.c b/src/input/input_mms.c
index 3d06653ea..191d1aed0 100644
--- a/src/input/input_mms.c
+++ b/src/input/input_mms.c
@@ -123,7 +123,9 @@ static buf_element_t *mms_plugin_read_block (input_plugin_t *this_gen,
lprintf ("mms_plugin_read_block: %"PRId64" bytes...\n", todo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_net.c b/src/input/input_net.c
index 964995bf6..a052d5650 100644
--- a/src/input/input_net.c
+++ b/src/input/input_net.c
@@ -292,7 +292,9 @@ static buf_element_t *net_plugin_read_block (input_plugin_t *this_gen,
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
off_t total_bytes;
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_pnm.c b/src/input/input_pnm.c
index afb64e3f5..718473819 100644
--- a/src/input/input_pnm.c
+++ b/src/input/input_pnm.c
@@ -98,7 +98,9 @@ static buf_element_t *pnm_plugin_read_block (input_plugin_t *this_gen,
lprintf ("pnm_plugin_read_block: %"PRId64" bytes...\n", todo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_pvr.c b/src/input/input_pvr.c
index feacc0edf..07f5d955d 100644
--- a/src/input/input_pvr.c
+++ b/src/input/input_pvr.c
@@ -1209,7 +1209,9 @@ static buf_element_t *pvr_plugin_read_block (input_plugin_t *this_gen, fifo_buff
}
buf = fifo->buffer_pool_alloc (fifo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer(buf);
return NULL;
}
diff --git a/src/input/input_rtp.c b/src/input/input_rtp.c
index 4d1fb43a9..d8822a3e1 100644
--- a/src/input/input_rtp.c
+++ b/src/input/input_rtp.c
@@ -528,7 +528,9 @@ static buf_element_t *rtp_plugin_read_block (input_plugin_t *this_gen,
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
int total_bytes;
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c
index 0522f555b..0e5af6043 100644
--- a/src/input/input_rtsp.c
+++ b/src/input/input_rtsp.c
@@ -98,7 +98,9 @@ static buf_element_t *rtsp_plugin_read_block (input_plugin_t *this_gen,
lprintf ("rtsp_plugin_read_block: %"PRId64" bytes...\n", todo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_smb.c b/src/input/input_smb.c
index b7c864f50..3c2086cc3 100644
--- a/src/input/input_smb.c
+++ b/src/input/input_smb.c
@@ -92,7 +92,9 @@ smb_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo,
off_t total_bytes;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/input/input_stdin_fifo.c b/src/input/input_stdin_fifo.c
index 2797568b6..55ac18a42 100644
--- a/src/input/input_stdin_fifo.c
+++ b/src/input/input_stdin_fifo.c
@@ -124,7 +124,9 @@ static buf_element_t *stdin_plugin_read_block (input_plugin_t *this_gen, fifo_bu
/* stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; */
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
- if (todo < 0 || todo > buf->size) {
+ if (todo > buf->max_size)
+ todo = buf->max_size;
+ if (todo < 0) {
buf->free_buffer (buf);
return NULL;
}
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index 6a0688f0d..483567994 100644
--- a/src/xine-engine/audio_decoder.c
+++ b/src/xine-engine/audio_decoder.c
@@ -89,16 +89,18 @@ static void *audio_decoder_loop (void *stream_gen) {
if (stream->audio_decoder_plugin) {
lprintf ("close old decoder\n");
-
+
+ stream->keep_ao_driver_open = !!(buf->decoder_flags & BUF_FLAG_GAPLESS_SW);
_x_free_audio_decoder (stream, stream->audio_decoder_plugin);
stream->audio_decoder_plugin = NULL;
stream->audio_track_map_entries = 0;
stream->audio_type = 0;
+ stream->keep_ao_driver_open = 0;
}
running_ticket->release(running_ticket, 0);
- if( !stream->gapless_switch )
+ if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) )
stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0);
buftype_unknown = 0;
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index f16f482aa..cf202cf8f 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -1611,7 +1611,7 @@ static void ao_close(xine_audio_port_t *this_gen, xine_stream_t *stream) {
pthread_mutex_unlock(&this->streams_lock);
/* close driver if no streams left */
- if (!ite && !this->grab_only && !stream->gapless_switch) {
+ if (!ite && !this->grab_only && !stream->keep_ao_driver_open) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: no streams left, closing driver\n");
if (this->audio_loop_running) {
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c
index ed5abb247..449b9f991 100644
--- a/src/xine-engine/demux.c
+++ b/src/xine-engine/demux.c
@@ -120,6 +120,16 @@ void _x_demux_flush_engine (xine_stream_t *stream) {
}
+struct timespec _x_compute_interval(unsigned int millisecs) {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ uint64_t ttimer = (uint64_t)ts.tv_sec*1000 + ts.tv_nsec/1000000 + millisecs;
+ ts.tv_sec = ttimer/1000;
+ ts.tv_nsec = (ttimer%1000)*1000000;
+ return ts;
+}
+
+
void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags ) {
buf_element_t *buf;
@@ -147,19 +157,20 @@ void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags
*/
static int demux_unstick_ao_loop (xine_stream_t *stream)
{
- if (!stream->audio_thread_created)
+/* if (!stream->audio_thread_created)
return 0;
-
+*/
int status = xine_get_status (stream);
- if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP)
+ if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP && stream->demux_plugin->get_status(stream->demux_plugin) != DEMUX_FINISHED)
return 0;
-
+#if 0
/* right, stream is stopped... */
audio_buffer_t *buf = stream->audio_out->get_buffer (stream->audio_out);
buf->num_frames = 0;
buf->stream = NULL;
stream->audio_out->put_buffer (stream->audio_out, buf, stream);
-
+#endif
+ lprintf("stuck\n");
return 1;
}
@@ -200,24 +211,27 @@ void _x_demux_control_headers_done (xine_stream_t *stream) {
stream->audio_fifo->put (stream->audio_fifo, buf_audio);
pthread_mutex_unlock(&stream->demux_mutex);
+ unsigned int max_iterations = 0;
while ((stream->header_count_audio < header_count_audio) ||
(stream->header_count_video < header_count_video)) {
- struct timeval tv;
- struct timespec ts;
lprintf ("waiting for headers. v:%d %d a:%d %d\n",
stream->header_count_video, header_count_video,
stream->header_count_audio, header_count_audio);
+
+ struct timespec ts = _x_compute_interval(1000);
+ int ret_wait;
- gettimeofday(&tv, NULL);
- ts.tv_sec = tv.tv_sec + 1;
- ts.tv_nsec = tv.tv_usec * 1000;
/* use timedwait to workaround buggy pthread broadcast implementations */
- pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts);
+ ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts);
- if (demux_unstick_ao_loop (stream))
+ if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) {
+ xine_log(stream->xine,
+ XINE_LOG_MSG,_("Stuck in _x_demux_control_headers_done(). Taking the emergency exit\n"));
+ stream->emergency_brake = 1;
break;
+ }
}
stream->demux_action_pending = 0;
@@ -231,15 +245,18 @@ void _x_demux_control_headers_done (xine_stream_t *stream) {
void _x_demux_control_start( xine_stream_t *stream ) {
buf_element_t *buf;
+ uint32_t flags = (stream->gapless_switch) ? BUF_FLAG_GAPLESS_SW : 0;
pthread_mutex_lock(&stream->demux_mutex);
buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo);
buf->type = BUF_CONTROL_START;
+ buf->decoder_flags = flags;
stream->video_fifo->put (stream->video_fifo, buf);
buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo);
buf->type = BUF_CONTROL_START;
+ buf->decoder_flags = flags;
stream->audio_fifo->put (stream->audio_fifo, buf);
pthread_mutex_unlock(&stream->demux_mutex);
@@ -371,13 +388,21 @@ static void *demux_loop (void *stream_gen) {
pthread_mutex_unlock( &stream->demux_lock );
pthread_mutex_lock (&stream->counter_lock);
+ struct timespec ts;
+ unsigned int max_iterations = 0;
+ int ret_wait;
while ((stream->finished_count_audio < finished_count_audio) ||
(stream->finished_count_video < finished_count_video)) {
lprintf ("waiting for finisheds.\n");
- pthread_cond_wait (&stream->counter_changed, &stream->counter_lock);
+ ts = _x_compute_interval(1000);
+ ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts);
- if (demux_unstick_ao_loop (stream))
+ if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) {
+ xine_log(stream->xine,
+ XINE_LOG_MSG,_("Stuck in demux_loop(). Taking the emergency exit\n"));
+ stream->emergency_brake = 1;
break;
+ }
}
pthread_mutex_unlock (&stream->counter_lock);
diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c
index 3cc4e37f7..af22ecdd0 100644
--- a/src/xine-engine/video_decoder.c
+++ b/src/xine-engine/video_decoder.c
@@ -161,7 +161,7 @@ static void *video_decoder_loop (void *stream_gen) {
running_ticket->release(running_ticket, 0);
- if( !stream->gapless_switch )
+ if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) )
stream->metronom->handle_video_discontinuity (stream->metronom,
DISC_STREAMSTART, 0);
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 722e04679..86b099922 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -456,6 +456,7 @@ void xine_stop (xine_stream_t *stream) {
static void close_internal (xine_stream_t *stream) {
int i ;
+ int gapless_switch = stream->gapless_switch;
if( stream->slave ) {
xine_close( stream->slave );
@@ -466,7 +467,7 @@ static void close_internal (xine_stream_t *stream) {
}
}
- if( !stream->gapless_switch ) {
+ if( !gapless_switch ) {
/* make sure that other threads cannot change the speed, especially pauseing the stream */
pthread_mutex_lock(&stream->speed_change_lock);
stream->ignore_speed_change = 1;
@@ -482,7 +483,7 @@ static void close_internal (xine_stream_t *stream) {
stop_internal( stream );
- if( !stream->gapless_switch ) {
+ if( !gapless_switch ) {
if (stream->video_out)
stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0);
if (stream->audio_out)
@@ -637,6 +638,7 @@ xine_stream_t *xine_stream_new (xine_t *this,
stream->early_finish_event = 0;
stream->delay_finish_event = 0;
stream->gapless_switch = 0;
+ stream->keep_ao_driver_open = 0;
stream->video_out = vo;
if (vo)
diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c
index 43a40f51c..a2015bb06 100644
--- a/src/xine-engine/xine_interface.c
+++ b/src/xine-engine/xine_interface.c
@@ -518,6 +518,9 @@ void xine_set_param (xine_stream_t *stream, int param, int value) {
case XINE_PARAM_GAPLESS_SWITCH:
stream->gapless_switch = !!value;
+ if( stream->gapless_switch && !stream->early_finish_event ) {
+ xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "frontend possibly buggy: gapless_switch without early_finish_event\n");
+ }
break;
default: