From bcaee71a3a763a545e1f8457aca26dc679462677 Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Mon, 14 Oct 2002 15:46:48 +0000 Subject: introduction of xine_stream_t and async xine events - all still in developement CVS patchset: 2828 CVS date: 2002/10/14 15:46:48 --- src/demuxers/Makefile.am | 166 +++---- src/demuxers/demux.h | 114 ++--- src/demuxers/demux_avi.c | 292 ++++++------ src/input/Makefile.am | 104 ++-- src/input/input_dvd.c | 11 +- src/input/input_file.c | 641 ++++++++++++------------- src/input/input_plugin.h | 320 ++++++------- src/input/net_buf_ctrl.c | 8 +- src/libspudec/spu_decoder_api.h | 1 + src/xine-engine/Makefile.am | 2 +- src/xine-engine/audio_decoder.c | 232 ++++----- src/xine-engine/audio_decoder.h | 80 ++++ src/xine-engine/audio_out.c | 28 +- src/xine-engine/audio_out.h | 27 +- src/xine-engine/demux.c | 70 +-- src/xine-engine/events.c | 239 +++++++--- src/xine-engine/events.h | 177 ------- src/xine-engine/load_plugins.c | 486 +++++++++++++++---- src/xine-engine/metronom.c | 8 +- src/xine-engine/metronom.h | 15 +- src/xine-engine/plugin_catalog.h | 32 +- src/xine-engine/video_decoder.c | 244 +++++----- src/xine-engine/video_decoder.h | 86 ++++ src/xine-engine/video_out.c | 27 +- src/xine-engine/video_out.h | 7 +- src/xine-engine/video_overlay.h | 7 +- src/xine-engine/xine.c | 991 +++++++++++++-------------------------- src/xine-engine/xine_interface.c | 59 +-- src/xine-engine/xine_internal.h | 270 ++++------- src/xine-engine/xine_plugin.h | 7 +- 30 files changed, 2344 insertions(+), 2407 deletions(-) create mode 100644 src/xine-engine/audio_decoder.h delete mode 100644 src/xine-engine/events.h create mode 100644 src/xine-engine/video_decoder.h (limited to 'src') diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index b2e972e4c..18e90d74c 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -6,59 +6,61 @@ libdir = $(XINE_PLUGINDIR) # Sensing of OGG/VORBIS, ZLIB and ASF is broken in cvscompile.sh. -if HAVE_VORBIS -ogg_module = xineplug_dmx_ogg.la -endif +#if HAVE_VORBIS +#ogg_module = xineplug_dmx_ogg.la +#endif -if HAVE_ZLIB -qt_modules = xineplug_dmx_qt.la -endif +#if HAVE_ZLIB +#qt_modules = xineplug_dmx_qt.la +#endif -if BUILD_ASF -asf_module = xineplug_dmx_asf.la -endif +#if BUILD_ASF +#asf_module = xineplug_dmx_asf.la +#endif ## # IMPORTANT: # --------- # All of xine demuxer plugins should be named like the scheme "xineplug_dmx_" -lib_LTLIBRARIES = $(ogg_module) $(asf_module) $(qt_modules) xineplug_dmx_avi.la\ - xineplug_dmx_mpeg_block.la xineplug_dmx_mpeg.la \ - xineplug_dmx_mpeg_elem.la xineplug_dmx_mpeg_audio.la \ - xineplug_dmx_cda.la xineplug_dmx_film.la \ - xineplug_dmx_roq.la xineplug_dmx_fli.la \ - xineplug_dmx_smjpeg.la xineplug_dmx_wav.la \ - xineplug_dmx_idcin.la xineplug_dmx_wc3movie.la \ - xineplug_dmx_vqa.la xineplug_dmx_voc.la \ - xineplug_dmx_aiff.la xineplug_dmx_snd.la \ - xineplug_dmx_yuv4mpeg2.la xineplug_dmx_real.la +#lib_LTLIBRARIES = $(ogg_module) $(asf_module) $(qt_modules) xineplug_dmx_avi.la\ +# xineplug_dmx_mpeg_block.la xineplug_dmx_mpeg.la \ +# xineplug_dmx_mpeg_elem.la xineplug_dmx_mpeg_audio.la \ +# xineplug_dmx_cda.la xineplug_dmx_film.la \ +# xineplug_dmx_roq.la xineplug_dmx_fli.la \ +# xineplug_dmx_smjpeg.la xineplug_dmx_wav.la \ +# xineplug_dmx_idcin.la xineplug_dmx_wc3movie.la \ +# xineplug_dmx_vqa.la xineplug_dmx_voc.la \ +# xineplug_dmx_aiff.la xineplug_dmx_snd.la \ +# xineplug_dmx_yuv4mpeg2.la xineplug_dmx_real.la # xineplug_dmx_mpeg_pes.la xineplug_dmx_mpeg_ts.la -xineplug_dmx_ogg_la_SOURCES = demux_ogg.c -xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS)\ - $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_ogg_la_LDFLAGS = -avoid-version -module +lib_LTLIBRARIES = xineplug_dmx_avi.la + +#xineplug_dmx_ogg_la_SOURCES = demux_ogg.c +#xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS)\ +# $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_ogg_la_LDFLAGS = -avoid-version -module xineplug_dmx_avi_la_SOURCES = demux_avi.c xineplug_dmx_avi_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la xineplug_dmx_avi_la_LDFLAGS = -avoid-version -module -xineplug_dmx_mpeg_block_la_SOURCES = demux_mpeg_block.c -xineplug_dmx_mpeg_block_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_mpeg_block_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_mpeg_block_la_SOURCES = demux_mpeg_block.c +#xineplug_dmx_mpeg_block_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_mpeg_block_la_LDFLAGS = -avoid-version -module -xineplug_dmx_mpeg_la_SOURCES = demux_mpeg.c -xineplug_dmx_mpeg_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_mpeg_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_mpeg_la_SOURCES = demux_mpeg.c +#xineplug_dmx_mpeg_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_mpeg_la_LDFLAGS = -avoid-version -module -xineplug_dmx_mpeg_audio_la_SOURCES = demux_mpgaudio.c -xineplug_dmx_mpeg_audio_la_LIBADD = -lm $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_mpeg_audio_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_mpeg_audio_la_SOURCES = demux_mpgaudio.c +#xineplug_dmx_mpeg_audio_la_LIBADD = -lm $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_mpeg_audio_la_LDFLAGS = -avoid-version -module -xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c -xineplug_dmx_mpeg_elem_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_mpeg_elem_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c +#xineplug_dmx_mpeg_elem_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_mpeg_elem_la_LDFLAGS = -avoid-version -module #xineplug_dmx_mpeg_pes_la_SOURCES = demux_pes.c #xineplug_dmx_mpeg_pes_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la @@ -68,68 +70,68 @@ xineplug_dmx_mpeg_elem_la_LDFLAGS = -avoid-version -module #xineplug_dmx_mpeg_ts_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la #xineplug_dmx_mpeg_ts_la_LDFLAGS = -avoid-version -module -xineplug_dmx_qt_la_SOURCES = demux_qt.c qtpalette.h -xineplug_dmx_qt_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_qt_la_SOURCES = demux_qt.c qtpalette.h +#xineplug_dmx_qt_la_LDFLAGS = -avoid-version -module -xineplug_dmx_asf_la_SOURCES = demux_asf.c -xineplug_dmx_asf_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_asf_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_asf_la_SOURCES = demux_asf.c +#xineplug_dmx_asf_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_asf_la_LDFLAGS = -avoid-version -module -xineplug_dmx_cda_la_SOURCES = demux_cda.c -xineplug_dmx_cda_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_cda_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_cda_la_SOURCES = demux_cda.c +#xineplug_dmx_cda_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_cda_la_LDFLAGS = -avoid-version -module -xineplug_dmx_film_la_SOURCES = demux_film.c -xineplug_dmx_film_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_film_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_film_la_SOURCES = demux_film.c +#xineplug_dmx_film_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_film_la_LDFLAGS = -avoid-version -module -xineplug_dmx_roq_la_SOURCES = demux_roq.c -xineplug_dmx_roq_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_roq_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_roq_la_SOURCES = demux_roq.c +#xineplug_dmx_roq_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_roq_la_LDFLAGS = -avoid-version -module -xineplug_dmx_fli_la_SOURCES = demux_fli.c -xineplug_dmx_fli_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_fli_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_fli_la_SOURCES = demux_fli.c +#xineplug_dmx_fli_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_fli_la_LDFLAGS = -avoid-version -module -xineplug_dmx_smjpeg_la_SOURCES = demux_smjpeg.c -xineplug_dmx_smjpeg_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_smjpeg_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_smjpeg_la_SOURCES = demux_smjpeg.c +#xineplug_dmx_smjpeg_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_smjpeg_la_LDFLAGS = -avoid-version -module -xineplug_dmx_wav_la_SOURCES = demux_wav.c -xineplug_dmx_wav_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_wav_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_wav_la_SOURCES = demux_wav.c +#xineplug_dmx_wav_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_wav_la_LDFLAGS = -avoid-version -module -xineplug_dmx_idcin_la_SOURCES = demux_idcin.c -xineplug_dmx_idcin_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_idcin_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_idcin_la_SOURCES = demux_idcin.c +#xineplug_dmx_idcin_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_idcin_la_LDFLAGS = -avoid-version -module -xineplug_dmx_wc3movie_la_SOURCES = demux_wc3movie.c -xineplug_dmx_wc3movie_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_wc3movie_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_wc3movie_la_SOURCES = demux_wc3movie.c +#xineplug_dmx_wc3movie_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_wc3movie_la_LDFLAGS = -avoid-version -module -xineplug_dmx_vqa_la_SOURCES = demux_vqa.c -xineplug_dmx_vqa_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_vqa_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_vqa_la_SOURCES = demux_vqa.c +#xineplug_dmx_vqa_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_vqa_la_LDFLAGS = -avoid-version -module -xineplug_dmx_voc_la_SOURCES = demux_voc.c -xineplug_dmx_voc_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_voc_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_voc_la_SOURCES = demux_voc.c +#xineplug_dmx_voc_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_voc_la_LDFLAGS = -avoid-version -module -xineplug_dmx_aiff_la_SOURCES = demux_aiff.c -xineplug_dmx_aiff_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_aiff_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_aiff_la_SOURCES = demux_aiff.c +#xineplug_dmx_aiff_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_aiff_la_LDFLAGS = -avoid-version -module -xineplug_dmx_snd_la_SOURCES = demux_snd.c -xineplug_dmx_snd_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_snd_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_snd_la_SOURCES = demux_snd.c +#xineplug_dmx_snd_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_snd_la_LDFLAGS = -avoid-version -module -xineplug_dmx_yuv4mpeg2_la_SOURCES = demux_yuv4mpeg2.c -xineplug_dmx_yuv4mpeg2_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_yuv4mpeg2_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_yuv4mpeg2_la_SOURCES = demux_yuv4mpeg2.c +#xineplug_dmx_yuv4mpeg2_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_yuv4mpeg2_la_LDFLAGS = -avoid-version -module -xineplug_dmx_real_la_SOURCES = demux_real.c -xineplug_dmx_real_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_dmx_real_la_LDFLAGS = -avoid-version -module +#xineplug_dmx_real_la_SOURCES = demux_real.c +#xineplug_dmx_real_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_dmx_real_la_LDFLAGS = -avoid-version -module include_HEADERS = demux.h qtpalette.h diff --git a/src/demuxers/demux.h b/src/demuxers/demux.h index 41e23d211..7234a64fd 100644 --- a/src/demuxers/demux.h +++ b/src/demuxers/demux.h @@ -17,16 +17,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux.h,v 1.19 2002/09/18 00:51:33 guenter Exp $ + * $Id: demux.h,v 1.20 2002/10/14 15:47:12 guenter Exp $ */ #ifndef HAVE_DEMUX_H #define HAVE_DEMUX_H -#ifdef __cplusplus -extern "C" { -#endif - #include "buffer.h" #include "xine_internal.h" #if defined(XINE_COMPILE) @@ -35,43 +31,68 @@ extern "C" { #include "input_plugin.h" #endif -#define DEMUXER_PLUGIN_IFACE_VERSION 11 +#define DEMUXER_PLUGIN_IFACE_VERSION 14 + +#define DEMUX_OK 0 +#define DEMUX_FINISHED 1 + +#define DEMUX_CANNOT_HANDLE 0 +#define DEMUX_CAN_HANDLE 1 + +#define METHOD_BY_CONTENT 1 +#define METHOD_BY_EXTENSION 2 + +typedef struct demux_class_s demux_class_t ; -#define DEMUX_OK 0 -#define DEMUX_FINISHED 1 +struct demux_class_s { -#define DEMUX_CANNOT_HANDLE 0 -#define DEMUX_CAN_HANDLE 1 + /* + * return human readable (verbose = 1 line) description for this plugin + */ + char* (*get_description) (demux_class_t *this); -#define DEMUX_DEFAULT_STRATEGY 0 -#define DEMUX_REVERT_STRATEGY 1 -#define DEMUX_CONTENT_STRATEGY 2 -#define DEMUX_EXTENSION_STRATEGY 3 + /* + * return human readable identifier for this plugin + */ + + char* (*get_identifier) (demux_class_t *this); + + /* + * return MIME types supported for this plugin + */ + + char* (*get_mimetypes) (demux_class_t *this); + + /* + * return ' ' seperated list of file extensions this + * demuxer is likely to handle + * (will be used to filter media files in + * file selection dialogs) + */ + + char* (*get_extensions) (demux_class_t *this); + + /* + * close down, free all resources + */ + void (*dispose) (demux_class_t *this); +}; -#define STAGE_BY_CONTENT 1 -#define STAGE_BY_EXTENSION 2 /* - * a demux plugin must implement these functions + * any demux plugin must implement these functions */ typedef struct demux_plugin_s demux_plugin_t; -struct demux_plugin_s -{ +struct demux_plugin_s { + /* - * ask demuxer to open the given stream (input-plugin) - * using the content-detection method specified in - * - * demuxer should send header/preview packages in this stage - * - * return values: - * DEMUX_CAN_HANDLE on success - * DEMUX_CANNOT_HANDLE on failure + * send headers, followed by BUF_CONTROL_HEADERS_DONE down the + * fifos, then return. do not start demux thread (yet) */ - int (*open) (demux_plugin_t *this, input_plugin_t *ip, - int stage); + void (*send_headers) (demux_plugin_t *this); /* * start demux thread @@ -106,17 +127,18 @@ struct demux_plugin_s */ int (*seek) (demux_plugin_t *this, - off_t start_pos, int start_time); + off_t start_pos, int start_time); /* - * stop & kill demux thread, free resources associated with current - * input stream + * stop & kill demux thread + * + * keep plugin ready for restart */ void (*stop) (demux_plugin_t *this) ; /* - * close demuxer, free all resources + * stop & kill demux thread, free resources */ void (*dispose) (demux_plugin_t *this) ; @@ -128,32 +150,18 @@ struct demux_plugin_s int (*get_status) (demux_plugin_t *this) ; /* - * return human readable identifier for this plugin + * estimate stream length in seconds + * may return 0 for non-seekable streams */ - char* (*get_identifier) (void); - - /* - * return MIME types supported for this plugin - */ + int (*get_stream_length) (demux_plugin_t *this); + - char* (*get_mimetypes) (void); /* - * estimate stream length in seconds - * may return 0 for non-seekable streams + * "backwards" link to plugin class */ - int (*get_stream_length) (demux_plugin_t *this); + demux_class_t *demux_class; } ; -/* - * demuxer plugins should provide this (and only this!) function call: - * - * demux_plugin_t *init_demux_plugin (int iface_version, xine_t *xine); - */ - -#ifdef __cplusplus -} -#endif - #endif diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index b4ccec6ae..a277ebb2f 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.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: demux_avi.c,v 1.113 2002/10/12 17:14:41 jkeil Exp $ + * $Id: demux_avi.c,v 1.114 2002/10/14 15:47:13 guenter Exp $ * * demultiplexer for avi streams * @@ -71,8 +71,6 @@ #define MAX_AUDIO_STREAMS 8 -#define VALID_ENDS "avi" - /* The following variable indicates the kind of error */ typedef struct @@ -168,9 +166,7 @@ typedef struct typedef struct demux_avi_s { demux_plugin_t demux_plugin; - xine_t *xine; - - config_values_t *config; + xine_stream_t *stream; fifo_buffer_t *audio_fifo; fifo_buffer_t *video_fifo; @@ -198,6 +194,16 @@ typedef struct demux_avi_s { idx_grow_t idx_grow; } demux_avi_t ; +typedef struct { + + demux_class_t demux_class; + + /* class-wide, global variables here */ + + xine_t *xine; + config_values_t *config; +} demux_avi_class_t; + #define AVI_ERR_SIZELIM 1 /* The write of the data would exceed the maximum size of the AVI file. This is more a warning than an error @@ -393,16 +399,16 @@ static void demux_avi_stop (demux_plugin_t *this_gen); * notify the user. Returns -1 if EOF was reached, the non-negative * return value of stopper otherwise. */ static long idx_grow(demux_avi_t *this, long (*stopper)(demux_avi_t *, void *), - void *stopdata) -{ + void *stopdata) { + unsigned long n; - long i; - long retval = -1; - long num_read = 0; - off_t ioff = 8; - char data[256]; - int did_osd = 0; - off_t savepos = this->input->seek(this->input, 0, SEEK_CUR); + long i; + long retval = -1; + long num_read = 0; + off_t ioff = 8; + char data[256]; + off_t savepos = this->input->seek(this->input, 0, SEEK_CUR); + this->input->seek(this->input, this->idx_grow.nexttagoffset, SEEK_SET); while ((retval = stopper(this, stopdata)) < 0) { @@ -410,22 +416,24 @@ static long idx_grow(demux_avi_t *this, long (*stopper)(demux_avi_t *, void *), num_read += 1; if (num_read % 1000 == 0) { - /* Update the user using the OSD */ - off_t file_len = this->input->get_length (this->input); - char str[60]; - - sprintf(str, "Building index (%3lld%%)", - 100 * this->idx_grow.nexttagoffset / file_len); - - this->xine->osd_renderer->filled_rect (this->xine->osd, - 0, 0, 299, 99, 0); - this->xine->osd_renderer->render_text (this->xine->osd, - 5, 30, str, OSD_TEXT1); - this->xine->osd_renderer->show (this->xine->osd, 0); - did_osd = 1; + /* send event to frontend about index generation progress */ + + xine_event_t event; + xine_idx_progress_data_t idx; + off_t file_len; + + file_len = this->input->get_length (this->input); + + idx.percent = 100 * this->idx_grow.nexttagoffset / file_len; + + event.type = XINE_EVENT_BUILDING_INDEX; + event.data = &idx; + event.data_length = sizeof (xine_idx_progress_data_t); + + xine_event_send (this->stream, &event); } - if( this->input->read(this->input, data,8) != 8 ) + if (this->input->read(this->input, data,8) != 8) break; n = str2ulong(data+4); @@ -466,12 +474,7 @@ static long idx_grow(demux_avi_t *this, long (*stopper)(demux_avi_t *, void *), } - /* Clear the OSD */ - if (did_osd) { - this->xine->osd_renderer->hide (this->xine->osd, 0); - } - - this->input->seek(this->input, savepos, SEEK_SET); + this->input->seek (this->input, savepos, SEEK_SET); if (retval < 0) retval = -1; return retval; @@ -649,7 +652,8 @@ static avi_t *AVI_init(demux_avi_t *this) { ERR_EXIT(AVI_ERR_NO_MEM); if (this->input->read(this->input, (char *)AVI->idx, n) != n ) { - xine_log (this->xine, XINE_LOG_MSG, _("demux_avi: avi index is broken\n")); + xine_log (this->stream->xine, XINE_LOG_MSG, + _("demux_avi: avi index is broken\n")); free (AVI->idx); /* Index is broken, reconstruct */ AVI->idx = NULL; AVI->n_idx = AVI->max_idx = 0; @@ -1162,13 +1166,13 @@ static void *demux_avi_loop (void *this_gen) { } while( this->status == DEMUX_OK ); if (this->send_end_buffers) { - xine_demux_control_end(this->xine, BUF_FLAG_END_STREAM); + xine_demux_control_end (this->stream, BUF_FLAG_END_STREAM); } printf ("demux_avi: demux loop finished.\n"); this->thread_running = 0; - pthread_mutex_unlock( &this->mutex ); + pthread_mutex_unlock (&this->mutex); pthread_exit(NULL); @@ -1180,27 +1184,27 @@ static void demux_avi_stop (demux_plugin_t *this_gen) { demux_avi_t *this = (demux_avi_t *) this_gen; void *p; - pthread_mutex_lock( &this->mutex ); + pthread_mutex_lock (&this->mutex); if (!this->thread_running) { printf ("demux_avi: stop...ignored\n"); - pthread_mutex_unlock( &this->mutex ); + pthread_mutex_unlock (&this->mutex); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - pthread_mutex_unlock( &this->mutex ); + pthread_mutex_unlock (&this->mutex); pthread_join (this->thread, &p); - xine_demux_flush_engine(this->xine); + xine_demux_flush_engine (this->stream); /* AVI_close (this->avi); this->avi = NULL; */ - xine_demux_control_end(this->xine, BUF_FLAG_END_USER); + xine_demux_control_end (this->stream, BUF_FLAG_END_USER); } static void demux_avi_dispose (demux_plugin_t *this_gen) { @@ -1218,19 +1222,20 @@ static int demux_avi_get_status (demux_plugin_t *this_gen) { return (this->thread_running?DEMUX_OK:DEMUX_FINISHED); } -static int demux_avi_send_headers (demux_avi_t *this) { +static void demux_avi_send_headers (demux_plugin_t *this_gen) { + demux_avi_t *this = (demux_avi_t *) this_gen; int i; pthread_mutex_lock (&this->mutex); - this->video_fifo = this->xine->video_fifo; - this->audio_fifo = this->xine->audio_fifo; + this->video_fifo = this->stream->video_fifo; + this->audio_fifo = this->stream->audio_fifo; this->status = DEMUX_OK; - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->avi->width; - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->avi->height; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->avi->width; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->avi->height; for (i=0; i < this->avi->n_audio; i++) printf ("demux_avi: audio format[%d] = 0x%x\n", @@ -1243,7 +1248,6 @@ static int demux_avi_send_headers (demux_avi_t *this) { if( !this->avi->audio[i]->audio_type ) { printf ("demux_avi: unknown audio type 0x%x\n", this->avi->audio[i]->wavex->wFormatTag); - xine_report_codec( this->xine, XINE_CODEC_AUDIO, this->avi->audio[i]->wavex->wFormatTag, 0, 0); this->no_audio = 1; this->avi->audio[i]->audio_type = BUF_CONTROL_NOP; } else @@ -1252,11 +1256,12 @@ static int demux_avi_send_headers (demux_avi_t *this) { (int)this->avi->audio[i]->wavex->wFormatTag); } - xine_demux_control_headers_done (this->xine); + this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1; + this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = !this->no_audio; - pthread_mutex_unlock (&this->mutex); + xine_demux_control_headers_done (this->stream); - return DEMUX_CAN_HANDLE; + pthread_mutex_unlock (&this->mutex); } static int demux_avi_start (demux_plugin_t *this_gen, @@ -1380,15 +1385,13 @@ static int demux_avi_start (demux_plugin_t *this_gen, * send start buffers */ if( !this->thread_running && (this->status == DEMUX_OK) ) { - xine_demux_control_start(this->xine); + xine_demux_control_start (this->stream); } else { - xine_demux_flush_engine(this->xine); + xine_demux_flush_engine (this->stream); } if( this->status == DEMUX_OK ) - { - xine_demux_control_newpts(this->xine, video_pts, BUF_FLAG_SEEK); - } + xine_demux_control_newpts (this->stream, video_pts, BUF_FLAG_SEEK); if( !this->thread_running && (this->status == DEMUX_OK) ) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); @@ -1407,8 +1410,6 @@ static int demux_avi_start (demux_plugin_t *this_gen, (char*)&this->avi->bih.biCompression); buf->free_buffer (buf); - xine_report_codec( this->xine, XINE_CODEC_VIDEO, this->avi->bih.biCompression, 0, 0); - this->status = DEMUX_FINISHED; } else { buf->type = this->avi->video_type; @@ -1496,143 +1497,142 @@ static int demux_avi_seek (demux_plugin_t *this_gen, return demux_avi_start (this_gen, start_pos, start_time); } -static int demux_avi_open(demux_plugin_t *this_gen, - input_plugin_t *input, int stage) { +static int demux_avi_get_stream_length (demux_plugin_t *this_gen) { demux_avi_t *this = (demux_avi_t *) this_gen; - if (! (input->get_capabilities(input) & INPUT_CAP_SEEKABLE)) { - printf("demux_avi.c: not seekable, can't handle!\n"); - return DEMUX_CANNOT_HANDLE; + + if (this->avi) { + return get_video_pts(this, this->avi->video_idx.video_frames) / 90000 ; } - switch(stage) { + return 0; +} - case STAGE_BY_CONTENT: { - if (input->get_blocksize(input)) - return DEMUX_CANNOT_HANDLE; +static void* open_plugin (void *class_gen, xine_stream_t *stream, + const void *input_gen) { + + input_plugin_t *input = (input_plugin_t *) input_gen; + demux_avi_t *this; - if (!(input->get_capabilities(input) & INPUT_CAP_SEEKABLE)) - return DEMUX_CANNOT_HANDLE; + if (! (input->get_capabilities(input) & INPUT_CAP_SEEKABLE)) { + printf("demux_avi.c: not seekable, can't handle!\n"); + return NULL; + } - input->seek(input, 0, SEEK_SET); + this = xine_xmalloc (sizeof (demux_avi_t)); + this->stream = stream; + this->input = input; - this->input = input; + this->demux_plugin.send_headers = demux_avi_send_headers; + this->demux_plugin.start = demux_avi_start; + this->demux_plugin.seek = demux_avi_seek; + this->demux_plugin.stop = demux_avi_stop; + this->demux_plugin.dispose = demux_avi_dispose; + this->demux_plugin.get_status = demux_avi_get_status; + this->demux_plugin.get_stream_length = demux_avi_get_stream_length; - if (this->avi) - AVI_close (this->avi); + this->status = DEMUX_FINISHED; + pthread_mutex_init (&this->mutex, NULL); - this->avi = AVI_init (this); + switch (stream->content_detection_method) { + + case XINE_DEMUX_CONTENT_STRATEGY: - if (this->avi) { + if (input->get_capabilities(input) & INPUT_CAP_BLOCK) { + printf ("demux_avi: AVI_init failed (AVI_errno: %d)\n", + this->AVI_errno); + free (this); + return NULL; + } - printf ("demux_avi: %ld frames\n", this->avi->video_idx.video_frames); + input->seek(input, 0, SEEK_SET); - strncpy(this->last_mrl, input->get_mrl (input), 1024); + this->avi = AVI_init (this); - return demux_avi_send_headers (this); + if (!this->avi) { + free (this); + return NULL; } - /* printf ("demux_avi: AVI_init failed (AVI_errno: %d)\n", this->AVI_errno); */ - - return DEMUX_CANNOT_HANDLE; - } break; - case STAGE_BY_EXTENSION: { + case XINE_DEMUX_EXTENSION_STRATEGY: { char *ending, *mrl; - char *m, *valid_ends; mrl = input->get_mrl (input); ending = strrchr(mrl, '.'); - if(ending) { - xine_strdupa(valid_ends, - this->config->register_string(this->config, - "mrl.ends_avi", VALID_ENDS, - _("valid mrls ending for avi demuxer"), - NULL, 20, NULL, NULL)); - while((m = xine_strsep(&valid_ends, ",")) != NULL) { - - while(*m == ' ' || *m == '\t') m++; - - if(!strcasecmp((ending + 1), m)) { - - this->input = input; + if (!ending) { + free (this); + return NULL; + } - if (this->avi) - AVI_close (this->avi); + if (strncasecmp (ending, ".AVI", 4)) { + free (this); + return NULL; + } - this->avi = AVI_init (this); + this->avi = AVI_init (this); - if (this->avi) { - strncpy(this->last_mrl, input->get_mrl (input), 1024); - return demux_avi_send_headers (this); - } else { - printf ("demux_avi: AVI_init failed (AVI_errno: %d)\n", - this->AVI_errno); - return DEMUX_CANNOT_HANDLE; - } - } - } + if (!this->avi) { + printf ("demux_avi: AVI_init failed (AVI_errno: %d)\n", + this->AVI_errno); + free (this); + return NULL; } - return DEMUX_CANNOT_HANDLE; } break; default: - return DEMUX_CANNOT_HANDLE; - break; + free (this); + return NULL; } - return DEMUX_CANNOT_HANDLE; + strncpy (this->last_mrl, input->get_mrl (input), 1024); + + printf ("demux_avi: %ld frames\n", this->avi->video_idx.video_frames); + + return this; +} + +static char *get_description (demux_class_t *this_gen) { + return "AVI/RIFF demux plugin"; } -static char *demux_avi_get_id(void) { +static char *get_identifier (demux_class_t *this_gen) { return "AVI"; } -static char *demux_avi_get_mimetypes(void) { +static char *get_extensions (demux_class_t *this_gen) { + return "avi"; +} + +static char *get_mimetypes (demux_class_t *this_gen) { return "video/msvideo: avi: AVI animation;" "video/x-msvideo: avi: AVI animation;"; } -static int demux_avi_get_stream_length (demux_plugin_t *this_gen) { - - demux_avi_t *this = (demux_avi_t *) this_gen; +static void class_dispose (demux_class_t *this_gen) { - if (this->avi) { - return get_video_pts(this, this->avi->video_idx.video_frames) / 90000 ; - } + demux_avi_class_t *this = (demux_avi_class_t *) this_gen; - return 0; + free (this); } -static void *init_demuxer_plugin(xine_t *xine, void *data) { +static void *init_plugin (xine_t *xine, void *data) { - demux_avi_t *this; + demux_avi_class_t *this; - this = xine_xmalloc (sizeof (demux_avi_t)); + this = xine_xmalloc (sizeof (demux_avi_class_t)); this->config = xine->config; this->xine = xine; - (void*) this->config->register_string(this->config, - "mrl.ends_avi", VALID_ENDS, - _("valid mrls ending for avi demuxer"), - NULL, 20, NULL, NULL); - - this->demux_plugin.open = demux_avi_open; - this->demux_plugin.start = demux_avi_start; - this->demux_plugin.seek = demux_avi_seek; - this->demux_plugin.stop = demux_avi_stop; - this->demux_plugin.dispose = demux_avi_dispose; - this->demux_plugin.get_status = demux_avi_get_status; - this->demux_plugin.get_identifier = demux_avi_get_id; - this->demux_plugin.get_stream_length = demux_avi_get_stream_length; - this->demux_plugin.get_mimetypes = demux_avi_get_mimetypes; - - this->status = DEMUX_FINISHED; - pthread_mutex_init( &this->mutex, NULL ); + this->demux_class.get_description = get_description; + this->demux_class.get_identifier = get_identifier; + this->demux_class.get_mimetypes = get_mimetypes; + this->demux_class.get_extensions = get_extensions; + this->demux_class.dispose = class_dispose; return this; } @@ -1643,6 +1643,6 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 11, "avi", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } + { PLUGIN_DEMUX, 12, "avi", XINE_VERSION_CODE, NULL, init_plugin, open_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL, NULL } }; diff --git a/src/input/Makefile.am b/src/input/Makefile.am index 1cd0900fd..c4bfc1ed4 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -18,74 +18,78 @@ libdir = $(XINE_PLUGINDIR) # All of xine input plugins should be named like the scheme "xineplug_inp_" # -if HAVE_CDROM_IOCTLS -in_dvd = xineplug_inp_dvd.la -in_vcd = xineplug_inp_vcd.la -in_cda = xineplug_inp_cda.la -endif +#if HAVE_CDROM_IOCTLS +#in_dvd = xineplug_inp_dvd.la +#in_vcd = xineplug_inp_vcd.la +#in_cda = xineplug_inp_cda.la +#endif # For DVD -if HAVE_DVDNAV -DVD_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \ - $(DVDNAV_CFLAGS) \ - -I$(top_srcdir)/src/input/libdvdread/ -link_dvdnav = $(DVDNAV_LIBS) -else -DVD_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \ - -I$(top_srcdir)/src/input/libdvdnav/ \ - -I$(top_srcdir)/src/input/libdvdread/ -link_dvdnav = libdvdnav/libdvdnav.la libdvdread/libdvdread.la -endif +#if HAVE_DVDNAV +#DVD_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \ +# $(DVDNAV_CFLAGS) \ +# -I$(top_srcdir)/src/input/libdvdread/ +#link_dvdnav = $(DVDNAV_LIBS) +#else +#DVD_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \ +# -I$(top_srcdir)/src/input/libdvdnav/ \ +# -I$(top_srcdir)/src/input/libdvdread/ +#link_dvdnav = libdvdnav/libdvdnav.la libdvdread/libdvdread.la +#endif AM_CFLAGS = $(DVD_CFLAGS) DEBUG_CFLAGS = @DEBUG_CFLAGS@ $(DVD_CFLAGS) lib_LTLIBRARIES = \ - $(in_cda) \ - $(in_dvd) \ - $(in_vcd) \ - xineplug_inp_file.la \ - xineplug_inp_http.la \ - xineplug_inp_mms.la \ - xineplug_inp_net.la \ - xineplug_inp_rtp.la \ - xineplug_inp_stdin_fifo.la - + xineplug_inp_file.la + +#lib_LTLIBRARIES = \ +# $(in_cda) \ +# $(in_dvd) \ +# $(in_vcd) \ +# xineplug_inp_file.la \ +# xineplug_inp_http.la \ +# xineplug_inp_mms.la \ +# xineplug_inp_net.la \ +# xineplug_inp_rtp.la \ +# xineplug_inp_stdin_fifo.la + + xineplug_inp_file_la_SOURCES = input_file.c xineplug_inp_file_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la xineplug_inp_file_la_LDFLAGS = -avoid-version -module -xineplug_inp_dvd_la_SOURCES = input_dvd.c -xineplug_inp_dvd_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la $(link_dvdnav) -xineplug_inp_dvd_la_LDFLAGS = -avoid-version -module +#xineplug_inp_dvd_la_SOURCES = input_dvd.c +#xineplug_inp_dvd_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la $(link_dvdnav) +#xineplug_inp_dvd_la_LDFLAGS = -avoid-version -module -xineplug_inp_net_la_SOURCES = input_net.c net_buf_ctrl.c -xineplug_inp_net_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_inp_net_la_LDFLAGS = -avoid-version -module +#xineplug_inp_net_la_SOURCES = input_net.c net_buf_ctrl.c +#xineplug_inp_net_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_inp_net_la_LDFLAGS = -avoid-version -module -xineplug_inp_mms_la_SOURCES = input_mms.c net_buf_ctrl.c mms.c -xineplug_inp_mms_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_inp_mms_la_LDFLAGS = -avoid-version -module +#xineplug_inp_mms_la_SOURCES = input_mms.c net_buf_ctrl.c mms.c +#xineplug_inp_mms_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_inp_mms_la_LDFLAGS = -avoid-version -module -xineplug_inp_vcd_la_SOURCES = input_vcd.c -xineplug_inp_vcd_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_inp_vcd_la_LDFLAGS = -avoid-version -module +#xineplug_inp_vcd_la_SOURCES = input_vcd.c +#xineplug_inp_vcd_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_inp_vcd_la_LDFLAGS = -avoid-version -module -xineplug_inp_stdin_fifo_la_SOURCES = input_stdin_fifo.c net_buf_ctrl.c -xineplug_inp_stdin_fifo_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_inp_stdin_fifo_la_LDFLAGS = -avoid-version -module +#xineplug_inp_stdin_fifo_la_SOURCES = input_stdin_fifo.c net_buf_ctrl.c +#xineplug_inp_stdin_fifo_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_inp_stdin_fifo_la_LDFLAGS = -avoid-version -module -xineplug_inp_rtp_la_SOURCES = input_rtp.c -xineplug_inp_rtp_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_inp_rtp_la_LDFLAGS = -avoid-version -module +#xineplug_inp_rtp_la_SOURCES = input_rtp.c +#xineplug_inp_rtp_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_inp_rtp_la_LDFLAGS = -avoid-version -module -xineplug_inp_http_la_SOURCES = input_http.c net_buf_ctrl.c -xineplug_inp_http_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_inp_http_la_LDFLAGS = -avoid-version -module +#xineplug_inp_http_la_SOURCES = input_http.c net_buf_ctrl.c +#xineplug_inp_http_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_inp_http_la_LDFLAGS = -avoid-version -module -xineplug_inp_cda_la_SOURCES = input_cda.c -xineplug_inp_cda_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -xineplug_inp_cda_la_LDFLAGS = -avoid-version -module +#xineplug_inp_cda_la_SOURCES = input_cda.c +#xineplug_inp_cda_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +#xineplug_inp_cda_la_LDFLAGS = -avoid-version -module include_HEADERS = input_plugin.h noinst_HEADERS = net_buf_ctrl.h mms.h diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c index 390b1949b..33077fb59 100644 --- a/src/input/input_dvd.c +++ b/src/input/input_dvd.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2000, 2001 the xine project, - * Rich Wareham + * Copyright (C) 2000-2002 the xine project, + * Rich Wareham * - * This file is part of xine, a unix video player. + * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,7 +18,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: input_dvd.c,v 1.92 2002/10/06 15:48:02 jkeil Exp $ + * $Id: input_dvd.c,v 1.93 2002/10/14 15:47:16 guenter Exp $ * */ @@ -1564,6 +1564,9 @@ static void *init_input_plugin (xine_t *xine, void *data) { /* * $Log: input_dvd.c,v $ + * Revision 1.93 2002/10/14 15:47:16 guenter + * introduction of xine_stream_t and async xine events - all still in developement + * * Revision 1.92 2002/10/06 15:48:02 jkeil * Proper alignment is needed for the array of "xine_mrl_t" structures on SPARC. * diff --git a/src/input/input_file.c b/src/input/input_file.c index 2550cd2ca..4aeb23796 100644 --- a/src/input/input_file.c +++ b/src/input/input_file.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: input_file.c,v 1.60 2002/09/22 14:29:40 mroi Exp $ + * $Id: input_file.c,v 1.61 2002/10/14 15:47:17 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -43,25 +43,258 @@ extern int errno; #define MAXFILES 65535 -#ifdef __GNUC__ -#define LOG_MSG_STDERR(xine, message, args...) { \ - xine_log(xine, XINE_LOG_MSG, message, ##args); \ - fprintf(stderr, message, ##args); \ - } -#define LOG_MSG(xine, message, args...) { \ - xine_log(xine, XINE_LOG_MSG, message, ##args); \ - printf(message, ##args); \ +typedef struct { + + input_class_t input_class; + + xine_t *xine; + config_values_t *config; + + int show_hidden_files; + char *origin_path; + + int mrls_allocated_entries; + xine_mrl_t **mrls; + +} file_input_class_t; + +typedef struct { + input_plugin_t input_plugin; + + xine_stream_t *stream; + + int fh; + char *mrl; + + FILE *sub; + +} file_input_plugin_t; + + +static uint32_t file_plugin_get_capabilities (input_plugin_t *this_gen) { + + return INPUT_CAP_SEEKABLE | INPUT_CAP_SPULANG; +} + + +static off_t file_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + + return read (this->fh, buf, len); +} + +/* + * helper function to release buffer + * in case demux thread is cancelled + */ +static void pool_release_buffer (void *arg) { + buf_element_t *buf = (buf_element_t *) arg; + if( buf != NULL ) + buf->free_buffer(buf); +} + +static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) { + + off_t num_bytes, total_bytes; + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + pthread_cleanup_push( pool_release_buffer, buf ); + + buf->content = buf->mem; + buf->type = BUF_DEMUX_BLOCK; + total_bytes = 0; + + while (total_bytes < todo) { + pthread_testcancel(); + num_bytes = read (this->fh, buf->mem + total_bytes, todo-total_bytes); + if (num_bytes <= 0) { + if (num_bytes < 0) + xine_log (this->stream->xine, XINE_LOG_MSG, + _("input_file: read error (%s)\n"), strerror(errno)); + buf->free_buffer (buf); + buf = NULL; + break; + } + total_bytes += num_bytes; } -#else -#define LOG_MSG_STDERR(xine, ...) { \ - xine_log(xine, XINE_LOG_MSG, __VA_ARGS__); \ - fprintf(stderr, __VA_ARGS__); \ + + if( buf != NULL ) + buf->size = total_bytes; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); + pthread_cleanup_pop(0); + + return buf; +} + +static off_t file_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + + return lseek (this->fh, offset, origin); +} + +static off_t file_plugin_get_current_pos (input_plugin_t *this_gen){ + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + + if (this->fh <0) + return 0; + + return lseek (this->fh, 0, SEEK_CUR); +} + +static off_t file_plugin_get_length (input_plugin_t *this_gen) { + + struct stat buf ; + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + + if (this->fh <0) + return 0; + + if (fstat (this->fh, &buf) == 0) { + return buf.st_size; + } else + perror ("system call fstat"); + return 0; +} + +static uint32_t file_plugin_get_blocksize (input_plugin_t *this_gen) { + return 0; +} + +/* + * Return 1 is filepathname is a directory, otherwise 0 + */ +static int is_a_dir(char *filepathname) { + struct stat pstat; + + stat(filepathname, &pstat); + + return (S_ISDIR(pstat.st_mode)); +} + +static int file_plugin_eject_media (input_plugin_t *this_gen) { + return 1; /* doesn't make sense */ +} + +static char* file_plugin_get_mrl (input_plugin_t *this_gen) { + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + + return this->mrl; +} + +static int file_plugin_get_optional_data (input_plugin_t *this_gen, + void *data, int data_type) { + + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + +#ifdef LOG + printf ("input_file: get optional data, type %08x, sub %p\n", + data_type, this->sub); +#endif + + switch(data_type) { + case INPUT_OPTIONAL_DATA_TEXTSPU0: + if(this->sub) { + FILE **tmp; + + /* dirty hacks... */ + tmp = data; + *tmp = this->sub; + + return INPUT_OPTIONAL_SUCCESS; + } + break; + + case INPUT_OPTIONAL_DATA_SPULANG: + sprintf(data, "%3s", (this->sub) ? "sub" : "none"); + return INPUT_OPTIONAL_SUCCESS; + break; + + default: + return INPUT_OPTIONAL_UNSUPPORTED; + break; + } -#define LOG_MSG(xine, ...) { \ - xine_log(xine, XINE_LOG_MSG, __VA_ARGS__); \ - printf(__VA_ARGS__); \ + + return INPUT_OPTIONAL_UNSUPPORTED; +} + +static void file_plugin_dispose (input_plugin_t *this_gen ) { + file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + + close(this->fh); + + if (this->sub) + fclose (this->sub); + + free (this->mrl); + + free (this); +} + +static void *open_plugin (void *cls_gen, xine_stream_t *stream, + const void *data) { + + file_input_class_t *cls = (file_input_class_t *) cls_gen; + file_input_plugin_t *this; + char *mrl = strdup ((char *) data); + FILE *sub; + char *filename, *subtitle; + int fh; + + if (!strncasecmp (mrl, "file://", 7)) + filename = &mrl[7]; + else + filename = mrl; + + subtitle = strrchr (filename, '%'); + if (subtitle) { + *subtitle = 0; + subtitle++; + + xine_log (cls->xine, XINE_LOG_MSG, + _("input_file: trying to open subtitle file '%s'\n"), + subtitle); + + sub = fopen (subtitle, "r"); + + } else + sub = NULL; + + + fh = open (filename, O_RDONLY); + + if (fh == -1) { + free (mrl); + return NULL; } -#endif + + this = (file_input_plugin_t *) xine_xmalloc (sizeof (file_input_plugin_t)); + this->stream = stream; + this->mrl = mrl; + this->fh = fh; + this->sub = sub; + + this->input_plugin.get_capabilities = file_plugin_get_capabilities; + this->input_plugin.read = file_plugin_read; + this->input_plugin.read_block = file_plugin_read_block; + this->input_plugin.seek = file_plugin_seek; + this->input_plugin.get_current_pos = file_plugin_get_current_pos; + this->input_plugin.get_length = file_plugin_get_length; + this->input_plugin.get_blocksize = file_plugin_get_blocksize; + this->input_plugin.get_mrl = file_plugin_get_mrl; + this->input_plugin.get_optional_data = file_plugin_get_optional_data; + this->input_plugin.dispose = file_plugin_dispose; + + return this; +} + + +/* + * plugin class functions + */ #ifndef S_ISLNK #define S_ISLNK(mode) 0 @@ -85,38 +318,16 @@ extern int errno; #define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) #endif -typedef struct { - input_plugin_t input_plugin; - - xine_t *xine; - - int fh; - int show_hidden_files; - char *origin_path; - FILE *sub; - char *mrl; - config_values_t *config; - - int mrls_allocated_entries; - xine_mrl_t **mrls; - -} file_input_plugin_t; - - -/* *************************************************************************** - * PRIVATES FUNCTIONS - */ - /* * Callback for config changes. */ static void hidden_bool_cb(void *data, xine_cfg_entry_t *cfg) { - file_input_plugin_t *this = (file_input_plugin_t *) data; + file_input_class_t *this = (file_input_class_t *) data; this->show_hidden_files = cfg->num_value; } static void origin_change_cb(void *data, xine_cfg_entry_t *cfg) { - file_input_plugin_t *this = (file_input_plugin_t *) data; + file_input_class_t *this = (file_input_class_t *) data; this->origin_path = cfg->str_value; } @@ -206,7 +417,9 @@ static uint32_t get_file_type(char *filepathname, char *origin, xine_t *xine) { if((lstat(filepathname, &pstat)) < 0) { sprintf(buf, "%s/%s", origin, filepathname); if((lstat(buf, &pstat)) < 0) { - LOG_MSG(xine, _("lstat failed for %s{%s}\n"), filepathname, origin); +#ifdef LOG + printf ("lstat failed for %s{%s}\n", filepathname, origin); +#endif file_type |= mrl_unknown; return file_type; } @@ -257,179 +470,17 @@ static off_t get_file_size(char *filepathname, char *origin) { return pstat.st_size; } -/* - * END OF PRIVATES - *****************************************************************************/ -/* - * - */ -static uint32_t file_plugin_get_capabilities (input_plugin_t *this_gen) { - - return INPUT_CAP_SEEKABLE | INPUT_CAP_PREVIEW | INPUT_CAP_GET_DIR | INPUT_CAP_SPULANG; -} - -/* - * - */ -static int file_plugin_open (input_plugin_t *this_gen, const char *mrl) { - - char *filename, *subtitle; - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - if (this->mrl) - free (this->mrl); - - this->mrl = strdup(mrl); - - if (!strncasecmp (this->mrl, "file://", 7)) - filename = &this->mrl[7]; - else - filename = this->mrl; - - subtitle = strrchr (filename, '%'); - if (subtitle) { - *subtitle = 0; - subtitle++; - - LOG_MSG(this->xine, _("input_file: trying to open subtitle file '%s'\n"), - subtitle); - - this->sub = fopen (subtitle, "r"); - - } else - this->sub = NULL; - - - this->fh = open (filename, O_RDONLY); - - if (this->fh == -1) { - return 0; - } - - return 1; -} - -/* - * - */ -static off_t file_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - return read (this->fh, buf, len); -} - -/* - * helper function to release buffer - * in case demux thread is cancelled - */ -static void pool_release_buffer (void *arg) { - buf_element_t *buf = (buf_element_t *) arg; - if( buf != NULL ) - buf->free_buffer(buf); -} - -/* - * - */ -static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) { - - off_t num_bytes, total_bytes; - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - buf_element_t *buf = fifo->buffer_pool_alloc (fifo); - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); - pthread_cleanup_push( pool_release_buffer, buf ); - - buf->content = buf->mem; - buf->type = BUF_DEMUX_BLOCK; - total_bytes = 0; - - while (total_bytes < todo) { - pthread_testcancel(); - num_bytes = read (this->fh, buf->mem + total_bytes, todo-total_bytes); - if (num_bytes <= 0) { - if (num_bytes < 0) - LOG_MSG_STDERR(this->xine, _("input_file: read error (%s)\n"), strerror(errno)); - buf->free_buffer (buf); - buf = NULL; - break; - } - total_bytes += num_bytes; - } - - if( buf != NULL ) - buf->size = total_bytes; - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); - pthread_cleanup_pop(0); - - return buf; -} - -/* - * - */ -static off_t file_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - return lseek (this->fh, offset, origin); -} - -/* - * - */ -static off_t file_plugin_get_current_pos (input_plugin_t *this_gen){ - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - if (this->fh <0) - return 0; - - return lseek (this->fh, 0, SEEK_CUR); -} - -/* - * - */ -static off_t file_plugin_get_length (input_plugin_t *this_gen) { - - struct stat buf ; - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - if (this->fh <0) - return 0; - - if (fstat (this->fh, &buf) == 0) { - return buf.st_size; - } else - perror ("system call fstat"); - return 0; +static char *file_class_get_description (input_class_t *this_gen) { + return _("file input plugin"); } -/* - * - */ -static uint32_t file_plugin_get_blocksize (input_plugin_t *this_gen) { - return 0; -} +static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, + const char *filename, int *nFiles) { -/* - * Return 1 is filepathname is a directory, otherwise 0 - */ -static int is_a_dir(char *filepathname) { - struct stat pstat; - - stat(filepathname, &pstat); + /* FIXME: this code needs cleanup badly */ - return (S_ISDIR(pstat.st_mode)); -} - -/* - * - */ -static xine_mrl_t **file_plugin_get_dir (input_plugin_t *this_gen, - const char *filename, int *nFiles) { - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + file_input_class_t *this = (file_input_class_t *) this_gen; struct dirent *pdirent; DIR *pdir; xine_mrl_t *hide_files, *dir_files, *norm_files; @@ -522,10 +573,8 @@ static xine_mrl_t **file_plugin_get_dir (input_plugin_t *this_gen, memset(linkbuf, 0, sizeof(linkbuf)); linksize = readlink(fullfilename, linkbuf, XINE_PATH_MAX + XINE_NAME_MAX); - if(linksize < 0) { - LOG_MSG_STDERR(this->xine, _("%s(%d): readlink() failed: %s\n"), - __XINE_FUNCTION__, __LINE__, strerror(errno)); - } + if(linksize < 0) + printf ("input_file: readlink() failed: %s\n", strerror(errno)); else { dir_files[num_dir_files].link = (char *) xine_xmalloc(linksize + 1); strncpy(dir_files[num_dir_files].link, linkbuf, linksize); @@ -562,8 +611,7 @@ static xine_mrl_t **file_plugin_get_dir (input_plugin_t *this_gen, linksize = readlink(fullfilename, linkbuf, XINE_PATH_MAX + XINE_NAME_MAX); if(linksize < 0) { - LOG_MSG_STDERR(this->xine, _("%s(%d): readlink() failed: %s\n"), - __XINE_FUNCTION__, __LINE__, strerror(errno)); + printf ("input_file: readlink() failed: %s\n", strerror(errno)); } else { hide_files[num_hide_files].link = (char *) @@ -598,8 +646,7 @@ static xine_mrl_t **file_plugin_get_dir (input_plugin_t *this_gen, linksize = readlink(fullfilename, linkbuf, XINE_PATH_MAX + XINE_NAME_MAX); if(linksize < 0) { - LOG_MSG_STDERR(this->xine, _("%s(%d): readlink() failed: %s\n"), - __XINE_FUNCTION__, __LINE__, strerror(errno)); + printf ("input_file: readlink() failed: %s\n", strerror(errno)); } else { norm_files[num_norm_files].link = (char *) @@ -743,143 +790,29 @@ static xine_mrl_t **file_plugin_get_dir (input_plugin_t *this_gen, return this->mrls; } -/* - * - */ -static int file_plugin_eject_media (input_plugin_t *this_gen) { - return 1; /* doesn't make sense */ -} - -/* - * - */ -static char* file_plugin_get_mrl (input_plugin_t *this_gen) { - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - return this->mrl; -} - -/* - * - */ -static void file_plugin_close (input_plugin_t *this_gen) { - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - close(this->fh); - this->fh = -1; - - if (this->sub) { - fclose (this->sub); - this->sub = NULL; - } -} - -/* - * - */ -static void file_plugin_stop (input_plugin_t *this_gen) { - - file_plugin_close(this_gen); -} - -/* - * - */ -static char *file_plugin_get_description (input_plugin_t *this_gen) { - return _("plain file input plugin as shipped with xine"); -} - -/* - * - */ -static char *file_plugin_get_identifier (input_plugin_t *this_gen) { - return "file"; -} - -/* - * - */ -static int file_plugin_get_optional_data (input_plugin_t *this_gen, - void *data, int data_type) { - - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - -#ifdef LOG - LOG_MSG(this->xine, _("input_file: get optional data, type %08x, sub %p\n"), - data_type, this->sub); -#endif - - switch(data_type) { - case INPUT_OPTIONAL_DATA_TEXTSPU0: - if(this->sub) { - FILE **tmp; - - /* dirty hacks... */ - tmp = data; - *tmp = this->sub; - - return INPUT_OPTIONAL_SUCCESS; - } - break; - - case INPUT_OPTIONAL_DATA_SPULANG: - sprintf(data, "%3s", (this->sub) ? "sub" : "none"); - return INPUT_OPTIONAL_SUCCESS; - break; - - default: - return INPUT_OPTIONAL_UNSUPPORTED; - break; - - } - - return INPUT_OPTIONAL_UNSUPPORTED; -} - -static void file_plugin_dispose (input_plugin_t *this_gen ) { - file_input_plugin_t *this = (file_input_plugin_t *) this_gen; - - if (this->mrl) - free (this->mrl); +static void file_class_dispose (input_class_t *this_gen) { + file_input_class_t *this = (file_input_class_t *) this_gen; free (this->mrls); free (this); } -static void *init_input_plugin (xine_t *xine, void *data) { +static void *init_plugin (xine_t *xine, void *data) { - file_input_plugin_t *this; + file_input_class_t *this; config_values_t *config; - this = (file_input_plugin_t *) xine_xmalloc (sizeof (file_input_plugin_t)); - config = xine->config; - this->xine = xine; + this = (file_input_class_t *) xine_xmalloc (sizeof (file_input_class_t)); - this->input_plugin.get_capabilities = file_plugin_get_capabilities; - this->input_plugin.open = file_plugin_open; - this->input_plugin.read = file_plugin_read; - this->input_plugin.read_block = file_plugin_read_block; - this->input_plugin.seek = file_plugin_seek; - this->input_plugin.get_current_pos = file_plugin_get_current_pos; - this->input_plugin.get_length = file_plugin_get_length; - this->input_plugin.get_blocksize = file_plugin_get_blocksize; - this->input_plugin.get_dir = file_plugin_get_dir; - this->input_plugin.eject_media = file_plugin_eject_media; - this->input_plugin.get_mrl = file_plugin_get_mrl; - this->input_plugin.close = file_plugin_close; - this->input_plugin.stop = file_plugin_stop; - this->input_plugin.get_description = file_plugin_get_description; - this->input_plugin.get_identifier = file_plugin_get_identifier; - this->input_plugin.get_autoplay_list = NULL; - this->input_plugin.get_optional_data = file_plugin_get_optional_data; - this->input_plugin.dispose = file_plugin_dispose; - this->input_plugin.is_branch_possible = NULL; + this->xine = xine; + this->config = xine->config; + config = xine->config; + + this->input_class.get_dir = file_class_get_dir; + this->input_class.get_description = file_class_get_description; + this->input_class.get_autoplay_list = NULL; + this->input_class.dispose = file_class_dispose; - this->fh = -1; - this->sub = NULL; - this->mrl = NULL; - this->config = config; - this->mrls = (xine_mrl_t **) xine_xmalloc(sizeof(xine_mrl_t*)); this->mrls_allocated_entries = 0; @@ -889,14 +822,18 @@ static void *init_input_plugin (xine_t *xine, void *data) { if(getcwd(current_dir, sizeof(current_dir)) == NULL) strcpy(current_dir, "."); - this->origin_path = config->register_string(this->config, "input.file_origin_path", - current_dir, _("file browsing start location"), - NULL, 0, origin_change_cb, (void *) this); + this->origin_path = config->register_string(config, "input.file_origin_path", + current_dir, + _("file browsing start location"), + NULL, 0, origin_change_cb, + (void *) this); } - this->show_hidden_files = this->config->register_bool(this->config, "input.file_hidden_files", - 1, _("list hidden files"), - NULL, 10, hidden_bool_cb, (void *) this); + this->show_hidden_files = config->register_bool(config, + "input.file_hidden_files", + 1, _("list hidden files"), + NULL, 10, hidden_bool_cb, + (void *) this); return this; } @@ -907,7 +844,7 @@ static void *init_input_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_INPUT, 8, "file", XINE_VERSION_CODE, NULL, init_input_plugin }, + { PLUGIN_INPUT, 8, "file", XINE_VERSION_CODE, NULL, init_plugin, open_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_plugin.h b/src/input/input_plugin.h index 360cd9447..20ce70653 100644 --- a/src/input/input_plugin.h +++ b/src/input/input_plugin.h @@ -17,24 +17,163 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: input_plugin.h,v 1.31 2002/09/22 14:29:40 mroi Exp $ + * $Id: input_plugin.h,v 1.32 2002/10/14 15:47:19 guenter Exp $ */ #ifndef HAVE_INPUT_PLUGIN_H #define HAVE_INPUT_PLUGIN_H -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include #include "buffer.h" #include "configfile.h" -#define INPUT_PLUGIN_IFACE_VERSION 8 +#define INPUT_PLUGIN_IFACE_VERSION 9 +typedef struct input_class_s input_class_t ; + +struct input_class_s { + + /* + * return short, human readable identifier for this plugin class + */ + char* (*get_identifier) (input_class_t *this); + + /* + * return human readable (verbose = 1 line) description for + * this plugin class + */ + char* (*get_description) (input_class_t *this); + + /* + * ls function, optional: may be NULL + * return value: NULL => filename is a file, **char=> filename is a dir + */ + xine_mrl_t ** (*get_dir) (input_class_t *this, const char *filename, int *nFiles); + + /* + * generate autoplay list, optional: may be NULL + * return value: list of MRLs + */ + char ** (*get_autoplay_list) (input_class_t *this, int *num_files); + + /* + * close down, free all resources + */ + void (*dispose) (input_class_t *this); + + /* + * eject/load the media (if possible) + * + * returns 0 for temporary failures + */ + int (*eject_media) (input_class_t *this); +}; + +typedef struct input_plugin_s input_plugin_t; + +struct input_plugin_s { + + /* + * return capabilities of input source + */ + + uint32_t (*get_capabilities) (input_plugin_t *this); + + /* + * read nlen bytes, return number of bytes read + */ + off_t (*read) (input_plugin_t *this, char *buf, off_t nlen); + + + /* + * read one block, return newly allocated block (or NULL on failure) + * for blocked input sources len must be == blocksize + * the fifo parameter is only used to get access to the buffer_pool_alloc function + */ + buf_element_t *(*read_block)(input_plugin_t *this, fifo_buffer_t *fifo, off_t len); + + + /* + * seek position, return new position + * + * if seeking failed, -1 is returned + */ + off_t (*seek) (input_plugin_t *this, off_t offset, int origin); + + + /* + * get current position in stream. + * + */ + off_t (*get_current_pos) (input_plugin_t *this); + + + /* + * return length of input (-1 => unlimited, e.g. stream) + */ + off_t (*get_length) (input_plugin_t *this); + + + /* + * return block size of input source (if supported, 0 otherwise) + */ + + uint32_t (*get_blocksize) (input_plugin_t *this); + + + /* + * return current MRL + */ + char * (*get_mrl) (input_plugin_t *this); + + + /* + * request optional data from input plugin. + */ + int (*get_optional_data) (input_plugin_t *this, void *data, int data_type); + + + /* + * close stream, free instance resources + */ + void (*dispose) (input_plugin_t *this); + + /* + * "backward" link to input plugin class struct + */ + + input_class_t *input_class; + +}; + +/* + * possible capabilites an input plugin can have: + */ +#define INPUT_CAP_NOCAP 0x00000000 +#define INPUT_CAP_SEEKABLE 0x00000001 +#define INPUT_CAP_BLOCK 0x00000002 +#define INPUT_CAP_CLUT 0x00000004 +#define INPUT_CAP_AUDIOLANG 0x00000008 +#define INPUT_CAP_SPULANG 0x00000010 +#define INPUT_CAP_VARIABLE_BITRATE 0x00000020 +/* for non-seekable plugins, allows content detection: */ +#define INPUT_CAP_PREVIEW 0x00000040 +#define INPUT_CAP_CHAPTERS 0x00000080 + + +#define INPUT_OPTIONAL_UNSUPPORTED 0 +#define INPUT_OPTIONAL_SUCCESS 1 + +#define INPUT_OPTIONAL_DATA_CLUT 1 +#define INPUT_OPTIONAL_DATA_AUDIOLANG 2 +#define INPUT_OPTIONAL_DATA_SPULANG 3 +#define INPUT_OPTIONAL_DATA_TEXTSPU0 4 +#define INPUT_OPTIONAL_DATA_TEXTSPU1 5 +#define INPUT_OPTIONAL_DATA_TEXTSPU2 6 +#define INPUT_OPTIONAL_DATA_PREVIEW 7 + #define MAX_MRL_ENTRIES 255 /* Types of mrls returned by get_dir() */ @@ -136,174 +275,5 @@ extern "C" { } \ } -typedef struct input_plugin_s input_plugin_t; - -struct input_plugin_s -{ - - /* - * return capabilities of input source - */ - - uint32_t (*get_capabilities) (input_plugin_t *this); - - /* - * open input MRL - return 1 if succ - */ - int (*open) (input_plugin_t *this, const char *mrl); - - - /* - * read nlen bytes, return number of bytes read - */ - off_t (*read) (input_plugin_t *this, char *buf, off_t nlen); - - - /* - * read one block, return newly allocated block (or NULL on failure) - * for blocked input sources len must be == blocksize - * the fifo parameter is only used to get access to the buffer_pool_alloc function - */ - buf_element_t *(*read_block)(input_plugin_t *this, fifo_buffer_t *fifo, off_t len); - - - /* - * seek position, return new position - * - * if seeking failed, -1 is returned - */ - off_t (*seek) (input_plugin_t *this, off_t offset, int origin); - - - /* - * get current position in stream. - * - */ - off_t (*get_current_pos) (input_plugin_t *this); - - - /* - * return length of input (-1 => unlimited, e.g. stream) - */ - off_t (*get_length) (input_plugin_t *this); - - - /* - * return block size of input source (if supported, 0 otherwise) - */ - - uint32_t (*get_blocksize) (input_plugin_t *this); - - - /* - * ls function - * return value: NULL => filename is a file, **char=> filename is a dir - */ - xine_mrl_t ** (*get_dir) (input_plugin_t *this, const char *filename, int *nFiles); - - - /* - * eject/load the media (if it's possible) - * - * returns 0 for temporary failures - */ - int (*eject_media) (input_plugin_t *this); - - - /* - * return current MRL - */ - char * (*get_mrl) (input_plugin_t *this); - - - /* - * stop input source - */ - void (*stop) (input_plugin_t *this); - - - /* - * close input source - */ - void (*close) (input_plugin_t *this); - - - /* - * return human readable (verbose = 1 line) description for this plugin - */ - char* (*get_description) (input_plugin_t *this); - - - /* - * return short, human readable identifier for this plugin - * this is used for GUI buttons, The identifier must have max. 4 characters - * characters (max. 5 including terminating \0) - */ - char* (*get_identifier) (input_plugin_t *this); - - - /* - * generate autoplay list - * return value: list of MRLs - */ - char ** (*get_autoplay_list) (input_plugin_t *this, int *nFiles); - - - /* - * request optional data from input plugin. - */ - int (*get_optional_data) (input_plugin_t *this, void *data, int data_type); - - /* - * check if it is possible/valid to directly branch to this MRL - * optional: may be NULL - */ - - int (*is_branch_possible) (input_plugin_t *this, char *next_mrl); - - /* - * free resources - */ - void (*dispose) (input_plugin_t *this); -}; - -/* - * possible capabilites an input plugin can have: - */ -#define INPUT_CAP_NOCAP 0x00000000 -#define INPUT_CAP_SEEKABLE 0x00000001 -#define INPUT_CAP_BLOCK 0x00000002 -#define INPUT_CAP_AUTOPLAY 0x00000004 -#define INPUT_CAP_GET_DIR 0x00000008 -#define INPUT_CAP_BROWSABLE 0x00000010 -#define INPUT_CAP_CLUT 0x00000020 -#define INPUT_CAP_AUDIOLANG 0x00000040 -#define INPUT_CAP_SPULANG 0x00000080 -#define INPUT_CAP_VARIABLE_BITRATE 0x00000100 -#define INPUT_CAP_PREVIEW 0x00000200 /* Requires INPUT_CAP_SEEKABLE */ -#define INPUT_CAP_CHAPTERS 0x00000400 - - -#define INPUT_OPTIONAL_UNSUPPORTED 0 -#define INPUT_OPTIONAL_SUCCESS 1 - -#define INPUT_OPTIONAL_DATA_CLUT 1 -#define INPUT_OPTIONAL_DATA_AUDIOLANG 2 -#define INPUT_OPTIONAL_DATA_SPULANG 3 -#define INPUT_OPTIONAL_DATA_TEXTSPU0 4 -#define INPUT_OPTIONAL_DATA_TEXTSPU1 5 -#define INPUT_OPTIONAL_DATA_TEXTSPU2 6 -#define INPUT_OPTIONAL_DATA_PREVIEW 7 - -/* - * each input plugin _must_ implement this function: - * - * input_plugin_t *init_input_plugin (int iface, xine_t *xine) ; - * - */ - -#ifdef __cplusplus -} -#endif #endif diff --git a/src/input/net_buf_ctrl.c b/src/input/net_buf_ctrl.c index 3065e5885..e9537bf6e 100644 --- a/src/input/net_buf_ctrl.c +++ b/src/input/net_buf_ctrl.c @@ -32,9 +32,9 @@ #define DEFAULT_LOW_WATER_MARK 2 #define DEFAULT_HIGH_WATER_MARK 5 -/* + #define LOG -*/ + struct nbc_s { xine_t *xine; @@ -55,8 +55,8 @@ void nbc_check_buffers (nbc_t *this) { } #ifdef LOG if (this->buffering) { - xine_log (this->xine, XINE_LOG_MSG, - "net_buf_ctl: buffering (%d/%d)...\n", fifo_fill, this->high_water_mark); + printf ("net_buf_ctl: buffering (%d/%d)...\n", + fifo_fill, this->high_water_mark); } #endif if (fifo_filllow_water_mark) { diff --git a/src/libspudec/spu_decoder_api.h b/src/libspudec/spu_decoder_api.h index 34ed1b0f4..937bc7507 100644 --- a/src/libspudec/spu_decoder_api.h +++ b/src/libspudec/spu_decoder_api.h @@ -55,6 +55,7 @@ struct spu_decoder_s { int (*get_nav_pci) (spu_decoder_t *this, pci_t *nav_pci); + void *node; /* used by plugin loader */ }; typedef struct spu_button_s spu_button_t; diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am index 59e3c0899..6eb07a850 100644 --- a/src/xine-engine/Makefile.am +++ b/src/xine-engine/Makefile.am @@ -24,7 +24,7 @@ libxine_la_LDFLAGS = \ include_HEADERS = buffer.h metronom.h configfile.h vo_scale.h \ audio_out.h resample.h video_out.h xine_internal.h spu_decoder.h \ lrb.h video_overlay.h osd.h scratch.h xine_plugin.h xineintl.h \ - plugin_catalog.h + plugin_catalog.h audio_decoder.h video_decoder.h noinst_HEADERS = bswap.h nvtvd.h diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 9ad8ddfdc..892fdbf8d 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.84 2002/09/18 00:51:34 guenter Exp $ + * $Id: audio_decoder.c,v 1.85 2002/10/14 15:47:23 guenter Exp $ * * * functions that implement audio decoding @@ -40,10 +40,10 @@ #define LOG */ -void *audio_decoder_loop (void *this_gen) { +void *audio_decoder_loop (void *stream_gen) { buf_element_t *buf; - xine_t *this = (xine_t *) this_gen; + xine_stream_t *stream = (xine_stream_t *) stream_gen; int running = 1; audio_decoder_t *decoder; static int prof_audio_decode = -1; @@ -58,7 +58,7 @@ void *audio_decoder_loop (void *this_gen) { printf ("audio_loop: waiting for package...\n"); #endif - buf = this->audio_fifo->get (this->audio_fifo); + buf = stream->audio_fifo->get (stream->audio_fifo); #ifdef LOG @@ -67,75 +67,79 @@ void *audio_decoder_loop (void *this_gen) { #endif if (buf->input_pos) - this->cur_input_pos = buf->input_pos; + stream->input_pos = buf->input_pos; if (buf->input_length) - this->cur_input_length = buf->input_length; + stream->input_length = buf->input_length; if (buf->input_time) { - this->cur_input_time = buf->input_time; - pthread_mutex_lock (&this->osd_lock); - if( this->curtime_needed_for_osd && !(--this->curtime_needed_for_osd) ) - xine_internal_osd (this, ">",90000); - pthread_mutex_unlock (&this->osd_lock); + stream->input_time = buf->input_time; } switch (buf->type) { + case BUF_CONTROL_HEADERS_DONE: + pthread_mutex_lock (&stream->counter_lock); + stream->header_count_audio++; + pthread_cond_broadcast (&stream->counter_changed); + pthread_mutex_unlock (&stream->counter_lock); + break; + case BUF_CONTROL_START: - if (this->cur_audio_decoder_plugin) { - this->cur_audio_decoder_plugin->close (this->cur_audio_decoder_plugin); - this->cur_audio_decoder_plugin = NULL; - this->audio_track_map_entries = 0; - this->audio_type = 0; + if (stream->audio_decoder_plugin) { + free_audio_decoder (stream, stream->audio_decoder_plugin); + stream->audio_decoder_plugin = NULL; + stream->audio_track_map_entries = 0; + stream->audio_type = 0; } - pthread_mutex_lock (&this->finished_lock); - this->audio_finished = 0; - pthread_mutex_unlock (&this->finished_lock); - - this->metronom->handle_audio_discontinuity (this->metronom, DISC_STREAMSTART, 0); + stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0); break; case BUF_CONTROL_END: - if (this->cur_audio_decoder_plugin) { - this->cur_audio_decoder_plugin->close (this->cur_audio_decoder_plugin); - this->cur_audio_decoder_plugin = NULL; - this->audio_track_map_entries = 0; - this->audio_type = 0; + if (stream->audio_decoder_plugin) { + free_audio_decoder (stream, stream->audio_decoder_plugin); + stream->audio_decoder_plugin = NULL; + stream->audio_track_map_entries = 0; + stream->audio_type = 0; } + + /* wait for video to reach this marker, if necessary */ - pthread_mutex_lock (&this->finished_lock); + pthread_mutex_lock (&stream->counter_lock); - if (!this->audio_finished ) { - this->audio_finished = 1; - - if (this->video_finished) { - if( this->playing_logo ) - buf->decoder_flags = 0; - this->playing_logo = 0; - - if( buf->decoder_flags & BUF_FLAG_END_STREAM ) - xine_notify_stream_finished (this); - } - } + stream->finished_count_audio++; - pthread_mutex_unlock (&this->finished_lock); + printf ("audio_decoder: reached end marker # %d\n", + stream->finished_count_audio); - this->audio_channel_auto = -1; + pthread_cond_broadcast (&stream->counter_changed); - /* future magic - coming soon - lrb_flush (this->audio_temp); - */ + if (stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO]) { + + while (stream->finished_count_video < stream->finished_count_audio) { + pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); + } + } + + pthread_mutex_unlock (&stream->counter_lock); + + if (!stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO]) { + /* set engine status, send frontend notification event */ + xine_handle_stream_end (stream, + buf->decoder_flags & BUF_FLAG_END_STREAM); + } + + stream->audio_channel_auto = -1; break; case BUF_CONTROL_QUIT: - if (this->cur_audio_decoder_plugin) { - this->cur_audio_decoder_plugin->close (this->cur_audio_decoder_plugin); - this->cur_audio_decoder_plugin = NULL; - this->audio_track_map_entries = 0; - this->audio_type = 0; + if (stream->audio_decoder_plugin) { + free_audio_decoder (stream, stream->audio_decoder_plugin); + stream->audio_decoder_plugin = NULL; + stream->audio_track_map_entries = 0; + stream->audio_type = 0; } running = 0; break; @@ -144,21 +148,21 @@ void *audio_decoder_loop (void *this_gen) { break; case BUF_CONTROL_RESET_DECODER: - if (this->cur_audio_decoder_plugin) - this->cur_audio_decoder_plugin->reset (this->cur_audio_decoder_plugin); - if (this->audio_out) - this->audio_out->control(this->audio_out, AO_CTRL_FLUSH_BUFFERS); + if (stream->audio_decoder_plugin) + stream->audio_decoder_plugin->reset (stream->audio_decoder_plugin); + if (stream->audio_out) + stream->audio_out->control(stream->audio_out, AO_CTRL_FLUSH_BUFFERS); break; case BUF_CONTROL_DISCONTINUITY: - this->metronom->handle_audio_discontinuity (this->metronom, DISC_RELATIVE, buf->disc_off); + stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off); break; case BUF_CONTROL_NEWPTS: if (buf->decoder_flags && BUF_FLAG_SEEK) { - this->metronom->handle_audio_discontinuity (this->metronom, DISC_STREAMSEEK, buf->disc_off); + stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off); } else { - this->metronom->handle_audio_discontinuity (this->metronom, DISC_ABSOLUTE, buf->disc_off); + stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_ABSOLUTE, buf->disc_off); } break; @@ -166,7 +170,7 @@ void *audio_decoder_loop (void *this_gen) { { printf ("audio_decoder: suggested switching to stream_id %02x\n", buf->decoder_info[0]); - this->audio_channel_auto = buf->decoder_info[0] & 0xff; + stream->audio_channel_auto = buf->decoder_info[0] & 0xff; } break; @@ -182,83 +186,79 @@ void *audio_decoder_loop (void *this_gen) { /* printf("audio_decoder: buf_type=%08x auto=%08x user=%08x\n", buf->type, - this->audio_channel_auto, - this->audio_channel_user); + stream->audio_channel_auto, + stream->audio_channel_user); */ /* update track map */ i = 0; - while ( (iaudio_track_map_entries) && (this->audio_track_map[i]type) ) + while ( (iaudio_track_map_entries) && (stream->audio_track_map[i]type) ) i++; - if ( (i==this->audio_track_map_entries) || (this->audio_track_map[i] != buf->type) ) { + if ( (i==stream->audio_track_map_entries) || (stream->audio_track_map[i] != buf->type) ) { - j = this->audio_track_map_entries; + j = stream->audio_track_map_entries; while (j>i) { - this->audio_track_map[j] = this->audio_track_map[j-1]; + stream->audio_track_map[j] = stream->audio_track_map[j-1]; j--; } - this->audio_track_map[i] = buf->type; - this->audio_track_map_entries++; + stream->audio_track_map[i] = buf->type; + stream->audio_track_map_entries++; } /* find out which audio type to decode */ - if (this->audio_channel_user > -2) { + if (stream->audio_channel_user > -2) { - if (this->audio_channel_user == -1) { + if (stream->audio_channel_user == -1) { /* auto */ - if (this->audio_channel_auto>=0) { + if (stream->audio_channel_auto>=0) { - if ((buf->type & 0xFF) == this->audio_channel_auto) { + if ((buf->type & 0xFF) == stream->audio_channel_auto) { audio_type = buf->type; } else audio_type = -1; } else - audio_type = this->audio_track_map[0]; + audio_type = stream->audio_track_map[0]; } else { - if (this->audio_channel_user <= this->audio_track_map_entries) - audio_type = this->audio_track_map[this->audio_channel_user]; + if (stream->audio_channel_user <= stream->audio_track_map_entries) + audio_type = stream->audio_track_map[stream->audio_channel_user]; else audio_type = -1; } - /* now, decode this buffer if it's the right audio type */ + /* now, decode stream buffer if it's the right audio type */ if (buf->type == audio_type) { int streamtype = (buf->type>>16) & 0xFF; - decoder = get_audio_decoder (this, streamtype); + decoder = get_audio_decoder (stream, streamtype); /* close old decoder of audio type has changed */ - if (audio_type != this->audio_type) { + if (audio_type != stream->audio_type) { - if (this->cur_audio_decoder_plugin) { - this->cur_audio_decoder_plugin->close (this->cur_audio_decoder_plugin); - this->cur_audio_decoder_plugin = NULL; + if (stream->audio_decoder_plugin) { + free_audio_decoder (stream, stream->audio_decoder_plugin); + stream->audio_decoder_plugin = NULL; } if (decoder) { xine_event_t event; - this->meta_info[XINE_META_INFO_AUDIOCODEC] - = strdup (decoder->get_identifier()); - xine_report_codec( this, XINE_CODEC_AUDIO, 0, buf->type, 1); - - this->cur_audio_decoder_plugin = decoder; - this->cur_audio_decoder_plugin->init (this->cur_audio_decoder_plugin, this->audio_out); + stream->audio_decoder_plugin = decoder; - this->audio_type = audio_type; + stream->audio_type = audio_type; - event.type = XINE_EVENT_UI_CHANNELS_CHANGED; - xine_send_event(this, &event); + event.type = XINE_EVENT_UI_CHANNELS_CHANGED; + event.data_length = 0; + xine_event_send(stream, &event); } } @@ -267,15 +267,16 @@ void *audio_decoder_loop (void *this_gen) { if (decoder) decoder->decode_data (decoder, buf); else if( buf->type != buftype_unknown ) { - xine_log (this, XINE_LOG_MSG, "audio_decoder: no plugin available to handle '%s'\n", + xine_log (stream->xine, XINE_LOG_MSG, + "audio_decoder: no plugin available to handle '%s'\n", buf_audio_name( buf->type ) ); - xine_report_codec( this, XINE_CODEC_AUDIO, 0, buf->type, 0); buftype_unknown = buf->type; } } } } else if( buf->type != buftype_unknown ) { - xine_log (this, XINE_LOG_MSG, "audio_decoder: unknown buffer type: %08x\n", + xine_log (stream->xine, XINE_LOG_MSG, + "audio_decoder: unknown buffer type: %08x\n", buf->type ); buftype_unknown = buf->type; } @@ -289,15 +290,14 @@ void *audio_decoder_loop (void *this_gen) { pthread_exit(NULL); } -void audio_decoder_init (xine_t *this) { +void audio_decoder_init (xine_stream_t *stream) { pthread_attr_t pth_attrs; struct sched_param pth_params; int err; - if (this->audio_out == NULL) { - this->audio_finished = 1; - this->audio_fifo = NULL; + if (stream->audio_out == NULL) { + stream->audio_fifo = NULL; return; } @@ -308,14 +308,14 @@ void audio_decoder_init (xine_t *this) { * We provide buffers of 8k size instead of 2k for demuxers sending * larger chunks. */ - this->audio_fifo = fifo_buffer_new (230, 8192); - this->audio_channel_user = -1; - this->audio_channel_auto = 0; - this->audio_track_map_entries = 0; - this->audio_type = 0; + stream->audio_fifo = fifo_buffer_new (230, 8192); + stream->audio_channel_user = -1; + stream->audio_channel_auto = 0; + stream->audio_track_map_entries = 0; + stream->audio_type = 0; /* future magic - coming soon - this->audio_temp = lrb_new (100, this->audio_fifo); + stream->audio_temp = lrb_new (100, stream->audio_fifo); */ pthread_attr_init(&pth_attrs); @@ -324,41 +324,41 @@ void audio_decoder_init (xine_t *this) { pthread_attr_setschedparam(&pth_attrs, &pth_params); pthread_attr_setscope(&pth_attrs, PTHREAD_SCOPE_SYSTEM); - if ((err = pthread_create (&this->audio_thread, - &pth_attrs, audio_decoder_loop, this)) != 0) { + if ((err = pthread_create (&stream->audio_thread, + &pth_attrs, audio_decoder_loop, stream)) != 0) { fprintf (stderr, "audio_decoder: can't create new thread (%s)\n", strerror(err)); abort(); } } -void audio_decoder_shutdown (xine_t *this) { +void audio_decoder_shutdown (xine_stream_t *stream) { buf_element_t *buf; void *p; - if (this->audio_fifo) { - /* this->audio_fifo->clear(this->audio_fifo); */ + if (stream->audio_fifo) { + /* stream->audio_fifo->clear(stream->audio_fifo); */ - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_QUIT; - this->audio_fifo->put (this->audio_fifo, buf); + stream->audio_fifo->put (stream->audio_fifo, buf); - pthread_join (this->audio_thread, &p); + pthread_join (stream->audio_thread, &p); } - if(this->audio_out) { - this->audio_out->exit (this->audio_out); - this->audio_out = NULL; + if(stream->audio_out) { + stream->audio_out->exit (stream->audio_out); + stream->audio_out = NULL; } - if (this->audio_fifo) { - this->audio_fifo->dispose (this->audio_fifo); - this->audio_fifo = NULL; + if (stream->audio_fifo) { + stream->audio_fifo->dispose (stream->audio_fifo); + stream->audio_fifo = NULL; } } -int xine_get_audio_channel (xine_t *this) { +int xine_get_audio_channel (xine_stream_t *stream) { - return this->audio_type & 0xFFFF; + return stream->audio_type & 0xFFFF; } diff --git a/src/xine-engine/audio_decoder.h b/src/xine-engine/audio_decoder.h new file mode 100644 index 000000000..dd5fcc591 --- /dev/null +++ b/src/xine-engine/audio_decoder.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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.h,v 1.3 2002/10/14 15:47:25 guenter Exp $ + * + * xine audio decoder plugin interface + * + */ + +#ifndef HAVE_AUDIO_DECODER_H +#define HAVE_AUDIO_DECODER_H + +#include +#include "buffer.h" + +#define AUDIO_DECODER_IFACE_VERSION 10 + +/* + * generic xine audio decoder plugin interface + */ + +typedef struct audio_decoder_class_s audio_decoder_class_t; + +struct audio_decoder_class_s { + + /* + * return short, human readable identifier for this plugin class + */ + char* (*get_identifier) (audio_decoder_class_t *this); + + /* + * return human readable (verbose = 1 line) description for + * this plugin class + */ + char* (*get_description) (audio_decoder_class_t *this); +}; + + +typedef struct audio_decoder_s audio_decoder_t; + +struct audio_decoder_s { + + /* + * decode data from buf and feed decoded samples to + * audio output + */ + void (*decode_data) (audio_decoder_t *this, buf_element_t *buf); + + /* + * reset decoder after engine flush (prepare for new + * audio data not related to recently decoded data) + */ + void (*reset) (audio_decoder_t *this); + + /* + * close down, free all resources + */ + void (*dispose) (audio_decoder_t *this); + + void *node; /* used by plugin loader */ + +}; + +#endif diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 5e2da61f9..e0c371629 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -17,7 +17,7 @@ * along with self program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_out.c,v 1.69 2002/10/12 19:20:02 jkeil Exp $ + * $Id: audio_out.c,v 1.70 2002/10/14 15:47:25 guenter Exp $ * * 22-8-2001 James imported some useful AC3 sections from the previous alsa driver. * (c) 2001 Andy Lo A Foe @@ -581,28 +581,28 @@ static int ao_open(ao_instance_t *this, switch (mode) { case AO_CAP_MODE_MONO: - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 1; + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 1; break; case AO_CAP_MODE_STEREO: - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 2; + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 2; break; case AO_CAP_MODE_4CHANNEL: - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 4; + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 4; break; case AO_CAP_MODE_5CHANNEL: - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 5; + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 5; break; case AO_CAP_MODE_5_1CHANNEL: - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 6; + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 6; break; case AO_CAP_MODE_A52: case AO_CAP_MODE_AC5: default: - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 255; /* unknown */ + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 255; /* unknown */ } - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = bits; - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = rate; + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = bits; + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = rate; this->input.mode = mode; this->input.rate = rate; @@ -861,9 +861,10 @@ static int ao_control (ao_instance_t *this, int cmd, ...) { return rval; } -ao_instance_t *ao_new_instance (xine_ao_driver_t *driver, xine_t *xine) { +ao_instance_t *ao_new_instance (xine_ao_driver_t *driver, + xine_stream_t *stream) { - config_values_t *config = xine->config; + config_values_t *config = stream->xine->config; ao_instance_t *this; int i; static char *resample_modes[] = {"auto", "off", "on", NULL}; @@ -871,8 +872,9 @@ ao_instance_t *ao_new_instance (xine_ao_driver_t *driver, xine_t *xine) { this = xine_xmalloc (sizeof (ao_instance_t)) ; this->driver = driver; - this->metronom = xine->metronom; - this->xine = xine; + this->metronom = stream->metronom; + this->xine = stream->xine; + this->stream = stream; pthread_mutex_init( &this->driver_lock, NULL ); this->open = ao_open; diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h index e43d5f3a4..68e0ca750 100644 --- a/src/xine-engine/audio_out.h +++ b/src/xine-engine/audio_out.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: audio_out.h,v 1.34 2002/09/18 00:51:34 guenter Exp $ + * $Id: audio_out.h,v 1.35 2002/10/14 15:47:27 guenter Exp $ */ #ifndef HAVE_AUDIO_OUT_H #define HAVE_AUDIO_OUT_H @@ -124,6 +124,8 @@ struct xine_ao_driver_s { * See AO_CTRL_* below. */ int (*control) (xine_ao_driver_t *this, int cmd, /* arg */ ...); + + void *node; }; /* @@ -203,9 +205,10 @@ struct ao_instance_s { /* private stuff */ xine_ao_driver_t *driver; - pthread_mutex_t driver_lock; - metronom_t *metronom; - xine_t *xine; + pthread_mutex_t driver_lock; + metronom_t *metronom; + xine_stream_t *stream; + xine_t *xine; int audio_loop_running; int audio_paused; @@ -231,20 +234,12 @@ struct ao_instance_s { int64_t passthrough_offset; }; -/* This initiates the audio_out sync routines +/* + * this initiates the audio_out sync routines * found in ./src/xine-engine/audio_out.c */ -ao_instance_t *ao_new_instance (xine_ao_driver_t *driver, xine_t *xine) ; -/* - * to build a dynamic audio output plugin, - * you have to implement these driver: - * - * - * xine_ao_driver_t *init_audio_out_plugin (config_values_t *config) - * - * init this plugin, check if device is available - * - */ +ao_instance_t *ao_new_instance (xine_ao_driver_t *driver, + xine_stream_t *stream) ; /* * audio output modes + capabilities diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index 008f6ca1d..8453bf91f 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -32,92 +32,92 @@ * indication must be sent. relative discontinuities are likely * to cause "jumps" on metronom. */ -void xine_demux_flush_engine (xine_t *this) { +void xine_demux_flush_engine (xine_stream_t *stream) { buf_element_t *buf; - this->video_fifo->clear(this->video_fifo); + stream->video_fifo->clear(stream->video_fifo); - if( this->audio_fifo ) - this->audio_fifo->clear(this->audio_fifo); + if( stream->audio_fifo ) + stream->audio_fifo->clear(stream->audio_fifo); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_RESET_DECODER; - this->video_fifo->put (this->video_fifo, buf); + stream->video_fifo->put (stream->video_fifo, buf); - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + if(stream->audio_fifo) { + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_RESET_DECODER; - this->audio_fifo->put (this->audio_fifo, buf); + stream->audio_fifo->put (stream->audio_fifo, buf); } - this->metronom->adjust_clock(this->metronom, - this->metronom->get_current_time(this->metronom) + 30 * 90000 ); + stream->metronom->adjust_clock(stream->metronom, + stream->metronom->get_current_time(stream->metronom) + 30 * 90000 ); } -void xine_demux_control_newpts( xine_t *this, int64_t pts, uint32_t flags ) { +void xine_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags ) { buf_element_t *buf; - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_NEWPTS; buf->decoder_flags = flags; buf->disc_off = pts; - this->video_fifo->put (this->video_fifo, buf); + stream->video_fifo->put (stream->video_fifo, buf); - if (this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + if (stream->audio_fifo) { + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_NEWPTS; buf->decoder_flags = flags; buf->disc_off = pts; - this->audio_fifo->put (this->audio_fifo, buf); + stream->audio_fifo->put (stream->audio_fifo, buf); } } -void xine_demux_control_headers_done (xine_t *this) { +void xine_demux_control_headers_done (xine_stream_t *stream) { buf_element_t *buf; - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_HEADERS_DONE; - this->video_fifo->put (this->video_fifo, buf); + stream->video_fifo->put (stream->video_fifo, buf); - if (this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + if (stream->audio_fifo) { + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_HEADERS_DONE; - this->audio_fifo->put (this->audio_fifo, buf); + stream->audio_fifo->put (stream->audio_fifo, buf); } } -void xine_demux_control_start( xine_t *this ) { +void xine_demux_control_start( xine_stream_t *stream ) { buf_element_t *buf; - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + stream->video_fifo->put (stream->video_fifo, buf); - if (this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + if (stream->audio_fifo) { + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); + stream->audio_fifo->put (stream->audio_fifo, buf); } } -void xine_demux_control_end( xine_t *this, uint32_t flags ) { +void xine_demux_control_end( xine_stream_t *stream, uint32_t flags ) { buf_element_t *buf; - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = flags; - this->video_fifo->put (this->video_fifo, buf); + stream->video_fifo->put (stream->video_fifo, buf); - if (this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + if (stream->audio_fifo) { + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = flags; - this->audio_fifo->put (this->audio_fifo, buf); + stream->audio_fifo->put (stream->audio_fifo, buf); } } diff --git a/src/xine-engine/events.c b/src/xine-engine/events.c index c41486550..1e2c11965 100644 --- a/src/xine-engine/events.c +++ b/src/xine-engine/events.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000-2001 the xine project + * Copyright (C) 2000-2002 the xine project * - * This file is part of xine, a unix video player. + * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -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: + * $Id: events.c,v 1.10 2002/10/14 15:47:33 guenter Exp $ * * Event handling functions * @@ -29,88 +29,185 @@ #include "xine_internal.h" -int xine_register_event_listener (xine_t *this, - xine_event_listener_cb_t listener, - void *user_data) { - /* Ensure the listener is non-NULL */ - if(listener == NULL) { - return 0; +xine_event_t *xine_event_get (xine_event_queue_t *queue) { + + xine_event_t *event; + + pthread_mutex_lock (&queue->lock); + + event = (xine_event_t *) xine_list_first_content (queue->events); + if (event) + xine_list_delete_current (queue->events); + + pthread_mutex_unlock (&queue->lock); + + return event; +} + +xine_event_t *xine_event_wait (xine_event_queue_t *queue) { + + xine_event_t *event; + + pthread_mutex_lock (&queue->lock); + + while (!(event = (xine_event_t *) xine_list_first_content (queue->events))) { + pthread_cond_wait (&queue->new_event, &queue->lock); } - pthread_mutex_lock(&this->event_lock); - /* Check we hava a slot free */ - if(this->num_event_listeners < XINE_MAX_EVENT_LISTENERS) { + xine_list_delete_current (queue->events); + + pthread_mutex_unlock (&queue->lock); + + return event; +} + +void xine_event_free (xine_event_t *event) { + free (event->data); + free (event); +} + +void xine_event_send (xine_stream_t *stream, const xine_event_t *event) { + + xine_event_queue_t *queue; + + pthread_mutex_lock (&stream->event_queues_lock); + + queue = (xine_event_queue_t *)xine_list_first_content (stream->event_queues); + + while (queue) { + + xine_event_t *cevent; + + cevent = malloc (sizeof (xine_event_t)); + cevent->type = event->type; + cevent->stream = event->stream; + cevent->data_length = event->data_length; + cevent->data = malloc (event->data_length); + memcpy (cevent->data, event->data, event->data_length); - this->event_listeners[this->num_event_listeners] = listener; - this->event_listener_user_data[this->num_event_listeners] = user_data; + pthread_mutex_lock (&queue->lock); + xine_list_append_content (queue->events, cevent); + pthread_cond_signal (&queue->new_event); + pthread_mutex_unlock (&queue->lock); + + queue=(xine_event_queue_t *)xine_list_next_content (stream->event_queues); + } + + pthread_mutex_unlock (&stream->event_queues_lock); +} + + +xine_event_queue_t *xine_event_new_queue (xine_stream_t *stream) { + + xine_event_queue_t *queue; - this->num_event_listeners++; + queue = malloc (sizeof (xine_event_queue_t)); - pthread_mutex_unlock(&this->event_lock); - return 1; - } + pthread_mutex_init (&queue->lock, NULL); + pthread_cond_init (&queue->new_event, NULL); + queue->events = xine_list_new (); + queue->stream = stream; - pthread_mutex_unlock(&this->event_lock); - return 0; + pthread_mutex_lock (&stream->event_queues_lock); + xine_list_append_content (stream->event_queues, queue); + pthread_mutex_unlock (&stream->event_queues_lock); + + return queue; } -void xine_send_event(xine_t *this, xine_event_t *event) { - uint16_t i; +void xine_event_dispose_queue (xine_event_queue_t *queue) { + + xine_stream_t *stream = queue->stream; + xine_event_t *event; + xine_event_t qevent; + xine_event_queue_t *q; + + pthread_mutex_lock (&stream->event_queues_lock); + + q = (xine_event_queue_t *) xine_list_first_content (stream->event_queues); + + while (q && (q != queue)) + q = (xine_event_queue_t *) xine_list_next_content (stream->event_queues); + + if (!q) { + printf ("events: tried to dispose queue which is not in list\n"); + + pthread_mutex_unlock (&stream->event_queues_lock); + return; + } + + xine_list_delete_current (stream->event_queues); + pthread_mutex_unlock (&stream->event_queues_lock); + + /* + * send quit event + */ - pthread_mutex_lock(&this->event_lock); - while (this->event_pending[event->type]) - /* there is already one event of that type around */ - pthread_cond_wait(&this->event_handled, &this->event_lock); - this->event_pending[event->type] = 1; - pthread_mutex_unlock(&this->event_lock); + qevent.type = XINE_EVENT_QUIT; + qevent.data_length = 0; + + pthread_mutex_lock (&queue->lock); + xine_list_append_content (queue->events, &event); + pthread_cond_signal (&queue->new_event); + pthread_mutex_unlock (&queue->lock); + + /* + * join listener thread, if any + */ - /* Iterate through all event handlers */ - for(i=0; i < this->num_event_listeners; i++) { - (this->event_listeners[i]) ((void *)this->event_listener_user_data[i], event); + if (queue->listener_thread) { + void *p; + pthread_join (*queue->listener_thread, &p); } - this->event_pending[event->type] = 0; - pthread_cond_signal(&this->event_handled); + /* + * clean up pending events + */ + + while ( (event = xine_event_get (queue)) ) { + xine_event_free (event); + } + + free (queue); } -int xine_remove_event_listener(xine_t *this, - xine_event_listener_cb_t listener) { - uint16_t i, found, pending; - - found = 1; - - pthread_mutex_lock(&this->event_lock); - /* wait for any pending events */ - do { - pending = 0; - for (i = 0; i < XINE_MAX_EVENT_TYPES; i++) - pending += this->event_pending[i]; - if (pending) - pthread_cond_wait(&this->event_handled, &this->event_lock); - } while (pending); - - i = 0; - /* Attempt to find the listener */ - while((found == 1) && (i < this->num_event_listeners)) { - if(this->event_listeners[i] == listener) { - /* Set found flag */ - found = 0; - - this->event_listeners[i] = NULL; - - /* If possible, move the last listener to the hole thats left */ - if(this->num_event_listeners > 1) { - this->event_listeners[i] = this->event_listeners[this->num_event_listeners - 1]; - this->event_listener_user_data[i] = this->event_listener_user_data[this->num_event_listeners - 1]; - this->event_listeners[this->num_event_listeners - 1] = NULL; - } - - this->num_event_listeners --; - } - - i++; + +static void *listener_loop (void *queue_gen) { + + xine_event_queue_t *queue = (xine_event_queue_t *) queue_gen; + int running = 1; + + while (running) { + + xine_event_t *event; + + event = xine_event_wait (queue); + + if (event->type == XINE_EVENT_QUIT) + running = 0; + else + queue->callback (queue->user_data, event); + + xine_event_free (event); } - pthread_mutex_unlock(&this->event_lock); - return found; + pthread_exit(NULL); +} + + +void xine_event_create_listener_thread (xine_event_queue_t *queue, + xine_event_listener_cb_t callback, + void *user_data) { + int err; + + queue->listener_thread = malloc (sizeof (pthread_t)); + queue->callback = callback; + queue->user_data = user_data; + + if ((err = pthread_create (queue->listener_thread, + NULL, listener_loop, queue)) != 0) { + fprintf (stderr, "events: can't create new thread (%s)\n", + strerror(err)); + abort(); + } } diff --git a/src/xine-engine/events.h b/src/xine-engine/events.h deleted file mode 100644 index b96416694..000000000 --- a/src/xine-engine/events.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2000-2001 the xine project - * - * Copyright (C) Rich Wareham - July 2001 - * - * This file is part of xine, a unix video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - */ - -#ifndef HAVE_EVENTS_H -#define HAVE_EVENTS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - * This file defines types for many events which can be sent in xine. - */ - -/* event types */ - -#define XINE_EVENT_MOUSE_BUTTON 1 -#define XINE_EVENT_MOUSE_MOVE 2 -#define XINE_EVENT_SPU_BUTTON 3 -#define XINE_EVENT_SPU_CLUT 4 -#define XINE_EVENT_UI_CHANNELS_CHANGED 5 /* inform ui that new channel info is available */ -#define XINE_EVENT_UI_SET_TITLE 6 /* request title display change in ui */ -#define XINE_EVENT_INPUT_MENU1 7 -#define XINE_EVENT_INPUT_MENU2 8 -#define XINE_EVENT_INPUT_MENU3 9 -#define XINE_EVENT_INPUT_UP 10 -#define XINE_EVENT_INPUT_DOWN 11 -#define XINE_EVENT_INPUT_LEFT 12 -#define XINE_EVENT_INPUT_RIGHT 13 -#define XINE_EVENT_INPUT_SELECT 14 -#define XINE_EVENT_PLAYBACK_FINISHED 15 -#define XINE_EVENT_BRANCHED 16 -#define XINE_EVENT_NEED_NEXT_MRL 17 -#define XINE_EVENT_INPUT_NEXT 18 -#define XINE_EVENT_INPUT_PREVIOUS 19 -#define XINE_EVENT_INPUT_ANGLE_NEXT 20 -#define XINE_EVENT_INPUT_ANGLE_PREVIOUS 21 -#define XINE_EVENT_SPU_FORCEDISPLAY 22 -#define XINE_EVENT_FRAME_CHANGE 23 -#define XINE_EVENT_CLOSED_CAPTION 24 -#define XINE_EVENT_INPUT_BUTTON_FORCE 25 -#define XINE_EVENT_INPUT_MENU4 26 -#define XINE_EVENT_INPUT_MENU5 27 -#define XINE_EVENT_INPUT_MENU6 28 -#define XINE_EVENT_INPUT_MENU7 29 - -#define XINE_EVENT_INPUT_NUMBER_0 30 -#define XINE_EVENT_INPUT_NUMBER_1 31 -#define XINE_EVENT_INPUT_NUMBER_2 32 -#define XINE_EVENT_INPUT_NUMBER_3 33 -#define XINE_EVENT_INPUT_NUMBER_4 34 -#define XINE_EVENT_INPUT_NUMBER_5 35 -#define XINE_EVENT_INPUT_NUMBER_6 36 -#define XINE_EVENT_INPUT_NUMBER_7 37 -#define XINE_EVENT_INPUT_NUMBER_8 38 -#define XINE_EVENT_INPUT_NUMBER_9 39 -#define XINE_EVENT_INPUT_NUMBER_10_ADD 40 - -#define XINE_EVENT_ASPECT_CHANGE 41 /* Generally should be viewed as a hint to the GUI */ -#define XINE_EVENT_OUTPUT_VIDEO 42 -#define XINE_EVENT_OUTPUT_NO_VIDEO 43 - - -/* - * generic event type. - */ -typedef struct { - uint32_t type; /* The event type (determines remainder of struct) */ - - /* Event dependent data goes after this. */ -} xine_event_t; - -/* - * input events - */ -typedef struct { - xine_event_t event; - uint8_t button; /* Generally 1 = left, 2 = mid, 3 = right */ - uint16_t x,y; /* In Image space */ -} xine_input_event_t; - -/* - * Menu events - */ -typedef struct { - xine_event_t event; - uint8_t button; /* Generally 1 = left, 2 = mid, 3 = right */ - uint16_t status; /* 0:no status, 1:selected, 2:actioned */ - uint8_t command[8]; /* DVD virtual machine command. */ -} xine_menu_event_t; - -/* - * SPU event - send control events to the spu decoder - */ -typedef struct { - xine_event_t event; - void *data; -} xine_spu_event_t; - -/* - * UI event - send information to/from UI. - */ - -typedef struct { - xine_event_t event; - void *data; - uint32_t data_len; - int handled; -} xine_ui_event_t; - -/* - * next_mrl - */ -typedef struct { - xine_event_t event; - char *mrl; - int handled; -} xine_next_mrl_event_t; - -/* - * notify frame change - */ -typedef struct { - xine_event_t event; - int width; - int height; - int aspect; -} xine_frame_change_event_t; - -/* - * closed caption - */ -typedef struct { - xine_event_t event; - uint8_t *buffer; - uint32_t buf_len; - int64_t pts; - uint32_t scr; -} xine_closed_caption_event_t; - -/* - * Aspect ratio change (suggested) - */ -typedef struct { - xine_event_t event; - int ratio_code; - int scale_permission; -} xine_aspect_ratio_event_t; - -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_EVENTS_H */ - diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index e248a2777..0bc17c9ff 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.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: load_plugins.c,v 1.98 2002/09/22 14:29:40 mroi Exp $ + * $Id: load_plugins.c,v 1.99 2002/10/14 15:47:37 guenter Exp $ * * * Load input/demux/audio_out/video_out/codec plugins @@ -135,11 +135,13 @@ static void _insert_plugin (xine_t *this, } entry = xine_xmalloc(sizeof(plugin_node_t)); - entry->filename = _strclone(filename); - entry->info = xine_xmalloc(sizeof(plugin_info_t)); - *(entry->info) = *info; - entry->info->id = _strclone(info->id); - entry->info->init = NULL; + entry->filename = _strclone(filename); + entry->info = xine_xmalloc(sizeof(plugin_info_t)); + *(entry->info) = *info; + entry->info->id = _strclone(info->id); + entry->info->init = NULL; + entry->plugin_class = NULL; + entry->ref = 0; switch (info->type){ @@ -188,7 +190,7 @@ static void _insert_plugin (xine_t *this, } -static plugin_catalog_t *_empty_catalog(void){ +static plugin_catalog_t *_new_catalog(void){ plugin_catalog_t *catalog; @@ -201,6 +203,8 @@ static plugin_catalog_t *_empty_catalog(void){ catalog->aout = xine_list_new(); catalog->vout = xine_list_new(); + pthread_mutex_init (&catalog->lock, NULL); + return catalog; } @@ -328,9 +332,9 @@ static void collect_plugins(xine_t *this, char *path){ * generic 2nd stage plugin loader */ -static void *_load_plugin(xine_t *this, - char *filename, plugin_info_t *target, - void *data) { +static void *_load_plugin_class(xine_t *this, + char *filename, plugin_info_t *target, + void *data) { void *lib; @@ -385,7 +389,7 @@ static void load_plugins(xine_t *this) { node->info->id, node->filename); #endif - node->plugin = _load_plugin(this, node->filename, node->info, NULL); + node->plugin_class = _load_plugin_class (this, node->filename, node->info, NULL); node = xine_list_next_content (this->plugin_catalog->input); } @@ -402,7 +406,7 @@ static void load_plugins(xine_t *this) { node->info->id, node->filename); #endif - node->plugin = _load_plugin(this, node->filename, node->info, NULL); + node->plugin_class = _load_plugin_class (this, node->filename, node->info, NULL); node = xine_list_next_content (this->plugin_catalog->demux); } @@ -585,7 +589,7 @@ void scan_plugins (xine_t *this) { abort(); } - this->plugin_catalog = _empty_catalog(); + this->plugin_catalog = _new_catalog(); /* TODO: add more plugin dir(s), maybe ~/.xine/plugins or /usr/local/... */ collect_plugins(this, XINE_PLUGINDIR); @@ -594,7 +598,108 @@ void scan_plugins (xine_t *this) { map_decoders (this); } -static const char **_xine_get_featured_input_plugin_ids(xine_t *this, int feature) { +/* + * input / demuxer plugin loading + */ + +input_plugin_t *find_input_plugin (xine_stream_t *stream, const char *mrl) { + + xine_t *xine = stream->xine; + plugin_catalog_t *catalog = xine->plugin_catalog; + plugin_node_t *node; + + pthread_mutex_lock (&catalog->lock); + + node = xine_list_first_content (catalog->input); + while (node) { + input_plugin_t *plugin; + + if ((plugin = node->info->open (node->plugin_class, stream, mrl))) { + pthread_mutex_unlock (&catalog->lock); + return plugin; + } + + node = xine_list_next_content (stream->xine->plugin_catalog->input); + } + + pthread_mutex_unlock (&catalog->lock); + + return NULL; +} + +static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int method2, + input_plugin_t *input) { + + int i; + int methods[3]; + xine_t *xine = stream->xine; + plugin_catalog_t *catalog = xine->plugin_catalog; + + methods[0] = method1; + methods[1] = method2; + methods[2] = -1; + + if (methods[0] == -1) { + printf ("load_plugins: probe_demux method1 = %d is not allowed \n", method1); + abort(); + } + + i = 0; + while (methods[i] != -1) { + + plugin_node_t *node; + + stream->content_detection_method = methods[i]; + + pthread_mutex_lock (&catalog->lock); + + node = xine_list_first_content (catalog->demux); + + while (node) { + demux_plugin_t *plugin; + + if ((plugin = node->info->open (node->plugin_class, stream, input))) { + pthread_mutex_unlock (&catalog->lock); + return plugin; + } + + node = xine_list_next_content (stream->xine->plugin_catalog->demux); + } + + pthread_mutex_unlock (&catalog->lock); + + i++; + } + + return NULL; +} + +demux_plugin_t *find_demux_plugin (xine_stream_t *stream, input_plugin_t *input) { + + switch (stream->xine->demux_strategy) { + + case XINE_DEMUX_DEFAULT_STRATEGY: + return probe_demux (stream, METHOD_BY_CONTENT, METHOD_BY_EXTENSION, input); + + case XINE_DEMUX_REVERT_STRATEGY: + return probe_demux (stream, METHOD_BY_EXTENSION, METHOD_BY_CONTENT, input); + + case XINE_DEMUX_CONTENT_STRATEGY: + return probe_demux (stream, METHOD_BY_CONTENT, -1, input); + + case XINE_DEMUX_EXTENSION_STRATEGY: + return probe_demux (stream, METHOD_BY_EXTENSION, -1, input); + + default: + printf ("load_plugins: unknown content detection strategy %d\n", + stream->xine->demux_strategy); + abort(); + } + + return NULL; +} + +const char *const *xine_get_autoplay_input_plugin_ids(xine_t *this) { plugin_catalog_t *catalog; int i; @@ -602,13 +707,15 @@ static const char **_xine_get_featured_input_plugin_ids(xine_t *this, int featur catalog = this->plugin_catalog; + pthread_mutex_lock (&catalog->lock); + i = 0; node = xine_list_first_content (catalog->input); while (node) { - input_plugin_t *ip; + input_class_t *ic; - ip = (input_plugin_t *) node->plugin; - if (ip->get_capabilities(ip) & feature) { + ic = (input_class_t *) node->plugin_class; + if (ic->get_autoplay_list) { catalog->ids[i] = node->info->id; @@ -619,20 +726,45 @@ static const char **_xine_get_featured_input_plugin_ids(xine_t *this, int featur catalog->ids[i] = NULL; + pthread_mutex_unlock (&catalog->lock); + return catalog->ids; } -const char *const *xine_get_autoplay_input_plugin_ids(xine_t *this) { +const char *const *xine_get_browsable_input_plugin_ids(xine_t *this) { - return (_xine_get_featured_input_plugin_ids(this, INPUT_CAP_AUTOPLAY)); -} -const char *const *xine_get_browsable_input_plugin_ids(xine_t *this) { + plugin_catalog_t *catalog; + int i; + plugin_node_t *node; + + catalog = this->plugin_catalog; - return (_xine_get_featured_input_plugin_ids(this, INPUT_CAP_GET_DIR)); + pthread_mutex_lock (&catalog->lock); + + i = 0; + node = xine_list_first_content (catalog->input); + while (node) { + input_class_t *ic; + + ic = (input_class_t *) node->plugin_class; + if (ic->get_dir) { + + catalog->ids[i] = node->info->id; + + i++; + } + node = xine_list_next_content (catalog->input); + } + + catalog->ids[i] = NULL; + + pthread_mutex_unlock (&catalog->lock); + + return catalog->ids; } -const char *xine_get_input_plugin_description(xine_t *this, const char *plugin_id) { +const char *xine_get_input_plugin_description (xine_t *this, const char *plugin_id) { plugin_catalog_t *catalog; plugin_node_t *node; @@ -644,9 +776,9 @@ const char *xine_get_input_plugin_description(xine_t *this, const char *plugin_i if (!strcasecmp (node->info->id, plugin_id)) { - input_plugin_t *ip = (input_plugin_t *) node->plugin; + input_class_t *ic = (input_class_t *) node->plugin_class; - return ip->get_description(ip); + return ic->get_description(ic); } node = xine_list_next_content (catalog->input); } @@ -657,32 +789,61 @@ const char *xine_get_input_plugin_description(xine_t *this, const char *plugin_i * video out plugins section */ +static xine_vo_driver_t *_load_video_driver (xine_t *this, plugin_node_t *node, + void *data) { + + xine_vo_driver_t *driver; + + if (!node->plugin_class) + node->plugin_class = _load_plugin_class (this, node->filename, node->info, data); + + if (!node->plugin_class) + return NULL; + + driver = (xine_vo_driver_t *) node->info->open (node->plugin_class, NULL, data); + + if (driver) { + driver->node = node; + node->ref ++; + } else { + + /* FIXME + if (!node->ref) + unload class + */ + } + + return driver; +} + xine_vo_driver_t *xine_open_video_driver (xine_t *this, - const char *id, - int visual_type, void *visual) { + const char *id, + int visual_type, void *visual) { plugin_node_t *node; xine_vo_driver_t *driver; vo_info_t *vo_info; + plugin_catalog_t *catalog = this->plugin_catalog; driver = NULL; - node = xine_list_first_content (this->plugin_catalog->vout); + pthread_mutex_lock (&catalog->lock); + + node = xine_list_first_content (catalog->vout); while (node) { vo_info = node->info->special_info; if (vo_info->visual_type == visual_type) { if (id) { if (!strcasecmp (node->info->id, id)) { - driver = (xine_vo_driver_t*)_load_plugin (this, node->filename, - node->info, visual); + driver = _load_video_driver (this, node, visual); break; } } else { - driver = (xine_vo_driver_t*)_load_plugin (this, node->filename, - node->info, visual); + driver = _load_video_driver (this, node, visual); + if (driver) { xine_cfg_entry_t entry; @@ -699,12 +860,14 @@ xine_vo_driver_t *xine_open_video_driver (xine_t *this, } } - node = xine_list_next_content (this->plugin_catalog->vout); + node = xine_list_next_content (catalog->vout); } if (!driver) printf ("load_plugins: failed to load video output plugin <%s>\n", id); + pthread_mutex_unlock (&catalog->lock); + return driver; } @@ -720,6 +883,8 @@ const char *const *xine_list_audio_output_plugins (xine_t *this) { catalog = this->plugin_catalog; + pthread_mutex_lock (&catalog->lock); + i = 0; node = xine_list_first_content (catalog->aout); while (node) { @@ -733,6 +898,8 @@ const char *const *xine_list_audio_output_plugins (xine_t *this) { catalog->ids[i] = NULL; + pthread_mutex_unlock (&catalog->lock); + return catalog->ids; } @@ -744,6 +911,8 @@ const char *const *xine_list_video_output_plugins (xine_t *this) { catalog = this->plugin_catalog; + pthread_mutex_lock (&catalog->lock); + i = 0; node = xine_list_first_content (catalog->vout); while (node) { @@ -757,15 +926,47 @@ const char *const *xine_list_video_output_plugins (xine_t *this) { catalog->ids[i] = NULL; + pthread_mutex_unlock (&catalog->lock); + return catalog->ids; } +static xine_ao_driver_t *_load_audio_driver (xine_t *this, plugin_node_t *node, + void *data) { + + xine_ao_driver_t *driver; + + if (!node->plugin_class) + node->plugin_class = _load_plugin_class (this, node->filename, node->info, data); + + if (!node->plugin_class) + return NULL; + + driver = (xine_ao_driver_t *) node->info->open (node->plugin_class, NULL, data); + + if (driver) { + driver->node = node; + node->ref ++; + } else { + + /* FIXME + if (!node->ref) + unload class + */ + } + + return driver; +} + xine_ao_driver_t *xine_open_audio_driver (xine_t *this, const char *id, - void *data) { + void *data) { plugin_node_t *node; xine_ao_driver_t *driver; ao_info_t *ao_info; + plugin_catalog_t *catalog = this->plugin_catalog; + + pthread_mutex_lock (&catalog->lock); driver = NULL; @@ -776,11 +977,11 @@ xine_ao_driver_t *xine_open_audio_driver (xine_t *this, const char *id, if (id) { if (!strcasecmp(node->info->id, id)) { - driver = (xine_ao_driver_t*)_load_plugin(this, node->filename, node->info, data); + driver = _load_audio_driver (this, node, data); break; } } else { - driver = (xine_ao_driver_t*)_load_plugin (this, node->filename, node->info, data); + driver = _load_audio_driver (this, node, data); if (driver) { xine_cfg_entry_t entry; @@ -805,9 +1006,19 @@ xine_ao_driver_t *xine_open_audio_driver (xine_t *this, const char *id, else printf ("load_plugins: audio output auto-probing didn't find any usable audio driver.\n"); } + + pthread_mutex_unlock (&catalog->lock); + return driver; } +void xine_close_audio_driver (xine_t *this, xine_ao_driver_t *driver) { + + /* FIXME : implement */ + +} + + /* * get autoplay mrl list from input plugin */ @@ -825,14 +1036,12 @@ char **xine_get_autoplay_mrls (xine_t *this, const char *plugin_id, if (!strcasecmp (node->info->id, plugin_id)) { - input_plugin_t *ip = (input_plugin_t *) node->plugin; + input_class_t *ic = (input_class_t *) node->plugin_class; - if (!( ip->get_capabilities(ip) & INPUT_CAP_AUTOPLAY)) + if (!ic->get_autoplay_list) return NULL; - /* this->cur_input_plugin = ip; FIXME: needed? */ - - return ip->get_autoplay_list (ip, num_mrls); + return ic->get_autoplay_list (ic, num_mrls); } node = xine_list_next_content (catalog->input); } @@ -855,117 +1064,223 @@ xine_mrl_t **xine_get_browse_mrls (xine_t *this, const char *plugin_id, if (!strcasecmp (node->info->id, plugin_id)) { - input_plugin_t *ip = (input_plugin_t *) node->plugin; + input_class_t *ic = (input_class_t *) node->plugin_class; - if (!( ip->get_capabilities(ip) & INPUT_CAP_GET_DIR)) + if (!ic->get_dir) return NULL; - return ip->get_dir (ip, start_mrl, num_mrls); + return ic->get_dir (ic, start_mrl, num_mrls); } node = xine_list_next_content (catalog->input); } return NULL; } -video_decoder_t *get_video_decoder (xine_t *this, uint8_t stream_type) { +video_decoder_t *get_video_decoder (xine_stream_t *stream, uint8_t stream_type) { - plugin_node_t *node; - int i, j; + plugin_node_t *node; + int i, j; + plugin_catalog_t *catalog = stream->xine->plugin_catalog; #ifdef LOG printf ("load_plugins: looking for video decoder for streamtype %02x\n", stream_type); #endif + pthread_mutex_lock (&catalog->lock); + for (i = 0; i < PLUGINS_PER_TYPE; i++) { - node = this->plugin_catalog->video_decoder_map[stream_type][i]; + + video_decoder_t *vd=NULL; + + node = catalog->video_decoder_map[stream_type][i]; - if (!node) + if (!node) { + pthread_mutex_unlock (&catalog->lock); return NULL; + } - if (!node->plugin) - node->plugin = _load_plugin(this, node->filename, node->info, NULL); + if (!node->plugin_class) + node->plugin_class = _load_plugin_class (stream->xine, node->filename, + node->info, NULL); - if (node->plugin) - return node->plugin; - else { + if (!node->plugin_class) { /* remove non working plugin from catalog */ for (j = i + 1; j < PLUGINS_PER_TYPE; j++) - this->plugin_catalog->video_decoder_map[stream_type][j - 1] = - this->plugin_catalog->video_decoder_map[stream_type][j]; - this->plugin_catalog->video_decoder_map[stream_type][PLUGINS_PER_TYPE] = NULL; + catalog->video_decoder_map[stream_type][j - 1] = + catalog->video_decoder_map[stream_type][j]; + catalog->video_decoder_map[stream_type][PLUGINS_PER_TYPE] = NULL; i--; + pthread_mutex_unlock (&catalog->lock); + return NULL; } + + vd = (video_decoder_t *) node->info->open (node->plugin_class, stream, NULL); + + if (vd) { + vd->node = node; + node->ref ++; + } + + pthread_mutex_unlock (&catalog->lock); + return vd; } + + pthread_mutex_unlock (&catalog->lock); return NULL; } -audio_decoder_t *get_audio_decoder (xine_t *this, uint8_t stream_type) { +void free_video_decoder (xine_stream_t *stream, video_decoder_t *vd) { + plugin_catalog_t *catalog = stream->xine->plugin_catalog; + plugin_node_t *node = vd->node; + + pthread_mutex_lock (&catalog->lock); + + vd->dispose (vd); + + node->ref--; + /* FIXME: unload plugin if no-longer used */ + + pthread_mutex_unlock (&catalog->lock); +} + + +audio_decoder_t *get_audio_decoder (xine_stream_t *stream, uint8_t stream_type) { - plugin_node_t *node; - int i, j; + plugin_node_t *node; + int i, j; + plugin_catalog_t *catalog = stream->xine->plugin_catalog; #ifdef LOG printf ("load_plugins: looking for audio decoder for streamtype %02x\n", stream_type); #endif + pthread_mutex_lock (&catalog->lock); + for (i = 0; i < PLUGINS_PER_TYPE; i++) { - node = this->plugin_catalog->audio_decoder_map[stream_type][i]; - if (!node) + audio_decoder_t *ad; + + node = catalog->audio_decoder_map[stream_type][i]; + + if (!node) { + pthread_mutex_unlock (&catalog->lock); return NULL; + } - if (!node->plugin) - node->plugin = _load_plugin(this, node->filename, node->info, NULL); + if (!node->plugin_class) + node->plugin_class = _load_plugin_class (stream->xine, node->filename, + node->info, NULL); - if (node->plugin) - return node->plugin; - else { + if (!node->plugin_class) { /* remove non working plugin from catalog */ for (j = i + 1; j < PLUGINS_PER_TYPE; j++) - this->plugin_catalog->audio_decoder_map[stream_type][j - 1] = - this->plugin_catalog->audio_decoder_map[stream_type][j]; - this->plugin_catalog->audio_decoder_map[stream_type][PLUGINS_PER_TYPE] = NULL; + catalog->audio_decoder_map[stream_type][j - 1] = + catalog->audio_decoder_map[stream_type][j]; + catalog->audio_decoder_map[stream_type][PLUGINS_PER_TYPE] = NULL; i--; + pthread_mutex_unlock (&catalog->lock); + return NULL; + } + + ad = (audio_decoder_t *) node->info->open (node->plugin_class, stream, NULL); + + if (ad) { + ad->node = node; + node->ref ++; } + + pthread_mutex_unlock (&catalog->lock); + return ad; } + + pthread_mutex_unlock (&catalog->lock); return NULL; } -spu_decoder_t *get_spu_decoder (xine_t *this, uint8_t stream_type) { +void free_audio_decoder (xine_stream_t *stream, audio_decoder_t *ad) { + plugin_catalog_t *catalog = stream->xine->plugin_catalog; + plugin_node_t *node = ad->node; + + pthread_mutex_lock (&catalog->lock); + + ad->dispose (ad); - plugin_node_t *node; - int i, j; + node->ref--; + /* FIXME: unload plugin if no-longer used */ + + pthread_mutex_unlock (&catalog->lock); +} + + +spu_decoder_t *get_spu_decoder (xine_stream_t *stream, uint8_t stream_type) { + + plugin_node_t *node; + int i, j; + plugin_catalog_t *catalog = stream->xine->plugin_catalog; #ifdef LOG printf ("load_plugins: looking for spu decoder for streamtype %02x\n", stream_type); #endif + pthread_mutex_lock (&catalog->lock); + for (i = 0; i < PLUGINS_PER_TYPE; i++) { - node = this->plugin_catalog->spu_decoder_map[stream_type][i]; + spu_decoder_t *sd; + + node = catalog->spu_decoder_map[stream_type][i]; - if (!node) + if (!node) { + pthread_mutex_unlock (&catalog->lock); return NULL; + } - if (!node->plugin) - node->plugin = _load_plugin(this, node->filename, node->info, NULL); + if (!node->plugin_class) + node->plugin_class = _load_plugin_class (stream->xine, node->filename, + node->info, NULL); - if (node->plugin) - return node->plugin; - else { + if (!node->plugin_class) { /* remove non working plugin from catalog */ for (j = i + 1; j < PLUGINS_PER_TYPE; j++) - this->plugin_catalog->spu_decoder_map[stream_type][j - 1] = - this->plugin_catalog->spu_decoder_map[stream_type][j]; - this->plugin_catalog->spu_decoder_map[stream_type][PLUGINS_PER_TYPE] = NULL; + catalog->spu_decoder_map[stream_type][j - 1] = + catalog->spu_decoder_map[stream_type][j]; + catalog->spu_decoder_map[stream_type][PLUGINS_PER_TYPE] = NULL; i--; + pthread_mutex_unlock (&catalog->lock); + return NULL; + } + + sd = (spu_decoder_t *) node->info->open (node->plugin_class, stream, NULL); + + if (sd) { + sd->node = node; + node->ref ++; } + + pthread_mutex_unlock (&catalog->lock); + return sd; } + + pthread_mutex_unlock (&catalog->lock); return NULL; } +void free_spu_decoder (xine_stream_t *stream, spu_decoder_t *sd) { + plugin_catalog_t *catalog = stream->xine->plugin_catalog; + plugin_node_t *node = sd->node; + + pthread_mutex_lock (&catalog->lock); + + sd->dispose (sd); + + node->ref--; + /* FIXME: unload plugin if no-longer used */ + + pthread_mutex_unlock (&catalog->lock); +} + /* * dispose all currently loaded plugins (shutdown) @@ -973,7 +1288,9 @@ spu_decoder_t *get_spu_decoder (xine_t *this, uint8_t stream_type) { void dispose_plugins (xine_t *this) { - /* FIXME: adapt old code */ +/* FIXME */ + +#if 0 plugin_node_t *node; node = xine_list_first_content (this->plugin_catalog->demux); @@ -996,7 +1313,6 @@ void dispose_plugins (xine_t *this) { node = xine_list_next_content (this->plugin_catalog->input); } -#if 0 for (i = 0; i < this->num_audio_decoders_loaded; i++) this->audio_decoders_loaded[i]->dispose (this->audio_decoders_loaded[i]); diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index d189142c0..de31f1916 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.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: metronom.c,v 1.93 2002/09/05 22:29:17 mroi Exp $ + * $Id: metronom.c,v 1.94 2002/10/14 15:47:38 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -657,7 +657,7 @@ static int metronom_sync_loop (metronom_t *this) { scr_plugin_t** scr; int64_t pts; - while (((xine_t*)this->xine)->status != XINE_STATUS_QUIT) { + while (this->stream->status != XINE_STATUS_QUIT) { pts = this->scr_master->get_current(this->scr_master); for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++) @@ -699,12 +699,12 @@ static void metronom_exit (metronom_t *this) { } -metronom_t * metronom_init (int have_audio, void *xine) { +metronom_t * metronom_init (int have_audio, xine_stream_t *stream) { metronom_t *this = xine_xmalloc (sizeof (metronom_t)); int err; - this->xine = xine; + this->stream = stream; this->set_audio_rate = metronom_set_audio_rate; this->got_video_frame = metronom_got_video_frame; this->got_audio_samples = metronom_got_audio_samples; diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 3fb081b37..77ec59614 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.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: metronom.h,v 1.36 2002/09/05 22:29:17 mroi Exp $ + * $Id: metronom.h,v 1.37 2002/10/14 15:47:39 guenter Exp $ * * metronom: general pts => virtual calculation/assoc * @@ -51,6 +51,7 @@ extern "C" { #include #include #include "video_out.h" +#include "xine.h" typedef struct metronom_s metronom_t ; typedef struct scr_plugin_s scr_plugin_t; @@ -63,11 +64,6 @@ typedef struct scr_plugin_s scr_plugin_t; struct metronom_s { - /* - * pointer to current xine object. a void pointer is used to avoid type declaration clash. - */ - void *xine; - /* * called by audio output driver to inform metronom about current audio * samplerate @@ -205,6 +201,11 @@ struct metronom_s { void (*exit) (metronom_t *this); + /* + * pointer to current xine stream object. + */ + xine_stream_t *stream; + /* * metronom internal stuff */ @@ -247,7 +248,7 @@ struct metronom_s { int force_audio_jump; }; -metronom_t *metronom_init (int have_audio, void *xine); +metronom_t *metronom_init (int have_audio, xine_stream_t *stream); /* * metronom options diff --git a/src/xine-engine/plugin_catalog.h b/src/xine-engine/plugin_catalog.h index 9e166d813..fd0581488 100644 --- a/src/xine-engine/plugin_catalog.h +++ b/src/xine-engine/plugin_catalog.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: plugin_catalog.h,v 1.5 2002/09/09 13:57:13 mroi Exp $ + * $Id: plugin_catalog.h,v 1.6 2002/10/14 15:47:39 guenter Exp $ * * xine-internal header: Definitions for plugin lists * @@ -36,26 +36,28 @@ #define PLUGINS_PER_TYPE 10 typedef struct { - char *filename; - plugin_info_t *info; - void *plugin; + char *filename; + plugin_info_t *info; + void *plugin_class; + int ref; /* count instances created of this plugin */ } plugin_node_t ; struct plugin_catalog_s { - xine_list_t *input; - xine_list_t *demux; - xine_list_t *spu; - xine_list_t *audio; - xine_list_t *video; - xine_list_t *aout; - xine_list_t *vout; + xine_list_t *input; + xine_list_t *demux; + xine_list_t *spu; + xine_list_t *audio; + xine_list_t *video; + xine_list_t *aout; + xine_list_t *vout; - plugin_node_t *audio_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; - plugin_node_t *video_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; - plugin_node_t *spu_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; + plugin_node_t *audio_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; + plugin_node_t *video_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; + plugin_node_t *spu_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; - const char *ids[PLUGIN_MAX]; + const char *ids[PLUGIN_MAX]; + pthread_mutex_t lock; }; typedef struct plugin_catalog_s plugin_catalog_t; diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index c910101f4..0464a9e69 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.99 2002/09/18 15:37:43 mroi Exp $ + * $Id: video_decoder.c,v 1.100 2002/10/14 15:47:40 guenter Exp $ * */ @@ -37,28 +37,28 @@ #define VIDEO_DECODER_LOG */ -static spu_decoder_t* update_spu_decoder(xine_t *this, int type) { +static spu_decoder_t* update_spu_decoder (xine_stream_t *this, int type) { int streamtype = (type>>16) & 0xFF; spu_decoder_t *spu_decoder = get_spu_decoder (this, streamtype); - if (spu_decoder && this->cur_spu_decoder_plugin != spu_decoder) { + if (spu_decoder && this->spu_decoder_plugin != spu_decoder) { - if (this->cur_spu_decoder_plugin) - this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); + if (this->spu_decoder_plugin) + this->spu_decoder_plugin->close (this->spu_decoder_plugin); - this->cur_spu_decoder_plugin = spu_decoder; + this->spu_decoder_plugin = spu_decoder; - this->cur_spu_decoder_plugin->init (this->cur_spu_decoder_plugin, + this->spu_decoder_plugin->init (this->spu_decoder_plugin, this->video_out); } return spu_decoder; } -void *video_decoder_loop (void *this_gen) { +void *video_decoder_loop (void *stream_gen) { buf_element_t *buf; - xine_t *this = (xine_t *) this_gen; + xine_stream_t *stream = (xine_stream_t *) stream_gen; int running = 1; int streamtype; video_decoder_t *decoder; @@ -78,18 +78,14 @@ void *video_decoder_loop (void *this_gen) { printf ("video_decoder: getting buffer...\n"); #endif - buf = this->video_fifo->get (this->video_fifo); + buf = stream->video_fifo->get (stream->video_fifo); if (buf->input_pos) - this->cur_input_pos = buf->input_pos; + stream->input_pos = buf->input_pos; if (buf->input_length) - this->cur_input_length = buf->input_length; + stream->input_length = buf->input_length; if (buf->input_time) { - this->cur_input_time = buf->input_time; - pthread_mutex_lock (&this->osd_lock); - if( this->curtime_needed_for_osd && !(--this->curtime_needed_for_osd) ) - xine_internal_osd (this, ">",90000); - pthread_mutex_unlock (&this->osd_lock); + stream->input_time = buf->input_time; } #ifdef VIDEO_DECODER_LOG @@ -98,28 +94,26 @@ void *video_decoder_loop (void *this_gen) { switch (buf->type & 0xffff0000) { case BUF_CONTROL_HEADERS_DONE: - this->header_sent_counter++; + pthread_mutex_lock (&stream->counter_lock); + stream->header_count_video++; + pthread_cond_broadcast (&stream->counter_changed); + pthread_mutex_unlock (&stream->counter_lock); break; case BUF_CONTROL_START: - if (this->cur_video_decoder_plugin) { - this->cur_video_decoder_plugin->close (this->cur_video_decoder_plugin); - this->cur_video_decoder_plugin = NULL; + if (stream->video_decoder_plugin) { + free_video_decoder (stream, stream->video_decoder_plugin); + stream->video_decoder_plugin = NULL; } - if (this->cur_spu_decoder_plugin) { - this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); - this->cur_spu_decoder_plugin = NULL; + if (stream->spu_decoder_plugin) { + free_spu_decoder (stream, stream->spu_decoder_plugin); + stream->spu_decoder_plugin = NULL; } - pthread_mutex_lock (&this->finished_lock); - this->video_finished = 0; - this->spu_finished = 0; - - pthread_mutex_unlock (&this->finished_lock); - - this->metronom->handle_video_discontinuity (this->metronom, DISC_STREAMSTART, 0); + stream->metronom->handle_video_discontinuity (stream->metronom, + DISC_STREAMSTART, 0); break; case BUF_SPU_SUBP_CONTROL: @@ -129,7 +123,7 @@ void *video_decoder_loop (void *this_gen) { case BUF_SPU_NAV: xine_profiler_start_count (prof_spu_decode); - spu_decoder = update_spu_decoder(this, buf->type); + spu_decoder = update_spu_decoder(stream, buf->type); if (spu_decoder) { spu_decoder->decode_data (spu_decoder, buf); @@ -140,120 +134,122 @@ void *video_decoder_loop (void *this_gen) { case BUF_CONTROL_SPU_CHANNEL: { - xine_ui_event_t ui_event; + xine_event_t ui_event; /* We use widescreen spu as the auto selection, because widescreen * display is common. SPU decoders can choose differently if it suits * them. */ - this->spu_channel_auto = buf->decoder_info[0]; - this->spu_channel_letterbox = buf->decoder_info[1]; - this->spu_channel_pan_scan = buf->decoder_info[2]; - if (this->spu_channel_user == -1) - this->spu_channel = this->spu_channel_auto; + stream->spu_channel_auto = buf->decoder_info[0]; + stream->spu_channel_letterbox = buf->decoder_info[1]; + stream->spu_channel_pan_scan = buf->decoder_info[2]; + if (stream->spu_channel_user == -1) + stream->spu_channel = stream->spu_channel_auto; /* Inform UI of SPU channel changes */ - ui_event.event.type = XINE_EVENT_UI_CHANNELS_CHANGED; - ui_event.data = NULL; - xine_send_event(this, &ui_event.event); - + ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED; + ui_event.data_length = 0; + + xine_event_send (stream, &ui_event); } break; case BUF_CONTROL_END: - if (this->cur_video_decoder_plugin) { - this->cur_video_decoder_plugin->close (this->cur_video_decoder_plugin); - this->cur_video_decoder_plugin = NULL; + if (stream->video_decoder_plugin) { + free_video_decoder (stream, stream->video_decoder_plugin); + stream->video_decoder_plugin = NULL; } - if (this->cur_spu_decoder_plugin) { - this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); - this->cur_spu_decoder_plugin = NULL; + if (stream->spu_decoder_plugin) { + free_spu_decoder (stream, stream->spu_decoder_plugin); + stream->spu_decoder_plugin = NULL; } - pthread_mutex_lock (&this->finished_lock); - this->spu_finished = 1; - - if (!this->video_finished ) { - this->video_finished = 1; - - if (this->audio_finished) { - if( this->playing_logo ) - buf->decoder_flags = 0; - this->playing_logo = 0; - - if( buf->decoder_flags & BUF_FLAG_END_STREAM ) - xine_notify_stream_finished (this); - } + + /* wait for audio to reach this marker, if necessary */ + + pthread_mutex_lock (&stream->counter_lock); + + stream->finished_count_video++; + + printf ("video_decoder: reached end marker # %d\n", + stream->finished_count_video); + + pthread_cond_broadcast (&stream->counter_changed); + + if (stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] + && stream->audio_fifo) { + + while (stream->finished_count_video > stream->finished_count_audio) { + pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); + } } + + pthread_mutex_unlock (&stream->counter_lock); - pthread_mutex_unlock (&this->finished_lock); + if (stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO]) { + /* set engine status, send frontend notification event */ + xine_handle_stream_end (stream, + buf->decoder_flags & BUF_FLAG_END_STREAM); + } break; case BUF_CONTROL_QUIT: - if (this->cur_video_decoder_plugin) { - this->cur_video_decoder_plugin->close (this->cur_video_decoder_plugin); - this->cur_video_decoder_plugin = NULL; + if (stream->video_decoder_plugin) { + free_video_decoder (stream, stream->video_decoder_plugin); + stream->video_decoder_plugin = NULL; } - if (this->cur_spu_decoder_plugin) { - this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); - this->cur_spu_decoder_plugin = NULL; + if (stream->spu_decoder_plugin) { + free_spu_decoder (stream, stream->spu_decoder_plugin); + stream->spu_decoder_plugin = NULL; } running = 0; break; case BUF_CONTROL_RESET_DECODER: - if (this->cur_video_decoder_plugin) { - this->cur_video_decoder_plugin->reset (this->cur_video_decoder_plugin); + if (stream->video_decoder_plugin) { + stream->video_decoder_plugin->reset (stream->video_decoder_plugin); } - if (this->cur_spu_decoder_plugin) { - this->cur_spu_decoder_plugin->reset (this->cur_spu_decoder_plugin); + if (stream->spu_decoder_plugin) { + stream->spu_decoder_plugin->reset (stream->spu_decoder_plugin); } break; case BUF_CONTROL_DISCONTINUITY: printf ("video_decoder: discontinuity ahead\n"); - this->video_in_discontinuity = 1; + stream->video_in_discontinuity = 1; - this->metronom->handle_video_discontinuity (this->metronom, DISC_RELATIVE, buf->disc_off); + stream->metronom->handle_video_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off); - this->video_in_discontinuity = 0; + stream->video_in_discontinuity = 0; break; case BUF_CONTROL_NEWPTS: printf ("video_decoder: new pts %lld\n", buf->disc_off); - this->video_in_discontinuity = 1; + stream->video_in_discontinuity = 1; if (buf->decoder_flags & BUF_FLAG_SEEK) { - this->metronom->handle_video_discontinuity (this->metronom, DISC_STREAMSEEK, buf->disc_off); + stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off); } else { - this->metronom->handle_video_discontinuity (this->metronom, DISC_ABSOLUTE, buf->disc_off); + stream->metronom->handle_video_discontinuity (stream->metronom, DISC_ABSOLUTE, buf->disc_off); } - this->video_in_discontinuity = 0; + stream->video_in_discontinuity = 0; break; case BUF_CONTROL_AUDIO_CHANNEL: { - xine_ui_event_t ui_event; + xine_event_t ui_event; /* Inform UI of AUDIO channel changes */ - ui_event.event.type = XINE_EVENT_UI_CHANNELS_CHANGED; - ui_event.data = NULL; - xine_send_event(this, &ui_event.event); + ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED; + ui_event.data_length = 0; + xine_event_send (stream, &ui_event); } break; case BUF_CONTROL_NOP: - /* Inform UI of NO_VIDEO usage */ - if(buf->decoder_flags & BUF_FLAG_NO_VIDEO) { - xine_ui_event_t ui_event; - - ui_event.event.type = XINE_EVENT_OUTPUT_NO_VIDEO; - ui_event.data = this->cur_input_plugin->get_mrl(this->cur_input_plugin); - xine_send_event(this, &ui_event.event); - } break; default: @@ -268,44 +264,32 @@ void *video_decoder_loop (void *this_gen) { streamtype = (buf->type>>16) & 0xFF; - decoder = get_video_decoder (this, streamtype); + decoder = get_video_decoder (stream, streamtype); if (decoder) { - if (this->cur_video_decoder_plugin != decoder) { - xine_ui_event_t ui_event; + if (stream->video_decoder_plugin != decoder) { - if (this->cur_video_decoder_plugin) { - this->cur_video_decoder_plugin->close (this->cur_video_decoder_plugin); - printf ("video_decoder: closing old decoder >%s<\n",this->cur_video_decoder_plugin->get_identifier()); + if (stream->video_decoder_plugin) { + free_video_decoder (stream, stream->video_decoder_plugin); } - this->cur_video_decoder_plugin = decoder; - this->cur_video_decoder_plugin->init (this->cur_video_decoder_plugin, this->video_out); - - this->meta_info[XINE_META_INFO_VIDEOCODEC] - = strdup (decoder->get_identifier()); - - xine_report_codec( this, XINE_CODEC_VIDEO, 0, buf->type, 1); - - ui_event.event.type = XINE_EVENT_OUTPUT_VIDEO; - ui_event.data = this->cur_input_plugin->get_mrl(this->cur_input_plugin); - xine_send_event(this, &ui_event.event); - + stream->video_decoder_plugin = decoder; } - decoder->decode_data (this->cur_video_decoder_plugin, buf); + decoder->decode_data (stream->video_decoder_plugin, buf); - } else if( buf->type != buftype_unknown ) { - xine_log (this, XINE_LOG_MSG, "video_decoder: no plugin available to handle '%s'\n", - buf_video_name( buf->type ) ); - xine_report_codec( this, XINE_CODEC_VIDEO, 0, buf->type, 0); - buftype_unknown = buf->type; - } - } else if( buf->type != buftype_unknown ) { - xine_log (this, XINE_LOG_MSG, "video_decoder: unknown buffer type: %08x\n", - buf->type ); + } else if (buf->type != buftype_unknown) { + xine_log (stream->xine, XINE_LOG_MSG, + "video_decoder: no plugin available to handle '%s'\n", + buf_video_name( buf->type ) ); buftype_unknown = buf->type; + } + } else if (buf->type != buftype_unknown) { + xine_log (stream->xine, XINE_LOG_MSG, + "video_decoder: unknown buffer type: %08x\n", + buf->type ); + buftype_unknown = buf->type; } xine_profiler_stop_count (prof_video_decode); @@ -320,7 +304,7 @@ void *video_decoder_loop (void *this_gen) { pthread_exit(NULL); } -void video_decoder_init (xine_t *this) { +void video_decoder_init (xine_stream_t *stream) { pthread_attr_t pth_attrs; struct sched_param pth_params; @@ -333,7 +317,7 @@ void video_decoder_init (xine_t *this) { * We provide buffers of 8k size instead of 2k for demuxers sending * larger chunks. */ - this->video_fifo = fifo_buffer_new (500, 8192); + stream->video_fifo = fifo_buffer_new (500, 8192); pthread_attr_init(&pth_attrs); pthread_attr_getschedparam(&pth_attrs, &pth_params); @@ -341,32 +325,32 @@ void video_decoder_init (xine_t *this) { pthread_attr_setschedparam(&pth_attrs, &pth_params); pthread_attr_setscope(&pth_attrs, PTHREAD_SCOPE_SYSTEM); - if ((err = pthread_create (&this->video_thread, - &pth_attrs, video_decoder_loop, this)) != 0) { + if ((err = pthread_create (&stream->video_thread, + &pth_attrs, video_decoder_loop, stream)) != 0) { fprintf (stderr, "video_decoder: can't create new thread (%s)\n", strerror(err)); abort(); } - this->video_in_discontinuity = 0; + stream->video_in_discontinuity = 0; } -void video_decoder_shutdown (xine_t *this) { +void video_decoder_shutdown (xine_stream_t *stream) { buf_element_t *buf; void *p; printf ("video_decoder: shutdown...\n"); - /* this->video_fifo->clear(this->video_fifo); */ + /* stream->video_fifo->clear(stream->video_fifo); */ - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); printf ("video_decoder: shutdown...2\n"); buf->type = BUF_CONTROL_QUIT; - this->video_fifo->put (this->video_fifo, buf); + stream->video_fifo->put (stream->video_fifo, buf); printf ("video_decoder: shutdown...3\n"); - pthread_join (this->video_thread, &p); + pthread_join (stream->video_thread, &p); printf ("video_decoder: shutdown...4\n"); } diff --git a/src/xine-engine/video_decoder.h b/src/xine-engine/video_decoder.h new file mode 100644 index 000000000..5fbcfb4d9 --- /dev/null +++ b/src/xine-engine/video_decoder.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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.h,v 1.3 2002/10/14 15:47:40 guenter Exp $ + * + * xine video decoder plugin interface + * + */ + +#ifndef HAVE_VIDEO_DECODER_H +#define HAVE_VIDEO_DECODER_H + +#include +#include "buffer.h" + +#define VIDEO_DECODER_IFACE_VERSION 11 + +/* + * generic xine video decoder plugin interface + */ + +typedef struct video_decoder_class_s video_decoder_class_t; + +struct video_decoder_class_s { + + /* + * return short, human readable identifier for this plugin class + */ + char* (*get_identifier) (video_decoder_class_t *this); + + /* + * return human readable (verbose = 1 line) description for + * this plugin class + */ + char* (*get_description) (video_decoder_class_t *this); +}; + + +typedef struct video_decoder_s video_decoder_t; + +struct video_decoder_s { + + /* + * decode data from buf and feed decoded frames to + * video output + */ + void (*decode_data) (video_decoder_t *this, buf_element_t *buf); + + /* + * reset decoder after engine flush (prepare for new + * video data not related to recently decoded data) + */ + void (*reset) (video_decoder_t *this); + + /* + * flush out any frames that are still stored in the decoder + */ + void (*flush) (video_decoder_t *this); + + /* + * close down, free all resources + */ + void (*dispose) (video_decoder_t *this); + + + void *node; /*used by plugin loader */ + +}; + +#endif diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 5a9d91fca..879059fb8 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.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_out.c,v 1.104 2002/09/09 03:06:14 miguelfreitas Exp $ + * $Id: video_out.c,v 1.105 2002/10/14 15:47:41 guenter Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -54,6 +54,7 @@ typedef struct { xine_vo_driver_t *driver; metronom_t *metronom; xine_t *xine; + xine_stream_t *stream; img_buf_fifo_t *free_img_buf_queue; img_buf_fifo_t *display_img_buf_queue; @@ -550,11 +551,11 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts) { */ pthread_mutex_lock( &this->free_img_buf_queue->mutex ); if (img && !img->next && - (this->xine->video_fifo->size(this->xine->video_fifo) < 10 - || this->xine->video_in_discontinuity) ) { + (this->stream->video_fifo->size(this->stream->video_fifo) < 10 + || this->stream->video_in_discontinuity) ) { printf ("video_out: possible still frame (fifosize = %d)\n", - this->xine->video_fifo->size(this->xine->video_fifo)); + this->stream->video_fifo->size(this->stream->video_fifo)); this->img_backup = duplicate_frame (this, img); } @@ -620,7 +621,7 @@ static void paused_loop( vos_t *this, int64_t vpts ) /* prevent decoder thread from allocating new frames */ this->free_img_buf_queue->locked_for_read = 1; - while( this->xine->speed == XINE_SPEED_PAUSE ) { + while (this->stream->speed == XINE_SPEED_PAUSE) { /* we need at least one free frame to keep going */ if( this->display_img_buf_queue->first && @@ -716,7 +717,7 @@ static void *video_out_loop (void *this_gen) { diff = vpts - this->last_delivery_pts; if (diff > 30000 && !this->display_img_buf_queue->first) { - if (this->xine->cur_video_decoder_plugin) { + if (this->stream->video_decoder_plugin) { #ifdef LOG printf ("video_out: flushing current video decoder plugin (%d %d)\n", @@ -724,7 +725,7 @@ static void *video_out_loop (void *this_gen) { this->free_img_buf_queue->num_buffers); #endif - this->xine->cur_video_decoder_plugin->flush(this->xine->cur_video_decoder_plugin); + this->stream->video_decoder_plugin->flush(this->stream->video_decoder_plugin); } this->last_delivery_pts = vpts; } @@ -747,8 +748,8 @@ static void *video_out_loop (void *this_gen) { do { vpts = this->metronom->get_current_time (this->metronom); - if( this->xine->speed == XINE_SPEED_PAUSE ) - paused_loop( this, vpts ); + if (this->stream->speed == XINE_SPEED_PAUSE) + paused_loop (this, vpts); usec_to_sleep = (next_frame_vpts - vpts) * 100 / 9; @@ -886,7 +887,8 @@ static void vo_enable_overlay (vo_instance_t *this_gen, int overlay_enabled) { } -vo_instance_t *vo_new_instance (xine_vo_driver_t *driver, xine_t *xine) { +vo_instance_t *vo_new_instance (xine_vo_driver_t *driver, + xine_stream_t *stream) { vos_t *this; int i; @@ -898,8 +900,9 @@ vo_instance_t *vo_new_instance (xine_vo_driver_t *driver, xine_t *xine) { this = xine_xmalloc (sizeof (vos_t)) ; this->driver = driver; - this->xine = xine; - this->metronom = xine->metronom; + this->xine = stream->xine; + this->metronom = stream->metronom; + this->stream = stream; this->vo.open = vo_open; this->vo.get_frame = vo_get_frame; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index fa955cac9..2e7585af7 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.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: video_out.h,v 1.63 2002/10/09 05:13:40 storri Exp $ + * $Id: video_out.h,v 1.64 2002/10/14 15:47:42 guenter Exp $ * * * xine version of video_out.h @@ -303,6 +303,8 @@ struct xine_vo_driver_s { */ int (*redraw_needed) (xine_vo_driver_t *this); + void *node; /* needed by plugin_loader */ + }; typedef struct rle_elem_s { @@ -363,7 +365,8 @@ video_overlay_instance_t *video_overlay_new_instance (); * a given video driver */ -vo_instance_t *vo_new_instance (xine_vo_driver_t *driver, xine_t *xine) ; +vo_instance_t *vo_new_instance (xine_vo_driver_t *driver, + xine_stream_t *stream) ; #ifdef __cplusplus } diff --git a/src/xine-engine/video_overlay.h b/src/xine-engine/video_overlay.h index be6d392ff..d2d50348c 100644 --- a/src/xine-engine/video_overlay.h +++ b/src/xine-engine/video_overlay.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: video_overlay.h,v 1.8 2002/04/09 13:20:44 jcdutton Exp $ + * $Id: video_overlay.h,v 1.9 2002/10/14 15:47:43 guenter Exp $ * */ @@ -25,6 +25,7 @@ #define HAVE_VIDEO_OVERLAY_H #include "xine_internal.h" +#include "events.h" #ifdef __GNUC__ #define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) {y: (_y), cr: (_cr), cb: (_cb)} @@ -67,10 +68,10 @@ typedef struct vo_buttons_s { int32_t right; uint32_t select_color[OVL_PALETTE_SIZE]; uint8_t select_trans[OVL_PALETTE_SIZE]; - xine_menu_event_t select_event; + xine_event_t select_event; uint32_t active_color[OVL_PALETTE_SIZE]; uint8_t active_trans[OVL_PALETTE_SIZE]; - xine_menu_event_t active_event; + xine_event_t active_event; int32_t clip_rgb_clut; /* true if clut was converted to rgb*/ /* FIXME: Probably not needed ^^^ */ } vo_buttons_t; diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index f8474baf2..51b57d0a1 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.164 2002/10/12 19:22:05 jkeil Exp $ + * $Id: xine.c,v 1.165 2002/10/14 15:47:43 guenter Exp $ * * top-level xine functions * @@ -57,507 +57,362 @@ #include "xineutils.h" #include "compat.h" -#define LOGO_DELAY 500000 /* usec */ +void xine_notify_stream_finished (xine_stream_t *stream) { -static void play_logo_internal (xine_t *this) { - pthread_mutex_lock (&this->logo_lock); - this->playing_logo = 1; - if( !xine_open_internal(this, this->logo_mrl) ) - this->playing_logo = 0; - else { - xine_play_internal (this, 0, 0); - this->status = XINE_STATUS_LOGO; - } - pthread_mutex_unlock (&this->logo_lock); -} - -/* config callback for logo mrl changing */ -static void _logo_change_cb(void *data, xine_cfg_entry_t *cfg) { - xine_t *this = (xine_t *) data; - - pthread_mutex_lock (&this->logo_lock); - this->logo_mrl = cfg->str_value; - pthread_mutex_unlock (&this->logo_lock); - - /* - * Start playback of new mrl only if - * current status is XINE_STATUS_STOP or XINE_STATUS_LOGO - */ - pthread_mutex_lock (&this->xine_lock); - if(this->metronom && (this->status == XINE_STATUS_LOGO || this->status == XINE_STATUS_STOP)) { - xine_stop_internal(this); - this->metronom->adjust_clock(this->metronom, - this->metronom->get_current_time(this->metronom) + 30 * 90000 ); - play_logo_internal(this); - } - pthread_mutex_unlock (&this->xine_lock); -} - -void * xine_notify_stream_finished_thread (void * this_gen) { - xine_t *this = this_gen; xine_event_t event; - pthread_mutex_lock (&this->xine_lock); - xine_stop_internal (this); - pthread_mutex_unlock (&this->xine_lock); - - event.type = XINE_EVENT_PLAYBACK_FINISHED; - xine_send_event (this, &event); - - xine_usec_sleep (LOGO_DELAY); - - pthread_mutex_lock (&this->xine_lock); - if (this->status == XINE_STATUS_STOP) { - play_logo_internal(this); - } - pthread_mutex_unlock (&this->xine_lock); - - return NULL; -} - -void xine_notify_stream_finished (xine_t *this) { - int err; - - if (this->status == XINE_STATUS_QUIT) + if (stream->status == XINE_STATUS_QUIT) return; - if (this->finished_thread_running) - pthread_join (this->finished_thread, NULL); - - this->finished_thread_running = 1; - - /* This thread will just execute xine_stop and (possibly) xine_play then die. - It might look useless but i need to detach this code from the current - thread to make sure that video_decoder and audio_decoder are running and - freeing buffers. Free buffers might be needed by the main thread during - a xine_play, for example. + event.data_length = 0; + event.type = XINE_EVENT_UI_PLAYBACK_FINISHED; - This is not a theorical situation: i was able to trigger it with simple - user actions (play,seek,etc). [MF] - */ - if ((err = pthread_create (&this->finished_thread, - NULL, xine_notify_stream_finished_thread, this)) != 0) { - printf (_("xine_notify_stream_finished: can't create new thread (%s)\n"), - strerror(err)); - abort(); - } + xine_event_send (stream, &event); } -void xine_report_codec( xine_t *this, int codec_type, uint32_t fourcc, uint32_t buf_type, int handled ) { +void xine_report_codec (xine_stream_t *stream, int codec_type, + uint32_t fourcc, uint32_t buf_type, int handled) { - if( this->report_codec_cb ) { - if( codec_type == XINE_CODEC_VIDEO ) { - if( !buf_type ) - buf_type = fourcc_to_buf_video( fourcc ); - - this->report_codec_cb( this->report_codec_user_data, - codec_type, fourcc, - buf_video_name( buf_type ), handled ); - } else { - if( !buf_type ) - buf_type = formattag_to_buf_audio( fourcc ); - - this->report_codec_cb( this->report_codec_user_data, - codec_type, fourcc, - buf_audio_name( buf_type ), handled ); - } - } -} - -int xine_register_report_codec_cb(xine_t *this, - xine_report_codec_cb_t report_codec, - void *user_data) { - - this->report_codec_cb = report_codec; - this->report_codec_user_data = user_data; - return 1; -} - -void xine_internal_osd (xine_t *this, char *str, int duration) { - - uint32_t seconds; - char tstr[256]; - int64_t start_time; - - this->curtime_needed_for_osd = 0; - start_time = this->metronom->get_current_time (this->metronom); - - if (this->osd_display) { - - this->osd_renderer->filled_rect (this->osd, 0, 0, 299, 99, 0); - this->osd_renderer->render_text (this->osd, 0, 5, str, OSD_TEXT1); - - seconds = this->cur_input_time; - - sprintf (tstr, "%02d:%02d:%02d", - seconds / (60 * 60), - (seconds % (60*60)) / 60, - seconds % 60); - - this->osd_renderer->render_text (this->osd, 45, 5, tstr, OSD_TEXT1); - - this->osd_renderer->show (this->osd, start_time); - this->osd_renderer->hide (this->osd, start_time+duration); + if (codec_type == XINE_CODEC_VIDEO) { + stream->stream_info[XINE_STREAM_INFO_VIDEO_FOURCC] = fourcc; + stream->stream_info[XINE_STREAM_INFO_VIDEO_HANDLED] = handled; + } else { + stream->stream_info[XINE_STREAM_INFO_AUDIO_FOURCC] = fourcc; + stream->stream_info[XINE_STREAM_INFO_AUDIO_HANDLED] = handled; } } -static void update_osd_display(void *this_gen, xine_cfg_entry_t *entry) -{ - xine_t *this = (xine_t *) this_gen; - - this->osd_display = entry->num_value; -} - -static void xine_set_speed_internal (xine_t *this, int speed) { +static void xine_set_speed_internal (xine_stream_t *stream, int speed) { - this->metronom->set_speed (this->metronom, speed); + stream->metronom->set_speed (stream->metronom, speed); /* see coment on audio_out loop about audio_paused */ - if( this->audio_out ) { - this->audio_out->audio_paused = (speed != XINE_SPEED_NORMAL) + - (speed == XINE_SPEED_PAUSE); + if( stream->audio_out ) { + stream->audio_out->audio_paused = (speed != XINE_SPEED_NORMAL) + + (speed == XINE_SPEED_PAUSE); /* * slow motion / fast forward does not play sound, drop buffered * samples from the sound driver */ if (speed != XINE_SPEED_NORMAL && speed != XINE_SPEED_PAUSE) - this->audio_out->control(this->audio_out, AO_CTRL_FLUSH_BUFFERS); + stream->audio_out->control(stream->audio_out, AO_CTRL_FLUSH_BUFFERS); - this->audio_out->control(this->audio_out, - speed == XINE_SPEED_PAUSE ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME); + stream->audio_out->control(stream->audio_out, + speed == XINE_SPEED_PAUSE ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME); } - - this->speed = speed; + + stream->speed = speed; } -void xine_stop_internal (xine_t *this) { +static void xine_stop_internal (xine_stream_t *stream) { + + int finished_count_audio = 0; + int finished_count_video = 0; - printf ("xine_stop. status before = %d\n", this->status); + printf ("xine: xine_stop. status before = %d\n", stream->status); - if (this->status == XINE_STATUS_STOP) { - printf ("xine_stop ignored\n"); + if (stream->status == XINE_STATUS_STOP) { + printf ("xine: xine_stop ignored\n"); return; } /* make sure we're not in "paused" state */ - xine_set_speed_internal(this, XINE_SPEED_NORMAL); + xine_set_speed_internal (stream, XINE_SPEED_NORMAL); /* Don't change status if we're quitting */ - if(this->status != XINE_STATUS_QUIT) - this->status = XINE_STATUS_STOP; + if (stream->status != XINE_STATUS_QUIT) + stream->status = XINE_STATUS_STOP; - printf ("xine_stop: stopping demuxer\n"); - if(this->cur_demuxer_plugin) { - this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin); - this->cur_demuxer_plugin = NULL; + /* + * stop demux + */ + + pthread_mutex_lock (&stream->counter_lock); + if (stream->audio_fifo) + finished_count_audio = stream->finished_count_audio + 1; + else + finished_count_audio = 0; + + finished_count_video = stream->finished_count_video + 1; + pthread_mutex_unlock (&stream->counter_lock); + + printf ("xine_stop: stopping demux\n"); + if (stream->demux_plugin) { + stream->demux_plugin->dispose (stream->demux_plugin); + stream->demux_plugin = NULL; + + /* + * wait until engine has really stopped + */ + + pthread_mutex_lock (&stream->counter_lock); + while ((stream->finished_count_audiofinished_count_videocounter_changed, &stream->counter_lock); + } + pthread_mutex_unlock (&stream->counter_lock); } - printf ("xine_stop: stopped demuxer\n"); + printf ("xine_stop: demux stopped\n"); - if(this->cur_input_plugin) { - this->cur_input_plugin->close(this->cur_input_plugin); - if (strcmp(this->cur_mrl, this->logo_mrl) != 0) - /* remember the last input plugin for a possible eject */ - this->last_input_plugin = this->cur_input_plugin; + /* + * close input plugin + */ + + if (stream->input_plugin) { + stream->input_plugin->dispose(stream->input_plugin); + stream->input_plugin = NULL; } /* remove buffered samples from the sound device driver */ - if (this->audio_out) - this->audio_out->control(this->audio_out, AO_CTRL_FLUSH_BUFFERS); + if (stream->audio_out) + stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS); printf ("xine_stop: done\n"); } -void xine_stop (xine_t *this) { - pthread_mutex_lock (&this->xine_lock); - xine_stop_internal(this); +void xine_stop (xine_stream_t *stream) { + + pthread_mutex_lock (&stream->frontend_lock); + + xine_stop_internal (stream); /* - this will make output threads discard about everything - am i abusing of xine architeture? :) - */ - this->metronom->adjust_clock(this->metronom, - this->metronom->get_current_time(this->metronom) + 30 * 90000 ); + * stream will make output threads discard about everything + * am i abusing of xine architeture? :) + */ + stream->metronom->adjust_clock (stream->metronom, + stream->metronom->get_current_time(stream->metronom) + 30 * 90000 ); - if(this->status == XINE_STATUS_STOP) { - play_logo_internal(this); - } - - pthread_mutex_unlock (&this->xine_lock); + pthread_mutex_unlock (&stream->frontend_lock); } +xine_stream_t *xine_stream_new (xine_t *this, + xine_ao_driver_t *ao, xine_vo_driver_t *vo) { -/* - * demuxer probing - */ -static int probe_demux (xine_t *this, int stage1, int stage2) { - - int i; - int stages[3]; + xine_stream_t *stream; + int i; - stages[0] = stage1; - stages[1] = stage2; - stages[2] = -1; + printf ("xine: xine_stream_new\n"); - if (stages[0] == -1) { - printf ("xine: probe_demux stage1 = %d is not allowed \n", stage1); - return 0; - } + /* + * create a new stream object + */ - i = 0; - while (stages[i] != -1) { + pthread_mutex_lock (&this->streams_lock); - plugin_node_t *node; + stream = (xine_stream_t *) xine_xmalloc (sizeof (xine_stream_t)) ; - node = xine_list_first_content (this->plugin_catalog->demux); + stream->xine = this; + stream->status = XINE_STATUS_STOP; + for (i=0; istream_info[i] = 0; + stream->meta_info[i] = NULL; + } + stream->speed = XINE_SPEED_NORMAL; + stream->input_pos = 0; + stream->input_length = 0; + stream->input_time = 0; + stream->spu_out = NULL; + stream->spu_decoder_plugin = NULL; + stream->audio_channel_user = -1; + stream->audio_channel_auto = 0; + stream->spu_channel_auto = -1; + stream->spu_channel_letterbox = -1; + stream->spu_channel_pan_scan = -1; + stream->spu_channel_user = -1; + stream->spu_channel = -1; + stream->video_driver = vo; + stream->video_in_discontinuity = 0; + stream->video_channel = 0; + stream->header_count_audio = 0; + stream->header_count_video = 0; + stream->finished_count_audio = 0; + stream->finished_count_video = 0; + stream->err = 0; - while (node) { - demux_plugin_t *plugin; + /* + * init mutexes and conditions + */ - plugin = (demux_plugin_t *) node->plugin; + pthread_mutex_init (&stream->frontend_lock, NULL); + pthread_mutex_init (&stream->event_queues_lock, NULL); + pthread_mutex_init (&stream->osd_lock, NULL); + pthread_mutex_init (&stream->counter_lock, NULL); + pthread_cond_init (&stream->counter_changed, NULL); - if (plugin->open (plugin, - this->cur_input_plugin, - stages[i]) == DEMUX_CAN_HANDLE) { - - this->cur_demuxer_plugin = plugin; + /* + * create a metronom + */ - return 1; - } - node = xine_list_next_content (this->plugin_catalog->demux); - } - i++; - } + stream->metronom = metronom_init ( (ao != NULL), stream); - return 0; -} + /* + * alloc fifos, init and start decoder threads + */ -/* - * try to find a demuxer which handle current mrl. - */ -static int find_demuxer(xine_t *this) { + stream->video_out = vo_new_instance (vo, stream); + video_decoder_init (stream); - this->cur_demuxer_plugin = NULL; + if (ao) + stream->audio_out = ao_new_instance (ao, stream); + audio_decoder_init (stream); - switch (this->demux_strategy) { + /* + * osd + */ - case DEMUX_DEFAULT_STRATEGY: - if (probe_demux (this, STAGE_BY_CONTENT, STAGE_BY_EXTENSION)) - return 1; - break; + stream->osd_renderer = osd_renderer_init (stream->video_out->get_overlay_instance (stream->video_out), stream->xine->config ); + + /* + * register stream + */ - case DEMUX_REVERT_STRATEGY: - if (probe_demux (this, STAGE_BY_EXTENSION, STAGE_BY_CONTENT)) - return 1; - break; + xine_list_append_content (this->streams, stream); - case DEMUX_CONTENT_STRATEGY: - if (probe_demux (this, STAGE_BY_CONTENT, -1)) - return 1; - break; + pthread_mutex_unlock (&this->streams_lock); - case DEMUX_EXTENSION_STRATEGY: - if (probe_demux (this, STAGE_BY_EXTENSION, -1)) - return 1; - break; - } - - return 0; + return stream; } -int xine_open_internal (xine_t *this, const char *mrl) { - - printf ("xine: open mrl '%s'\n", mrl); +static int xine_open_internal (xine_stream_t *stream, const char *mrl) { - /* - * is this an 'opt:' mrlstyle ? - */ - if (xine_config_change_opt(this->config, mrl)) { - xine_event_t event; - - this->status = XINE_STATUS_STOP; - - event.type = XINE_EVENT_PLAYBACK_FINISHED; - pthread_mutex_unlock (&this->xine_lock); - xine_send_event (this, &event); - pthread_mutex_lock (&this->xine_lock); - return 1; - } + int header_count_audio; + int header_count_video; /* - * stop engine only for different mrl + * find an input plugin */ - if ((this->status == XINE_STATUS_PLAY && strcmp (mrl, this->cur_mrl)) - || (this->status == XINE_STATUS_LOGO)) { - - printf ("xine: stopping engine\n"); + if (!(stream->input_plugin = find_input_plugin (stream, mrl))) { + xine_log (stream->xine, XINE_LOG_MSG, + _("xine: cannot find input plugin for this MRL\n")); - if (this->speed != XINE_SPEED_NORMAL) - xine_set_speed_internal (this, XINE_SPEED_NORMAL); + stream->err = XINE_ERROR_NO_INPUT_PLUGIN; + return 0; + } + stream->input_class = stream->input_plugin->input_class; + stream->meta_info[XINE_META_INFO_INPUT_PLUGIN] + = strdup (stream->input_class->get_identifier (stream->input_class)); - if(this->cur_demuxer_plugin) { - this->playing_logo = 0; - this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin); - } - - if(this->cur_input_plugin) { - if (strcmp (mrl, this->cur_mrl)) - this->cur_input_plugin->close(this->cur_input_plugin); - else - this->cur_input_plugin->stop(this->cur_input_plugin); - } + /* + * find a demux plugin + */ + if (!find_demux_plugin (stream, stream->input_plugin)) { + xine_log (stream->xine, XINE_LOG_MSG, + _("xine: couldn't find demux for >%s<\n"), mrl); + stream->input_plugin->dispose (stream->input_plugin); + stream->input_plugin = NULL; + stream->err = XINE_ERROR_NO_DEMUX_PLUGIN; /* remove buffered samples from the sound device driver */ - if (this->audio_out) - this->audio_out->control(this->audio_out, AO_CTRL_FLUSH_BUFFERS); + if (stream->audio_out) + stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS); - this->status = XINE_STATUS_STOP; + stream->status = XINE_STATUS_STOP; + return 0; } - if (this->status == XINE_STATUS_STOP) { - - plugin_node_t *node; - int i, header_count; - - /* - * (1/3) reset metainfo - */ - - for (i=0; istream_info[i] = 0; - if (this->meta_info[i]) { - free (this->meta_info[i]); - this->meta_info[i] = NULL; - } - } + stream->meta_info[XINE_META_INFO_SYSTEMLAYER] + = strdup (stream->demux_plugin->demux_class->get_identifier()); - /* - * (2/3) start engine for new mrl' - */ + /* + * start metronom clock + */ - printf ("xine: starting engine for new mrl\n"); + stream->metronom->start_clock (stream->metronom, 0); - /* - * find input plugin - */ - this->cur_input_plugin = NULL; - node = xine_list_first_content (this->plugin_catalog->input); - while (node) { - input_plugin_t *plugin; - - plugin = (input_plugin_t *) node->plugin; - - if (plugin->open (plugin, mrl)) { - this->cur_input_plugin = plugin; - break; - } - node = xine_list_next_content (this->plugin_catalog->input); - } + /* + * send and decode headers + */ - if (!this->cur_input_plugin) { - xine_log (this, XINE_LOG_MSG, - _("xine: cannot find input plugin for this MRL\n")); - this->cur_demuxer_plugin = NULL; - this->err = XINE_ERROR_NO_INPUT_PLUGIN; + pthread_mutex_lock (&stream->counter_lock); + if (stream->audio_fifo) + header_count_audio = stream->header_count_audio + 1; + else + header_count_audio = 0; - return 0; - } + header_count_video = stream->header_count_video + 1; + pthread_mutex_unlock (&stream->counter_lock); - this->meta_info[XINE_META_INFO_INPUT_PLUGIN] - = strdup (this->cur_input_plugin->get_identifier(this->cur_input_plugin)); + stream->demux_plugin->send_headers (stream->demux_plugin); - /* - * find demuxer plugin - */ - header_count = this->header_sent_counter+1; - - if (!find_demuxer(this)) { - xine_log (this, XINE_LOG_MSG, - _("xine: couldn't find demuxer for >%s<\n"), mrl); - this->cur_input_plugin->close(this->cur_input_plugin); - this->err = XINE_ERROR_NO_DEMUXER_PLUGIN; - return 0; - } + pthread_mutex_lock (&stream->counter_lock); + while ((stream->header_count_audioheader_count_videocounter_changed, &stream->counter_lock); + } + pthread_mutex_unlock (&stream->counter_lock); - this->meta_info[XINE_META_INFO_SYSTEMLAYER] - = strdup (this->cur_demuxer_plugin->get_identifier()); + return 1; +} - /* FIXME: ?? limited length ??? */ - strncpy (this->cur_mrl, mrl, 1024); +int xine_open (xine_stream_t *stream, const char *mrl) { - printf ("xine: engine start successful - waiting for headers to be sent\n"); + int ret; - /* - * (3/3) wait for headers to be sent and decoded - */ + pthread_mutex_lock (&stream->frontend_lock); - while (header_count>this->header_sent_counter) { - printf ("xine: waiting for headers.\n"); - xine_usec_sleep (20000); - } + printf ("xine: xine_open %s\n", mrl); - printf ("xine: xine_open done.\n"); + ret = xine_open_internal (stream, mrl); - return 1; - } + pthread_mutex_unlock (&stream->frontend_lock); - printf ("xine: xine_open ignored (same mrl, already playing)\n"); - return 0; + return ret; } -int xine_play_internal (xine_t *this, int start_pos, int start_time) { + +static int xine_play_internal (xine_stream_t *stream, int start_pos, int start_time) { double share ; off_t pos, len; int demux_status; - printf ("xine: xine_play_internal\n"); + printf ("xine: xine_play\n"); - if (this->speed != XINE_SPEED_NORMAL) - xine_set_speed_internal (this, XINE_SPEED_NORMAL); + if (stream->speed != XINE_SPEED_NORMAL) + xine_set_speed_internal (stream, XINE_SPEED_NORMAL); /* - * start/seek demuxer + * start/seek demux */ if (start_pos) { /* FIXME: do we need to protect concurrent access to input plugin here? */ - len = this->cur_input_plugin->get_length (this->cur_input_plugin); + len = stream->input_plugin->get_length (stream->input_plugin); share = (double) start_pos / 65535; pos = (off_t) (share * len) ; } else pos = 0; - if (this->status == XINE_STATUS_STOP) { + if (stream->status == XINE_STATUS_STOP) { - demux_status = this->cur_demuxer_plugin->start (this->cur_demuxer_plugin, + demux_status = stream->demux_plugin->start (stream->demux_plugin, pos, start_time); } else { - demux_status = this->cur_demuxer_plugin->seek (this->cur_demuxer_plugin, + demux_status = stream->demux_plugin->seek (stream->demux_plugin, pos, start_time); } if (demux_status != DEMUX_OK) { - xine_log (this, XINE_LOG_MSG, - _("xine_play: demuxer failed to start\n")); + xine_log (stream->xine, XINE_LOG_MSG, + _("xine_play: demux failed to start\n")); - this->err = XINE_ERROR_DEMUXER_FAILED; + stream->err = XINE_ERROR_DEMUX_FAILED; - if( this->status == XINE_STATUS_STOP ) - this->cur_input_plugin->close(this->cur_input_plugin); + if (stream->status == XINE_STATUS_STOP) + stream->input_plugin->dispose(stream->input_plugin); + pthread_mutex_unlock (&stream->frontend_lock); return 0; } else { - - this->status = XINE_STATUS_PLAY; - - /* osd will be updated as soon as we know cur_input_time */ - if( !this->playing_logo ) - this->curtime_needed_for_osd = 5; + stream->status = XINE_STATUS_PLAY; } printf ("xine: xine_play_internal ...done\n"); @@ -565,102 +420,88 @@ int xine_play_internal (xine_t *this, int start_pos, int start_time) { return 1; } -int xine_open (xine_t *this, const char *mrl) { +int xine_play (xine_stream_t *stream, int start_pos, int start_time) { + int ret; - pthread_mutex_lock (&this->xine_lock); - ret = xine_open_internal (this, mrl); - pthread_mutex_unlock (&this->xine_lock); - - return ret; -} + pthread_mutex_lock (&stream->frontend_lock); -int xine_play (xine_t *this, int start_pos, int start_time) { - int ret; + ret = xine_play_internal (stream, start_pos, start_time); - pthread_mutex_lock (&this->xine_lock); - ret = xine_play_internal (this, start_pos, start_time); - pthread_mutex_unlock (&this->xine_lock); + pthread_mutex_unlock (&stream->frontend_lock); return ret; } - -int xine_eject (xine_t *this) { +int xine_eject (xine_stream_t *stream) { int status; - if(this->last_input_plugin == NULL) + if (!stream->input_class) return 0; - pthread_mutex_lock (&this->xine_lock); + pthread_mutex_lock (&stream->frontend_lock); status = 0; - if (((this->status == XINE_STATUS_STOP) || (this->status == XINE_STATUS_LOGO)) - && this->last_input_plugin && this->last_input_plugin->eject_media) { + if ((stream->status == XINE_STATUS_STOP) + && stream->input_class && stream->input_class->eject_media) { - status = this->last_input_plugin->eject_media (this->last_input_plugin); + status = stream->input_class->eject_media (stream->input_class); } - pthread_mutex_unlock (&this->xine_lock); + pthread_mutex_unlock (&stream->frontend_lock); return status; } -void xine_exit (xine_t *this) { +void xine_dispose (xine_stream_t *stream) { - int i; + printf ("xine: xine_dispose\n"); - /* skip some cleanup steps, when xine_init wasn't run */ - if (this->video_driver && this->metronom) { + stream->status = XINE_STATUS_QUIT; - /* cleanup things from xine_init... */ - this->status = XINE_STATUS_QUIT; + xine_stop(stream); - xine_stop(this); + printf ("xine_exit: shutdown audio\n"); - pthread_mutex_lock (&this->finished_lock); + audio_decoder_shutdown (stream); - if (this->finished_thread_running) - pthread_join (this->finished_thread, NULL); + printf ("xine_exit: shutdown video\n"); - pthread_mutex_unlock (&this->finished_lock); + video_decoder_shutdown (stream); - printf ("xine_exit: shutdown audio\n"); + stream->osd_renderer->close( stream->osd_renderer ); + stream->video_out->exit (stream->video_out); + stream->video_fifo->dispose (stream->video_fifo); - audio_decoder_shutdown (this); + pthread_mutex_destroy (&stream->frontend_lock); + pthread_mutex_destroy (&stream->counter_lock); + pthread_mutex_destroy (&stream->osd_lock); + pthread_mutex_destroy (&stream->event_queues_lock); + pthread_cond_destroy (&stream->counter_changed); - printf ("xine_exit: shutdown video\n"); + free (stream); +} - video_decoder_shutdown (this); +void xine_exit (xine_t *this) { - this->osd_renderer->close( this->osd_renderer ); - this->video_out->exit (this->video_out); - this->video_fifo->dispose (this->video_fifo); + /* FIXME */ - this->metronom->exit (this->metronom); + printf ("xine_exit: bye!\n"); - printf ("xine_exit: bye!\n"); - } +#if 0 - /* cleanup things from xine_new... */ - this->status = XINE_STATUS_QUIT; + int i; for (i = 0; i < XINE_LOG_NUM; i++) - this->log_buffers[i]->dispose (this->log_buffers[i]); - - dispose_plugins (this); - xine_profiler_print_results (); - this->config->dispose(this->config); + stream->log_buffers[i]->dispose (stream->log_buffers[i]); - pthread_mutex_destroy (&this->logo_lock); - pthread_mutex_destroy (&this->xine_lock); - pthread_mutex_destroy (&this->finished_lock); - pthread_mutex_destroy (&this->osd_lock); - pthread_mutex_destroy (&this->event_lock); - pthread_cond_destroy (&this->event_handled); + stream->metronom->exit (stream->metronom); - free (this); + dispose_plugins (stream); + xine_profiler_print_results (); + stream->config->dispose(stream->config); +#endif } xine_t *xine_new (void) { @@ -683,22 +524,6 @@ xine_t *xine_new (void) { bindtextdomain("xine-lib", XINE_LOCALEDIR); #endif - /* - * init locks - */ - - pthread_mutex_init (&this->xine_lock, NULL); - - pthread_mutex_init (&this->finished_lock, NULL); - - pthread_mutex_init (&this->osd_lock, NULL); - - pthread_mutex_init (&this->event_lock, NULL); - - pthread_cond_init (&this->event_handled, NULL); - - this->finished_thread_running = 0; - /* * config */ @@ -711,33 +536,12 @@ xine_t *xine_new (void) { for (i = 0; i < XINE_LOG_NUM; i++) this->log_buffers[i] = new_scratch_buffer (25); - - /* - * defaults - */ - this->err = XINE_ERROR_NONE; - this->spu_channel_auto = -1; - this->spu_channel_letterbox = -1; - this->spu_channel_pan_scan = -1; - this->spu_channel_user = -1; - this->cur_input_pos = 0; - this->cur_input_length = 0; - this->last_input_plugin = NULL; - this->num_event_listeners = 0; /* initially there are none */ - this->cur_input_plugin = NULL; - this->cur_spu_decoder_plugin = NULL; - this->report_codec_cb = NULL; - this->header_sent_counter = 0; - - /* - * meta info + /* + * streams_lock */ - for (i=0; istream_info[i] = 0; - this->meta_info [i] = NULL; - } + pthread_mutex_init (&this->streams_lock, NULL); /* * plugins @@ -745,48 +549,21 @@ xine_t *xine_new (void) { scan_plugins(this); - /* - * logo - */ - - pthread_mutex_init (&this->logo_lock, NULL); - - pthread_mutex_lock (&this->logo_lock); - this->logo_mrl = this->config->register_string(this->config, - "misc.logo_mrl", - XINE_LOGO_FILE, - _("logo mrl, displayed in video output window"), - NULL, 0, _logo_change_cb, - (void *) this); - pthread_mutex_unlock (&this->logo_lock); - return this; - } -void xine_init (xine_t *this, - xine_ao_driver_t *ao, - xine_vo_driver_t *vo) { +void xine_init (xine_t *this) { static char *demux_strategies[] = {"default", "reverse", "content", "extension", NULL}; - this->video_driver = vo; - /* initialize color conversion tables and functions */ init_yuv_conversion(); - - /* - * create a metronom - */ - - this->metronom = metronom_init ( (ao != NULL), this); - /* probe for optimized memcpy or config setting */ xine_probe_fast_memcpy (this->config); - + /* * content detection strategy */ @@ -797,216 +574,121 @@ void xine_init (xine_t *this, demux_strategies, "media format detection strategy", NULL, 10, NULL, NULL); - /* - * init and start decoder threads + * keep track of all opened streams */ - this->video_out = vo_new_instance (vo, this); - video_decoder_init (this); - - this->osd_renderer = osd_renderer_init (this->video_out->get_overlay_instance (this->video_out), this->config ); - - this->osd = this->osd_renderer->new_object (this->osd_renderer, 300, 100); - this->osd_renderer->set_font (this->osd, "cetus", 24); - this->osd_renderer->set_text_palette (this->osd, TEXTPALETTE_WHITE_BLACK_TRANSPARENT, OSD_TEXT1 ); - this->osd_renderer->set_position (this->osd, 10,10); - - this->osd_display = this->config->register_bool (this->config, - "misc.osd_display", 1, - "Show status on play, pause, ff, ...", - NULL, 0, - update_osd_display, this ); - - if (ao) - this->audio_out = ao_new_instance (ao, this); - - audio_decoder_init (this); - - /* - * start metronom clock (needed for osd) - */ - - this->metronom->start_clock (this->metronom, 0); - - if (this->osd_display) { - - char tstr[30]; - - this->osd_renderer->filled_rect (this->osd, 0, 0, 299, 99, 0); - sprintf (tstr, "xine-lib v%01d.%01d.%01d", XINE_MAJOR, XINE_MINOR, XINE_SUB); - - this->osd_renderer->render_text (this->osd, 5, 5, tstr, OSD_TEXT1); - - this->osd_renderer->show (this->osd, 0); - this->osd_renderer->hide (this->osd, 300000); - } - - this->status = XINE_STATUS_STOP; + this->streams = xine_list_new(); + pthread_mutex_init (&this->streams_lock, NULL); - play_logo_internal(this); } -void xine_select_spu_channel (xine_t *this, int channel) { +void xine_select_spu_channel (xine_stream_t *stream, int channel) { - pthread_mutex_lock (&this->xine_lock); + pthread_mutex_lock (&stream->frontend_lock); - this->spu_channel_user = (channel >= -2 ? channel : -2); + stream->spu_channel_user = (channel >= -2 ? channel : -2); - switch (this->spu_channel_user) { + switch (stream->spu_channel_user) { case -2: - this->spu_channel = -1; - this->video_out->enable_ovl (this->video_out, 0); + stream->spu_channel = -1; + stream->video_out->enable_ovl (stream->video_out, 0); break; case -1: - this->spu_channel = this->spu_channel_auto; - this->video_out->enable_ovl (this->video_out, 1); + stream->spu_channel = stream->spu_channel_auto; + stream->video_out->enable_ovl (stream->video_out, 1); break; default: - this->spu_channel = this->spu_channel_user; - this->video_out->enable_ovl (this->video_out, 1); + stream->spu_channel = stream->spu_channel_user; + stream->video_out->enable_ovl (stream->video_out, 1); } - pthread_mutex_unlock (&this->xine_lock); + pthread_mutex_unlock (&stream->frontend_lock); } -static int xine_get_current_position (xine_t *this) { +static int xine_get_current_position (xine_stream_t *stream) { off_t len; double share; - pthread_mutex_lock (&this->xine_lock); + pthread_mutex_lock (&stream->frontend_lock); - if (!this->cur_input_plugin) { + if (!stream->input_plugin) { printf ("xine: xine_get_current_position: no input source\n"); - pthread_mutex_unlock (&this->xine_lock); + pthread_mutex_unlock (&stream->frontend_lock); return 0; } - /* pos = this->mCurInput->seek (0, SEEK_CUR); */ - len = this->cur_input_length; - if (len == 0) len = this->cur_input_plugin->get_length (this->cur_input_plugin); - share = (double) this->cur_input_pos / (double) len * 65535; + /* pos = stream->mCurInput->seek (0, SEEK_CUR); */ + len = stream->input_length; + if (len == 0) len = stream->input_plugin->get_length (stream->input_plugin); + share = (double) stream->input_pos / (double) len * 65535; - pthread_mutex_unlock (&this->xine_lock); + pthread_mutex_unlock (&stream->frontend_lock); return (int) share; } -int xine_get_status(xine_t *this) { - int status; - - status = this->status; - if( status == XINE_STATUS_LOGO ) - status = XINE_STATUS_STOP; - return status; +int xine_get_status (xine_stream_t *stream) { + return stream->status; } /* * trick play */ -void xine_set_speed (xine_t *this, int speed) { +void xine_set_speed (xine_stream_t *stream, int speed) { - pthread_mutex_lock (&this->xine_lock); + pthread_mutex_lock (&stream->frontend_lock); if (speed <= XINE_SPEED_PAUSE) speed = XINE_SPEED_PAUSE; else if (speed > XINE_SPEED_FAST_4) speed = XINE_SPEED_FAST_4; - /* osd */ - - pthread_mutex_lock (&this->osd_lock); - switch (speed) { - case XINE_SPEED_PAUSE: - xine_internal_osd (this, "<", 90000); - break; - case XINE_SPEED_SLOW_4: - xine_internal_osd (this, "<>", 20000 * speed); - break; - case XINE_SPEED_SLOW_2: - xine_internal_osd (this, "@>", 20000 * speed); - break; - case XINE_SPEED_NORMAL: - xine_internal_osd (this, ">", 20000 * speed); - break; - case XINE_SPEED_FAST_2: - xine_internal_osd (this, "$$", 20000 * speed); - break; - case XINE_SPEED_FAST_4: - xine_internal_osd (this, "$$$", 20000 * speed); - break; - } - pthread_mutex_unlock (&this->osd_lock); - printf ("xine: set_speed %d\n", speed); - xine_set_speed_internal (this, speed); + xine_set_speed_internal (stream, speed); - pthread_mutex_unlock (&this->xine_lock); + pthread_mutex_unlock (&stream->frontend_lock); } -int xine_get_speed (xine_t *this) { - return this->speed; +int xine_get_speed (xine_stream_t *stream) { + return stream->speed; } /* * time measurement / seek */ -static int xine_get_stream_length (xine_t *this) { +static int xine_get_stream_length (xine_stream_t *stream) { - if(this->cur_demuxer_plugin) - return this->cur_demuxer_plugin->get_stream_length (this->cur_demuxer_plugin); + if (stream->demux_plugin) + return stream->demux_plugin->get_stream_length (stream->demux_plugin); return 0; } -int xine_get_pos_length (xine_t *this, int *pos_stream, +int xine_get_pos_length (xine_stream_t *stream, int *pos_stream, int *pos_time, int *length_time) { if (pos_stream) - *pos_stream = xine_get_current_position (this); + *pos_stream = xine_get_current_position (stream); if (pos_time) - *pos_time = this->cur_input_time * 1000; + *pos_time = stream->input_time * 1000; if (length_time) - *length_time = xine_get_stream_length (this) * 1000; + *length_time = xine_get_stream_length (stream) * 1000; return 1; } -static int xine_get_audio_capabilities(xine_t *this) { - - if(this->audio_out) - return (this->audio_out->get_capabilities(this->audio_out)); - - return AO_CAP_NOCAP; -} - -static int xine_get_audio_property(xine_t *this, int property) { - - if(this->audio_out) - return(this->audio_out->get_property(this->audio_out, property)); - - return 0; -} - -static int xine_set_audio_property(xine_t *this, int property, int value) { - - if(this->audio_out) - return(this->audio_out->set_property(this->audio_out, property, value)); - - return ~value; -} - -int xine_get_current_frame (xine_t *this, int *width, int *height, +int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, int *ratio_code, int *format, uint8_t *img) { vo_frame_t *frame; - frame = this->video_out->get_last_frame (this->video_out); + frame = stream->video_out->get_last_frame (stream->video_out); if (!frame) return 0; @@ -1041,42 +723,39 @@ int xine_get_current_frame (xine_t *this, int *width, int *height, return 1; } -const char * xine_get_spu_lang (xine_t *this, int channel) { +int xine_get_spu_lang (xine_stream_t *stream, int channel, char *lang) { - if (this->cur_input_plugin) { - if (this->cur_input_plugin->get_capabilities (this->cur_input_plugin) & INPUT_CAP_SPULANG) { - this->cur_input_plugin->get_optional_data (this->cur_input_plugin, - this->spu_lang, - INPUT_OPTIONAL_DATA_SPULANG); - return this->spu_lang; + if (stream->input_plugin) { + if (stream->input_plugin->get_capabilities (stream->input_plugin) & INPUT_CAP_SPULANG) { + stream->input_plugin->get_optional_data (stream->input_plugin, lang, + INPUT_OPTIONAL_DATA_SPULANG); + return 1; } } - return NULL; + return 0; } -const char* xine_get_audio_lang (xine_t *this, int channel) { +int xine_get_audio_lang (xine_stream_t *stream, int channel, char *lang) { - if (this->cur_input_plugin) { - if (this->cur_input_plugin->get_capabilities (this->cur_input_plugin) & INPUT_CAP_AUDIOLANG) { - this->cur_input_plugin->get_optional_data (this->cur_input_plugin, - this->audio_lang, - INPUT_OPTIONAL_DATA_AUDIOLANG); - return this->audio_lang; + if (stream->input_plugin) { + if (stream->input_plugin->get_capabilities (stream->input_plugin) & INPUT_CAP_AUDIOLANG) { + stream->input_plugin->get_optional_data (stream->input_plugin, lang, + INPUT_OPTIONAL_DATA_AUDIOLANG); + return 1; } } - return NULL; + return 0; } -int xine_get_spu_channel (xine_t *this) { - - return this->spu_channel_user; +int xine_get_spu_channel (xine_stream_t *stream) { + return stream->spu_channel_user; } -osd_renderer_t *xine_get_osd_renderer (xine_t *this) { +osd_renderer_t *xine_get_osd_renderer (xine_stream_t *stream) { - return this->osd_renderer; + return stream->osd_renderer; } /* @@ -1127,11 +806,11 @@ void xine_register_log_cb (xine_t *this, xine_log_cb_t cb, void *user_data) { } -int xine_get_error (xine_t *this) { - return this->err; +int xine_get_error (xine_stream_t *stream) { + return stream->err; } -int xine_trick_mode (xine_t *this, int mode, int value) { +int xine_trick_mode (xine_stream_t *stream, int mode, int value) { printf ("xine: xine_trick_mode not implemented yet.\n"); abort (); } diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 541fe3f0a..677a16c67 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.22 2002/09/22 14:29:40 mroi Exp $ + * $Id: xine_interface.c,v 1.23 2002/10/14 15:47:44 guenter Exp $ * * convenience/abstraction layer, functions to implement * libxine's public interface @@ -304,41 +304,42 @@ void xine_config_reset (xine_t *this) { pthread_mutex_unlock(&config->config_lock); } -int xine_gui_send_vo_data (xine_t *this, +int xine_gui_send_vo_data (xine_stream_t *stream, int type, void *data) { - return this->video_driver->gui_data_exchange (this->video_driver, type, data); + return stream->video_driver->gui_data_exchange (stream->video_driver, + type, data); } -void xine_set_param (xine_t *this, int param, int value) { +void xine_set_param (xine_stream_t *stream, int param, int value) { switch (param) { case XINE_PARAM_SPEED: - xine_set_speed (this, value); + xine_set_speed (stream, value); break; case XINE_PARAM_AV_OFFSET: - this->metronom->set_option (this->metronom, METRONOM_AV_OFFSET, value); + stream->metronom->set_option (stream->metronom, METRONOM_AV_OFFSET, value); break; case XINE_PARAM_AUDIO_CHANNEL_LOGICAL: - pthread_mutex_lock (&this->xine_lock); + pthread_mutex_lock (&stream->frontend_lock); if (value < -2) value = -2; - this->audio_channel_user = value; - pthread_mutex_unlock (&this->xine_lock); + stream->audio_channel_user = value; + pthread_mutex_unlock (&stream->frontend_lock); break; case XINE_PARAM_SPU_CHANNEL: - xine_select_spu_channel (this, value); + xine_select_spu_channel (stream, value); break; case XINE_PARAM_VIDEO_CHANNEL: - pthread_mutex_lock (&this->xine_lock); + pthread_mutex_lock (&stream->frontend_lock); if (value<0) value = 0; - this->video_channel = value; - pthread_mutex_unlock (&this->xine_lock); + stream->video_channel = value; + pthread_mutex_unlock (&stream->frontend_lock); break; case XINE_PARAM_AUDIO_VOLUME: @@ -357,7 +358,7 @@ void xine_set_param (xine_t *this, int param, int value) { case XINE_PARAM_VO_ZOOM_Y: case XINE_PARAM_VO_PAN_SCAN: case XINE_PARAM_VO_TVMODE: - this->video_driver->set_property(this->video_driver, param & 0xffffff, value); + stream->video_driver->set_property(stream->video_driver, param & 0xffffff, value); break; default: @@ -365,23 +366,23 @@ void xine_set_param (xine_t *this, int param, int value) { } } -int xine_get_param (xine_t *this, int param) { +int xine_get_param (xine_stream_t *stream, int param) { switch (param) { case XINE_PARAM_SPEED: - return this->speed; + return stream->speed; case XINE_PARAM_AV_OFFSET: - return this->metronom->get_option (this->metronom, METRONOM_AV_OFFSET); + return stream->metronom->get_option (stream->metronom, METRONOM_AV_OFFSET); case XINE_PARAM_AUDIO_CHANNEL_LOGICAL: - return this->audio_channel_user; + return stream->audio_channel_user; case XINE_PARAM_SPU_CHANNEL: - return this->spu_channel_user; + return stream->spu_channel_user; case XINE_PARAM_VIDEO_CHANNEL: - return this->video_channel; + return stream->video_channel; case XINE_PARAM_AUDIO_VOLUME: return -1; /* FIXME: implement */ @@ -399,7 +400,7 @@ int xine_get_param (xine_t *this, int param) { case XINE_PARAM_VO_ZOOM_Y: case XINE_PARAM_VO_PAN_SCAN: case XINE_PARAM_VO_TVMODE: - return this->video_driver->get_property(this->video_driver, param & 0xffffff); + return stream->video_driver->get_property(stream->video_driver, param & 0xffffff); break; default: @@ -409,18 +410,18 @@ int xine_get_param (xine_t *this, int param) { return 0; } -uint32_t xine_get_stream_info (xine_t *this, int info) { +uint32_t xine_get_stream_info (xine_stream_t *stream, int info) { switch (info) { case XINE_STREAM_INFO_SEEKABLE: - if (this->cur_input_plugin) - return this->cur_input_plugin->get_capabilities (this->cur_input_plugin) & INPUT_CAP_SEEKABLE; + if (stream->input_plugin) + return stream->input_plugin->get_capabilities (stream->input_plugin) & INPUT_CAP_SEEKABLE; return 0; case XINE_STREAM_INFO_HAS_CHAPTERS: - if (this->cur_input_plugin) - return this->cur_input_plugin->get_capabilities (this->cur_input_plugin) & INPUT_CAP_CHAPTERS; + if (stream->input_plugin) + return stream->input_plugin->get_capabilities (stream->input_plugin) & INPUT_CAP_CHAPTERS; return 0; case XINE_STREAM_INFO_BITRATE: @@ -435,7 +436,7 @@ uint32_t xine_get_stream_info (xine_t *this, int info) { case XINE_STREAM_INFO_AUDIO_BITS: case XINE_STREAM_INFO_AUDIO_SAMPLERATE: case XINE_STREAM_INFO_AUDIO_BITRATE: - return this->stream_info[info]; + return stream->stream_info[info]; default: printf ("xine_interface: error, unknown stream info (%d) requested\n", @@ -444,8 +445,8 @@ uint32_t xine_get_stream_info (xine_t *this, int info) { return 0; } -const char *xine_get_meta_info (xine_t *this, int info) { +const char *xine_get_meta_info (xine_stream_t *stream, int info) { - return this->meta_info[info]; + return stream->meta_info[info]; } diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index a00095ee4..a07916a9e 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.103 2002/09/20 22:34:26 f1rmb Exp $ + * $Id: xine_internal.h,v 1.104 2002/10/14 15:47:45 guenter Exp $ * */ @@ -66,245 +66,183 @@ extern "C" { #include "scratch.h" #include "xineintl.h" #include "plugin_catalog.h" +#include "video_decoder.h" +#include "audio_decoder.h" -#define VIDEO_DECODER_IFACE_VERSION 10 -#define AUDIO_DECODER_IFACE_VERSION 9 #define XINE_MAX_EVENT_LISTENERS 50 #define XINE_MAX_EVENT_TYPES 100 +#define XINE_CODEC_AUDIO 0 +#define XINE_CODEC_VIDEO 1 + /* used by plugin loader */ #define XINE_VERSION_CODE XINE_MAJOR_VERSION*10000+XINE_MINOR_VERSION*100+XINE_SUB_VERSION /* - * generic xine video decoder plugin interface - * - * for a dynamic plugin make sure you provide this function call: - * video_decoder_t *init_video_decoder_plugin (int iface_version, - * xine_t *xine); + * log constants */ -typedef struct video_decoder_s video_decoder_t; - -struct video_decoder_s { - - void (*init) (video_decoder_t *this, vo_instance_t *video_out); - - void (*decode_data) (video_decoder_t *this, buf_element_t *buf); - - void (*reset) (video_decoder_t *this); - - void (*flush) (video_decoder_t *this); - - void (*close) (video_decoder_t *this); - - char* (*get_identifier) (void); - - void (*dispose) (video_decoder_t *this); +#define XINE_LOG_MSG 0 /* warnings, errors, ... */ +#define XINE_LOG_PLUGIN 1 +#define XINE_LOG_NUM 2 /* # of log buffers defined */ -}; +#define XINE_STREAM_INFO_MAX 99 /* - * generic xine audio decoder plugin interface - * - * for a dynamic plugin make sure you provide this function call: - * audio_decoder_t *init_audio_decoder_plugin (int iface_version, - * xine_t *xine); + * the "big" xine struct, holding everything together */ -typedef struct audio_decoder_s audio_decoder_t; - -struct audio_decoder_s { - - void (*init) (audio_decoder_t *this, ao_instance_t *audio_out); - - void (*decode_data) (audio_decoder_t *this, buf_element_t *buf); - - void (*reset) (audio_decoder_t *this); +struct xine_s { - void (*close) (audio_decoder_t *this); + config_values_t *config; - char* (*get_identifier) (void); + plugin_catalog_t *plugin_catalog; + + int demux_strategy; - void (*dispose) (audio_decoder_t *this); + /* log output that may be presented to the user */ + scratch_buffer_t *log_buffers[XINE_LOG_NUM]; + xine_list_t *streams; + pthread_mutex_t streams_lock; }; /* - * log constants + * xine event queue */ -#define XINE_LOG_MSG 0 /* warnings, errors, ... */ -#define XINE_LOG_PLUGIN 1 -#define XINE_LOG_NUM 2 /* # of log buffers defined */ - -#define XINE_STREAM_INFO_MAX 99 +struct xine_event_queue_s { + xine_list_t *events; + pthread_mutex_t lock; + pthread_cond_t new_event; + xine_stream_t *stream; + pthread_t *listener_thread; + xine_event_listener_cb_t callback; + void *user_data; +}; /* - * the big xine struct, holding everything together + * xine_stream - per-stream parts of the xine engine */ -struct xine_s { - - /* private : */ - - metronom_t *metronom; - - config_values_t *config; - - /* MRL of displayed logo */ - char *logo_mrl; - /* Logo manipulation mutex */ - pthread_mutex_t logo_lock; - - plugin_catalog_t *plugin_catalog; +struct xine_stream_s { - input_plugin_t *cur_input_plugin; - /* kept to do proper ejecting (otherwise we eject the logo) */ - input_plugin_t *last_input_plugin; - - demux_plugin_t *cur_demuxer_plugin; - int demux_strategy; + xine_t *xine; int status; - int speed; - off_t cur_input_pos; - off_t cur_input_length; - int cur_input_time; - char cur_mrl[1024]; - spu_functions_t *spu_out; - pthread_t spu_thread; - spu_decoder_t *cur_spu_decoder_plugin; - int spu_finished; + input_plugin_t *input_plugin; + input_class_t *input_class; /* eject */ + int content_detection_method; + demux_plugin_t *demux_plugin; - /* *_user: -2 => off - -1 => auto (use *_auto value) - >=0 => respect the user's choice - */ - - int audio_channel_user; - int audio_channel_auto; - int spu_channel_user; - int spu_channel_auto; - int spu_channel_letterbox; - int spu_channel_pan_scan; - int spu_channel; + metronom_t *metronom; + int speed; + off_t input_pos; + off_t input_length; + int input_time; xine_vo_driver_t *video_driver; vo_instance_t *video_out; fifo_buffer_t *video_fifo; pthread_t video_thread; - video_decoder_t *cur_video_decoder_plugin; - int video_finished; + video_decoder_t *video_decoder_plugin; int video_in_discontinuity; int video_channel; - osd_renderer_t *osd_renderer; - osd_object_t *osd; - int osd_display; - ao_instance_t *audio_out; fifo_buffer_t *audio_fifo; lrb_t *audio_temp; pthread_t audio_thread; - audio_decoder_t *cur_audio_decoder_plugin; + audio_decoder_t *audio_decoder_plugin; uint32_t audio_track_map[50]; int audio_track_map_entries; - int audio_finished; uint32_t audio_type; + /* *_user: -2 => off + -1 => auto (use *_auto value) + >=0 => respect the user's choice + */ + int audio_channel_user; + int audio_channel_auto; - /* Lock for xine player functions */ - pthread_mutex_t xine_lock; - - /* Lock for xxx_finished variables */ - pthread_mutex_t finished_lock; - - /* Array of event handlers. */ - xine_event_listener_cb_t event_listeners[XINE_MAX_EVENT_LISTENERS]; - void *event_listener_user_data[XINE_MAX_EVENT_LISTENERS]; - uint16_t num_event_listeners; - uint8_t event_pending[XINE_MAX_EVENT_TYPES]; - pthread_cond_t event_handled; - pthread_mutex_t event_lock; - - /* scratch string buffers */ - char str[1024]; - char spu_lang[80]; - char audio_lang[80]; - - /* log output that may be presented to the user */ - scratch_buffer_t *log_buffers[XINE_LOG_NUM]; + spu_functions_t *spu_out; + pthread_t spu_thread; + spu_decoder_t *spu_decoder_plugin; + int spu_channel_user; + int spu_channel_auto; + int spu_channel_letterbox; + int spu_channel_pan_scan; + int spu_channel; - int err; + /* lock for public xine player functions */ + pthread_mutex_t frontend_lock; - pthread_t finished_thread; - int finished_thread_running; - - xine_report_codec_cb_t report_codec_cb; - void *report_codec_user_data; - - int playing_logo; - int curtime_needed_for_osd; pthread_mutex_t osd_lock; + osd_renderer_t *osd_renderer; /* stream meta information */ int stream_info[XINE_STREAM_INFO_MAX]; char *meta_info [XINE_STREAM_INFO_MAX]; - int header_sent_counter; /* wait for headers sent */ -}; + /* wait for headers sent / stream decoding finished */ + pthread_mutex_t counter_lock; + pthread_cond_t counter_changed; + int header_count_audio; + int header_count_video; + int finished_count_audio; + int finished_count_video; -/* - * private function prototypes: - */ + /* event mechanism */ + xine_list_t *event_queues; + pthread_mutex_t event_queues_lock; -int xine_open_internal (xine_t *this, const char *mrl); -int xine_play_internal (xine_t *this, - int start_pos, int start_time); -void xine_stop_internal (xine_t *this); -void xine_notify_stream_finished (xine_t *this); -void xine_report_codec (xine_t *this, int codec_type, - uint32_t fourcc, uint32_t buf_type, int handled ); -void xine_internal_osd (xine_t *this, char *str, int duration); + int err; +}; -void video_decoder_init (xine_t *this); -void video_decoder_shutdown (xine_t *this); -void audio_decoder_init (xine_t *this); -void audio_decoder_shutdown (xine_t *this); -/* - * demuxer helper functions from demux.c +/* + * private function prototypes: */ -void xine_demux_flush_engine (xine_t *this); +void xine_handle_stream_end (xine_stream_t *stream, int non_user); -void xine_demux_control_newpts (xine_t *this, int64_t pts, uint32_t flags ); +/* find and instantiate input and demux plugins */ -void xine_demux_control_headers_done (xine_t *this ); +input_plugin_t *find_input_plugin (xine_stream_t *stream, const char *mrl); +demux_plugin_t *find_demux_plugin (xine_stream_t *stream, input_plugin_t *input); -void xine_demux_control_start (xine_t *this ); +/* create decoder fifos and threads */ -void xine_demux_control_end (xine_t *this, uint32_t flags ); +void video_decoder_init (xine_stream_t *stream); +void video_decoder_shutdown (xine_stream_t *stream); -/* - * plugin management - */ +void audio_decoder_init (xine_stream_t *stream); +void audio_decoder_shutdown (xine_stream_t *stream); -/* - * on-demand loading of audio/video/spu decoder plugins - */ +/* demuxer helper functions from demux.c */ -video_decoder_t *get_video_decoder (xine_t *this, uint8_t stream_type); -audio_decoder_t *get_audio_decoder (xine_t *this, uint8_t stream_type); -spu_decoder_t *get_spu_decoder (xine_t *this, uint8_t stream_type); +void xine_demux_flush_engine (xine_stream_t *stream); +void xine_demux_control_newpts (xine_stream_t *stream, int64_t pts, uint32_t flags); +void xine_demux_control_headers_done (xine_stream_t *stream); +void xine_demux_control_start (xine_stream_t *stream); +void xine_demux_control_end (xine_stream_t *stream, uint32_t flags); /* * plugin_loader functions * */ +/* on-demand loading of audio/video/spu decoder plugins */ + +video_decoder_t *get_video_decoder (xine_stream_t *stream, uint8_t stream_type); +void free_video_decoder (xine_stream_t *stream, video_decoder_t *decoder); +audio_decoder_t *get_audio_decoder (xine_stream_t *stream, uint8_t stream_type); +void free_audio_decoder (xine_stream_t *stream, audio_decoder_t *decoder); +spu_decoder_t *get_spu_decoder (xine_stream_t *stream, uint8_t stream_type); +void free_spu_decoder (xine_stream_t *stream, spu_decoder_t *decoder); + /* * load_video_output_plugin * @@ -327,13 +265,13 @@ xine_vo_driver_t *xine_load_video_output_plugin(xine_t *this, xine_ao_driver_t *xine_load_audio_output_plugin (xine_t *self, char *id); -void xine_set_speed (xine_t *this, int speed) ; +void xine_set_speed (xine_stream_t *stream, int speed) ; -void xine_select_spu_channel (xine_t *this, int channel) ; +void xine_select_spu_channel (xine_stream_t *stream, int channel) ; -int xine_get_audio_channel (xine_t *this) ; +int xine_get_audio_channel (xine_stream_t *stream) ; -int xine_get_spu_channel (xine_t *this) ; +int xine_get_spu_channel (xine_stream_t *stream) ; #ifdef __cplusplus } diff --git a/src/xine-engine/xine_plugin.h b/src/xine-engine/xine_plugin.h index 99297cc7e..16845dbf0 100644 --- a/src/xine-engine/xine_plugin.h +++ b/src/xine-engine/xine_plugin.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_plugin.h,v 1.3 2002/09/05 16:24:14 guenter Exp $ + * $Id: xine_plugin.h,v 1.4 2002/10/14 15:47:46 guenter Exp $ * * generic plugin definitions * @@ -26,7 +26,7 @@ #ifndef XINE_PLUGIN_H #define XINE_PLUGIN_H -#define PLUGIN_NONE 0 +#define PLUGIN_NONE 0 #define PLUGIN_INPUT 1 #define PLUGIN_DEMUX 2 #define PLUGIN_AUDIO_DECODER 3 @@ -42,7 +42,8 @@ typedef struct { char *id; /* a name that identifies this plugin */ uint32_t version; /* version number, increased every release */ void *special_info; /* plugin-type specific, see structs below */ - void *(*init)(xine_t *, void *); /* used to get/initialize an instance*/ + void *(*init)(xine_t *, void *); /* init the plugin class */ + void *(*open)(void *, xine_stream_t *, const void *); /* create an instance*/ } plugin_info_t; -- cgit v1.2.3