summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Roitzsch <mroi@users.sourceforge.net>2002-10-31 16:58:12 +0000
committerMichael Roitzsch <mroi@users.sourceforge.net>2002-10-31 16:58:12 +0000
commit8434b64bf82e3f111ca461a9789707558dff5dd3 (patch)
treec03b8c5961715b410e0d55d1b116c39a797c45f5
parenta3608a5b290a41d0d9614e2316586c220fa7a5e9 (diff)
downloadxine-lib-8434b64bf82e3f111ca461a9789707558dff5dd3.tar.gz
xine-lib-8434b64bf82e3f111ca461a9789707558dff5dd3.tar.bz2
new syntax for MRLs
basic changes: - MRLs are a subset of URIs - important new delimiter is # - everything before the # will be passed to the input plugin - after the # you can add several ;-separated stream parameters: novideo - video will be ignored noaudio - audio will be ignored nospu - spus will be ignored demux:... - specify the demuxer to use (e.g. demux:mpeg_block) entry:value - assign any config entry a new value CVS patchset: 3112 CVS date: 2002/10/31 16:58:12
-rw-r--r--doc/MRLs71
-rw-r--r--include/xine.h.in6
-rw-r--r--src/xine-engine/audio_decoder.c5
-rw-r--r--src/xine-engine/configfile.c16
-rw-r--r--src/xine-engine/load_plugins.c25
-rw-r--r--src/xine-engine/video_decoder.c7
-rw-r--r--src/xine-engine/xine.c184
-rw-r--r--src/xine-engine/xine_internal.h3
8 files changed, 278 insertions, 39 deletions
diff --git a/doc/MRLs b/doc/MRLs
new file mode 100644
index 000000000..45b43ecfd
--- /dev/null
+++ b/doc/MRLs
@@ -0,0 +1,71 @@
+proposition of generic syntax of MRLs
+=====================================
+
+This document defines a draft for a syntactic specification of MRLs as
+used by xine-lib. The language of MRLs is designed to be a true subset
+of the language of URIs as given in RFC2396. A type 2 grammar for the
+language of MRLs is given in EBNF below.
+
+Semantically, MRLs consist of two distinct parts that are evaluated by
+different components of the xine architecture. The first part,
+derivable from the symbol <input_source> in the given grammar, is
+completely handed to the input plugins, with input plugins signaling
+if they can handle the MRL.
+The second part, derivable from <stream_setup> and delimited from the
+first by a crosshatch ('#') contains parameters that modify the
+initialization and playback behaviour of the stream to which the MRL
+is passed. The possible parameters should be self-explaining, when
+looking into the grammar.
+
+The following definition should be regarded as a guideline only.
+Of course any given input plugin only understands a subset of all
+possible MRLs. On the other hand, invalid MRLs according to this
+definition might be understood for convenience reasons.
+Some user awareness is required at this point.
+
+EBNF grammar for MRLs:
+
+<mrl> ::= <input_source>[#<stream_setup>]
+<input_source> ::= (<absolute_mrl>|<relative_mrl>)
+<absolute_mrl> ::= <input>:(<net_path>|<abs_path>)[?<query>]
+<relative_mrl> ::= (<abs_path>|<rel_path>)
+<net_path> ::= //<authority>[<abs_path>]
+<abs_path> ::= /<path_segments>
+<rel_path> ::= <rel_segment>[<abs_path>]
+<rel_segment> ::= <rel_char>{<rel_char>}
+<rel_char> ::= (<unreserved>|<escaped>|;|@|&|=|+|$|,)
+<input> ::= <alpha>{(<alpha>|<digit>|+|-|.)}
+<authority> ::= (<server>|<reg_name>)
+<server> ::= [[<userinfo>@]<host>[:<port>]]
+<userinfo> ::= {(<unreserved>|<escaped>|;|:|&|=|+|$|,)}
+<host> ::= (<hostname>|<ipv4_address>)
+<hostname> ::= {<domainlabel>.}<toplabel>[.]
+<domainlabel> ::= (<alphanum>|<alphanum>{(<alphanum>|-)}<alphanum>)
+<toplabel> ::= (<alpha>|<alpha>{(<alphanum>|-)}<alphanum>)
+<ipv4_address> ::= <digit>{<digit>}.<digit>{<digit>}.<digit>{<digit>}.<digit>{<digit>}
+<port> ::= {<digit>}
+<reg_name> ::= <reg_char>{<reg_char>}
+<reg_char> ::= (<unreserved>|<escaped>|;|:|@|&|=|+|$|,)
+<path_segments> ::= <segment>{/<segment>}
+<segment> ::= {<path_char>}{;<param>}
+<param> ::= {<path_char>}
+<path_char> ::= (<unreserved>|<escaped>|:|@|&|=|+|$|,)
+<query> ::= {<mrl_char>}
+<stream_setup> ::= <stream_option>;{<stream_option>}
+<stream_option> ::= (<configoption>|<demux>|novideo|noaudio|nospu)
+<configoption> ::= <configentry>:<configvalue>
+<configentry> ::= <unreserved>{<unreserved>}
+<configvalue> ::= <conf_char>{<conf_char>}
+<demux> ::= demux:<stream_char>{<stream_char>}
+<stream_char> ::= (<unreserved>|<escaped>|:|@|&|=|+|$|,)
+<mrl_char> ::= (<reserved>|<unreserved>|<escaped>)
+<reserved> ::= (;|/|?|:|@|&|=|+|$|,)
+<unreserved> ::= (<alphanum>|<mark>)
+<mark> ::= (-|_|.|!|~|*|'|(|))
+<escaped> ::= %<hex><hex>
+<hex> ::= (<digit>|A|B|C|D|E|F|a|b|c|d|e|f)
+<alphanum> ::= (<alpha>|<digit>)
+<alpha> ::= (<lowalpha>|<upalpha>)
+<lowalpha> ::= (a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)
+<upalpha> ::= (A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z)
+<digit> ::= (0|1|2|3|4|5|6|7|8|9)
diff --git a/include/xine.h.in b/include/xine.h.in
index f48b4d508..1a84ff8bb 100644
--- a/include/xine.h.in
+++ b/include/xine.h.in
@@ -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.h.in,v 1.30 2002/10/28 03:24:42 miguelfreitas Exp $
+ * $Id: xine.h.in,v 1.31 2002/10/31 16:58:13 mroi Exp $
*
* public xine-lib (libxine) interface and documentation
*
@@ -293,6 +293,7 @@ void xine_register_log_cb (xine_t *self, xine_log_cb_t cb,
#define XINE_ERROR_NO_INPUT_PLUGIN 1
#define XINE_ERROR_NO_DEMUX_PLUGIN 2
#define XINE_ERROR_DEMUX_FAILED 3
+#define XINE_ERROR_MALFORMED_MRL 4
/*
* xine engine parameters
@@ -369,6 +370,9 @@ void xine_register_log_cb (xine_t *self, xine_log_cb_t cb,
#define XINE_STREAM_INFO_HAS_CHAPTERS 17
#define XINE_STREAM_INFO_HAS_VIDEO 18
#define XINE_STREAM_INFO_HAS_AUDIO 19
+#define XINE_STREAM_INFO_IGNORE_VIDEO 20
+#define XINE_STREAM_INFO_IGNORE_AUDIO 21
+#define XINE_STREAM_INFO_IGNORE_SPU 22
/* xine_get_meta_info */
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index 890298251..82dc22baf 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.87 2002/10/29 16:02:43 mroi Exp $
+ * $Id: audio_decoder.c,v 1.88 2002/10/31 16:58:14 mroi Exp $
*
*
* functions that implement audio decoding
@@ -173,6 +173,9 @@ void *audio_decoder_loop (void *stream_gen) {
default:
+ if (stream->stream_info[XINE_STREAM_INFO_IGNORE_AUDIO])
+ break;
+
xine_profiler_start_count (prof_audio_decode);
if ( (buf->type & 0xFF000000) == BUF_AUDIO_BASE ) {
diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c
index c82bdde17..76c3a293d 100644
--- a/src/xine-engine/configfile.c
+++ b/src/xine-engine/configfile.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: configfile.c,v 1.39 2002/10/31 10:45:36 mroi Exp $
+ * $Id: configfile.c,v 1.40 2002/10/31 16:58:15 mroi Exp $
*
* config object (was: file) management - implementation
*
@@ -792,13 +792,11 @@ int xine_config_change_opt(config_values_t *config, const char *opt) {
printf ("configfile: change_opt '%s'\n", opt);
#endif
- if(config && opt && (!strncasecmp(opt, "opt:", 4))) {
- char *optsafe;
+ if(config && opt) {
char *key, *value;
- xine_strdupa(optsafe, opt);
- key = &optsafe[4];
- value = strrchr(optsafe, '=');
+ key = strdup(opt);
+ value = strrchr(key, ':');
if(key && strlen(key) && value && strlen(value)) {
@@ -824,14 +822,14 @@ int xine_config_change_opt(config_values_t *config, const char *opt) {
break;
case CONFIG_TYPE_UNKNOWN:
-#ifdef LOG
- printf("configfile: change_opt() try to update an CONFIG_TYPE_UNKNOWN entry\n");
-#endif
+ entry->unknown_value = strdup(value);
+ handled = 1;
break;
}
}
}
+ free(key);
}
return handled;
diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c
index 71d7a8750..510d5d04a 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.107 2002/10/27 01:52:15 guenter Exp $
+ * $Id: load_plugins.c,v 1.108 2002/10/31 16:58:16 mroi Exp $
*
*
* Load input/demux/audio_out/video_out/codec plugins
@@ -697,6 +697,29 @@ demux_plugin_t *find_demux_plugin (xine_stream_t *stream, input_plugin_t *input)
return NULL;
}
+demux_plugin_t *find_demux_plugin_by_name(xine_stream_t *stream, const char *name, input_plugin_t *input) {
+
+ plugin_catalog_t *catalog = stream->xine->plugin_catalog;
+ plugin_node_t *node;
+ demux_plugin_t *plugin;
+
+ pthread_mutex_lock(&catalog->lock);
+ node = xine_list_first_content(catalog->demux);
+
+ while (node) {
+ if (strcasecmp(node->info->id, name) == 0) {
+ if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) {
+ pthread_mutex_unlock (&catalog->lock);
+ return plugin;
+ }
+ }
+ node = xine_list_next_content(catalog->demux);
+ }
+
+ pthread_mutex_unlock(&catalog->lock);
+ return NULL;
+}
+
const char *const *xine_get_autoplay_input_plugin_ids(xine_t *this) {
plugin_catalog_t *catalog;
diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c
index 9b3eff3ba..e59ef3255 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.106 2002/10/29 16:02:49 mroi Exp $
+ * $Id: video_decoder.c,v 1.107 2002/10/31 16:58:23 mroi Exp $
*
*/
@@ -135,6 +135,8 @@ void *video_decoder_loop (void *stream_gen) {
case BUF_SPU_PACKAGE:
case BUF_SPU_NAV:
xine_profiler_start_count (prof_spu_decode);
+ if (stream->stream_info[XINE_STREAM_INFO_IGNORE_SPU])
+ break;
if (!stream->spu_decoder_plugin) {
update_spu_decoder(stream, buf->type);
}
@@ -281,6 +283,9 @@ void *video_decoder_loop (void *stream_gen) {
default:
xine_profiler_start_count (prof_video_decode);
+
+ if (stream->stream_info[XINE_STREAM_INFO_IGNORE_VIDEO])
+ break;
if ( (buf->type & 0xFF000000) == BUF_VIDEO_BASE ) {
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index a7f6142a8..a6990ff6b 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.185 2002/10/30 17:51:13 miguelfreitas Exp $
+ * $Id: xine.c,v 1.186 2002/10/31 16:58:24 mroi Exp $
*
* top-level xine functions
*
@@ -368,6 +368,7 @@ static int xine_open_internal (xine_stream_t *stream, const char *mrl) {
int header_count_audio;
int header_count_video;
+ char *stream_setup;
#ifdef LOG
printf ("xine: xine_open_internal '%s'...\n", mrl);
@@ -384,43 +385,176 @@ static int xine_open_internal (xine_stream_t *stream, const char *mrl) {
#endif
/*
- * find an input plugin
+ * look for a stream_setup in MRL
*/
+
+ if ((stream_setup = strchr(mrl, '#'))) {
+ char *input_source = (char *)malloc(stream_setup - mrl + 1);
+ memcpy(input_source, mrl, stream_setup - mrl);
+ input_source[stream_setup - mrl] = '\0';
+
+ /*
+ * find an input plugin
+ */
- 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 (!(stream->input_plugin = find_input_plugin (stream, input_source))) {
+ xine_log (stream->xine, XINE_LOG_MSG,
+ _("xine: cannot find input plugin for this MRL\n"));
- 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));
+ stream->err = XINE_ERROR_NO_INPUT_PLUGIN;
+ free(input_source);
+ 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));
+ free(input_source);
#ifdef LOG
- printf ("xine: input plugin %s found\n",
- stream->input_plugin->input_class->get_identifier(stream->input_plugin->input_class));
+ printf ("xine: input plugin %s found\n",
+ stream->input_plugin->input_class->get_identifier(stream->input_plugin->input_class));
#endif
- /*
- * find a demux plugin
- */
- if (!(stream->demux_plugin=find_demux_plugin (stream, stream->input_plugin))) {
- xine_log (stream->xine, XINE_LOG_MSG,
- _("xine: couldn't find demux for >%s<\n"), mrl);
- stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
+ while (stream_setup && *stream_setup && *(++stream_setup)) {
+ if (strncasecmp(stream_setup, "demux", 5) == 0) {
+ if (*(stream_setup += 5) == ':') {
+ /* demuxer specified by name */
+ char *tmp = ++stream_setup;
+ char *demux_name;
+ stream_setup = strchr(stream_setup, ';');
+ if (stream_setup) {
+ demux_name = (char *)malloc(stream_setup - tmp + 1);
+ memcpy(demux_name, tmp, stream_setup - tmp);
+ demux_name[stream_setup - tmp] = '\0';
+ } else {
+ demux_name = (char *)malloc(strlen(tmp));
+ memcpy(demux_name, tmp, strlen(tmp));
+ demux_name[strlen(tmp)] = '\0';
+ }
+ if (!(stream->demux_plugin = find_demux_plugin_by_name(stream, demux_name, stream->input_plugin))) {
+ xine_log(stream->xine, XINE_LOG_MSG,
+ _("xine: specified demuxer %s failed to start\n"), demux_name);
+ stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
+ stream->status = XINE_STATUS_STOP;
+ free(demux_name);
+ return 0;
+ }
+#ifdef LOG
+ printf ("xine: demux and input plugin found\n");
+#endif
- stream->status = XINE_STATUS_STOP;
- return 0;
+ stream->meta_info[XINE_META_INFO_SYSTEMLAYER]
+ = strdup (stream->demux_plugin->demux_class->get_identifier(stream->demux_plugin->demux_class));
+ free(demux_name);
+ } else {
+ printf("xine: error while parsing mrl\n");
+ stream->err = XINE_ERROR_MALFORMED_MRL;
+ stream->status = XINE_STATUS_STOP;
+ return 0;
+ }
+ continue;
+ }
+ if (strncasecmp(stream_setup, "novideo", 7) == 0) {
+ stream_setup += 7;
+ if (*stream_setup == ';' || *stream_setup == '\0') {
+ stream->stream_info[XINE_STREAM_INFO_IGNORE_VIDEO] = 1;
+ } else {
+ printf("xine: error while parsing mrl\n");
+ stream->err = XINE_ERROR_MALFORMED_MRL;
+ stream->status = XINE_STATUS_STOP;
+ return 0;
+ }
+ printf("xine: ignoring video\n");
+ continue;
+ }
+ if (strncasecmp(stream_setup, "noaudio", 7) == 0) {
+ stream_setup += 7;
+ if (*stream_setup == ';' || *stream_setup == '\0') {
+ stream->stream_info[XINE_STREAM_INFO_IGNORE_AUDIO] = 1;
+ } else {
+ printf("xine: error while parsing mrl\n");
+ stream->err = XINE_ERROR_MALFORMED_MRL;
+ stream->status = XINE_STATUS_STOP;
+ return 0;
+ }
+ printf("xine: ignoring audio\n");
+ continue;
+ }
+ if (strncasecmp(stream_setup, "nospu", 5) == 0) {
+ stream_setup += 5;
+ if (*stream_setup == ';' || *stream_setup == '\0') {
+ stream->stream_info[XINE_STREAM_INFO_IGNORE_SPU] = 1;
+ } else {
+ printf("xine: error while parsing mrl\n");
+ stream->err = XINE_ERROR_MALFORMED_MRL;
+ stream->status = XINE_STATUS_STOP;
+ return 0;
+ }
+ printf("xine: ignoring subpicture\n");
+ continue;
+ }
+ {
+ /* when we got here, the stream setup parameter must be a config entry */
+ char *tmp = stream_setup;
+ if ((stream_setup = strchr(stream_setup, ';'))) {
+ char *config_entry = (char *)malloc(stream_setup - tmp + 1);
+ memcpy(config_entry, tmp, stream_setup - tmp);
+ config_entry[stream_setup - tmp] = '\0';
+ xine_config_change_opt(stream->xine->config, config_entry);
+ free(config_entry);
+ } else {
+ xine_config_change_opt(stream->xine->config, tmp);
+ }
+ }
+ }
+
+ } else {
+
+ /* no stream setup found in MRL, continue as ususal */
+
+ /*
+ * find an input plugin
+ */
+
+ 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"));
+
+ 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));
+
+#ifdef LOG
+ printf ("xine: input plugin %s found\n",
+ stream->input_plugin->input_class->get_identifier(stream->input_plugin->input_class));
+#endif
}
+
+ if (!stream->demux_plugin) {
+
+ /*
+ * find a demux plugin
+ */
+ if (!(stream->demux_plugin=find_demux_plugin (stream, stream->input_plugin))) {
+ xine_log (stream->xine, XINE_LOG_MSG,
+ _("xine: couldn't find demux for >%s<\n"), mrl);
+ stream->err = XINE_ERROR_NO_DEMUX_PLUGIN;
+
+ stream->status = XINE_STATUS_STOP;
+ return 0;
+ }
+
#ifdef LOG
- printf ("xine: demux and input plugin found\n");
+ printf ("xine: demux and input plugin found\n");
#endif
- stream->meta_info[XINE_META_INFO_SYSTEMLAYER]
- = strdup (stream->demux_plugin->demux_class->get_identifier(stream->demux_plugin->demux_class));
+ stream->meta_info[XINE_META_INFO_SYSTEMLAYER]
+ = strdup (stream->demux_plugin->demux_class->get_identifier(stream->demux_plugin->demux_class));
+ }
/*
* send and decode headers
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 0beb014ae..ee4f83e77 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.110 2002/10/30 17:51:13 miguelfreitas Exp $
+ * $Id: xine_internal.h,v 1.111 2002/10/31 16:58:25 mroi Exp $
*
*/
@@ -228,6 +228,7 @@ void xine_handle_stream_end (xine_stream_t *stream, int non_user);
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);
+demux_plugin_t *find_demux_plugin_by_name (xine_stream_t *stream, const char *name, input_plugin_t *input);
/* create decoder fifos and threads */