summaryrefslogtreecommitdiff
path: root/src/xine-engine/xine.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/xine.c')
-rw-r--r--src/xine-engine/xine.c221
1 files changed, 202 insertions, 19 deletions
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index f49a988c9..e44419ecf 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -47,6 +47,8 @@
#include <locale.h>
#endif
+#include <basedir.h>
+
#define LOG_MODULE "xine"
#define LOG_VERBOSE
/*
@@ -127,23 +129,42 @@ void _x_extra_info_merge( extra_info_t *dst, extra_info_t *src ) {
}
}
-static void ticket_acquire(xine_ticket_t *this, int irrevocable) {
+static int ticket_acquire_internal(xine_ticket_t *this, int irrevocable, int nonblocking) {
+ int must_wait = 0;
pthread_mutex_lock(&this->lock);
if (this->ticket_revoked && !this->irrevocable_tickets)
- pthread_cond_wait(&this->issued, &this->lock);
+ must_wait = !nonblocking;
else if (this->atomic_revoke && !pthread_equal(this->atomic_revoker_thread, pthread_self()))
+ must_wait = 1;
+
+ if (must_wait) {
+ if (nonblocking) {
+ pthread_mutex_unlock(&this->lock);
+ return 0;
+ }
+
pthread_cond_wait(&this->issued, &this->lock);
+ }
this->tickets_granted++;
if (irrevocable)
this->irrevocable_tickets++;
pthread_mutex_unlock(&this->lock);
+ return 1;
}
-static void ticket_release(xine_ticket_t *this, int irrevocable) {
+static int ticket_acquire_nonblocking(xine_ticket_t *this, int irrevocable) {
+ return ticket_acquire_internal(this, irrevocable, 1);
+}
+
+static void ticket_acquire(xine_ticket_t *this, int irrevocable) {
+ ticket_acquire_internal(this, irrevocable, 0);
+}
+
+static void ticket_release_internal(xine_ticket_t *this, int irrevocable, int nonblocking) {
pthread_mutex_lock(&this->lock);
@@ -153,12 +174,20 @@ static void ticket_release(xine_ticket_t *this, int irrevocable) {
if (this->ticket_revoked && !this->tickets_granted)
pthread_cond_broadcast(&this->revoked);
- if (this->ticket_revoked && !this->irrevocable_tickets)
+ if (this->ticket_revoked && !this->irrevocable_tickets && !nonblocking)
pthread_cond_wait(&this->issued, &this->lock);
pthread_mutex_unlock(&this->lock);
}
+static void ticket_release_nonblocking(xine_ticket_t *this, int irrevocable) {
+ ticket_release_internal(this, irrevocable, 1);
+}
+
+static void ticket_release(xine_ticket_t *this, int irrevocable) {
+ ticket_release_internal(this, irrevocable, 0);
+}
+
static void ticket_renew(xine_ticket_t *this, int irrevocable) {
pthread_mutex_lock(&this->lock);
@@ -212,8 +241,37 @@ static void ticket_revoke(xine_ticket_t *this, int atomic) {
pthread_mutex_unlock(&this->revoke_lock);
}
+static int ticket_lock_port_rewiring(xine_ticket_t *this, int ms_timeout) {
+
+ if (ms_timeout >= 0) {
+ struct timespec abstime;
+
+ struct timeval now;
+ gettimeofday(&now, 0);
+
+ abstime.tv_sec = now.tv_sec + ms_timeout / 1000;
+ abstime.tv_nsec = now.tv_usec * 1000 + (ms_timeout % 1000) * 1e6;
+
+ if (abstime.tv_nsec > 1e9) {
+ abstime.tv_nsec -= 1e9;
+ abstime.tv_sec++;
+ }
+
+ return (0 == pthread_mutex_timedlock(&this->port_rewiring_lock, &abstime));
+ }
+
+ pthread_mutex_lock(&this->port_rewiring_lock);
+ return 1;
+}
+
+static void ticket_unlock_port_rewiring(xine_ticket_t *this) {
+
+ pthread_mutex_unlock(&this->port_rewiring_lock);
+}
+
static void ticket_dispose(xine_ticket_t *this) {
+ pthread_mutex_destroy(&this->port_rewiring_lock);
pthread_mutex_destroy(&this->lock);
pthread_mutex_destroy(&this->revoke_lock);
pthread_cond_destroy(&this->issued);
@@ -227,15 +285,20 @@ static xine_ticket_t *ticket_init(void) {
port_ticket = (xine_ticket_t *) xine_xmalloc(sizeof(xine_ticket_t));
- port_ticket->acquire = ticket_acquire;
- port_ticket->release = ticket_release;
- port_ticket->renew = ticket_renew;
- port_ticket->issue = ticket_issue;
- port_ticket->revoke = ticket_revoke;
- port_ticket->dispose = ticket_dispose;
+ port_ticket->acquire_nonblocking = ticket_acquire_nonblocking;
+ port_ticket->acquire = ticket_acquire;
+ port_ticket->release_nonblocking = ticket_release_nonblocking;
+ port_ticket->release = ticket_release;
+ port_ticket->renew = ticket_renew;
+ port_ticket->issue = ticket_issue;
+ port_ticket->revoke = ticket_revoke;
+ port_ticket->lock_port_rewiring = ticket_lock_port_rewiring;
+ port_ticket->unlock_port_rewiring = ticket_unlock_port_rewiring;
+ port_ticket->dispose = ticket_dispose;
pthread_mutex_init(&port_ticket->lock, NULL);
pthread_mutex_init(&port_ticket->revoke_lock, NULL);
+ pthread_mutex_init(&port_ticket->port_rewiring_lock, NULL);
pthread_cond_init(&port_ticket->issued, NULL);
pthread_cond_init(&port_ticket->revoked, NULL);
@@ -429,6 +492,7 @@ static int stream_rewire_audio(xine_post_out_t *output, void *data)
if (!data)
return 0;
+ stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) {
@@ -439,6 +503,7 @@ static int stream_rewire_audio(xine_post_out_t *output, void *data)
stream->audio_out = new_port;
stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
+ stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
return 1;
}
@@ -453,6 +518,7 @@ static int stream_rewire_video(xine_post_out_t *output, void *data)
if (!data)
return 0;
+ stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1);
stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1);
if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) {
@@ -463,6 +529,7 @@ static int stream_rewire_video(xine_post_out_t *output, void *data)
stream->video_out = new_port;
stream->xine->port_ticket->issue(stream->xine->port_ticket, 1);
+ stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket);
return 1;
}
@@ -647,7 +714,7 @@ xine_stream_t *xine_stream_new (xine_t *this,
return stream;
}
-static void mrl_unescape(char *mrl) {
+void _x_mrl_unescape(char *mrl) {
int i, len = strlen(mrl);
for (i = 0; i < len; i++) {
@@ -795,7 +862,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
memcpy(demux_name, tmp, strlen(tmp));
demux_name[strlen(tmp)] = '\0';
}
- mrl_unescape(demux_name);
+ _x_mrl_unescape(demux_name);
if (!(stream->demux_plugin = _x_find_demux_plugin_by_name(stream, demux_name, stream->input_plugin))) {
xine_log(stream->xine, XINE_LOG_MSG, _("xine: specified demuxer %s failed to start\n"), demux_name);
stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
@@ -869,7 +936,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
memcpy(demux_name, tmp, strlen(tmp));
demux_name[strlen(tmp)] = '\0';
}
- mrl_unescape(demux_name);
+ _x_mrl_unescape(demux_name);
if (!(stream->demux_plugin = _x_find_demux_plugin_last_probe(stream, demux_name, stream->input_plugin))) {
xine_log(stream->xine, XINE_LOG_MSG, _("xine: last_probed demuxer %s failed to start\n"), demux_name);
stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
@@ -956,7 +1023,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
memcpy(volume, tmp, strlen(tmp));
volume[strlen(tmp)] = '\0';
}
- mrl_unescape(volume);
+ _x_mrl_unescape(volume);
xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, atoi(volume));
free(volume);
} else {
@@ -981,7 +1048,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
memcpy(compression, tmp, strlen(tmp));
compression[strlen(tmp)] = '\0';
}
- mrl_unescape(compression);
+ _x_mrl_unescape(compression);
xine_set_param(stream, XINE_PARAM_AUDIO_COMPR_LEVEL, atoi(compression));
free(compression);
} else {
@@ -1006,7 +1073,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
memcpy(subtitle_mrl, tmp, strlen(tmp));
subtitle_mrl[strlen(tmp)] = '\0';
}
- mrl_unescape(subtitle_mrl);
+ _x_mrl_unescape(subtitle_mrl);
stream->slave = xine_stream_new (stream->xine, NULL, stream->video_out );
stream->slave_affection = XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP;
if( xine_open( stream->slave, subtitle_mrl ) ) {
@@ -1041,7 +1108,7 @@ static int open_internal (xine_stream_t *stream, const char *mrl) {
memcpy(config_entry, tmp, strlen(tmp));
config_entry[strlen(tmp)] = '\0';
}
- mrl_unescape(config_entry);
+ _x_mrl_unescape(config_entry);
retval = _x_config_change_opt(stream->xine->config, config_entry);
if (retval <= 0) {
if (retval == 0) {
@@ -1410,6 +1477,8 @@ void xine_exit (xine_t *this) {
WSACleanup();
#endif
+ xdgFreeHandle(this->basedir_handle);
+
free (this);
}
@@ -1535,8 +1604,11 @@ static void config_save_cb (void *this_gen, xine_cfg_entry_t *entry) {
}
void xine_init (xine_t *this) {
- static const char *demux_strategies[] = {"default", "reverse", "content",
- "extension", NULL};
+ static const char *const demux_strategies[] = {"default", "reverse", "content",
+ "extension", NULL};
+
+ /* First of all, initialise libxdg-basedir as it's used by plugins. */
+ this->basedir_handle = xdgAllocHandle();
/* initialize color conversion tables and functions */
init_yuv_conversion();
@@ -1969,6 +2041,9 @@ const char *const *xine_get_log_names (xine_t *this) {
static inline void check_log_alloc (xine_t *this, int buf)
{
+ if ( this->log_buffers[buf] )
+ return;
+
pthread_mutex_lock (&this->log_lock);
if ( ! this->log_buffers[buf] )
@@ -2040,3 +2115,111 @@ int xine_stream_master_slave(xine_stream_t *master, xine_stream_t *slave,
slave->master = master->master;
return 1;
}
+
+int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *num_audio_buffers, int *num_video_frames, int *num_audio_frames)
+{
+ int ticket_acquired = -1;
+
+ if (num_video_buffers)
+ *num_video_buffers = (stream->video_fifo ? stream->video_fifo->size(stream->video_fifo) : 0);
+
+ if (num_audio_buffers)
+ *num_audio_buffers = (stream->audio_fifo ? stream->audio_fifo->size(stream->audio_fifo) : 0);
+
+ if ((num_video_frames && stream->video_out)
+ || (num_audio_frames && stream->audio_out)) {
+
+ ticket_acquired = stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1);
+ }
+
+ if (num_video_frames)
+ *num_video_frames = ((ticket_acquired && stream->video_out) ? stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_IN_FIFO) : 0);
+
+ if (num_audio_frames)
+ *num_audio_frames = ((ticket_acquired && stream->audio_out) ? stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_IN_FIFO) : 0);
+
+ if (ticket_acquired > 0)
+ stream->xine->port_ticket->release_nonblocking(stream->xine->port_ticket, 1);
+
+ return ticket_acquired != 0;
+}
+
+int _x_lock_port_rewiring(xine_t *xine, int ms_timeout)
+{
+ return xine->port_ticket->lock_port_rewiring(xine->port_ticket, ms_timeout);
+}
+
+void _x_unlock_port_rewiring(xine_t *xine)
+{
+ xine->port_ticket->unlock_port_rewiring(xine->port_ticket);
+}
+
+int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out)
+{
+ if (ms_to_time_out >= 0) {
+ struct timespec abstime;
+
+ struct timeval now;
+ gettimeofday(&now, 0);
+
+ abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000;
+ abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6;
+
+ if (abstime.tv_nsec > 1e9) {
+ abstime.tv_nsec -= 1e9;
+ abstime.tv_sec++;
+ }
+
+ return (0 == pthread_mutex_timedlock(&stream->frontend_lock, &abstime));
+ }
+
+ pthread_mutex_lock(&stream->frontend_lock);
+ return 1;
+}
+
+void _x_unlock_frontend(xine_stream_t *stream)
+{
+ pthread_mutex_unlock(&stream->frontend_lock);
+}
+
+int _x_query_unprocessed_osd_events(xine_stream_t *stream)
+{
+ video_overlay_manager_t *ovl;
+ int redraw_needed;
+
+ if (!stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1))
+ return -1;
+
+ ovl = stream->video_out->get_overlay_manager(stream->video_out);
+ redraw_needed = ovl->redraw_needed(ovl, 0);
+
+ if (redraw_needed)
+ stream->video_out->trigger_drawing(stream->video_out);
+
+ stream->xine->port_ticket->release_nonblocking(stream->xine->port_ticket, 1);
+
+ return redraw_needed;
+}
+
+int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing)
+{
+ if (!stream->demux_plugin)
+ return -1;
+ return stream->demux_plugin->seek(stream->demux_plugin, start_pos, start_time, playing);
+}
+
+int _x_continue_stream_processing(xine_stream_t *stream)
+{
+ return stream->status != XINE_STATUS_STOP
+ && stream->status != XINE_STATUS_QUIT;
+}
+
+void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream)
+{
+ stream->first_frame_flag = 2;
+}
+
+void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream)
+{
+ stream->first_frame_flag = 1;
+}