2019-01-13 21:03:10 +01:00
|
|
|
using System;
|
2014-05-16 21:16:29 +02:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
2019-01-13 20:26:31 +01:00
|
|
|
using MediaBrowser.Controller.Entities;
|
|
|
|
using MediaBrowser.Controller.Providers;
|
|
|
|
using MediaBrowser.Model.Entities;
|
|
|
|
using MediaBrowser.Model.Extensions;
|
2016-10-24 04:45:23 +02:00
|
|
|
using MediaBrowser.Model.Globalization;
|
2019-01-13 20:26:31 +01:00
|
|
|
using MediaBrowser.Model.IO;
|
2014-05-16 21:16:29 +02:00
|
|
|
|
|
|
|
namespace MediaBrowser.Providers.MediaInfo
|
|
|
|
{
|
|
|
|
public class SubtitleResolver
|
|
|
|
{
|
|
|
|
private readonly ILocalizationManager _localization;
|
2014-07-26 19:30:15 +02:00
|
|
|
private readonly IFileSystem _fileSystem;
|
2014-05-16 21:16:29 +02:00
|
|
|
|
2019-02-24 15:47:59 +01:00
|
|
|
private static readonly HashSet<string> SubtitleExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
2017-11-05 22:51:23 +01:00
|
|
|
{
|
|
|
|
".srt",
|
|
|
|
".ssa",
|
|
|
|
".ass",
|
|
|
|
".sub",
|
|
|
|
".smi",
|
|
|
|
".sami",
|
|
|
|
".vtt"
|
|
|
|
};
|
|
|
|
|
2014-07-26 19:30:15 +02:00
|
|
|
public SubtitleResolver(ILocalizationManager localization, IFileSystem fileSystem)
|
2014-05-16 21:16:29 +02:00
|
|
|
{
|
|
|
|
_localization = localization;
|
2014-07-26 19:30:15 +02:00
|
|
|
_fileSystem = fileSystem;
|
2014-05-16 21:16:29 +02:00
|
|
|
}
|
|
|
|
|
2017-11-05 22:51:23 +01:00
|
|
|
public List<MediaStream> GetExternalSubtitleStreams(Video video,
|
2014-05-16 21:16:29 +02:00
|
|
|
int startIndex,
|
|
|
|
IDirectoryService directoryService,
|
|
|
|
bool clearCache)
|
|
|
|
{
|
|
|
|
var streams = new List<MediaStream>();
|
|
|
|
|
2018-09-12 19:26:21 +02:00
|
|
|
if (!video.IsFileProtocol)
|
|
|
|
{
|
|
|
|
return streams;
|
|
|
|
}
|
|
|
|
|
|
|
|
AddExternalSubtitleStreams(streams, video.ContainingFolderPath, video.Path, startIndex, directoryService, clearCache);
|
2017-11-05 22:51:23 +01:00
|
|
|
|
|
|
|
startIndex += streams.Count;
|
|
|
|
|
2019-02-24 15:47:59 +01:00
|
|
|
string folder = video.GetInternalMetadataPath();
|
|
|
|
|
|
|
|
if (!Directory.Exists(folder))
|
|
|
|
{
|
|
|
|
return streams;
|
|
|
|
}
|
|
|
|
|
2017-11-05 22:51:23 +01:00
|
|
|
try
|
|
|
|
{
|
2019-02-24 15:47:59 +01:00
|
|
|
AddExternalSubtitleStreams(streams, folder, video.Path, startIndex, directoryService, clearCache);
|
2017-11-05 22:51:23 +01:00
|
|
|
}
|
|
|
|
catch (IOException)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return streams;
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<string> GetExternalSubtitleFiles(Video video,
|
|
|
|
IDirectoryService directoryService,
|
|
|
|
bool clearCache)
|
|
|
|
{
|
|
|
|
var list = new List<string>();
|
|
|
|
|
2018-09-12 19:26:21 +02:00
|
|
|
if (!video.IsFileProtocol)
|
|
|
|
{
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
var streams = GetExternalSubtitleStreams(video, 0, directoryService, clearCache);
|
|
|
|
|
2017-11-05 22:51:23 +01:00
|
|
|
foreach (var stream in streams)
|
|
|
|
{
|
|
|
|
list.Add(stream.Path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2018-09-12 19:26:21 +02:00
|
|
|
private void AddExternalSubtitleStreams(List<MediaStream> streams, string folder,
|
2017-11-05 22:51:23 +01:00
|
|
|
string videoPath,
|
|
|
|
int startIndex,
|
|
|
|
IDirectoryService directoryService,
|
|
|
|
bool clearCache)
|
2018-09-12 19:26:21 +02:00
|
|
|
{
|
|
|
|
var files = directoryService.GetFilePaths(folder, clearCache).OrderBy(i => i).ToArray();
|
|
|
|
|
|
|
|
AddExternalSubtitleStreams(streams, videoPath, startIndex, files);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddExternalSubtitleStreams(List<MediaStream> streams,
|
|
|
|
string videoPath,
|
|
|
|
int startIndex,
|
|
|
|
string[] files)
|
2017-11-05 22:51:23 +01:00
|
|
|
{
|
2019-01-26 23:23:43 +01:00
|
|
|
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(videoPath);
|
2015-12-26 19:35:53 +01:00
|
|
|
videoFileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(videoFileNameWithoutExtension);
|
2014-05-16 21:16:29 +02:00
|
|
|
|
2017-03-29 08:26:48 +02:00
|
|
|
foreach (var fullName in files)
|
2014-05-16 21:16:29 +02:00
|
|
|
{
|
2017-11-05 22:51:23 +01:00
|
|
|
var extension = Path.GetExtension(fullName);
|
|
|
|
|
2019-02-24 15:47:59 +01:00
|
|
|
if (!SubtitleExtensions.Contains(extension))
|
2017-11-05 22:51:23 +01:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-01-26 23:23:43 +01:00
|
|
|
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
|
2015-12-26 19:35:53 +01:00
|
|
|
fileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(fileNameWithoutExtension);
|
2014-05-16 21:16:29 +02:00
|
|
|
|
2017-11-05 22:51:23 +01:00
|
|
|
if (!string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) &&
|
|
|
|
!fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-01-27 12:03:43 +01:00
|
|
|
var codec = Path.GetExtension(fullName).ToLowerInvariant().TrimStart('.');
|
2014-05-16 21:16:29 +02:00
|
|
|
|
2016-11-08 19:44:23 +01:00
|
|
|
if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
codec = "srt";
|
|
|
|
}
|
|
|
|
|
2014-05-16 21:16:29 +02:00
|
|
|
// If the subtitle file matches the video file name
|
|
|
|
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
streams.Add(new MediaStream
|
|
|
|
{
|
|
|
|
Index = startIndex++,
|
|
|
|
Type = MediaStreamType.Subtitle,
|
|
|
|
IsExternal = true,
|
|
|
|
Path = fullName,
|
|
|
|
Codec = codec
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
var isForced = fullName.IndexOf(".forced.", StringComparison.OrdinalIgnoreCase) != -1 ||
|
|
|
|
fullName.IndexOf(".foreign.", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
|
2015-12-26 19:35:53 +01:00
|
|
|
var isDefault = fullName.IndexOf(".default.", StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
|
2014-05-16 21:16:29 +02:00
|
|
|
// Support xbmc naming conventions - 300.spanish.srt
|
|
|
|
var language = fileNameWithoutExtension
|
|
|
|
.Replace(".forced", string.Empty, StringComparison.OrdinalIgnoreCase)
|
|
|
|
.Replace(".foreign", string.Empty, StringComparison.OrdinalIgnoreCase)
|
2018-09-12 19:26:21 +02:00
|
|
|
.Replace(".default", string.Empty, StringComparison.OrdinalIgnoreCase)
|
2014-05-16 21:16:29 +02:00
|
|
|
.Split('.')
|
|
|
|
.LastOrDefault();
|
|
|
|
|
|
|
|
// Try to translate to three character code
|
|
|
|
// Be flexible and check against both the full and three character versions
|
2018-09-12 19:26:21 +02:00
|
|
|
var culture = _localization.FindLanguageInfo(language);
|
2014-05-16 21:16:29 +02:00
|
|
|
|
|
|
|
if (culture != null)
|
|
|
|
{
|
|
|
|
language = culture.ThreeLetterISOLanguageName;
|
|
|
|
}
|
|
|
|
|
|
|
|
streams.Add(new MediaStream
|
|
|
|
{
|
|
|
|
Index = startIndex++,
|
|
|
|
Type = MediaStreamType.Subtitle,
|
|
|
|
IsExternal = true,
|
|
|
|
Path = fullName,
|
|
|
|
Codec = codec,
|
|
|
|
Language = language,
|
2015-12-26 19:35:53 +01:00
|
|
|
IsForced = isForced,
|
|
|
|
IsDefault = isDefault
|
2014-05-16 21:16:29 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-26 19:35:53 +01:00
|
|
|
private string NormalizeFilenameForSubtitleComparison(string filename)
|
|
|
|
{
|
|
|
|
// Try to account for sloppy file naming
|
|
|
|
filename = filename.Replace("_", string.Empty);
|
|
|
|
filename = filename.Replace(" ", string.Empty);
|
|
|
|
|
2016-07-21 04:55:35 +02:00
|
|
|
// can't normalize this due to languages such as pt-br
|
|
|
|
//filename = filename.Replace("-", string.Empty);
|
|
|
|
|
2015-12-26 19:35:53 +01:00
|
|
|
//filename = filename.Replace(".", string.Empty);
|
|
|
|
|
|
|
|
return filename;
|
|
|
|
}
|
2014-05-16 21:16:29 +02:00
|
|
|
}
|
|
|
|
}
|