AudioResolver.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #pragma warning disable CA1002, CS1591
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Runtime.CompilerServices;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Emby.Naming.Audio;
  9. using Emby.Naming.Common;
  10. using Jellyfin.Extensions;
  11. using MediaBrowser.Controller.Entities;
  12. using MediaBrowser.Controller.MediaEncoding;
  13. using MediaBrowser.Controller.Providers;
  14. using MediaBrowser.Model.Dlna;
  15. using MediaBrowser.Model.Dto;
  16. using MediaBrowser.Model.Entities;
  17. using MediaBrowser.Model.Globalization;
  18. using MediaBrowser.Model.MediaInfo;
  19. namespace MediaBrowser.Providers.MediaInfo
  20. {
  21. public class AudioResolver
  22. {
  23. private readonly ILocalizationManager _localizationManager;
  24. private readonly IMediaEncoder _mediaEncoder;
  25. private readonly NamingOptions _namingOptions;
  26. public AudioResolver(
  27. ILocalizationManager localizationManager,
  28. IMediaEncoder mediaEncoder,
  29. NamingOptions namingOptions)
  30. {
  31. _localizationManager = localizationManager;
  32. _mediaEncoder = mediaEncoder;
  33. _namingOptions = namingOptions;
  34. }
  35. public async IAsyncEnumerable<MediaStream> GetExternalAudioStreams(
  36. Video video,
  37. int startIndex,
  38. IDirectoryService directoryService,
  39. bool clearCache,
  40. [EnumeratorCancellation] CancellationToken cancellationToken)
  41. {
  42. cancellationToken.ThrowIfCancellationRequested();
  43. if (!video.IsFileProtocol)
  44. {
  45. yield break;
  46. }
  47. IEnumerable<string> paths = GetExternalAudioFiles(video, directoryService, clearCache);
  48. foreach (string path in paths)
  49. {
  50. string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
  51. Model.MediaInfo.MediaInfo mediaInfo = await GetMediaInfo(path, cancellationToken);
  52. foreach (MediaStream mediaStream in mediaInfo.MediaStreams)
  53. {
  54. mediaStream.Index = startIndex++;
  55. mediaStream.Type = MediaStreamType.Audio;
  56. mediaStream.IsExternal = true;
  57. mediaStream.Path = path;
  58. mediaStream.IsDefault = false;
  59. mediaStream.Title = null;
  60. if (string.IsNullOrEmpty(mediaStream.Language))
  61. {
  62. // Try to translate to three character code
  63. // Be flexible and check against both the full and three character versions
  64. var language = StringExtensions.RightPart(fileNameWithoutExtension, '.').ToString();
  65. if (language != fileNameWithoutExtension)
  66. {
  67. var culture = _localizationManager.FindLanguageInfo(language);
  68. language = culture == null ? language : culture.ThreeLetterISOLanguageName;
  69. mediaStream.Language = language;
  70. }
  71. }
  72. yield return mediaStream;
  73. }
  74. }
  75. }
  76. public IEnumerable<string> GetExternalAudioFiles(
  77. Video video,
  78. IDirectoryService directoryService,
  79. bool clearCache)
  80. {
  81. if (!video.IsFileProtocol)
  82. {
  83. yield break;
  84. }
  85. // Check if video folder exists
  86. string folder = video.ContainingFolderPath;
  87. if (!Directory.Exists(folder))
  88. {
  89. yield break;
  90. }
  91. string videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
  92. var files = directoryService.GetFilePaths(folder, clearCache, true);
  93. for (int i = 0; i < files.Count; i++)
  94. {
  95. string file = files[i];
  96. string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
  97. if (!AudioFileParser.IsAudioFile(file, _namingOptions))
  98. {
  99. continue;
  100. }
  101. // The audio filename must either be equal to the video filename or start with the video filename followed by a dot
  102. if (videoFileNameWithoutExtension.Equals(fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)
  103. || (fileNameWithoutExtension.Length > videoFileNameWithoutExtension.Length
  104. && fileNameWithoutExtension[videoFileNameWithoutExtension.Length] == '.'
  105. && fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)))
  106. {
  107. yield return file;
  108. }
  109. }
  110. }
  111. private Task<Model.MediaInfo.MediaInfo> GetMediaInfo(string path, CancellationToken cancellationToken)
  112. {
  113. cancellationToken.ThrowIfCancellationRequested();
  114. return _mediaEncoder.GetMediaInfo(
  115. new MediaInfoRequest
  116. {
  117. MediaType = DlnaProfileType.Audio,
  118. MediaSource = new MediaSourceInfo
  119. {
  120. Path = path,
  121. Protocol = MediaProtocol.File
  122. }
  123. },
  124. cancellationToken);
  125. }
  126. }
  127. }