add subtitle management page

This commit is contained in:
Luke Pulverenti
2014-05-17 00:24:10 -04:00
parent 26aa47eefd
commit c8e4889ac7
21 changed files with 426 additions and 129 deletions

View File

@@ -142,7 +142,7 @@ namespace MediaBrowser.Providers.MediaInfo
var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager);
return prober.ProbeVideo(item, directoryService, cancellationToken);
return prober.ProbeVideo(item, directoryService, true, cancellationToken);
}
public Task<ItemUpdateType> FetchAudioInfo<T>(T item, CancellationToken cancellationToken)

View File

@@ -60,7 +60,7 @@ namespace MediaBrowser.Providers.MediaInfo
_subtitleManager = subtitleManager;
}
public async Task<ItemUpdateType> ProbeVideo<T>(T item, IDirectoryService directoryService, CancellationToken cancellationToken)
public async Task<ItemUpdateType> ProbeVideo<T>(T item, IDirectoryService directoryService, bool enableSubtitleDownloading, CancellationToken cancellationToken)
where T : Video
{
var isoMount = await MountIsoIfNeeded(item, cancellationToken).ConfigureAwait(false);
@@ -105,7 +105,7 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
await Fetch(item, cancellationToken, result, isoMount, blurayDiscInfo, directoryService).ConfigureAwait(false);
await Fetch(item, cancellationToken, result, isoMount, blurayDiscInfo, directoryService, enableSubtitleDownloading).ConfigureAwait(false);
}
finally
@@ -160,7 +160,7 @@ namespace MediaBrowser.Providers.MediaInfo
return result;
}
protected async Task Fetch(Video video, CancellationToken cancellationToken, InternalMediaInfoResult data, IIsoMount isoMount, BlurayDiscInfo blurayInfo, IDirectoryService directoryService)
protected async Task Fetch(Video video, CancellationToken cancellationToken, InternalMediaInfoResult data, IIsoMount isoMount, BlurayDiscInfo blurayInfo, IDirectoryService directoryService, bool enableSubtitleDownloading)
{
var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data);
var mediaStreams = mediaInfo.MediaStreams;
@@ -208,7 +208,7 @@ namespace MediaBrowser.Providers.MediaInfo
FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
}
await AddExternalSubtitles(video, mediaStreams, directoryService, cancellationToken).ConfigureAwait(false);
await AddExternalSubtitles(video, mediaStreams, directoryService, enableSubtitleDownloading, cancellationToken).ConfigureAwait(false);
FetchWtvInfo(video, data);
@@ -416,13 +416,17 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
/// <param name="video">The video.</param>
/// <param name="currentStreams">The current streams.</param>
private async Task AddExternalSubtitles(Video video, List<MediaStream> currentStreams, IDirectoryService directoryService, CancellationToken cancellationToken)
/// <param name="directoryService">The directory service.</param>
/// <param name="enableSubtitleDownloading">if set to <c>true</c> [enable subtitle downloading].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task AddExternalSubtitles(Video video, List<MediaStream> currentStreams, IDirectoryService directoryService, bool enableSubtitleDownloading, CancellationToken cancellationToken)
{
var subtitleResolver = new SubtitleResolver(_localization);
var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, false).ToList();
if ((_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
if (enableSubtitleDownloading && (_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
video is Episode) ||
(_config.Configuration.SubtitleOptions.DownloadMovieSubtitles &&
video is Movie))

View File

@@ -124,7 +124,10 @@ namespace MediaBrowser.Providers.MediaInfo
Name = video.Name,
ParentIndexNumber = video.ParentIndexNumber,
ProductionYear = video.ProductionYear,
ProviderIds = video.ProviderIds
ProviderIds = video.ProviderIds,
// Stop as soon as we find something
SearchAllProviders = false
};
var episode = video as Episode;
@@ -143,7 +146,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (result != null)
{
await _subtitleManager.DownloadSubtitles(video, result.Id, result.ProviderName, cancellationToken)
await _subtitleManager.DownloadSubtitles(video, result.Id, cancellationToken)
.ConfigureAwait(false);
return true;

View File

@@ -1,8 +1,10 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
@@ -23,12 +25,16 @@ namespace MediaBrowser.Providers.Subtitles
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _monitor;
private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo;
public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor)
public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IItemRepository itemRepo)
{
_logger = logger;
_fileSystem = fileSystem;
_monitor = monitor;
_libraryManager = libraryManager;
_itemRepo = itemRepo;
}
public void AddParts(IEnumerable<ISubtitleProvider> subtitleProviders)
@@ -38,15 +44,45 @@ namespace MediaBrowser.Providers.Subtitles
public async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
var contentType = request.ContentType;
var providers = _subtitleProviders
.Where(i => i.SupportedMediaTypes.Contains(request.ContentType))
.Where(i => i.SupportedMediaTypes.Contains(contentType))
.ToList();
// If not searching all, search one at a time until something is found
if (!request.SearchAllProviders)
{
foreach (var provider in providers)
{
try
{
var searchResults = await provider.Search(request, cancellationToken).ConfigureAwait(false);
var list = searchResults.ToList();
if (list.Count > 0)
{
Normalize(list);
return list;
}
}
catch (Exception ex)
{
_logger.ErrorException("Error downloading subtitles from {0}", ex, provider.Name);
}
}
return new List<RemoteSubtitleInfo>();
}
var tasks = providers.Select(async i =>
{
try
{
return await i.Search(request, cancellationToken).ConfigureAwait(false);
var searchResults = await i.Search(request, cancellationToken).ConfigureAwait(false);
var list = searchResults.ToList();
Normalize(list);
return list;
}
catch (Exception ex)
{
@@ -62,17 +98,21 @@ namespace MediaBrowser.Providers.Subtitles
public async Task DownloadSubtitles(Video video,
string subtitleId,
string providerName,
CancellationToken cancellationToken)
{
var provider = _subtitleProviders.First(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase));
var response = await provider.GetSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
using (var stream = response.Stream)
{
var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower() + "." + response.Format.ToLower());
var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower());
if (response.IsForced)
{
savePath += ".forced";
}
savePath += "." + response.Format.ToLower();
_logger.Info("Saving subtitles to {0}", savePath);
@@ -139,5 +179,93 @@ namespace MediaBrowser.Providers.Subtitles
return SearchSubtitles(request, cancellationToken);
}
private void Normalize(IEnumerable<RemoteSubtitleInfo> subtitles)
{
foreach (var sub in subtitles)
{
sub.Id = GetProviderId(sub.ProviderName) + "_" + sub.Id;
}
}
private string GetProviderId(string name)
{
return name.ToLower().GetMD5().ToString("N");
}
private ISubtitleProvider GetProvider(string id)
{
return _subtitleProviders.First(i => string.Equals(id, GetProviderId(i.Name)));
}
public Task DeleteSubtitles(string itemId, int index)
{
var stream = _itemRepo.GetMediaStreams(new MediaStreamQuery
{
Index = index,
ItemId = new Guid(itemId),
Type = MediaStreamType.Subtitle
}).First();
var path = stream.Path;
_monitor.ReportFileSystemChangeBeginning(path);
try
{
File.Delete(path);
}
finally
{
_monitor.ReportFileSystemChangeComplete(path, false);
}
return _libraryManager.GetItemById(itemId).RefreshMetadata(new MetadataRefreshOptions
{
ImageRefreshMode = ImageRefreshMode.ValidationOnly,
MetadataRefreshMode = MetadataRefreshMode.ValidationOnly
}, CancellationToken.None);
}
public Task<SubtitleResponse> GetRemoteSubtitles(string id, CancellationToken cancellationToken)
{
var parts = id.Split(new[] { '_' }, 2);
var provider = GetProvider(parts.First());
id = parts.Last();
return provider.GetSubtitles(id, cancellationToken);
}
public IEnumerable<SubtitleProviderInfo> GetProviders(string itemId)
{
var video = _libraryManager.GetItemById(itemId) as Video;
VideoContentType mediaType;
if (video is Episode)
{
mediaType = VideoContentType.Episode;
}
else if (video is Movie)
{
mediaType = VideoContentType.Movie;
}
else
{
// These are the only supported types
return new List<SubtitleProviderInfo>();
}
var providers = _subtitleProviders
.Where(i => i.SupportedMediaTypes.Contains(mediaType))
.ToList();
return providers.Select(i => new SubtitleProviderInfo
{
Name = i.Name,
Id = GetProviderId(i.Name)
});
}
}
}