summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/xine-engine/audio_decoder.c46
-rw-r--r--src/xine-engine/osd.c35
-rw-r--r--src/xine-engine/osd.h5
-rw-r--r--src/xine-engine/post.c115
-rw-r--r--src/xine-engine/post.h59
-rw-r--r--src/xine-engine/video_decoder.c40
-rw-r--r--src/xine-engine/xine.c230
-rw-r--r--src/xine-engine/xine_interface.c116
-rw-r--r--src/xine-engine/xine_internal.h67
9 files changed, 458 insertions, 255 deletions
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index ffccf247e..e6c6411f3 100644
--- a/src/xine-engine/audio_decoder.c
+++ b/src/xine-engine/audio_decoder.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_decoder.c,v 1.119 2004/01/09 01:26:34 miguelfreitas Exp $
+ * $Id: audio_decoder.c,v 1.120 2004/02/12 18:19:12 mroi Exp $
*
*
* functions that implement audio decoding
@@ -51,6 +51,7 @@ static void *audio_decoder_loop (void *stream_gen) {
buf_element_t *last_header = NULL;
int replaying_headers = 0;
xine_stream_t *stream = (xine_stream_t *) stream_gen;
+ xine_ticket_t *running_ticket = stream->xine->port_ticket;
int running = 1;
int prof_audio_decode = -1;
uint32_t buftype_unknown = 0;
@@ -59,36 +60,26 @@ static void *audio_decoder_loop (void *stream_gen) {
if (prof_audio_decode == -1)
prof_audio_decode = xine_profiler_allocate_slot ("audio decoder/output");
+ running_ticket->acquire(running_ticket, 0);
+
while (running) {
lprintf ("audio_loop: waiting for package...\n");
- if( !replaying_headers )
+ if( !replaying_headers ) {
+ running_ticket->release(running_ticket, 0);
buf = stream->audio_fifo->get (stream->audio_fifo);
+ running_ticket->acquire(running_ticket, 0);
+ }
lprintf ("audio_loop: got package pts = %lld, type = %08x\n", buf->pts, buf->type);
_x_extra_info_merge( stream->audio_decoder_extra_info, buf->extra_info );
stream->audio_decoder_extra_info->seek_count = stream->video_seek_count;
-
- /* check for a new port to use */
- if (stream->next_audio_port) {
- uint32_t bits, rate;
- int mode;
-
- /* noone is allowed to modify the next port from now on */
- pthread_mutex_lock(&stream->next_audio_port_lock);
- if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) {
- /* register our stream at the new output port */
- stream->next_audio_port->open(stream->next_audio_port, stream, bits, rate, mode);
- stream->audio_out->close(stream->audio_out, stream);
- }
- stream->audio_out = stream->next_audio_port;
- stream->next_audio_port = NULL;
- pthread_mutex_unlock(&stream->next_audio_port_lock);
- pthread_cond_broadcast(&stream->next_audio_port_wired);
- }
-
+
+ if (running_ticket->ticket_revoked)
+ running_ticket->renew(running_ticket, 0);
+
switch (buf->type) {
case BUF_CONTROL_HEADERS_DONE:
@@ -112,7 +103,9 @@ static void *audio_decoder_loop (void *stream_gen) {
stream->audio_type = 0;
}
+ running_ticket->release(running_ticket, 0);
stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0);
+ running_ticket->acquire(running_ticket, 0);
buftype_unknown = 0;
break;
@@ -186,17 +179,23 @@ static void *audio_decoder_loop (void *stream_gen) {
case BUF_CONTROL_DISCONTINUITY:
if (stream->audio_decoder_plugin)
stream->audio_decoder_plugin->discontinuity (stream->audio_decoder_plugin);
+
+ running_ticket->release(running_ticket, 0);
stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off);
+ running_ticket->acquire(running_ticket, 0);
break;
case BUF_CONTROL_NEWPTS:
if (stream->audio_decoder_plugin)
stream->audio_decoder_plugin->discontinuity (stream->audio_decoder_plugin);
+
+ running_ticket->release(running_ticket, 0);
if (buf->decoder_flags & BUF_FLAG_SEEK) {
stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off);
} else {
stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_ABSOLUTE, buf->disc_off);
}
+ running_ticket->acquire(running_ticket, 0);
break;
case BUF_CONTROL_AUDIO_CHANNEL:
@@ -396,6 +395,8 @@ static void *audio_decoder_loop (void *stream_gen) {
}
}
+ running_ticket->release(running_ticket, 0);
+
return NULL;
}
@@ -461,9 +462,6 @@ void _x_audio_decoder_shutdown (xine_stream_t *stream) {
stream->audio_fifo->dispose (stream->audio_fifo);
stream->audio_fifo = NULL;
-
- /* wakeup any rewire operations */
- pthread_cond_broadcast(&stream->next_audio_port_wired);
}
int _x_get_audio_channel (xine_stream_t *stream) {
diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c
index 70213606a..4e16f06e6 100644
--- a/src/xine-engine/osd.c
+++ b/src/xine-engine/osd.c
@@ -48,6 +48,8 @@
#define LOG
*/
+#define XINE_ENGINE_INTERNAL
+
#include "xine_internal.h"
#include "video_out/alphablend.h"
#include "xine-engine/bswap.h"
@@ -173,14 +175,20 @@ static osd_object_t *osd_new_object (osd_renderer_t *this, int width, int height
static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) {
osd_renderer_t *this = osd->renderer;
+ video_overlay_manager_t *ovl_manager;
rle_elem_t rle, *rle_p=0;
int x, y, spare;
uint8_t *c;
lprintf("osd=%p vpts=%lld\n", osd, vpts);
+
+ this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1);
+
+ ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out);
if( osd->handle < 0 ) {
- if( (osd->handle = this->video_overlay->get_handle(this->video_overlay,0)) == -1 ) {
+ if( (osd->handle = ovl_manager->get_handle(ovl_manager, 0)) == -1 ) {
+ this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1);
return 0;
}
}
@@ -258,10 +266,12 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) {
this->event.event_type = OVERLAY_EVENT_SHOW;
this->event.vpts = vpts;
- this->video_overlay->add_event(this->video_overlay,(void *)&this->event);
+ ovl_manager->add_event(ovl_manager, (void *)&this->event);
}
pthread_mutex_unlock (&this->osd_mutex);
+ this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1);
+
return 1;
}
@@ -286,6 +296,7 @@ static int osd_show_unscaled (osd_object_t *osd, int64_t vpts) {
static int osd_hide (osd_object_t *osd, int64_t vpts) {
osd_renderer_t *this = osd->renderer;
+ video_overlay_manager_t *ovl_manager;
lprintf("osd=%p vpts=%lld\n",osd, vpts);
@@ -301,7 +312,11 @@ static int osd_hide (osd_object_t *osd, int64_t vpts) {
this->event.event_type = OVERLAY_EVENT_HIDE;
this->event.vpts = vpts;
- this->video_overlay->add_event(this->video_overlay,(void *)&this->event);
+
+ this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1);
+ ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out);
+ ovl_manager->add_event(ovl_manager, (void *)&this->event);
+ this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1);
pthread_mutex_unlock (&this->osd_mutex);
@@ -1211,6 +1226,7 @@ static void osd_preload_fonts (osd_renderer_t *this, char *path) {
static void osd_free_object (osd_object_t *osd_to_close) {
osd_renderer_t *this = osd_to_close->renderer;
+ video_overlay_manager_t *ovl_manager;
osd_object_t *osd, *last;
if( osd_to_close->handle >= 0 ) {
@@ -1222,8 +1238,12 @@ static void osd_free_object (osd_object_t *osd_to_close) {
memset( this->event.object.overlay, 0, sizeof(this->event.object.overlay) );
this->event.event_type = OVERLAY_EVENT_FREE_HANDLE;
this->event.vpts = 0;
- this->video_overlay->add_event(this->video_overlay,(void *)&this->event);
-
+
+ this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1);
+ ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out);
+ ovl_manager->add_event(ovl_manager, (void *)&this->event);
+ this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1);
+
osd_to_close->handle = -1; /* handle will be freed */
}
@@ -1314,9 +1334,11 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) {
capabilities |= XINE_OSD_CAP_FREETYPE2;
#endif
+ this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0);
if( this->stream->video_out->get_capabilities(this->stream->video_out) &
VO_CAP_UNSCALED_OVERLAY)
capabilities |= XINE_OSD_CAP_UNSCALED;
+ this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0);
return capabilities;
}
@@ -1326,13 +1348,12 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) {
* initialize the osd rendering engine
*/
-osd_renderer_t *_x_osd_renderer_init( video_overlay_manager_t *video_overlay, xine_stream_t *stream ) {
+osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) {
osd_renderer_t *this;
char str[1024];
this = xine_xmalloc(sizeof(osd_renderer_t));
- this->video_overlay = video_overlay;
this->stream = stream;
this->event.object.overlay = xine_xmalloc( sizeof(vo_overlay_t) );
diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h
index f1b884550..fc1a31bca 100644
--- a/src/xine-engine/osd.h
+++ b/src/xine-engine/osd.h
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* OSD stuff (text and graphic primitives)
- * $Id: osd.h,v 1.23 2003/12/09 00:02:36 f1rmb Exp $
+ * $Id: osd.h,v 1.24 2004/02/12 18:19:12 mroi Exp $
*/
#ifndef HAVE_OSD_H
@@ -215,7 +215,6 @@ struct osd_renderer_s {
/* private stuff */
pthread_mutex_t osd_mutex;
- video_overlay_manager_t *video_overlay;
video_overlay_event_t event;
osd_object_t *osds; /* instances of osd */
osd_font_t *fonts; /* loaded fonts */
@@ -228,7 +227,7 @@ struct osd_renderer_s {
/*
* initialize the osd rendering engine
*/
-osd_renderer_t *_x_osd_renderer_init( video_overlay_manager_t *video_overlay, xine_stream_t *stream );
+osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream );
/*
diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c
index 58771dbb9..ae9c9ab09 100644
--- a/src/xine-engine/post.c
+++ b/src/xine-engine/post.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: post.c,v 1.21 2004/01/07 19:52:43 mroi Exp $
+ * $Id: post.c,v 1.22 2004/02/12 18:19:12 mroi Exp $
*/
/*
@@ -56,7 +56,7 @@ static uint32_t post_video_get_capabilities(xine_video_port_t *port_gen) {
static void post_video_open(xine_video_port_t *port_gen, xine_stream_t *stream) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- _x_post_rewire_video(port);
+ _x_post_rewire(port->post);
_x_post_inc_usage(port);
if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->open(port->original_port, stream);
@@ -72,7 +72,7 @@ static vo_frame_t *post_video_get_frame(xine_video_port_t *port_gen, uint32_t wi
post_video_port_t *port = (post_video_port_t *)port_gen;
vo_frame_t *frame;
- _x_post_rewire_video(port);
+ _x_post_rewire(port->post);
if (port->port_lock) pthread_mutex_lock(port->port_lock);
frame = port->original_port->get_frame(port->original_port,
width, height, ratio, format, flags);
@@ -188,25 +188,20 @@ static int post_video_rewire(xine_post_out_t *output_gen, void *data) {
post_out_t *output = (post_out_t *)output_gen;
xine_video_port_t *new_port = (xine_video_port_t *)data;
post_video_port_t *input_port = (post_video_port_t *)output->user_data;
+ post_plugin_t *this = output->post;
if (!new_port)
return 0;
- pthread_mutex_lock(&input_port->next_port_lock);
- pthread_mutex_lock(&input_port->usage_lock);
- input_port->next_port = new_port;
- while (input_port->next_port) {
- if (input_port->usage_count == 0) {
- /* we can safely rewire right here, the plugin is not in use */
- input_port->original_port = new_port;
- input_port->next_port = NULL;
- }
- pthread_mutex_unlock(&input_port->usage_lock);
- if (input_port->next_port)
- pthread_cond_wait(&input_port->next_port_wire, &input_port->next_port_lock);
- pthread_mutex_lock(&input_port->usage_lock);
- }
- pthread_mutex_unlock(&input_port->usage_lock);
- pthread_mutex_unlock(&input_port->next_port_lock);
+
+ this->running_ticket->revoke(this->running_ticket, 1);
+
+ new_port->open(new_port, (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream);
+ input_port->original_port->close(input_port->original_port,
+ (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream);
+ input_port->original_port = new_port;
+
+ this->running_ticket->issue(this->running_ticket, 1);
+
return 1;
}
@@ -237,8 +232,6 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_
port->new_manager = &port->manager_storage;
port->post = post;
- pthread_mutex_init(&port->next_port_lock, NULL);
- pthread_cond_init(&port->next_port_wire, NULL);
pthread_mutex_init(&port->usage_lock, NULL);
pthread_mutex_init(&port->free_frames_lock, NULL);
@@ -268,22 +261,6 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_
}
-void _x_post_rewire_video(post_video_port_t *port) {
- if (port->next_port) {
- pthread_mutex_lock(&port->next_port_lock);
- if (port->next_port) {
- port->next_port->open(port->next_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream);
- port->original_port->close(port->original_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream);
- port->original_port = port->next_port;
- port->next_port = NULL;
- pthread_mutex_unlock(&port->next_port_lock);
- pthread_cond_broadcast(&port->next_port_wire);
- } else
- pthread_mutex_unlock(&port->next_port_lock);
- }
-}
-
-
/* dummy intercept functions for frames */
static void post_frame_free(vo_frame_t *vo_img) {
post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
@@ -630,7 +607,7 @@ static int post_audio_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
post_audio_port_t *port = (post_audio_port_t *)port_gen;
int result;
- _x_post_rewire_audio(port);
+ _x_post_rewire(port->post);
_x_post_inc_usage(port);
if (port->port_lock) pthread_mutex_lock(port->port_lock);
result = port->original_port->open(port->original_port, stream, bits, rate, mode);
@@ -649,7 +626,7 @@ static audio_buffer_t *post_audio_get_buffer(xine_audio_port_t *port_gen) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
audio_buffer_t *buf;
- _x_post_rewire_audio(port);
+ _x_post_rewire(port->post);
if (port->port_lock) pthread_mutex_lock(port->port_lock);
buf = port->original_port->get_buffer(port->original_port);
if (port->port_lock) pthread_mutex_unlock(port->port_lock);
@@ -723,25 +700,21 @@ static int post_audio_rewire(xine_post_out_t *output_gen, void *data) {
post_out_t *output = (post_out_t *)output_gen;
xine_audio_port_t *new_port = (xine_audio_port_t *)data;
post_audio_port_t *input_port = (post_audio_port_t *)output->user_data;
+ post_plugin_t *this = output->post;
if (!new_port)
return 0;
- pthread_mutex_lock(&input_port->next_port_lock);
- pthread_mutex_lock(&input_port->usage_lock);
- input_port->next_port = new_port;
- while (input_port->next_port) {
- if (input_port->usage_count == 0) {
- /* we can safely rewire right here, the plugin is not in use */
- input_port->original_port = new_port;
- input_port->next_port = NULL;
- }
- pthread_mutex_unlock(&input_port->usage_lock);
- if (input_port->next_port)
- pthread_cond_wait(&input_port->next_port_wire, &input_port->next_port_lock);
- pthread_mutex_lock(&input_port->usage_lock);
- }
- pthread_mutex_unlock(&input_port->usage_lock);
- pthread_mutex_unlock(&input_port->next_port_lock);
+
+ this->running_ticket->revoke(this->running_ticket, 1);
+
+ new_port->open(new_port, (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream,
+ input_port->bits, input_port->rate, input_port->mode);
+ input_port->original_port->close(input_port->original_port,
+ (input_port->stream == POST_NULL_STREAM) ? NULL : input_port->stream);
+ input_port->original_port = new_port;
+
+ this->running_ticket->issue(this->running_ticket, 1);
+
return 1;
}
@@ -767,8 +740,6 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_
port->original_port = original;
port->post = post;
- pthread_mutex_init(&port->next_port_lock, NULL);
- pthread_cond_init(&port->next_port_wire, NULL);
pthread_mutex_init(&port->usage_lock, NULL);
if (input) {
@@ -797,23 +768,6 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_
}
-void _x_post_rewire_audio(post_audio_port_t *port) {
- if (port->next_port) {
- pthread_mutex_lock(&port->next_port_lock);
- if (port->next_port) {
- port->next_port->open(port->next_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream,
- port->bits, port->rate, port->mode);
- port->original_port->close(port->original_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream);
- port->original_port = port->next_port;
- port->next_port = NULL;
- pthread_mutex_unlock(&port->next_port_lock);
- pthread_cond_broadcast(&port->next_port_wire);
- } else
- pthread_mutex_unlock(&port->next_port_lock);
- }
-}
-
-
int _x_post_dispose(post_plugin_t *this) {
int i, in_use = 0;
@@ -865,6 +819,9 @@ int _x_post_dispose(post_plugin_t *this) {
free(this->xine_post.audio_input);
free(this->xine_post.video_input);
+ /* these were allocated in the plugin loader */
+ free(this->input_ids);
+ free(this->output_ids);
for (input = xine_list_first_content(this->input); input;
input = xine_list_next_content(this->input)) {
@@ -874,8 +831,6 @@ int _x_post_dispose(post_plugin_t *this) {
post_video_port_t *port = (post_video_port_t *)input->data;
vo_frame_t *first, *second;
- pthread_mutex_destroy(&port->next_port_lock);
- pthread_cond_destroy(&port->next_port_wire);
pthread_mutex_destroy(&port->usage_lock);
pthread_mutex_destroy(&port->free_frames_lock);
@@ -893,8 +848,6 @@ int _x_post_dispose(post_plugin_t *this) {
{
post_audio_port_t *port = (post_audio_port_t *)input->data;
- pthread_mutex_destroy(&port->next_port_lock);
- pthread_cond_destroy(&port->next_port_wire);
pthread_mutex_destroy(&port->usage_lock);
free(port);
@@ -922,6 +875,12 @@ int _x_post_dispose(post_plugin_t *this) {
xine_list_free(this->input);
xine_list_free(this->output);
+ /* since the plugin loader does not know, when the plugin gets disposed,
+ * we have to handle the reference counter here */
+ pthread_mutex_lock(&this->xine->plugin_catalog->lock);
+ ((plugin_node_t *)this->node)->ref--;
+ pthread_mutex_unlock(&this->xine->plugin_catalog->lock);
+
return 1;
}
diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h
index 1ddc1b580..8e61a1009 100644
--- a/src/xine-engine/post.h
+++ b/src/xine-engine/post.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: post.h,v 1.17 2004/01/07 19:52:43 mroi Exp $
+ * $Id: post.h,v 1.18 2004/02/12 18:19:12 mroi Exp $
*
* post plugin definitions
*
@@ -97,14 +97,30 @@ struct post_plugin_s {
/* has dispose been called */
int dispose_pending;
- /* plugins don't have to care for the stuff below */
+ /* plugins don't have to init the stuff below */
+
+ /*
+ * the running ticket
+ *
+ * the plugin must assure to check for ticket revocation in
+ * intervals of finite length; this means that you must release
+ * the ticket before any operation that might block;
+ * note that all port functions are safe in this respect
+ *
+ * the running ticket is assigned to you by the engine
+ */
+ xine_ticket_t *running_ticket;
+
+ /* this is needed by the engine to decrement the reference counter
+ * on disposal of the plugin, but since this is useful, we expose it */
+ xine_t *xine;
/* used when the user requests a list of all inputs/outputs */
const char **input_ids;
const char **output_ids;
/* used by plugin loader */
- void *node;
+ void *node;
};
/* helper function to initialize a post_plugin_t */
@@ -157,13 +173,6 @@ struct post_video_port_s {
/* the original port to call its functions from inside yours */
xine_video_port_t *original_port;
- /* when we are rewiring, next port points to the new port */
- xine_video_port_t *next_port;
-
- /* rewiring synchronization */
- pthread_mutex_t next_port_lock;
- pthread_cond_t next_port_wire;
-
/* if you want to decide yourself, whether a given frame should
* be intercepted, fill in this function; get_frame() acts as
* a template method and asks your function; return a boolean;
@@ -232,11 +241,6 @@ struct post_video_port_s {
post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *port,
post_in_t **input, post_out_t **output);
-/* this will execute pending rewire operations, calling this at the beginning
- * of decoder-called functions like get_frame() and open() is a good idea
- * (if you do not intercept get_frame() or open(), this will be done automatically) */
-void _x_post_rewire_video(post_video_port_t *port);
-
/* use this to decorate and to undecorate a frame so that its functions
* can be replaced with own implementations, decoration is usually done in
* get_frame(), undecoration in frame->free() */
@@ -288,13 +292,6 @@ struct post_audio_port_s {
/* the original port to call its functions from inside yours */
xine_audio_port_t *original_port;
- /* when we are rewiring, next port points to the new port */
- xine_audio_port_t *next_port;
-
- /* rewiring synchronization */
- pthread_mutex_t next_port_lock;
- pthread_cond_t next_port_wire;
-
/* usage counter: how many objects are floating around that need
* these pointers to exist */
int usage_count;
@@ -325,11 +322,24 @@ struct post_audio_port_s {
post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *port,
post_in_t **input, post_out_t **output);
-/* this will execute pending rewire operations, calling this at the beginning
+
+/* this will allow pending rewire operations, calling this at the beginning
* of decoder-called functions like get_buffer() and open() is a good idea
* (if you do not intercept get_buffer() or open(), this will be done automatically) */
-void _x_post_rewire_audio(post_audio_port_t *port);
+static inline void _x_post_rewire(post_plugin_t *post) {
+ if (post->running_ticket->ticket_revoked)
+ post->running_ticket->renew(post->running_ticket, 1);
+}
+/* with these functions you can switch interruptions like rewiring or engine pausing
+ * off for a block of code; use this only when really necessary */
+static inline void _x_post_lock(post_plugin_t *post) {
+ post->running_ticket->acquire(post->running_ticket, 1);
+}
+static inline void _x_post_unlock(post_plugin_t *post) {
+ post->running_ticket->release(post->running_ticket, 1);
+ _x_post_rewire(post);
+}
/* the standard disposal operation; returns 1 if the plugin is really
* disposed and you should free everything you malloc()ed yourself */
@@ -354,7 +364,6 @@ do { \
pthread_mutex_lock(&(port)->usage_lock); \
(port)->usage_count--; \
if ((port)->usage_count == 0) { \
- pthread_cond_broadcast(&(port)->next_port_wire); \
if ((port)->post->dispose_pending) { \
pthread_mutex_unlock(&(port)->usage_lock); \
(port)->post->dispose((port)->post); \
diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c
index 49c115869..e9fe388d5 100644
--- a/src/xine-engine/video_decoder.c
+++ b/src/xine-engine/video_decoder.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_decoder.c,v 1.142 2003/12/05 15:55:05 f1rmb Exp $
+ * $Id: video_decoder.c,v 1.143 2004/02/12 18:19:12 mroi Exp $
*
*/
@@ -62,6 +62,7 @@ static void *video_decoder_loop (void *stream_gen) {
buf_element_t *buf;
xine_stream_t *stream = (xine_stream_t *) stream_gen;
+ xine_ticket_t *running_ticket = stream->xine->port_ticket;
int running = 1;
int streamtype;
int prof_video_decode = -1;
@@ -73,34 +74,24 @@ static void *video_decoder_loop (void *stream_gen) {
if (prof_spu_decode == -1)
prof_spu_decode = xine_profiler_allocate_slot ("spu decoder");
+ running_ticket->acquire(running_ticket, 0);
+
while (running) {
lprintf ("getting buffer...\n");
+ running_ticket->release(running_ticket, 0);
buf = stream->video_fifo->get (stream->video_fifo);
+ running_ticket->acquire(running_ticket, 0);
+
_x_extra_info_merge( stream->video_decoder_extra_info, buf->extra_info );
stream->video_decoder_extra_info->seek_count = stream->video_seek_count;
lprintf ("got buffer 0x%08x\n", buf->type);
- /* check for a new port to use */
- if (stream->next_video_port) {
- int64_t img_duration;
- int width, height;
-
- /* noone is allowed to modify the next port from now on */
- pthread_mutex_lock(&stream->next_video_port_lock);
- if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) {
- /* register our stream at the new output port */
- stream->next_video_port->open(stream->next_video_port, stream);
- stream->video_out->close(stream->video_out, stream);
- }
- stream->video_out = stream->next_video_port;
- stream->next_video_port = NULL;
- pthread_mutex_unlock(&stream->next_video_port_lock);
- pthread_cond_broadcast(&stream->next_video_port_wired);
- }
-
+ if (running_ticket->ticket_revoked)
+ running_ticket->renew(running_ticket, 0);
+
switch (buf->type & 0xffff0000) {
case BUF_CONTROL_HEADERS_DONE:
pthread_mutex_lock (&stream->counter_lock);
@@ -122,8 +113,10 @@ static void *video_decoder_loop (void *stream_gen) {
stream->spu_track_map_entries = 0;
}
+ running_ticket->release(running_ticket, 0);
stream->metronom->handle_video_discontinuity (stream->metronom,
DISC_STREAMSTART, 0);
+ running_ticket->acquire(running_ticket, 0);
buftype_unknown = 0;
break;
@@ -231,7 +224,9 @@ static void *video_decoder_loop (void *stream_gen) {
stream->video_decoder_plugin->discontinuity (stream->video_decoder_plugin);
}
+ running_ticket->release(running_ticket, 0);
stream->metronom->handle_video_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off);
+ running_ticket->acquire(running_ticket, 0);
break;
@@ -245,11 +240,13 @@ static void *video_decoder_loop (void *stream_gen) {
stream->video_decoder_plugin->discontinuity (stream->video_decoder_plugin);
}
+ running_ticket->release(running_ticket, 0);
if (buf->decoder_flags & BUF_FLAG_SEEK) {
stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off);
} else {
stream->metronom->handle_video_discontinuity (stream->metronom, DISC_ABSOLUTE, buf->disc_off);
}
+ running_ticket->acquire(running_ticket, 0);
break;
@@ -378,6 +375,8 @@ static void *video_decoder_loop (void *stream_gen) {
buf->free_buffer (buf);
}
+ running_ticket->release(running_ticket, 0);
+
return NULL;
}
@@ -455,7 +454,4 @@ void _x_video_decoder_shutdown (xine_stream_t *stream) {
stream->video_fifo->dispose (stream->video_fifo);
stream->video_fifo = NULL;
-
- /* wakeup any rewire operations */
- pthread_cond_broadcast(&stream->next_video_port_wired);
}
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 281cb0ac0..ec0de15d2 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine.c,v 1.280 2004/01/07 22:22:54 jstembridge Exp $
+ * $Id: xine.c,v 1.281 2004/02/12 18:19:00 mroi Exp $
*/
/*
@@ -127,15 +127,118 @@ void _x_extra_info_merge( extra_info_t *dst, extra_info_t *src ) {
}
}
+static void ticket_acquire(xine_ticket_t *this, int irrevocable) {
+
+ pthread_mutex_lock(&this->lock);
+
+ if (this->ticket_revoked && !this->irrevocable_tickets)
+ pthread_cond_wait(&this->issued, &this->lock);
+ else if (this->atomic_revoke && !pthread_equal(this->atomic_revoker_thread, pthread_self()))
+ pthread_cond_wait(&this->issued, &this->lock);
+
+ this->tickets_granted++;
+ if (irrevocable)
+ this->irrevocable_tickets++;
+
+ pthread_mutex_unlock(&this->lock);
+}
+
+static void ticket_release(xine_ticket_t *this, int irrevocable) {
+
+ pthread_mutex_lock(&this->lock);
+
+ this->tickets_granted--;
+ if (irrevocable)
+ this->irrevocable_tickets--;
+
+ if (this->ticket_revoked && !this->tickets_granted)
+ pthread_cond_broadcast(&this->revoked);
+ if (this->ticket_revoked && !this->irrevocable_tickets)
+ pthread_cond_wait(&this->issued, &this->lock);
+
+ pthread_mutex_unlock(&this->lock);
+}
+
+static void ticket_renew(xine_ticket_t *this, int irrevocable) {
+
+ pthread_mutex_lock(&this->lock);
+
+ this->tickets_granted--;
+
+ _x_assert(this->ticket_revoked);
+ if (!this->tickets_granted)
+ pthread_cond_broadcast(&this->revoked);
+ if (!this->irrevocable_tickets || !irrevocable)
+ pthread_cond_wait(&this->issued, &this->lock);
+
+ this->tickets_granted++;
+
+ pthread_mutex_unlock(&this->lock);
+}
+
+static void ticket_issue(xine_ticket_t *this, int atomic) {
+
+ if (!atomic)
+ pthread_mutex_lock(&this->revoke_lock);
+ pthread_mutex_lock(&this->lock);
+
+ this->pending_revocations--;
+ if (!this->pending_revocations)
+ pthread_cond_broadcast(&this->issued);
+ this->atomic_revoke = 0;
+
+ pthread_mutex_unlock(&this->lock);
+ pthread_mutex_unlock(&this->revoke_lock);
+}
+
+static void ticket_revoke(xine_ticket_t *this, int atomic) {
+
+ pthread_mutex_lock(&this->revoke_lock);
+ pthread_mutex_lock(&this->lock);
+
+ this->pending_revocations++;
+ this->ticket_revoked = 1;
+ if (this->tickets_granted)
+ pthread_cond_wait(&this->revoked, &this->lock);
+ _x_assert(!this->tickets_granted);
+ this->ticket_revoked = 0;
+ if (atomic) {
+ this->atomic_revoke = 1;
+ this->atomic_revoker_thread = pthread_self();
+ }
+
+ pthread_mutex_unlock(&this->lock);
+ if (!atomic)
+ pthread_mutex_unlock(&this->revoke_lock);
+}
+
+static void ticket_dispose(xine_ticket_t *this) {
+
+ pthread_mutex_destroy(&this->lock);
+ pthread_mutex_destroy(&this->revoke_lock);
+ pthread_cond_destroy(&this->issued);
+ pthread_cond_destroy(&this->revoked);
+
+ free(this);
+}
+
static void __set_speed_internal (xine_stream_t *stream, int speed) {
+ xine_t *xine = stream->xine;
+ if (xine->clock->speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE)
+ /* get all decoder and post threads in a state where they agree to be blocked */
+ xine->port_ticket->revoke(xine->port_ticket, 0);
+
+ if (xine->clock->speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE)
+ /* all decoder and post threads may continue now */
+ xine->port_ticket->issue(xine->port_ticket, 0);
+
stream->xine->clock->set_speed (stream->xine->clock, speed);
/* see coment on audio_out loop about audio_paused */
if( stream->audio_out ) {
- stream->audio_out->set_property( stream->audio_out, AO_PROP_PAUSED,
- (speed != XINE_SPEED_NORMAL) + (speed == XINE_SPEED_PAUSE) );
-
+ xine->port_ticket->acquire(xine->port_ticket, 1);
+
/*
* slow motion / fast forward does not play sound, drop buffered
* samples from the sound driver
@@ -145,6 +248,8 @@ static void __set_speed_internal (xine_stream_t *stream, int speed) {
stream->audio_out->control(stream->audio_out,
speed == XINE_SPEED_PAUSE ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME, NULL);
+
+ xine->port_ticket->release(xine->port_ticket, 1);
}
}
@@ -223,9 +328,10 @@ void xine_stop (xine_stream_t *stream) {
pthread_mutex_lock (&stream->frontend_lock);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
+
if (stream->audio_out)
stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1);
-
if (stream->video_out)
stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1);
@@ -235,11 +341,12 @@ void xine_stop (xine_stream_t *stream) {
xine_stop(stream->slave);
if (stream->video_out)
- stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0);
-
+ stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0);
if (stream->audio_out)
stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
+
pthread_mutex_unlock (&stream->frontend_lock);
}
@@ -299,24 +406,22 @@ static int __stream_rewire_audio(xine_post_out_t *output, void *data)
{
xine_stream_t *stream = (xine_stream_t *)output->data;
xine_audio_port_t *new_port = (xine_audio_port_t *)data;
- buf_element_t *buf;
-
+ uint32_t bits, rate;
+ int mode;
+
if (!data)
return 0;
- pthread_mutex_lock(&stream->next_audio_port_lock);
- stream->next_audio_port = new_port;
- if (stream->audio_thread) {
- buf = stream->audio_fifo->buffer_pool_try_alloc(stream->audio_fifo);
- if (buf) {
- /* wake up audio decoder thread */
- buf->type = BUF_CONTROL_NOP;
- stream->audio_fifo->insert(stream->audio_fifo, buf);
- }
- /* wait till rewiring is finished */
- pthread_cond_wait(&stream->next_audio_port_wired, &stream->next_audio_port_lock);
+ stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
+
+ if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) {
+ /* register our stream at the new output port */
+ new_port->open(new_port, stream, bits, rate, mode);
+ stream->audio_out->close(stream->audio_out, stream);
}
- pthread_mutex_unlock(&stream->next_audio_port_lock);
+ stream->audio_out = new_port;
+
+ stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
return 1;
}
@@ -325,24 +430,22 @@ static int __stream_rewire_video(xine_post_out_t *output, void *data)
{
xine_stream_t *stream = (xine_stream_t *)output->data;
xine_video_port_t *new_port = (xine_video_port_t *)data;
- buf_element_t *buf;
-
+ int64_t img_duration;
+ int width, height;
+
if (!data)
return 0;
- pthread_mutex_lock(&stream->next_video_port_lock);
- stream->next_video_port = new_port;
- if (stream->video_thread) {
- buf = stream->video_fifo->buffer_pool_try_alloc(stream->video_fifo);
- if (buf) {
- /* wake up video decoder thread */
- buf->type = BUF_CONTROL_NOP;
- stream->video_fifo->insert(stream->video_fifo, buf);
- }
- /* wait till rewiring is finished */
- pthread_cond_wait(&stream->next_video_port_wired, &stream->next_video_port_lock);
+ stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
+
+ if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) {
+ /* register our stream at the new output port */
+ new_port->open(new_port, stream);
+ stream->video_out->close(stream->video_out, stream);
}
- pthread_mutex_unlock(&stream->next_video_port_lock);
+ stream->video_out = new_port;
+
+ stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
return 1;
}
@@ -400,8 +503,6 @@ xine_stream_t *xine_stream_new (xine_t *this,
stream->finished_count_audio = 0;
stream->finished_count_video = 0;
stream->err = 0;
- stream->next_audio_port = NULL;
- stream->next_video_port = NULL;
stream->broadcaster = NULL;
/*
@@ -426,10 +527,6 @@ xine_stream_t *xine_stream_new (xine_t *this,
pthread_mutex_init (&stream->first_frame_lock, NULL);
pthread_cond_init (&stream->first_frame_reached, NULL);
pthread_mutex_init (&stream->current_extra_info_lock, NULL);
- pthread_mutex_init (&stream->next_video_port_lock, NULL);
- pthread_mutex_init (&stream->next_audio_port_lock, NULL);
- pthread_cond_init (&stream->next_video_port_wired, NULL);
- pthread_cond_init (&stream->next_audio_port_wired, NULL);
/*
* Clear meta/stream info
@@ -465,8 +562,7 @@ xine_stream_t *xine_stream_new (xine_t *this,
* osd
*/
if (vo)
- stream->osd_renderer = _x_osd_renderer_init (stream->video_out->get_overlay_manager (stream->video_out),
- stream );
+ stream->osd_renderer = _x_osd_renderer_init(stream);
else
stream->osd_renderer = NULL;
@@ -901,12 +997,6 @@ static int __open_internal (xine_stream_t *stream, const char *mrl) {
stream->input_plugin = NULL;
stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
- /* remove buffered samples from the sound device driver */
- /* why? */
- /*if (stream->audio_out)
- stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS, NULL);
- */
-
stream->status = XINE_STATUS_STOP;
xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "return from\n");
@@ -958,6 +1048,8 @@ static int __play_internal (xine_stream_t *stream, int start_pos, int start_time
if (stream->xine->clock->speed != XINE_SPEED_NORMAL)
__set_speed_internal (stream, XINE_SPEED_NORMAL);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
+
/* discard audio/video buffers to get engine going and take the lock faster */
if (stream->audio_out)
stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1);
@@ -999,6 +1091,8 @@ static int __play_internal (xine_stream_t *stream, int start_pos, int start_time
if (stream->video_out)
stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
+
/* before resuming the demuxer, set first_frame_flag */
pthread_mutex_lock (&stream->first_frame_lock);
stream->first_frame_flag = 2;
@@ -1123,10 +1217,6 @@ void xine_dispose (xine_stream_t *stream) {
pthread_mutex_destroy (&stream->demux_lock);
pthread_mutex_destroy (&stream->first_frame_lock);
pthread_cond_destroy (&stream->first_frame_reached);
- pthread_mutex_destroy (&stream->next_video_port_lock);
- pthread_mutex_destroy (&stream->next_audio_port_lock);
- pthread_cond_destroy (&stream->next_video_port_wired);
- pthread_cond_destroy (&stream->next_audio_port_wired);
stream->metronom->exit (stream->metronom);
@@ -1155,6 +1245,9 @@ void xine_exit (xine_t *this) {
if(this->config)
this->config->dispose(this->config);
+ if(this->port_ticket)
+ this->port_ticket->dispose(this->port_ticket);
+
#if defined(WIN32)
WSACleanup();
#endif
@@ -1212,12 +1305,21 @@ xine_t *xine_new (void) {
#endif /* WIN32 */
/*
- * streams_lock
+ * streams lock
*/
pthread_mutex_init (&this->streams_lock, NULL);
this->verbosity = XINE_VERBOSITY_NONE;
+
+ /*
+ * tickets
+ */
+
+ this->port_ticket = xine_xmalloc(sizeof(xine_ticket_t));
+ pthread_mutex_init(&this->port_ticket->lock, NULL);
+ pthread_mutex_init(&this->port_ticket->revoke_lock, NULL);
+ pthread_cond_init(&this->port_ticket->issued, NULL);
return this;
}
@@ -1338,7 +1440,17 @@ void xine_init (xine_t *this) {
this->clock = _x_metronom_clock_init(this);
this->clock->start_clock (this->clock, 0);
-
+
+ /*
+ * tickets
+ */
+ this->port_ticket->acquire = ticket_acquire;
+ this->port_ticket->release = ticket_release;
+ this->port_ticket->renew = ticket_renew;
+ this->port_ticket->issue = ticket_issue;
+ this->port_ticket->revoke = ticket_revoke;
+ this->port_ticket->dispose = ticket_dispose;
+
}
void _x_select_spu_channel (xine_stream_t *stream, int channel) {
@@ -1346,6 +1458,8 @@ void _x_select_spu_channel (xine_stream_t *stream, int channel) {
pthread_mutex_lock (&stream->frontend_lock);
stream->spu_channel_user = (channel >= -2 ? channel : -2);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+
switch (stream->spu_channel_user) {
case -2:
stream->spu_channel = -1;
@@ -1361,6 +1475,8 @@ void _x_select_spu_channel (xine_stream_t *stream, int channel) {
}
lprintf("set to %d\n",stream->spu_channel);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+
pthread_mutex_unlock (&stream->frontend_lock);
}
@@ -1485,8 +1601,10 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height,
vo_frame_t *frame;
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
frame = stream->video_out->get_last_frame (stream->video_out);
-
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+
if (!frame)
return 0;
diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c
index fff706bd2..e1a8abcb0 100644
--- a/src/xine-engine/xine_interface.c
+++ b/src/xine-engine/xine_interface.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_interface.c,v 1.77 2004/01/23 09:26:16 andruil Exp $
+ * $Id: xine_interface.c,v 1.78 2004/02/12 18:19:12 mroi Exp $
*
* convenience/abstraction layer, functions to implement
* libxine's public interface
@@ -361,33 +361,45 @@ void xine_set_param (xine_stream_t *stream, int param, int value) {
break;
case XINE_PARAM_AUDIO_VOLUME:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_MIXER_VOL, value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_AUDIO_MUTE:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_MUTE_VOL, value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_AUDIO_COMPR_LEVEL:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_COMPRESSOR, value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_AUDIO_AMP_LEVEL:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_AMP, value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_AUDIO_AMP_MUTE:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_AMP_MUTE, value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_AUDIO_CLOSE_DEVICE:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_CLOSE_DEVICE, value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_EQ_30HZ:
@@ -400,10 +412,12 @@ void xine_set_param (xine_stream_t *stream, int param, int value) {
case XINE_PARAM_EQ_4000HZ:
case XINE_PARAM_EQ_8000HZ:
case XINE_PARAM_EQ_16000HZ:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out,
param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ,
value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_VERBOSITY:
@@ -419,7 +433,9 @@ void xine_set_param (xine_stream_t *stream, int param, int value) {
case XINE_PARAM_VO_ZOOM_Y:
case XINE_PARAM_VO_PAN_SCAN:
case XINE_PARAM_VO_TVMODE:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
stream->video_out->set_property(stream->video_out, param, value);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_IGNORE_VIDEO:
@@ -449,54 +465,81 @@ void xine_set_param (xine_stream_t *stream, int param, int value) {
default:
xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine_interface: unknown param %d\n", param);
- }
+ }
}
int xine_get_param (xine_stream_t *stream, int param) {
+ int ret;
switch (param) {
case XINE_PARAM_SPEED:
- return stream->xine->clock->speed;
+ ret = stream->xine->clock->speed;
+ break;
case XINE_PARAM_AV_OFFSET:
- return stream->metronom->get_option (stream->metronom, METRONOM_AV_OFFSET);
+ ret = stream->metronom->get_option (stream->metronom, METRONOM_AV_OFFSET);
+ break;
case XINE_PARAM_SPU_OFFSET:
- return stream->metronom->get_option (stream->metronom, METRONOM_SPU_OFFSET);
+ ret = stream->metronom->get_option (stream->metronom, METRONOM_SPU_OFFSET);
+ break;
case XINE_PARAM_AUDIO_CHANNEL_LOGICAL:
- return stream->audio_channel_user;
+ ret = stream->audio_channel_user;
+ break;
case XINE_PARAM_SPU_CHANNEL:
- return stream->spu_channel_user;
+ ret = stream->spu_channel_user;
+ break;
case XINE_PARAM_VIDEO_CHANNEL:
- return stream->video_channel;
+ ret = stream->video_channel;
+ break;
case XINE_PARAM_AUDIO_VOLUME:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (!stream->audio_out)
- return -1;
- return stream->audio_out->get_property (stream->audio_out, AO_PROP_MIXER_VOL);
+ ret = -1;
+ else
+ ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MIXER_VOL);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ break;
case XINE_PARAM_AUDIO_MUTE:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (!stream->audio_out)
- return -1;
- return stream->audio_out->get_property (stream->audio_out, AO_PROP_MUTE_VOL);
+ ret = -1;
+ else
+ ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MUTE_VOL);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ break;
case XINE_PARAM_AUDIO_COMPR_LEVEL:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (!stream->audio_out)
- return -1;
- return stream->audio_out->get_property (stream->audio_out, AO_PROP_COMPRESSOR);
+ ret = -1;
+ else
+ ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_COMPRESSOR);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ break;
case XINE_PARAM_AUDIO_AMP_LEVEL:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (!stream->audio_out)
- return -1;
- return stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP);
+ ret = -1;
+ else
+ ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ break;
case XINE_PARAM_AUDIO_AMP_MUTE:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (!stream->audio_out)
- return -1;
- return stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP_MUTE);
+ ret = -1;
+ else
+ ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP_MUTE);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ break;
case XINE_PARAM_EQ_30HZ:
case XINE_PARAM_EQ_60HZ:
@@ -508,15 +551,18 @@ int xine_get_param (xine_stream_t *stream, int param) {
case XINE_PARAM_EQ_4000HZ:
case XINE_PARAM_EQ_8000HZ:
case XINE_PARAM_EQ_16000HZ:
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
if (!stream->audio_out)
- return -1;
-
- return stream->audio_out->get_property (stream->audio_out,
- param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ);
+ ret = -1;
+ else
+ ret= stream->audio_out->get_property (stream->audio_out,
+ param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
break;
case XINE_PARAM_VERBOSITY:
- return stream->xine->verbosity;
+ ret = stream->xine->verbosity;
+ break;
case XINE_PARAM_VO_HUE:
case XINE_PARAM_VO_SATURATION:
@@ -528,32 +574,40 @@ int xine_get_param (xine_stream_t *stream, int param) {
case XINE_PARAM_VO_ZOOM_Y:
case XINE_PARAM_VO_PAN_SCAN:
case XINE_PARAM_VO_TVMODE:
- return stream->video_out->get_property(stream->video_out, param);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ ret = stream->video_out->get_property(stream->video_out, param);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ break;
case XINE_PARAM_IGNORE_VIDEO:
- return _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_VIDEO);
+ ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_VIDEO);
+ break;
case XINE_PARAM_IGNORE_AUDIO:
- return _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_AUDIO);
+ ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_AUDIO);
+ break;
case XINE_PARAM_IGNORE_SPU:
- return _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_SPU);
+ ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_SPU);
+ break;
case XINE_PARAM_METRONOM_PREBUFFER:
- return stream->metronom->get_option(stream->metronom, METRONOM_PREBUFFER);
+ ret = stream->metronom->get_option(stream->metronom, METRONOM_PREBUFFER);
+ break;
case XINE_PARAM_BROADCASTER_PORT:
if( stream->broadcaster )
- return _x_get_broadcaster_port(stream->broadcaster);
+ ret = _x_get_broadcaster_port(stream->broadcaster);
else
- return 0;
+ ret = 0;
break;
default:
xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine_interface: unknown param %d\n", param);
+ ret = 0;
}
- return 0;
+ return ret;
}
uint32_t xine_get_stream_info (xine_stream_t *stream, int info) {
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 3bd7c319c..7953fd8cf 100644
--- a/src/xine-engine/xine_internal.h
+++ b/src/xine-engine/xine_internal.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_internal.h,v 1.153 2004/01/11 15:54:23 jstembridge Exp $
+ * $Id: xine_internal.h,v 1.154 2004/02/12 18:19:00 mroi Exp $
*
*/
@@ -89,6 +89,8 @@ extern "C" {
#define XINE_STREAM_INFO_MAX 99
+typedef struct xine_ticket_s xine_ticket_t;
+
/*
* the "big" xine struct, holding everything together
*/
@@ -111,6 +113,61 @@ struct xine_s {
pthread_mutex_t streams_lock;
metronom_clock_t *clock;
+
+#ifdef XINE_ENGINE_INTERNAL
+ xine_ticket_t *port_ticket;
+#endif
+};
+
+/*
+ * xine thread tickets
+ */
+
+struct xine_ticket_s {
+
+ /* the ticket owner must assure to check for ticket revocation in
+ * intervals of finite length; this means that you must release
+ * the ticket before any operation that might block
+ *
+ * you must never write to this member directly
+ */
+ int ticket_revoked;
+
+ /* apply for a ticket; between acquire and relese of an irrevocable
+ * ticket (be sure to pair them properly!), it is guaranteed that you
+ * will never be blocked by ticket revocation */
+ void (*acquire)(xine_ticket_t *self, int irrevocable);
+
+ /* give a ticket back */
+ void (*release)(xine_ticket_t *self, int irrevocable);
+
+ /* renew a ticket, when it has been revoked, see ticket_revoked above;
+ * irrevocable must be set to one, if your thread might have acquired
+ * irrevocable tickets you don't know of; set it to zero only when
+ * you know that this is impossible */
+ void (*renew)(xine_ticket_t *self, int irrevocable);
+
+#ifdef XINE_ENGINE_INTERNAL
+ /* allow handing out new tickets */
+ void (*issue)(xine_ticket_t *self, int atomic);
+
+ /* revoke all tickets and deny new ones;
+ * a pair of atomic revoke and issue cannot be interrupted by another
+ * revocation or by other threads acquiring tickets */
+ void (*revoke)(xine_ticket_t *self, int atomic);
+
+ void (*dispose)(xine_ticket_t *self);
+
+ pthread_mutex_t lock;
+ pthread_mutex_t revoke_lock;
+ pthread_cond_t issued;
+ pthread_cond_t revoked;
+ int tickets_granted;
+ int irrevocable_tickets;
+ int pending_revocations;
+ int atomic_revoke;
+ pthread_t atomic_revoker_thread;
+#endif
};
/*
@@ -264,14 +321,6 @@ struct xine_stream_s {
int err;
- /* on-the-fly port rewiring */
- xine_video_port_t *next_video_port;
- xine_audio_port_t *next_audio_port;
- pthread_mutex_t next_video_port_lock;
- pthread_mutex_t next_audio_port_lock;
- pthread_cond_t next_video_port_wired;
- pthread_cond_t next_audio_port_wired;
-
broadcaster_t *broadcaster;
#endif
};