[vlc-devel] [PATCH] input: subtitles: Added support for detecting external subtitle files on network shares

Benjamin Adolphi b.adolphi at gmail.com
Wed Mar 9 21:32:08 CET 2016


---
 src/input/input.c     | 95 +++++++++++++++++++++++++++------------------------
 src/input/subtitles.c | 52 ++++++++++++++--------------
 2 files changed, 78 insertions(+), 69 deletions(-)

diff --git a/src/input/input.c b/src/input/input.c
index 4a0caf4..a0ce7b9 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -102,8 +102,7 @@ enum {
     SUB_CANFAIL = 0x02,
 };
 
-static void input_SubtitleAdd( input_thread_t *, const char *, unsigned );
-static void input_SubtitleFileAdd( input_thread_t *, const char *, unsigned, bool );
+static void input_SubtitleAdd( input_thread_t *, const char *, unsigned, bool );
 static void input_ChangeState( input_thread_t *p_input, int i_state ); /* TODO fix name */
 
 #undef input_Create
@@ -953,7 +952,7 @@ static void LoadSubtitles( input_thread_t *p_input )
     if( psz_subtitle != NULL )
     {
         msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle );
-        input_SubtitleFileAdd( p_input, psz_subtitle, i_flags, true );
+        input_SubtitleAdd( p_input, psz_subtitle, i_flags, true );
         i_flags = SUB_NOFLAG;
     }
 
@@ -969,7 +968,7 @@ static void LoadSubtitles( input_thread_t *p_input )
             if( !psz_subtitle || strcmp( psz_subtitle, ppsz_subs[i] ) )
             {
                 i_flags |= SUB_CANFAIL;
-                input_SubtitleFileAdd( p_input, ppsz_subs[i], i_flags, false );
+                input_SubtitleAdd( p_input, ppsz_subs[i], i_flags, false );
                 i_flags = SUB_NOFLAG;
             }
 
