]> git.sesse.net Git - vlc/commitdiff
* modules/gui/macosx/playlist.?: implemented Save Playlist
authorDerk-Jan Hartman <hartman@videolan.org>
Mon, 22 Sep 2003 03:40:06 +0000 (03:40 +0000)
committerDerk-Jan Hartman <hartman@videolan.org>
Mon, 22 Sep 2003 03:40:06 +0000 (03:40 +0000)
* modules/gui/macosx/output.m: updated part of the Stream output dialog
* modules/demux/util/sub.c: removed sub_detect() and moved the sub-file and
  sub-autodetect file options to src/input/input.c
* src/input/input.c: added the moved options and use them to add subtitle
  tracks.
* src/libvlc.h: description strings etc for sub-file and sub-autodetect-file
* src/input/subtitles.c: new subtitles_Detect() largely based on the
  code used by MPlayer. Adapted for coding style and structure differences.

The autodetect routine can now detect multiple subtitle files and assigns scores
based on their names. if they much well enough they are sorted based on their
score. It will then return this set, and they will all be added as SPU tracks
to the current stream. The (un)selecting of these tracks will need to be fixed
because they all get assigned the es id 0xFF currently.

12 files changed:
Makefile.am
extras/MacOSX/Resources/English.lproj/MainMenu.nib/classes.nib
extras/MacOSX/Resources/English.lproj/MainMenu.nib/info.nib
extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib
include/ninput.h
modules/demux/util/sub.c
modules/gui/macosx/output.m
modules/gui/macosx/playlist.h
modules/gui/macosx/playlist.m
src/input/input.c
src/input/subtitles.c [new file with mode: 0644]
src/libvlc.h

index abd5644551a9d9852877b7fe2dea6876fb642eb4..9e9e7fee7434979b326ef918e60c7aff32495063 100644 (file)
@@ -293,7 +293,8 @@ SOURCES_libvlc_common = \
        src/input/input.c \
        src/input/stream.c \
        src/input/demux.c \
-       src/input/input_ext-plugins.c \
+       src/input/subtitles.c \
+        src/input/input_ext-plugins.c \
        src/input/input_ext-dec.c \
        src/input/input_ext-intf.c \
        src/input/input_dec.c \
