@@ -55,6 +55,8 @@ public class ProcessingService : ReactiveObject
5555 public const int QueuedTabIndex = 0 ;
5656 public const int CompletedTabIndex = 1 ;
5757
58+ private static HashSet < string > subtitleTokens = new HashSet < string > { "cc" , "forced" , "foreign" , "sdh" , "hi" , "default" } ;
59+
5860 private const double StopWarningThresholdMinutes = 5 ;
5961
6062 private IAppLogger logger = StaticResolver . Resolve < IAppLogger > ( ) ;
@@ -3647,8 +3649,9 @@ public static IList<ChosenSourceSubtitle> ChooseSubtitles(SourceTitle title, Pic
36473649 }
36483650
36493651 /// <summary>
3650- /// Finds the file subtitles for the given path and picker. This will find files that match sourcePath.ext or sourcePath.lng.ext,
3651- /// where lng is a 3-letter ISO language code and ext is a valid subtitle extension.
3652+ /// Finds the file subtitles for the given path and picker. This will find files that match sourcePath.ext or sourcePath[.token].ext.
3653+ /// token is a 3-letter ISO language code or tag like forced, cc, or sdh.
3654+ /// ext is a valid subtitle extension.
36523655 /// </summary>
36533656 /// <param name="sourcePath">The source path to check.</param>
36543657 /// <param name="picker">The picker settings to use.</param>
@@ -3672,11 +3675,8 @@ public static List<FileSubtitle> FindSubtitleFiles(
36723675 {
36733676 string extensionList = string . Join ( "|" , FileUtilities . SubtitleExtensions . Select ( ext => ext . Substring ( 1 ) ) ) ;
36743677
3675- string languageRegexPattern = "^.+\\ .(?<language>[a-zA-Z]{3})\\ .(?:" + extensionList + ")$" ;
3676- Regex langaugeRegex = new ( languageRegexPattern , RegexOptions . IgnoreCase ) ;
3677-
3678- string noLanguageRegexPattern = "^.+\\ .(?:" + extensionList + ")$" ;
3679- Regex noLanguageRegex = new ( noLanguageRegexPattern , RegexOptions . IgnoreCase ) ;
3678+ string regexPattern = "^.+\\ .(?:" + extensionList + ")$" ;
3679+ Regex regex = new ( regexPattern , RegexOptions . IgnoreCase ) ;
36803680
36813681 string directory = Path . GetDirectoryName ( sourcePath ) ;
36823682 string fileName = Path . GetFileNameWithoutExtension ( sourcePath ) ;
@@ -3695,52 +3695,52 @@ public static List<FileSubtitle> FindSubtitleFiles(
36953695 continue ;
36963696 }
36973697
3698- Match languageMatch = langaugeRegex . Match ( candidateFileName ) ;
3698+ // Subtitle file naming convention is to add extra tokens after the main file name
3699+ // For example:
3700+ // Movie.mp4
3701+ // Movie.srt
3702+ // Movie.eng.srt
3703+ // Movie.forced.eng.srt
3704+ // Movie.deu.srt
3705+ //
3706+ // We examine all the tokens to see if a language or subtitle name should be applied
3707+ string restOfFile = file . Substring ( fileName . Length + 1 ) ;
3708+ string [ ] tokens = restOfFile . Split ( "." ) ;
36993709
3700- bool matchedLanguage = false ;
3701- if ( languageMatch . Success )
3710+ Match nonLanguageMatch = regex . Match ( candidateFileName ) ;
3711+ if ( nonLanguageMatch . Success )
37023712 {
3703- string languageCode = languageMatch . Groups [ "language" ] . Value ;
3704- if ( HandBrakeLanguagesHelper . AllLanguagesDict . ContainsKey ( languageCode ) )
3705- {
3706- FileSubtitle fileSubtitle = StaticResolver . Resolve < SubtitlesService > ( ) . LoadSubtitleFile ( file , languageCode , openDialogOnMissingCharCode ) ;
3707- fileSubtitle . Default = ! hasDefault && picker . ExternalSubtitleImportDefault ;
3708- fileSubtitle . BurnedIn = ! hasBurnedIn && picker . ExternalSubtitleImportBurnIn ;
3709- result . Add ( fileSubtitle ) ;
3713+ string languageCode = picker . ExternalSubtitleImportLanguage ;
3714+ string name = null ;
37103715
3711- if ( picker . ExternalSubtitleImportDefault )
3716+ // Skip last token, it's the extension
3717+ for ( int i = 0 ; i < tokens . Length - 1 ; i ++ )
3718+ {
3719+ string token = tokens [ i ] ;
3720+ if ( token . Length == 3 && HandBrakeLanguagesHelper . AllLanguagesDict . ContainsKey ( token ) )
37123721 {
3713- hasDefault = true ;
3722+ languageCode = token ;
37143723 }
3715-
3716- if ( picker . ExternalSubtitleImportBurnIn )
3724+ else if ( subtitleTokens . Contains ( token ) )
37173725 {
3718- hasBurnedIn = true ;
3726+ name = token ;
37193727 }
3720-
3721- matchedLanguage = true ;
37223728 }
3723- }
37243729
3725- if ( ! matchedLanguage )
3726- {
3727- Match nonLanguageMatch = noLanguageRegex . Match ( candidateFileName ) ;
3728- if ( nonLanguageMatch . Success )
3729- {
3730- FileSubtitle fileSubtitle = StaticResolver . Resolve < SubtitlesService > ( ) . LoadSubtitleFile ( file , picker . ExternalSubtitleImportLanguage , openDialogOnMissingCharCode ) ;
3731- fileSubtitle . Default = ! hasDefault && picker . ExternalSubtitleImportDefault ;
3732- fileSubtitle . BurnedIn = ! hasBurnedIn && picker . ExternalSubtitleImportBurnIn ;
3733- result . Add ( fileSubtitle ) ;
3730+ FileSubtitle fileSubtitle = StaticResolver . Resolve < SubtitlesService > ( ) . LoadSubtitleFile ( file , languageCode , openDialogOnMissingCharCode ) ;
3731+ fileSubtitle . Default = ! hasDefault && picker . ExternalSubtitleImportDefault ;
3732+ fileSubtitle . BurnedIn = ! hasBurnedIn && picker . ExternalSubtitleImportBurnIn ;
3733+ fileSubtitle . Name = name ;
3734+ result . Add ( fileSubtitle ) ;
37343735
3735- if ( picker . ExternalSubtitleImportDefault )
3736- {
3737- hasDefault = true ;
3738- }
3736+ if ( picker . ExternalSubtitleImportDefault )
3737+ {
3738+ hasDefault = true ;
3739+ }
37393740
3740- if ( picker . ExternalSubtitleImportBurnIn )
3741- {
3742- hasBurnedIn = true ;
3743- }
3741+ if ( picker . ExternalSubtitleImportBurnIn )
3742+ {
3743+ hasBurnedIn = true ;
37443744 }
37453745 }
37463746 }
0 commit comments