]> git.sesse.net Git - vlc/blobdiff - src/input/input.c
Add LGPL license
[vlc] / src / input / input.c
index 0094846a61eb8528179ca959415a9522e776e3b2..b43df74f2120254915aef9667467f07bbd77e015 100644 (file)
@@ -85,7 +85,7 @@ static void UpdateGenericFromAccess( input_thread_t * );
 static int  UpdateTitleSeekpointFromDemux( input_thread_t * );
 static void UpdateGenericFromDemux( input_thread_t * );
 
-static void MRLSections( input_thread_t *, char *, int *, int *, int *, int *);
+static void MRLSections( const char *, int *, int *, int *, int *);
 
 static input_source_t *InputSourceNew( input_thread_t *);
 static int  InputSourceInit( input_thread_t *, input_source_t *,
@@ -292,19 +292,15 @@ input_item_t *input_GetItem( input_thread_t *p_input )
 static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj )
 {
     vlc_list_t *p_list;
-    int i;
 
     /* FIXME ObjectKillChildrens seems a very bad idea in fact */
-    i = vlc_internals( p_obj )->i_object_type;
-    if( i == VLC_OBJECT_VOUT ||i == VLC_OBJECT_AOUT ||
-        p_obj == VLC_OBJECT(p_input->p->p_sout) ||
-        i == VLC_OBJECT_DECODER )
+    if( p_obj == VLC_OBJECT(p_input->p->p_sout) )
         return;
 
     vlc_object_kill( p_obj );
 
     p_list = vlc_list_children( p_obj );
-    for( i = 0; i < p_list->i_count; i++ )
+    for( int i = 0; i < p_list->i_count; i++ )
         ObjectKillChildrens( p_input, p_list->p_values[i].p_object );
     vlc_list_release( p_list );
 }