index b6e5d083c2430dae68cbcd13b180a66e2fe0e72a..96a17635e902882e058802594ebb8d200a53c357 100644 (file)
             SUPERCLASS = NSObject; 
         }, 
         {
-            ACTIONS = {deleteItems = id; playItem = id; selectAll = id; }; 
+            ACTIONS = {deleteItems = id; playItem = id; savePlaylist = id; selectAll = id; }; 
             CLASS = VLCPlaylist; 
             LANGUAGE = ObjC; 
             OUTLETS = {
                 "o_ctx_menu" = id; 
                 "o_mi_delete" = id; 
                 "o_mi_play" = id; 
+                "o_mi_save_playlist" = id; 
                 "o_mi_selectall" = id; 
                 "o_table_view" = id; 
             }; 
index e79f79e539ddaeb0b218384a53a8388729e7f74a..7cd67703c339b9cbae1767eaed09ea22c365de6f 100644 (file)
@@ -7,7 +7,7 @@
        <key>IBEditorPositions</key>
        <dict>
                <key>29</key>
-               <string>261 897 419 44 0 0 1280 1002 </string>
+               <string>431 891 419 44 0 0 1280 1002 </string>
                <key>303</key>
                <string>60 509 104 114 0 0 1280 1002 </string>
                <key>909</key>
        <array>
                <integer>977</integer>
        </array>
-       <key>IBOpenObjects</key>
-       <array>
-               <integer>29</integer>
-       </array>
        <key>IBSystem Version</key>
        <string>6L60</string>
 </dict>
index f8113dae160c10952424f6259268960cf30d1aa3..046b1c47ab72f9a7faa458f8ddd37f9942544b28 100644 (file)
Binary files a/extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib and b/extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib differ
index 91817a869b6d6f67e03db01e1ee903084d220d8e..5bc4c8c19fe71ac421a5d351f8d2094a07a6330f 100644 (file)
@@ -2,7 +2,7 @@
  * ninput.h
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ninput.h,v 1.11 2003/09/13 17:42:15 fenrir Exp $
+ * $Id: ninput.h,v 1.12 2003/09/22 03:40:06 hartman Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -229,5 +229,19 @@ VLC_EXPORT( int,            demux_vaControlDefault, ( input_thread_t *, int i_qu
 /**
  * @}
  */
+
+
+/**
+ * \defgroup subtitles Subtitles
+ * @{
+ */
+
+/* Subtitles */
+VLC_EXPORT( char **,        subtitles_Detect,       ( input_thread_t *, char* path, char *fname ) );
+
+/**
+ * @}
+ */
+
 #endif
 
index fcdaec59490a3e52546390c3f640ab98d1b3c37e..d00e011c8466cd3d44ed136562bfc34ca30514e2 100644 (file)
@@ -2,7 +2,7 @@
  * sub.c
  *****************************************************************************
  * Copyright (C) 1999-2003 VideoLAN
- * $Id: sub.c,v 1.25 2003/08/26 19:43:51 hartman Exp $
+ * $Id: sub.c,v 1.26 2003/09/22 03:40:06 hartman Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -64,18 +64,11 @@ static char *ppsz_sub_type[] = { "microdvd", "subrip", "ssa1", "ssa2-4", "vplaye
 #define SUB_TYPE_LONGTEXT \
     "One from \"microdvd\", \"subrip\", \"ssa1\", \"ssa2-4\", \"vplayer\" " \
     "\"sami\" (nothing for autodetection, it should always work)."
-#define SUB_AUTO_LONGTEXT \
-    "Automatically detect a subtitle file, if no subtitle filename is" \
-    "is specified"
 
 vlc_module_begin();
     set_description( _("Text subtitles demux") );
     set_capability( "subtitle demux", 12 );
     add_category_hint( "Subtitles", NULL, VLC_TRUE );
-        add_file( "sub-file", NULL, NULL,
-                  "Subtitles file name", "Subtitles file name", VLC_TRUE );
-        add_bool( "sub-autodetect-file", VLC_TRUE, NULL, "Autodetect subtitle filename",
-                  SUB_AUTO_LONGTEXT, VLC_FALSE );
         add_float( "sub-fps", 0.0, NULL,
                    "Frames per second",
                    SUB_FPS_LONGTEXT, VLC_TRUE );
@@ -101,8 +94,6 @@ static int Open ( vlc_object_t *p_this )
     p_sub->pf_close = sub_close;
 
     /* Initialize the variables */
-    var_Create( p_this, "sub-file", VLC_VAR_FILE | VLC_VAR_DOINHERIT );
-    var_Create( p_this, "sub-autodetect-file", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
     var_Create( p_this, "sub-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
     var_Create( p_this, "sub-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
     var_Create( p_this, "sub-type", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
@@ -234,104 +225,6 @@ static struct
     { NULL,         SUB_TYPE_UNKNOWN,   "Unknow",   NULL }
 };
 
-/*****************************************************************************
- * sub_detect: Use the original filename to find a subtitle file
- *****************************************************************************/
-char* sub_detect( subtitle_demux_t *p_sub, char *psz_filename)
-{
-    DIR *p_dir_handle;
-    struct dirent *p_dir_afile;
-    char * ppsz_sub_exts[] = { "sub", "srt", "smi", "ssa", NULL};
-    char *psz_result, *psz_basename, *psz_dir = NULL;
-    char *psz_file_noext, *psz_extension;
-    int i;
-    size_t i_dirlen, i_baselen = 0;
-
-    if( psz_filename && *psz_filename )
-    {
-#ifdef WIN32
-        psz_basename = strrchr( psz_filename , '\\' );
-#else
-        psz_basename = strrchr( psz_filename , '/' );
-#endif
-        if( psz_basename )
-        {
-            i_dirlen = ( 1 + psz_basename ) - psz_filename;
-            psz_dir = (char*)malloc( i_dirlen + 1 );
-
-            if( !psz_dir )
-            {
-                return "";
-            }
-            strncpy( psz_dir, psz_filename, i_dirlen );
-            psz_dir[i_dirlen] = '\0';
-            ++psz_basename;
-        }
-        else
-        {
-            psz_basename = psz_filename;
-        }
-
-        psz_extension = strrchr( psz_basename , '.' );
-
-        if( psz_extension )
-        {
-            i_baselen = ( 1 + psz_extension ) - psz_basename;
-
-            psz_file_noext = (char*)malloc( i_baselen + 1 );
-            if( !psz_file_noext )
-            {
-                return "";
-            }
-            strncpy( psz_file_noext, psz_basename, i_baselen );
-            psz_file_noext[i_baselen] = '\0';
-            ++psz_extension;
-        }
-        else return "";
-
-        p_dir_handle = opendir( psz_dir ? psz_dir : "" );
-        if( p_dir_handle ) {
-            while(( p_dir_afile = readdir( p_dir_handle ))) {
-                char* psz_afile_ext = strrchr( p_dir_afile->d_name, '.' );
-
-                if( psz_afile_ext )
-                {
-                    int i_found = 0;
-
-                    ++psz_afile_ext;
-                    for (i = 0; ppsz_sub_exts[i]; i++) {
-                        if( strcmp( ppsz_sub_exts[i], psz_afile_ext ) == 0 ) {
-                            i_found = 1;
-                            break;
-                        }
-                    }
-                    if( i_found ) /* found a file with a subtitle extension */
-                    {
-                        if( strncmp( p_dir_afile->d_name, psz_file_noext, (strlen( p_dir_afile->d_name ) - strlen( psz_afile_ext) ) ) == 0 )
-                        {
-                            /* perfect match */
-                            msg_Dbg( p_sub, "autodetected subtitlefile: %s", strdup( p_dir_afile->d_name ) );
-                            if( psz_dir )
-                            {
-                                char *psz_append;
-                                psz_result = (char*)malloc( i_dirlen + strlen( p_dir_afile->d_name ) +1 );
-                                strncpy( psz_result, psz_dir, i_dirlen );
-                                psz_append = psz_result + i_dirlen;
-                                strncpy( psz_append, p_dir_afile->d_name, strlen( p_dir_afile->d_name ) );
-                                psz_result[i_dirlen + strlen( p_dir_afile->d_name )] = '\0';
-                                return psz_result;
-                            }
-                            else return strdup( p_dir_afile->d_name );
-                        }
-                    }
-                }
-            }
-            closedir( p_dir_handle );
-        }
-    }
-    return "";
-}
-
 /*****************************************************************************
  * sub_open: Open a subtitle file and add subtitle ES
  *****************************************************************************/
@@ -354,28 +247,11 @@ static int  sub_open ( subtitle_demux_t *p_sub,
     p_sub->subtitle = NULL;
     p_sub->p_input = p_input;
 
-    if( !psz_name || !*psz_name)
+    if( !psz_name )
     {
-        var_Get( p_sub, "sub-file", &val );
-        if( !val.psz_string || !*val.psz_string )
-        {
-            var_Get( p_sub, "sub-autodetect-file", &val );
-            if( val.b_bool )
-            {
-                psz_name = strdup( sub_detect( p_sub, p_input->psz_source));
-                if( !psz_name || !*psz_name ) return VLC_EGENERIC;
-            }
-            else
-            {
-                if( val.psz_string ) free( val.psz_string );
-                return VLC_EGENERIC;
-            }
-        }
-        else
-        {
-            psz_name = strdup( val.psz_string );
-            if( val.psz_string ) free( val.psz_string );
-        }
+        msg_Err( p_sub, "no subtitle file specified", psz_name );
+        free( psz_name );
+        return VLC_EGENERIC;
     }
     
     /* *** load the file *** */
index a8440cae27e7f6cee480c50d0bd70b9efed082fa..944913c11580d24392b5be8135059cd5b1c2c9ba 100644 (file)
@@ -2,7 +2,7 @@
  * output.m: MacOS X Output Dialog
  *****************************************************************************
  * Copyright (C) 2002-2003 VideoLAN
- * $Id: output.m,v 1.14 2003/09/19 23:03:27 hartman Exp $
+ * $Id: output.m,v 1.15 2003/09/22 03:40:05 hartman Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net> 
  *          Christophe Massiot <massiot@via.ecp.fr>
 
 - (void)initStrings
 {
-    NSArray *o_muxers = [NSArray arrayWithObjects: @"MPEG TS", @"MPEG PS", @"MPEG1",
-        @"AVI", @"Ogg", @"MPEG4", @"Quicktime", nil];
+    NSArray *o_muxers = [NSArray arrayWithObjects: @"MPEG TS", @"MPEG PS", @"MPEG 1",
+        @"Ogg", @"AVI", @"ASF", @"MPEG 4", @"Quicktime", nil];
     NSArray *o_a_channels = [NSArray arrayWithObjects: @"1", @"2", @"4", @"6", nil];
     NSArray *o_a_bitrates = [NSArray arrayWithObjects: @"96", @"128", @"192", @"256", @"512", nil];
     NSArray *o_v_bitrates = [NSArray arrayWithObjects:
     [o_stream_port_lbl setStringValue: _NS("Port")];
     [o_stream_ttl_lbl setStringValue: _NS("TTL")];
     [[o_stream_type itemAtIndex: 0] setTitle: _NS("HTTP")];
-    [[o_stream_type itemAtIndex: 1] setTitle: _NS("UDP")];
-    [[o_stream_type itemAtIndex: 2] setTitle: _NS("RTP")];
+    [[o_stream_type itemAtIndex: 1] setTitle: _NS("MMSH")];
+    [[o_stream_type itemAtIndex: 2] setTitle: _NS("UDP")];
+    [[o_stream_type itemAtIndex: 3] setTitle: _NS("RTP")];
     [o_stream_type_lbl setStringValue: _NS("Type")];
     
     [o_mux_lbl setStringValue: _NS("Encapsulation Method")];
     
     [o_sap_chkbox setEnabled: NO];
     [o_sap_name setEnabled: NO];
+    [[o_mux_selector itemAtIndex: 0] setEnabled: YES];
 
     if( [o_mode isEqualToString: _NS("File")] )
     {
         [o_stream_ttl_stp setEnabled: NO];
         [o_stream_type setEnabled: NO];
         [o_mux_selector setEnabled: YES];
-        [[o_mux_selector itemAtIndex: 1] setEnabled: YES];
-        [[o_mux_selector itemAtIndex: 2] setEnabled: YES];
-        [[o_mux_selector itemAtIndex: 3] setEnabled: YES];
-        [[o_mux_selector itemAtIndex: 4] setEnabled: YES];
-        [[o_mux_selector itemAtIndex: 5] setEnabled: YES];
-        [[o_mux_selector itemAtIndex: 6] setEnabled: YES];
+        [[o_mux_selector itemAtIndex: 1] setEnabled: YES]; // MPEG PS
+        [[o_mux_selector itemAtIndex: 2] setEnabled: YES]; // MPEG 1
+        [[o_mux_selector itemAtIndex: 3] setEnabled: YES]; // Ogg
+        [[o_mux_selector itemAtIndex: 4] setEnabled: YES]; // AVI
+        [[o_mux_selector itemAtIndex: 5] setEnabled: YES]; // ASF
+        [[o_mux_selector itemAtIndex: 6] setEnabled: YES]; // MPEG 4
+        [[o_mux_selector itemAtIndex: 7] setEnabled: YES]; // QuickTime
     }
     else if( [o_mode isEqualToString: _NS("Stream")] )
     {
             [o_stream_ttl_stp setEnabled: NO];
             [[o_mux_selector itemAtIndex: 1] setEnabled: YES];
             [[o_mux_selector itemAtIndex: 2] setEnabled: YES];
-            [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
-            [[o_mux_selector itemAtIndex: 4] setEnabled: YES];
+            [[o_mux_selector itemAtIndex: 3] setEnabled: YES];
+            [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
+        }
+        else if( [o_mode isEqualToString: _NS("MMSH")] )
+        {
+            [o_stream_address setEnabled: YES];
+            [o_stream_ttl setEnabled: NO];
+            [o_stream_ttl_stp setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 0] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 1] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 2] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 3] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 5] setEnabled: YES];
+            [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
         }
         else if( [o_mode isEqualToString: _NS("UDP")] )
         {
             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
             [o_sap_chkbox setEnabled: YES];
             [o_sap_name setEnabled: YES];
         }
             [[o_mux_selector itemAtIndex: 4] setEnabled: NO];
             [[o_mux_selector itemAtIndex: 5] setEnabled: NO];
             [[o_mux_selector itemAtIndex: 6] setEnabled: NO];
+            [[o_mux_selector itemAtIndex: 7] setEnabled: NO];
         }
     }
     if( ![[o_mux_selector selectedItem] isEnabled] )
     if ( [o_mux isEqualToString: _NS("AVI")] ) o_mux_string = @"avi";
     else if ( [o_mux isEqualToString: _NS("Ogg")] ) o_mux_string = @"ogg";
     else if ( [o_mux isEqualToString: _NS("MPEG PS")] ) o_mux_string = @"ps";
-    else if ( [o_mux isEqualToString: _NS("MPEG4")] ) o_mux_string = @"mp4";
-    else if ( [o_mux isEqualToString: _NS("MPEG1")] ) o_mux_string = @"mpeg1";
+    else if ( [o_mux isEqualToString: _NS("MPEG 4")] ) o_mux_string = @"mp4";
+    else if ( [o_mux isEqualToString: _NS("MPEG 1")] ) o_mux_string = @"mpeg1";
     else if ( [o_mux isEqualToString: _NS("Quicktime")] ) o_mux_string = @"mov";
+    else if ( [o_mux isEqualToString: _NS("ASF")] ) o_mux_string = @"asf";
     else o_mux_string = @"ts";
 
     if( [o_mode isEqualToString: _NS("File")] )
         
         if ( [o_mode isEqualToString: _NS("HTTP")] )
             o_mode = @"http";
+        else if ( [o_mode isEqualToString: _NS("MMSH")] )
+        {
+            if ( [o_mux isEqualToString: _NS("ASF")] ) o_mux_string = @"asfh";
+            o_mode = @"mmsh";
+        }
         else if ( [o_mode isEqualToString: _NS("UDP")] )
         {
             o_mode = @"udp";
     NSString *o_mux_string;
     if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG PS")] )
         o_mux_string = @"vob";
-    else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG1")] )
+    else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG 1")] )
         o_mux_string = @"mpg";
     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("AVI")] )
         o_mux_string = @"avi";
+    else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("ASF")] )
+        o_mux_string = @"asf";
     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("Ogg")] )
         o_mux_string = @"ogm";
-    else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG4")] )
+    else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("MPEG 4")] )
         o_mux_string = @"mp4";
     else if ( [[o_mux_selector titleOfSelectedItem] isEqualToString: _NS("Quicktime")] )
         o_mux_string = @"mov";
