SubtitleResolver.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using MediaBrowser.Model.Extensions;
  2. using MediaBrowser.Controller.Entities;
  3. using MediaBrowser.Controller.Localization;
  4. using MediaBrowser.Controller.Providers;
  5. using MediaBrowser.Model.Entities;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10. using CommonIO;
  11. namespace MediaBrowser.Providers.MediaInfo
  12. {
  13. public class SubtitleResolver
  14. {
  15. private readonly ILocalizationManager _localization;
  16. private readonly IFileSystem _fileSystem;
  17. public SubtitleResolver(ILocalizationManager localization, IFileSystem fileSystem)
  18. {
  19. _localization = localization;
  20. _fileSystem = fileSystem;
  21. }
  22. public IEnumerable<MediaStream> GetExternalSubtitleStreams(Video video,
  23. int startIndex,
  24. IDirectoryService directoryService,
  25. bool clearCache)
  26. {
  27. var files = GetSubtitleFiles(video, directoryService, _fileSystem, clearCache);
  28. var streams = new List<MediaStream>();
  29. var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(video.Path);
  30. videoFileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(videoFileNameWithoutExtension);
  31. foreach (var file in files)
  32. {
  33. var fullName = file.FullName;
  34. var fileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(file);
  35. fileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(fileNameWithoutExtension);
  36. var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
  37. // If the subtitle file matches the video file name
  38. if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
  39. {
  40. streams.Add(new MediaStream
  41. {
  42. Index = startIndex++,
  43. Type = MediaStreamType.Subtitle,
  44. IsExternal = true,
  45. Path = fullName,
  46. Codec = codec
  47. });
  48. }
  49. else if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
  50. {
  51. var isForced = fullName.IndexOf(".forced.", StringComparison.OrdinalIgnoreCase) != -1 ||
  52. fullName.IndexOf(".foreign.", StringComparison.OrdinalIgnoreCase) != -1;
  53. var isDefault = fullName.IndexOf(".default.", StringComparison.OrdinalIgnoreCase) != -1;
  54. // Support xbmc naming conventions - 300.spanish.srt
  55. var language = fileNameWithoutExtension
  56. .Replace(".forced", string.Empty, StringComparison.OrdinalIgnoreCase)
  57. .Replace(".foreign", string.Empty, StringComparison.OrdinalIgnoreCase)
  58. .Split('.')
  59. .LastOrDefault();
  60. // Try to translate to three character code
  61. // Be flexible and check against both the full and three character versions
  62. var culture = _localization.GetCultures()
  63. .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
  64. if (culture != null)
  65. {
  66. language = culture.ThreeLetterISOLanguageName;
  67. }
  68. streams.Add(new MediaStream
  69. {
  70. Index = startIndex++,
  71. Type = MediaStreamType.Subtitle,
  72. IsExternal = true,
  73. Path = fullName,
  74. Codec = codec,
  75. Language = language,
  76. IsForced = isForced,
  77. IsDefault = isDefault
  78. });
  79. }
  80. }
  81. return streams;
  82. }
  83. private string NormalizeFilenameForSubtitleComparison(string filename)
  84. {
  85. // Try to account for sloppy file naming
  86. filename = filename.Replace("-", string.Empty);
  87. filename = filename.Replace("_", string.Empty);
  88. filename = filename.Replace(" ", string.Empty);
  89. //filename = filename.Replace(".", string.Empty);
  90. return filename;
  91. }
  92. private static IEnumerable<string> SubtitleExtensions
  93. {
  94. get
  95. {
  96. return new[] { ".srt", ".ssa", ".ass", ".sub" };
  97. }
  98. }
  99. public static IEnumerable<FileSystemMetadata> GetSubtitleFiles(Video video, IDirectoryService directoryService, IFileSystem fileSystem, bool clearCache)
  100. {
  101. var containingPath = video.ContainingFolderPath;
  102. if (string.IsNullOrEmpty(containingPath))
  103. {
  104. throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
  105. }
  106. var files = directoryService.GetFiles(containingPath, clearCache);
  107. var videoFileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(video.Path);
  108. return files.Where(i =>
  109. {
  110. if (!i.Attributes.HasFlag(FileAttributes.Directory) &&
  111. SubtitleExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
  112. {
  113. var fileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(i);
  114. if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
  115. {
  116. return true;
  117. }
  118. if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
  119. {
  120. return true;
  121. }
  122. }
  123. return false;
  124. });
  125. }
  126. }
  127. }