@@ -1007,7 +1006,7 @@ static void LoadSubtitles( input_thread_t *p_input )
         {
             var_SetString( p_input, "sub-description", a->psz_description ? a->psz_description : "");
 
-            input_SubtitleAdd( p_input, psz_mrl, i_flags );
+            input_SubtitleAdd( p_input, psz_mrl, i_flags, false );
 
             i_flags = SUB_NOFLAG;
             free( psz_mrl );
@@ -1868,7 +1867,7 @@ static bool Control( input_thread_t *p_input,
 
         case INPUT_CONTROL_ADD_SUBTITLE:
             if( val.psz_string )
-                input_SubtitleFileAdd( p_input, val.psz_string, SUB_FORCED, true );
+                input_SubtitleAdd( p_input, val.psz_string, SUB_FORCED, true );
             break;
 
         case INPUT_CONTROL_ADD_SLAVE:
@@ -2772,18 +2771,62 @@ static void MRLSections( const char *p,
     *pi_chapter_end = chapter_end;
 }
 
+static bool input_DoesFileExist( input_thread_t *p_input, const char *psz_url )
+{
+    stream_t *stream = stream_UrlNew( p_input, psz_url );
+
+    if( stream == NULL )
+        return false;
+
+    stream_Delete( stream );
+    return true;
+}
+
 /*****************************************************************************
  * input_AddSubtitles: add a subtitle file and enable it
  *****************************************************************************/
 static void input_SubtitleAdd( input_thread_t *p_input,
-                               const char *url, unsigned i_flags )
+                               const char *psz_path, unsigned i_flags,
+                               bool b_check_idx)
 {
+    /* create a url in case we were given a local path */
+    char * psz_subtitle;
+    if( strstr( psz_path, "://" ) == NULL )
+        psz_subtitle = vlc_path2uri( psz_path, NULL );
+    else
+        psz_subtitle = strdup( psz_path );
+
+    /* if we are provided a subtitle.sub file,
+     * see if we don't have a subtitle.idx and use it instead */
+    char *psz_extension = b_check_idx ? strrchr( psz_subtitle, '.') : NULL;
+    if( psz_extension && strcmp( psz_extension, ".sub" ) == 0 )
+    {
+        char *psz_idxpath = strdup( psz_subtitle );
+        if( psz_idxpath )
+        {
+            psz_extension = psz_extension - psz_subtitle + psz_idxpath;
+            strcpy( psz_extension, ".idx" );
+
+            if( input_DoesFileExist( p_input, psz_idxpath ) )
+            {
+                msg_Dbg( p_input, "using %s as subtitle file instead of %s",
+                         psz_idxpath, psz_subtitle );
+                free( psz_subtitle );
+                psz_subtitle = psz_idxpath;
+            }
+            else
+                free( psz_idxpath );
+        }
+    }
+
     vlc_value_t count;
 
     var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL );
 
-    input_source_t *sub = InputSourceNew( p_input, url, "subtitle",
+    input_source_t *sub = InputSourceNew( p_input, psz_subtitle, "subtitle",
                                           (i_flags & SUB_CANFAIL) );
+
+    free( psz_subtitle );
     if( sub == NULL )
         return;
 
@@ -2811,42 +2854,6 @@ static void input_SubtitleAdd( input_thread_t *p_input,
     var_FreeList( &list, NULL );
 }
 
-static void input_SubtitleFileAdd( input_thread_t *p_input,
-                                   const char *psz_subtitle, unsigned i_flags,
-                                   bool b_check_idx )
-{
-    /* if we are provided a subtitle.sub file,
-     * see if we don't have a subtitle.idx and use it instead */
-    char *psz_idxpath = NULL;
-    char *psz_extension = b_check_idx ? strrchr( psz_subtitle, '.') : NULL;
-    if( psz_extension && strcmp( psz_extension, ".sub" ) == 0 )
-    {
-        psz_idxpath = strdup( psz_subtitle );
-        if( psz_idxpath )
-        {
-            struct stat st;
-
-            psz_extension = psz_extension - psz_subtitle + psz_idxpath;
-            strcpy( psz_extension, ".idx" );
-
-            if( !vlc_stat( psz_idxpath, &st ) && S_ISREG( st.st_mode ) )
-            {
-                msg_Dbg( p_input, "using %s as subtitle file instead of %s",
-                         psz_idxpath, psz_subtitle );
-                psz_subtitle = psz_idxpath;
-            }
-        }
-    }
-
-    char *url = vlc_path2uri( psz_subtitle, NULL );
-    free( psz_idxpath );
-    if( url == NULL )
-        return;
-
-    input_SubtitleAdd( p_input, url, i_flags );
-    free( url );
-}
-
 /*****************************************************************************
  * Statistics
  *****************************************************************************/
diff --git a/src/input/subtitles.c b/src/input/subtitles.c
index 23bf4f9..c8d0a00 100644
--- a/src/input/subtitles.c
+++ b/src/input/subtitles.c
@@ -238,12 +238,12 @@ static char **paths_to_list( const char *psz_dir, char *psz_path )
  * \ingroup Demux
  * \param p_this the calling \ref input_thread_t
  * \param psz_path a list of subdirectories (separated by a ',') to look in.
- * \param psz_name the complete filename to base the search on.
+ * \param psz_url the complete url to base the search on.
  * \return a NULL terminated array of filenames with detected possible subtitles.
  * The array contains max MAX_SUBTITLE_FILES items and you need to free it after use.
  */
 char **subtitles_Detect( input_thread_t *p_this, char *psz_path,
-                         const char *psz_name_org )
+                         const char *psz_url )
 {
     int i_fuzzy = var_GetInteger( p_this, "sub-autodetect-fuzzy" );
     if ( i_fuzzy == 0 )
@@ -256,30 +256,22 @@ char **subtitles_Detect( input_thread_t *p_this, char *psz_path,
     vlc_subfn_t *result = NULL; /* unsorted results */
     char **result2; /* sorted results */
 
-    if( !psz_name_org )
-        return NULL;
-
-    char *psz_fname = vlc_uri2path( psz_name_org );
-    if( !psz_fname )
+    if( !psz_url )
         return NULL;
 
     /* extract filename & dirname from psz_fname */
-    char *f_dir = strdup( psz_fname );
+    char *f_dir = strdup( psz_url );
     if( f_dir == NULL )
-    {
-        free( psz_fname );
         return NULL;
-    }
 
-    const char *f_fname = strrchr( psz_fname, DIR_SEP_CHAR );
+    const char *f_fname = strrchr( psz_url, '/' );
     if( !f_fname )
     {
         free( f_dir );
-        free( psz_fname );
         return NULL;
     }
     f_fname++; /* Skip the '/' */
-    f_dir[f_fname - psz_fname] = 0; /* keep dir separator in f_dir */
+    f_dir[f_fname - psz_url] = 0; /* keep dir separator in f_dir */
 
     i_fname_len = strlen( f_fname );
 
@@ -290,7 +282,6 @@ char **subtitles_Detect( input_thread_t *p_this, char *psz_path,
         free( f_dir );
         free( f_fname_noext );
         free( f_fname_trim );
-        free( psz_fname );
         return NULL;
     }
 
@@ -306,17 +297,28 @@ char **subtitles_Detect( input_thread_t *p_this, char *psz_path,
             continue;
 
         /* parse psz_src dir */
-        DIR *dir = vlc_opendir( psz_dir );
-        if( dir == NULL )
+        stream_t *stream = stream_UrlNew( p_this, psz_dir );
+        if(stream == NULL)
             continue;
 
         msg_Dbg( p_this, "looking for a subtitle file in %s", psz_dir );
 
-        const char *psz_name;
-        while( (psz_name = vlc_readdir( dir )) && i_sub_count < MAX_SUBTITLE_FILES )
+        input_item_t *item;
+        while( i_sub_count < MAX_SUBTITLE_FILES && (item = stream_ReadDir( stream )) != NULL )
         {
+            const char *psz_name = strrchr( item->psz_uri, '/' );
+            if( !psz_name )
+            {
+                input_item_Release(item);
+                continue;
+            }
+            psz_name++; /* Skip the '/' */
+
             if( psz_name[0] == '.' || !subtitles_Filter( psz_name ) )
+            {
+                input_item_Release( item );
                 continue;
+            }
 
             char tmp_fname_noext[strlen( psz_name ) + 1];
             char tmp_fname_trim[strlen( psz_name ) + 1];
@@ -357,15 +359,15 @@ char **subtitles_Detect( input_thread_t *p_this, char *psz_path,
             }
             if( i_prio >= i_fuzzy )
             {
-                struct stat st;
                 char *path;
 
                 if( asprintf( &path, "%s"DIR_SEP"%s", psz_dir, psz_name ) < 0 )
+                {
+                    input_item_Release( item );
                     continue;
+                }
 
-                if( strcmp( path, psz_fname )
-                 && vlc_stat( path, &st ) == 0
-                 && S_ISREG( st.st_mode ) && result )
+                if( strcmp( path, psz_url ) && item->i_type == ITEM_TYPE_FILE && result )
                 {
                     msg_Dbg( p_this,
                             "autodetected subtitle: %s with priority %d",
@@ -378,8 +380,9 @@ char **subtitles_Detect( input_thread_t *p_this, char *psz_path,
                 }
                 free( path );
             }
+            input_item_Release( item );
         }
-        closedir( dir );
+        stream_Delete( stream );
     }
     if( subdirs )
     {
@@ -390,7 +393,6 @@ char **subtitles_Detect( input_thread_t *p_this, char *psz_path,
     free( f_dir );
     free( f_fname_trim );
     free( f_fname_noext );
-    free( psz_fname );
 
     if( !result )
         return NULL;
-- 
2.7.2



More information about the vlc-devel mailing list