index 9e99e6f22d1fa8f8adb0663b76c32bb6ad494290..7046bd4f3a1a95d8f25e731eea2cadcf8cf7bd4a 100644 (file)
@@ -2,7 +2,7 @@
  * playlist.h: MacOS X interface plugin
  *****************************************************************************
  * Copyright (C) 2002-2003 VideoLAN
- * $Id: playlist.h,v 1.10 2003/07/27 23:05:41 hartman Exp $
+ * $Id: playlist.h,v 1.11 2003/09/22 03:40:05 hartman Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Derk-Jan Hartman <thedj@users.sourceforge.net>
@@ -43,6 +43,7 @@
 
     IBOutlet id o_ctx_menu;
 
+    IBOutlet id o_mi_save_playlist;
     IBOutlet id o_mi_play;
     IBOutlet id o_mi_delete;
     IBOutlet id o_mi_selectall;
@@ -53,6 +54,7 @@
 
 - (NSMenu *)menuForEvent:(NSEvent *)o_event;
 
+- (IBAction)savePlaylist:(id)sender;
 - (IBAction)playItem:(id)sender;
 - (IBAction)deleteItems:(id)sender;
 - (IBAction)selectAll:(id)sender;
index 8189af332ae8059ae9f3a8120743a30a41431f9d..61e55f291590437d43553a27024bcd5ebdf040e8 100644 (file)
@@ -2,7 +2,7 @@
  * playlist.m: MacOS X interface plugin
  *****************************************************************************
  * Copyright (C) 2002-2003 VideoLAN