@@ -319,13 +315,11 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
                                const char *psz_header, bool b_quick,
                                input_resource_t *p_resource )
 {
-    static const char input_name[] = "input";
     input_thread_t *p_input = NULL;                 /* thread descriptor */
     int i;
 
     /* Allocate descriptor */
-    p_input = vlc_custom_create( p_parent, sizeof( *p_input ),
-                                 VLC_OBJECT_INPUT, input_name );
+    p_input = vlc_custom_create( p_parent, sizeof( *p_input ), "input" );
     if( p_input == NULL )
         return NULL;
 
@@ -623,6 +617,7 @@ static void MainLoopDemux( input_thread_t *p_input, bool *pb_changed, bool *pb_d
     {
         msg_Dbg( p_input, "EOF reached" );
         p_input->p->input.b_eof = true;
+        es_out_Eos(p_input->p->p_es_out);
     }
     else if( i_ret < 0 )
     {
@@ -941,6 +936,7 @@ static void InitTitle( input_thread_t * p_input )
     if( p_input->b_preparsing )
         return;
 
+    vlc_mutex_lock( &p_input->p->p_item->lock );
     /* Create global title (from master) */
     p_input->p->i_title = p_master->i_title;
     p_input->p->title   = p_master->title;
@@ -957,6 +953,7 @@ static void InitTitle( input_thread_t * p_input )
     p_input->p->b_can_pace_control    = p_master->b_can_pace_control;
     p_input->p->b_can_pause        = p_master->b_can_pause;
     p_input->p->b_can_rate_control = p_master->b_can_rate_control;
+    vlc_mutex_unlock( &p_input->p->p_item->lock );
 }
 
 static void StartTitle( input_thread_t * p_input )
@@ -2359,9 +2356,7 @@ static int InputSourceInit( input_thread_t *p_input,
                             input_source_t *in, const char *psz_mrl,
                             const char *psz_forced_demux, bool b_in_can_fail )
 {
-    const char *psz_access;
-    const char *psz_demux;
-    char *psz_path;
+    const char *psz_access, *psz_demux, *psz_path, *psz_anchor;
     char *psz_var_demux = NULL;
     double f_fps;
 
@@ -2372,22 +2367,15 @@ static int InputSourceInit( input_thread_t *p_input,
         goto error;
 
     /* Split uri */
-    input_SplitMRL( &psz_access, &psz_demux, &psz_path, psz_dup );
+    input_SplitMRL( &psz_access, &psz_demux, &psz_path, &psz_anchor, psz_dup );
 
     msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
              psz_mrl, psz_access, psz_demux, psz_path );
     if( !p_input->b_preparsing )
     {
-        /* Hack to allow udp://@:port syntax */
-        if( !psz_access ||
-            (strncmp( psz_access, "udp", 3 ) &&
-             strncmp( psz_access, "rtp", 3 )) )
-        {
-            /* Find optional titles and seekpoints */
-            MRLSections( p_input, psz_path, &in->i_title_start, &in->i_title_end,
+        /* Find optional titles and seekpoints */
+        MRLSections( psz_anchor, &in->i_title_start, &in->i_title_end,
                      &in->i_seekpoint_start, &in->i_seekpoint_end );
-        }
-
         if( psz_forced_demux && *psz_forced_demux )
         {
             psz_demux = psz_forced_demux;
@@ -2744,8 +2732,7 @@ static void InputSourceMeta( input_thread_t *p_input,
         return;
 
     demux_meta_t *p_demux_meta =
-        vlc_custom_create( p_demux, sizeof( *p_demux_meta ),
-                           VLC_OBJECT_GENERIC, "demux meta" );
+        vlc_custom_create( p_demux, sizeof( *p_demux_meta ), "demux meta" );
     if( !p_demux_meta )
         return;
     p_demux_meta->p_demux = p_demux;
@@ -3036,144 +3023,115 @@ static void input_ChangeState( input_thread_t *p_input, int i_state )
  * MRLSplit: parse the access, demux and url part of the
  *           Media Resource Locator.
  *****************************************************************************/
-void input_SplitMRL( const char **ppsz_access, const char **ppsz_demux,
-                     char **ppsz_path, char *psz_dup )
+void input_SplitMRL( const char **access, const char **demux,
+                     const char **path, const char **anchor, char *buf )
 {
     char *p;
 
     /* Separate <path> from <access>[/<demux>]:// */
-    p = strstr( psz_dup, "://" );
+    p = strstr( buf, "://" );
     if( p != NULL )
     {
         *p = '\0';
         p += 3; /* skips "://" */
-        *ppsz_path = p;
+        *path = p;
 
         /* Remove HTML anchor if present (not supported).
          * The hash symbol itself should be URI-encoded. */
         p = strchr( p, '#' );
-        if( p )
-            *p = '\0';
+        if( p != NULL )
+        {
+            *(p++) = '\0';
+            *anchor = p;
+        }
+        else
+            *anchor = "";
     }
     else
     {
 #ifndef NDEBUG
         fprintf( stderr, "%s(\"%s\") probably not a valid URI!\n", __func__,
-                 psz_dup );
+                 buf );
 #endif
         /* Note: this is a valid non const pointer to "": */
-        *ppsz_path = psz_dup + strlen( psz_dup );
+        *path = buf + strlen( buf );
     }
 
     /* Separate access from demux */
-    p = strchr( psz_dup, '/' );
+    p = strchr( buf, '/' );
     if( p != NULL )
     {
         *(p++) = '\0';
         if( p[0] == '$' )
             p++;
-        *ppsz_demux = p;
+        *demux = p;
     }
     else
-        *ppsz_demux = "";
+        *demux = "";
 
     /* We really don't want module name substitution here! */
-    p = psz_dup;
+    p = buf;
     if( p[0] == '$' )
         p++;
-    *ppsz_access = p;
+    *access = p;
 }
 
-static inline bool next(char ** src)
+static const char *MRLSeekPoint( const char *str, int *title, int *chapter )
 {
     char *end;
-    errno = 0;
-    long result = strtol( *src, &end, 0 );
-    if( errno != 0 || result >= LONG_MAX || result <= LONG_MIN ||
-        end == *src )
+    unsigned long u;
+
+    /* Look for the title */
+    u = strtoul( str, &end, 0 );
+    *title = (str == end || u > (unsigned long)INT_MAX) ? -1 : (int)u;
+    str = end;
+
+    /* Look for the chapter */
+    if( *str == ':' )
     {
-        return false;
+        str++;
+        u = strtoul( str, &end, 0 );
+        *chapter = (str == end || u > (unsigned long)INT_MAX) ? -1 : (int)u;
+        str = end;
     }
-    *src = end;
-    return true;
+    else
+        *chapter = -1;
+
+    return str;
 }
 
+
 /*****************************************************************************
  * MRLSections: parse title and seekpoint info from the Media Resource Locator.
  *
  * Syntax:
- * [url][@[title-start][:chapter-start][-[title-end][:chapter-end]]]
+ * [url][@[title_start][:chapter_start][-[title_end][:chapter_end]]]
  *****************************************************************************/
-static void MRLSections( input_thread_t *p_input, char *psz_source,
+static void MRLSections( const char *p,
                          int *pi_title_start, int *pi_title_end,
                          int *pi_chapter_start, int *pi_chapter_end )
 {
-    char *psz, *psz_end, *psz_next, *psz_check;
-
-    *pi_title_start = *pi_title_end = -1;
-    *pi_chapter_start = *pi_chapter_end = -1;
+    *pi_title_start = *pi_title_end = *pi_chapter_start = *pi_chapter_end = -1;
 
-    /* Start by parsing titles and chapters */
-    if( !psz_source || !( psz = strrchr( psz_source, '@' ) ) ) return;
+    int title_start, chapter_start, title_end, chapter_end;
 
+    if( *p != '-' )
+        p = MRLSeekPoint( p, &title_start, &chapter_start );
+    else
+        title_start = chapter_start = -1;
 
-    /* Check we are really dealing with a title/chapter section */
-    psz_check = psz + 1;
-    if( !*psz_check ) return;
-    if( isdigit(*psz_check) )
-        if(!next(&psz_check)) return;
-    if( *psz_check != ':' && *psz_check != '-' && *psz_check ) return;
-    if( *psz_check == ':' && ++psz_check )
-    {
-        if( isdigit(*psz_check) )
-            if(!next(&psz_check)) return;
-    }
-    if( *psz_check != '-' && *psz_check ) return;
-    if( *psz_check == '-' && ++psz_check )
-    {
-        if( isdigit(*psz_check) )
-            if(!next(&psz_check)) return;
-    }
-    if( *psz_check != ':' && *psz_check ) return;
-    if( *psz_check == ':' && ++psz_check )
-    {
-        if( isdigit(*psz_check) )
-            if(!next(&psz_check)) return;
-    }
-    if( *psz_check ) return;
-
-    /* Separate start and end */
-    *psz++ = 0;
-    if( ( psz_end = strchr( psz, '-' ) ) ) *psz_end++ = 0;
-
-    /* Look for the start title */
-    *pi_title_start = strtol( psz, &psz_next, 0 );
-    if( !*pi_title_start && psz == psz_next ) *pi_title_start = -1;
-    *pi_title_end = *pi_title_start;
-    psz = psz_next;
-
-    /* Look for the start chapter */
-    if( *psz ) psz++;
-    *pi_chapter_start = strtol( psz, &psz_next, 0 );
-    if( !*pi_chapter_start && psz == psz_next ) *pi_chapter_start = -1;
-    *pi_chapter_end = *pi_chapter_start;
-
-    if( psz_end )
-    {
-        /* Look for the end title */
-        *pi_title_end = strtol( psz_end, &psz_next, 0 );
-        if( !*pi_title_end && psz_end == psz_next ) *pi_title_end = -1;
-        psz_end = psz_next;
+    if( *p == '-' )
+        p = MRLSeekPoint( p + 1, &title_end, &chapter_end );
+    else
+        title_end = chapter_end = -1;
 
-        /* Look for the end chapter */
-        if( *psz_end ) psz_end++;
-        *pi_chapter_end = strtol( psz_end, &psz_next, 0 );
-        if( !*pi_chapter_end && psz_end == psz_next ) *pi_chapter_end = -1;
-    }
+    if( *p ) /* syntax error */
+        return;
 
-    msg_Dbg( p_input, "source=`%s' title=%d/%d seekpoint=%d/%d",
-             psz_source, *pi_title_start, *pi_chapter_start,
-             *pi_title_end, *pi_chapter_end );
+    *pi_title_start = title_start;
+    *pi_title_end = title_end;
+    *pi_chapter_start = chapter_start;
+    *pi_chapter_end = chapter_end;
 }
 
 /*****************************************************************************