Commit 21c4f10c authored by Derk-Jan Hartman's avatar Derk-Jan Hartman

* modules/gui/macosx/playlist.?: implemented Save Playlist

* 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.
parent c66b7a83
......@@ -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 \
......
......@@ -311,7 +311,7 @@
SUPERCLASS = NSObject;
},
{
ACTIONS = {deleteItems = id; playItem = id; selectAll = id; };
ACTIONS = {deleteItems = id; playItem = id; savePlaylist = id; selectAll = id; };
CLASS = VLCPlaylist;
LANGUAGE = ObjC;
OUTLETS = {
......@@ -320,6 +320,7 @@
"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;
};
......
......@@ -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>
......@@ -21,10 +21,6 @@
<array>
<integer>977</integer>
</array>
<key>IBOpenObjects</key>
<array>
<integer>29</integer>
</array>
<key>IBSystem Version</key>
<string>6L60</string>
</dict>
......
......@@ -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
......@@ -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 *** */
......
......@@ -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>
......@@ -112,8 +112,8 @@
- (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:
......@@ -136,8 +136,9 @@
[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")];
......@@ -199,6 +200,7 @@
[o_sap_chkbox setEnabled: NO];
[o_sap_name setEnabled: NO];
[[o_mux_selector itemAtIndex: 0] setEnabled: YES];
if( [o_mode isEqualToString: _NS("File")] )
{
......@@ -211,12 +213,13 @@
[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")] )
{
......@@ -236,10 +239,25 @@
[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")] )
{
......@@ -252,6 +270,7 @@
[[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];
}
......@@ -266,6 +285,7 @@
[[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] )
......@@ -292,9 +312,10 @@
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")] )
......@@ -310,6 +331,11 @@
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";
......@@ -347,13 +373,15 @@
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";
......
......@@ -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;
......
......@@ -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];
......
/*****************************************************************************
* 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;
}
/*****************************************************************************
* 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