- * $Id: playlist.m,v 1.32 2003/09/20 13:46:00 hartman Exp $
+ * $Id: playlist.m,v 1.33 2003/09/22 03:40:05 hartman Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Derk-Jan Hartman <thedj@users.sourceforge.net>
@@ -187,6 +187,7 @@ int MacVersion102 = -1;
     [o_table_view registerForDraggedTypes: 
         [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
 
+    [o_mi_save_playlist setTitle: _NS("Save Playlist...")];
     [o_mi_play setTitle: _NS("Play")];
     [o_mi_delete setTitle: _NS("Delete")];
     [o_mi_selectall setTitle: _NS("Select All")];
@@ -221,6 +222,25 @@ int MacVersion102 = -1;
     return( o_ctx_menu );
 }
 
+- (IBAction)savePlaylist:(id)sender
+{
+    intf_thread_t * p_intf = [NSApp getIntf];
+    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                                       FIND_ANYWHERE );
+    
+    NSSavePanel *o_save_panel = [NSSavePanel savePanel];
+    NSString * o_name = [NSString stringWithFormat: @"%@.m3u", _NS("Untitled")];
+    [o_save_panel setTitle: _NS("Save Playlist")];
+    [o_save_panel setPrompt: _NS("Save")];
+
+    if( [o_save_panel runModalForDirectory: nil
+            file: o_name] == NSOKButton )
+    {
+        playlist_SaveFile( p_playlist, [[o_save_panel filename] fileSystemRepresentation] );
+    }
+
+}
+
 - (IBAction)playItem:(id)sender
 {
     intf_thread_t * p_intf = [NSApp getIntf];
index 7536a126abbd6cb83755f57e8d2fcc282d76a4f4..4ef56ceafba807ae06097c4d507e3f949a747f90 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
  * input.c: input thread
- * Read an MPEG2 stream, demultiplex and parse it before sending it to
+ * Read a stream, demultiplex and parse it before sending it to
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
- * $Id: input.c,v 1.242 2003/09/20 13:50:14 fenrir Exp $
+ * $Id: input.c,v 1.243 2003/09/22 03:40:06 hartman Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -110,6 +110,8 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
     var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
     var_Create( p_input, "audio-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
     var_Create( p_input, "spu-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
+    var_Create( p_input, "sub-file", VLC_VAR_FILE | VLC_VAR_DOINHERIT );
+    var_Create( p_input, "sub-autodetect-file", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
 
     var_Create( p_input, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     var_Create( p_input, "sout-audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
@@ -723,16 +725,31 @@ static int InitThread( input_thread_t * p_input )
         i_microsecondperframe = (int64_t)( (double)1000000.0 / (double)f_fps );
     }
 
-    /* Now add subtitles (for now only one) */
-    if( ( p_sub = subtitle_New( p_input, NULL, i_microsecondperframe ) ) )
+    /* Look for and add subtitle files */
+    var_Get( p_input, "sub-autodetect-file", &val );
+    if( val.b_bool )
     {
-        TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
-
-        /* see if it should be selected */
-        var_Get( p_sub, "sub-file", &val );
-        if( val.psz_string && *val.psz_string )
+        char **tmp = subtitles_Detect( p_input, "", p_input->psz_source );
+        char **tmp2 = tmp;
+        while (*tmp2)
         {
-            subtitle_Select( p_sub );
+            if( ( p_sub = subtitle_New( p_input, strdup(*tmp2++), i_microsecondperframe ) ) )
+            {
+                TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
+            }
+       }
+        free(tmp);
+    }
+    else
+    {
+        var_Get( p_input, "sub-file", &val );
+        if( val.psz_string )
+        {
+            if( ( p_sub = subtitle_New( p_input, strdup(val.psz_string), i_microsecondperframe ) ) )
+            {
+                TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
+            }
+            free( val.psz_string );
         }
     }
 
@@ -1293,4 +1310,3 @@ static int RateCallback    ( vlc_object_t *p_this, char const *psz_cmd,
     }
     return VLC_SUCCESS;
 }
-
diff --git a/src/input/subtitles.c b/src/input/subtitles.c
new file mode 100644 (file)
index 0000000..ca5f8df
--- /dev/null
@@ -0,0 +1,290 @@
+/*****************************************************************************
+ * subtitles.c
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: subtitles.c,v 1.1 2003/09/22 03:40:06 hartman Exp $
+ *
+ * Authors: Derk-Jan Hartman <hartman at videolan.org>
+ * This is adapted code from the GPL'ed MPlayer (http://mplayerhq.hu)
+ *
+ * This program 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.
+ *
+ * This program 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, USA.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include "ninput.h"
+#include <dirent.h>
+#include <ctype.h>
+
+#if defined( WIN32 )
+    #define DIRECTORY_SEPARATOR '\\'
+#else
+    #define DIRECTORY_SEPARATOR '/'
+#endif
+
+#define MAX_SUBTITLE_FILES 128
+
+
+static void strcpy_trim( char *d, char *s )
+{
+    /* skip leading whitespace */
+    while( *s && !isalnum(*s) )
+    {
+       s++;
+    }
+    for(;;)
+    {
+       /* copy word */
+       while( *s && isalnum(*s) )
+        {
+           *d = tolower(*s);
+           s++; d++;
+       }
+       if (*s == 0) break;
+       /* trim excess whitespace */
+       while( *s && !isalnum(*s) )
+        {
+           s++;
+       }
+       if( *s == 0 ) break;
+       *d++ = ' ';
+    }
+    *d = 0;
+}
+static void strcpy_strip_ext( char *d, char *s )
+{
+    char *tmp = strrchr(s, '.');
+    if( !tmp ) {
+       strcpy(d, s);
+       return;
+    }
+    else
+    {
+       strncpy(d, s, tmp - s);
+       d[tmp - s] = 0;
+    }
+    while( *d )
+    {
+       *d = tolower(*d);
+       d++;
+    }
+}
+static void strcpy_get_ext( char *d, char *s )
+{
+    char *tmp = strrchr(s, '.');
+    if( !tmp )
+    {
+       strcpy(d, "");
+       return;
+    } else strcpy( d, tmp + 1 );
+}
+
+static int whiteonly( char *s )
+{
+  while ( *s )
+  {
+       if( isalnum( *s ) ) return 0;
+       s++;
+  }
+  return 1;
+}
+
+typedef struct _subfn 
+{
+    int priority;
+    char *psz_fname;
+} subfn;
+
+static int compare_sub_priority( const void *a, const void *b )
+{
+    if (((subfn*)a)->priority > ((subfn*)b)->priority) {
+       return -1;
+    } else if (((subfn*)a)->priority < ((subfn*)b)->priority) {
+       return 1;
+    } else {
+       return strcoll(((subfn*)a)->psz_fname, ((subfn*)b)->psz_fname);
+    }
+}
+
+/*****************************************************************************
+ * subtitles_Detect: Use the original filename to find a subtitle files.
+ *****************************************************************************/
+char** subtitles_Detect( input_thread_t *p_input, char *psz_path, char *psz_fname )
+{
+    /* variables to be used for derivatives of psz_fname */
+    char *f_dir, *f_fname, *f_fname_noext, *f_fname_trim, *tmp;
+    /* variables to be used for derivatives FILE *f */
+    char *tmp_fname_noext, *tmp_fname_trim, *tmp_fname_ext, *tmpresult;
+    int len, i, j, i_sub_count, i_sub_match_fuzziness;
+    subfn *result; /* unsorted results */
+    char **result2; /* sorted results */
+    FILE *f;
+    DIR *d;
+    struct dirent *de;
+
+    char * sub_exts[] = {  "utf", "utf8", "utf-8", "sub", "srt", "smi", "txt", "ssa", NULL};
+    /* extensions from unsupported types */
+    /* rt, aqt, jss, js, ass */
+
+    i_sub_count = 0;
+    len = ( strlen( psz_fname ) > 256 ? strlen( psz_fname ) : 256 ) +
+        ( strlen( psz_path ) > 256 ? strlen( psz_path ) : 256 ) + 2;
+
+    f_dir = (char*)malloc(len);
+    f_fname = (char*)malloc(len);
+    f_fname_noext = (char*)malloc(len);
+    f_fname_trim = (char*)malloc(len);
+
+    tmp_fname_noext = (char*)malloc(len);
+    tmp_fname_trim = (char*)malloc(len);
+    tmp_fname_ext = (char*)malloc(len);
+
+    tmpresult = (char*)malloc(len);
+
+    result = (subfn*)malloc( sizeof(subfn) * MAX_SUBTITLE_FILES );
+    memset( result, 0, sizeof(subfn) * MAX_SUBTITLE_FILES );
+
+    /* extract filename & dirname from psz_fname */
+    tmp = strrchr( psz_fname, DIRECTORY_SEPARATOR );
+    if( tmp )
+    {
+        int pos;
+       strcpy( f_fname, tmp + 1 );
+       pos = tmp - psz_fname;
+       strncpy( f_dir, psz_fname, pos + 1 );
+       f_dir[pos + 1] = 0;
+    }
+    else
+    {
+       strcpy( f_fname, psz_fname );
+       strcpy( f_dir, "" );
+    }
+
+    strcpy_strip_ext( f_fname_noext, f_fname );
+    strcpy_trim( f_fname_trim, f_fname_noext );
+
+    i_sub_match_fuzziness = 3;
+    /* 0 = nothing
+     * 1 = any subtitle file
+     * 2 = any sub file containing movie name
+     * 3 = sub file matching movie name exactly
+     * 4 = sub file matching movie name with additional chars 
+     */
+    for( j = 0; j <= 1; j++)
+    {
+       d = opendir( j == 0 ? f_dir : psz_path );
+       if( d )
+        {
+            int b_found;
+           while( de = readdir( d ) )
+            {
+               /* retrieve various parts of the filename */
+               strcpy_strip_ext( tmp_fname_noext, de->d_name );
+               strcpy_get_ext( tmp_fname_ext, de->d_name );
+               strcpy_trim( tmp_fname_trim, tmp_fname_noext );
+
+               /* does it end with a subtitle extension? */
+               b_found = 0;
+               for( i = 0; sub_exts[i]; i++ )
+                {
+                   if( strcmp(sub_exts[i], tmp_fname_ext ) == 0 )
+                    {
+                       b_found = 1;
+                        msg_Dbg( p_input, "found subtitle: %s", de->d_name );
+                       break;
+                   }
+               }
+               /* we have a (likely) subtitle file */
+               if( b_found )
+                {
+                   int i_prio = 0;
+                   if( !i_prio && strcmp( tmp_fname_trim, f_fname_trim ) == 0 )
+                    {
+                       /* matches the movie name exactly */
+                       i_prio = 4;
+                   }
+                   if( !i_prio && ( tmp = strstr( tmp_fname_trim, f_fname_trim ) ) )
+                    {
+                       /* contains the movie name */
+                        tmp += strlen( f_fname_trim );
+                        if( whiteonly( tmp ) )
+                        {
+                            /* chars in front of the movie name */
+                            i_prio = 2;
+                        }
+                        else
+                        {
+                            /* chars after (and possibly in front of) the movie name */
+                            i_prio = 3;
+                        }
+                   }
+                   if( !i_prio )
+                    {
+                       /* doesn't contain the movie name */
+                       if( j == 0 ) i_prio = 1;
+                   }
+
+                   if( i_prio >= i_sub_match_fuzziness )
+                    {
+                        sprintf( tmpresult, "%s%s", j == 0 ? f_dir : psz_path, de->d_name );
+                        msg_Dbg( p_input, "autodetected subtitle: %s with priority %d", de->d_name, i_prio );
+                       if( f = fopen( tmpresult, "rt" ) )
+                        {
+                           fclose( f );
+                           result[i_sub_count].priority = i_prio;
+                           result[i_sub_count].psz_fname = strdup( tmpresult );
+                           i_sub_count++;
+                       }
+                   }
+
+               }
+               if( i_sub_count >= MAX_SUBTITLE_FILES ) break;
+           }
+           closedir( d );
+       }
+    }
+    
+    free( f_dir );
+    free( f_fname );
+    free( f_fname_noext );
+    free( f_fname_trim );
+
+    free( tmp_fname_noext );
+    free( tmp_fname_trim );
+    free( tmp_fname_ext );
+
+    free( tmpresult );
+
+    qsort( result, i_sub_count, sizeof( subfn ), compare_sub_priority );
+
+    result2 = (char**)malloc( sizeof(char*) * ( i_sub_count + 1 ) );
+    memset( result2, 0, sizeof(char*) * ( i_sub_count + 1 ) );
+
+    for( i = 0; i < i_sub_count; i++ )
+    {
+       result2[i] = result[i].psz_fname;
+    }
+    result2[i_sub_count] = NULL;
+    free( result );
+    return result2;
+}
+
index 734a589980e9282cfe67d3192c2548489adff796..2ae4c3dfca7df6b2c432bf4a6977413bcc0eee61 100644 (file)
@@ -2,7 +2,7 @@
  * libvlc.h: main libvlc header
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
- * $Id: libvlc.h,v 1.86 2003/09/20 19:37:54 hartman Exp $
+ * $Id: libvlc.h,v 1.87 2003/09/22 03:40:06 hartman Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -259,10 +259,20 @@ static char *ppsz_language[] = { "auto", "en", "en_GB", "es", "de", "fr", "it",
     "Give the stream number of the audio channel you want to use in a DVD " \
     "(from 1 to n).")
 
-#define INPUT_SUBT_TEXT N_("Choose subtitles")
+#define INPUT_SUBT_TEXT N_("Choose subtitles track")
 #define INPUT_SUBT_LONGTEXT N_( \
-    "Give the stream number of the subtitle channel you want to use in a " \
-    "DVD (from 1 to n).")
+    "Give the stream number of the subtitle channel you want to use " \
+    "(from 1 to n).")
+
+#define SUB_AUTO_TEXT N_("Autodetect subtitle files")
+#define SUB_AUTO_LONGTEXT \
+    "Automatically detect a subtitle file, if no subtitle filename is" \
+    "is specified."
+
+#define SUB_FILE_TEXT N_("Use subtitle file")
+#define SUB_FILE_LONGTEXT \
+    "Load this subtitle file. To be used when autodetect cannot detect " \
+    "your subtitlefile."
 
 #define DVD_DEV_TEXT N_("DVD device")
 #ifdef WIN32
@@ -562,6 +572,11 @@ vlc_module_begin();
                  INPUT_CHAN_TEXT, INPUT_CHAN_LONGTEXT, VLC_TRUE );
     add_integer( "spu-channel", -1, NULL,
                  INPUT_SUBT_TEXT, INPUT_SUBT_LONGTEXT, VLC_TRUE );
+    add_bool( "sub-autodetect-file", VLC_TRUE, NULL,
+                 SUB_AUTO_TEXT, SUB_AUTO_LONGTEXT, VLC_FALSE );
+    add_file( "sub-file", NULL, NULL,
+                 SUB_FILE_TEXT, SUB_FILE_LONGTEXT, VLC_TRUE );
+
 
     add_file( "dvd", DVD_DEVICE, NULL, DVD_DEV_TEXT, DVD_DEV_LONGTEXT, VLC_FALSE );
     add_file( "vcd", VCD_DEVICE, NULL, VCD_DEV_TEXT, VCD_DEV_LONGTEXT, VLC_FALSE );