expose omdb to metadata config

This commit is contained in:
Luke Pulverenti 2014-02-15 11:36:09 -05:00
parent 4e414ebc91
commit 8b71ab2e7d
20 changed files with 232 additions and 107 deletions

View File

@ -32,7 +32,7 @@ namespace MediaBrowser.Api
/// <summary>
/// The application paths
/// </summary>
private readonly IServerApplicationPaths AppPaths;
private readonly IServerApplicationPaths _appPaths;
/// <summary>
/// Initializes a new instance of the <see cref="ApiEntryPoint" /> class.
@ -42,7 +42,7 @@ namespace MediaBrowser.Api
public ApiEntryPoint(ILogger logger, IServerApplicationPaths appPaths)
{
Logger = logger;
AppPaths = appPaths;
_appPaths = appPaths;
Instance = this;
}
@ -71,7 +71,7 @@ namespace MediaBrowser.Api
/// </summary>
private void DeleteEncodedMediaCache()
{
foreach (var file in Directory.EnumerateFiles(AppPaths.TranscodingTempPath)
foreach (var file in Directory.EnumerateFiles(_appPaths.TranscodingTempPath)
.Where(i => EntityResolutionHelper.VideoFileExtensions.Contains(Path.GetExtension(i)))
.ToList())
{

View File

@ -709,8 +709,15 @@ namespace MediaBrowser.Common.Implementations
{
Logger.Info("Disposing " + part.GetType().Name);
try
{
part.Dispose();
}
catch (Exception ex)
{
Logger.ErrorException("Error disposing {0}", ex, part.GetType().Name);
}
}
}
}

View File

@ -178,7 +178,7 @@ namespace MediaBrowser.Controller.Entities.Audio
// Refresh all non-songs
foreach (var item in others)
{
if (tasks.Count > 3)
if (tasks.Count > 4)
{
await Task.WhenAll(tasks).ConfigureAwait(false);
tasks.Clear();
@ -202,7 +202,9 @@ namespace MediaBrowser.Controller.Entities.Audio
}
});
tasks.Add(RefreshItem(item, refreshOptions, innerProgress, cancellationToken));
// Avoid implicitly captured closure
var taskChild = item;
tasks.Add(Task.Run(async () => await RefreshItem(taskChild, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken));
}
await Task.WhenAll(tasks).ConfigureAwait(false);

View File

@ -1236,7 +1236,7 @@ namespace MediaBrowser.Controller.Entities
public virtual Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
{
return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, cancellationToken);
return LibraryManager.UpdateItem(this, updateReason, cancellationToken);
}
/// <summary>

View File

@ -521,7 +521,7 @@ namespace MediaBrowser.Controller.Entities
foreach (var child in children)
{
if (tasks.Count >= 8)
if (tasks.Count >= 4)
{
await Task.WhenAll(tasks).ConfigureAwait(false);
tasks.Clear();
@ -552,7 +552,10 @@ namespace MediaBrowser.Controller.Entities
}
else
{
tasks.Add(RefreshChildMetadata(child, refreshOptions, false, innerProgress, cancellationToken));
// Avoid implicitly captured closure
var taskChild = child;
tasks.Add(Task.Run(async () => await RefreshChildMetadata(taskChild, refreshOptions, false, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken));
}
}

View File

@ -99,7 +99,7 @@ namespace MediaBrowser.Controller.Entities.Movies
// Refresh songs
foreach (var item in items)
{
if (tasks.Count >= 2)
if (tasks.Count >= 4)
{
await Task.WhenAll(tasks).ConfigureAwait(false);
tasks.Clear();
@ -123,7 +123,9 @@ namespace MediaBrowser.Controller.Entities.Movies
}
});
tasks.Add(RefreshItem(item, refreshOptions, innerProgress, cancellationToken));
// Avoid implicitly captured closure
var taskChild = item;
tasks.Add(Task.Run(async () => await RefreshItem(taskChild, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken));
}
await Task.WhenAll(tasks).ConfigureAwait(false);

View File

@ -102,7 +102,11 @@ namespace MediaBrowser.Controller.Entities
public TrailerInfo GetLookupInfo()
{
return GetItemLookupInfo<TrailerInfo>();
var info = GetItemLookupInfo<TrailerInfo>();
info.IsLocalTrailer = IsLocalTrailer;
return info;
}
}
}

View File

@ -1,4 +1,5 @@
using MediaBrowser.Model.Logging;
using System.Collections.Concurrent;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.IO;
@ -19,7 +20,7 @@ namespace MediaBrowser.Controller.Providers
{
private readonly ILogger _logger;
private readonly Dictionary<string, List<FileSystemInfo>> _cache = new Dictionary<string, List<FileSystemInfo>>(StringComparer.OrdinalIgnoreCase);
private readonly ConcurrentDictionary<string, List<FileSystemInfo>> _cache = new ConcurrentDictionary<string, List<FileSystemInfo>>(StringComparer.OrdinalIgnoreCase);
public DirectoryService(ILogger logger)
{
@ -43,7 +44,7 @@ namespace MediaBrowser.Controller.Providers
entries = new List<FileSystemInfo>();
}
_cache.Add(path, entries);
_cache.TryAdd(path, entries);
}
return entries;

View File

@ -142,7 +142,7 @@ namespace MediaBrowser.Controller.Providers
public class TrailerInfo : ItemLookupInfo
{
public bool IsLocalTrailer { get; set; }
}
public class BookInfo : ItemLookupInfo

View File

@ -45,7 +45,12 @@ namespace MediaBrowser.Providers.BoxSets
// We don't already have an Id, need to fetch it
if (string.IsNullOrEmpty(tmdbId))
{
tmdbId = await GetTmdbId(id, cancellationToken).ConfigureAwait(false);
var searchResult = await new MovieDbSearch(_logger, _json).FindCollectionId(id, cancellationToken).ConfigureAwait(false);
if (searchResult != null)
{
tmdbId = searchResult.id.ToString(_enUs);
}
}
var result = new MetadataResult<BoxSet>();
@ -190,11 +195,6 @@ namespace MediaBrowser.Providers.BoxSets
return DownloadInfo(tmdbId, preferredMetadataLanguage, cancellationToken);
}
private Task<string> GetTmdbId(ItemLookupInfo id, CancellationToken cancellationToken)
{
return new MovieDbSearch(_logger, _json).FindCollectionId(id, cancellationToken);
}
public string Name
{
get { return "TheMovieDb"; }

View File

@ -327,7 +327,7 @@ namespace MediaBrowser.Providers.Manager
}
// Local metadata is king - if any is found don't run remote providers
if ((!options.ReplaceAllMetadata && !hasLocalMetadata) || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh)
if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh))
{
await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false);
}

View File

@ -39,8 +39,12 @@ namespace MediaBrowser.Providers.Movies
// Don't search for music video id's because it is very easy to misidentify.
if (string.IsNullOrEmpty(tmdbId) && string.IsNullOrEmpty(imdbId) && typeof(T) != typeof(MusicVideo))
{
tmdbId = await new MovieDbSearch(_logger, _jsonSerializer)
.FindMovieId(itemId, cancellationToken).ConfigureAwait(false);
var searchResult = await new MovieDbSearch(_logger, _jsonSerializer).FindMovieId(itemId, cancellationToken).ConfigureAwait(false);
if (searchResult != null)
{
tmdbId = searchResult.id.ToString(_usCulture);
}
}
if (!string.IsNullOrEmpty(tmdbId) || !string.IsNullOrEmpty(imdbId))

View File

@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Movies
/// <summary>
/// Class MovieDbProvider
/// </summary>
public class MovieDbProvider : IRemoteMetadataProvider<Movie, MovieInfo>, IDisposable
public class MovieDbProvider : IRemoteMetadataProvider<Movie, MovieInfo>, IDisposable, IHasOrder
{
internal readonly SemaphoreSlim MovieDbResourcePool = new SemaphoreSlim(1, 1);
@ -529,5 +529,14 @@ namespace MediaBrowser.Providers.Movies
public Keywords keywords { get; set; }
public Trailers trailers { get; set; }
}
public int Order
{
get
{
// After Omdb
return 1;
}
}
}
}

View File

@ -29,22 +29,22 @@ namespace MediaBrowser.Providers.Movies
_json = json;
}
public Task<string> FindSeriesId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
public Task<TmdbMovieSearchResult> FindSeriesId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
{
return FindId(idInfo, "tv", cancellationToken);
}
public Task<string> FindMovieId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
public Task<TmdbMovieSearchResult> FindMovieId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
{
return FindId(idInfo, "movie", cancellationToken);
}
public Task<string> FindCollectionId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
public Task<TmdbMovieSearchResult> FindCollectionId(ItemLookupInfo idInfo, CancellationToken cancellationToken)
{
return FindId(idInfo, "collection", cancellationToken);
}
private async Task<string> FindId(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken)
private async Task<TmdbMovieSearchResult> FindId(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken)
{
var name = idInfo.Name;
var year = idInfo.Year;
@ -101,7 +101,7 @@ namespace MediaBrowser.Providers.Movies
return id;
}
private async Task<string> AttemptFindId(string name, string type, int? year, string language, CancellationToken cancellationToken)
private async Task<TmdbMovieSearchResult> AttemptFindId(string name, string type, int? year, string language, CancellationToken cancellationToken)
{
var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, type);
@ -114,16 +114,16 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false))
{
var searchResult = _json.DeserializeFromStream<TmdbMovieSearchResults>(json);
return FindIdOfBestResult(searchResult.results, name, year);
return FindBestResult(searchResult.results, name, year);
}
}
private string FindIdOfBestResult(List<TmdbMovieSearchResult> results, string name, int? year)
private TmdbMovieSearchResult FindBestResult(List<TmdbMovieSearchResult> results, string name, int? year)
{
if (year.HasValue)
{
// Take the first result from the same year
var id = results.Where(i =>
var result = results.FirstOrDefault(i =>
{
// Make sure it has a name
if (!string.IsNullOrEmpty(i.title ?? i.name))
@ -138,17 +138,15 @@ namespace MediaBrowser.Providers.Movies
}
return false;
})
.Select(i => i.id.ToString(CultureInfo.InvariantCulture))
.FirstOrDefault();
});
if (!string.IsNullOrEmpty(id))
if (result != null)
{
return id;
return null;
}
// Take the first result within one year
id = results.Where(i =>
result = results.FirstOrDefault(i =>
{
// Make sure it has a name
if (!string.IsNullOrEmpty(i.title ?? i.name))
@ -163,27 +161,23 @@ namespace MediaBrowser.Providers.Movies
}
return false;
})
.Select(i => i.id.ToString(CultureInfo.InvariantCulture))
.FirstOrDefault();
});
if (!string.IsNullOrEmpty(id))
if (result != null)
{
return id;
return null;
}
}
// Just take the first one
return results.Where(i => !string.IsNullOrEmpty(i.title ?? i.name))
.Select(i => i.id.ToString(CultureInfo.InvariantCulture))
.FirstOrDefault();
return results.FirstOrDefault(i => !string.IsNullOrEmpty(i.title ?? i.name));
}
/// <summary>
/// Class TmdbMovieSearchResult
/// </summary>
private class TmdbMovieSearchResult
public class TmdbMovieSearchResult
{
/// <summary>
/// Gets or sets a value indicating whether this <see cref="TmdbMovieSearchResult" /> is adult.

View File

@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Movies
{
public class MovieDbTrailerProvider : IRemoteMetadataProvider<Trailer, TrailerInfo>
public class MovieDbTrailerProvider : IRemoteMetadataProvider<Trailer, TrailerInfo>, IHasOrder
{
public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
{
@ -22,5 +22,14 @@ namespace MediaBrowser.Providers.Movies
{
return MovieDbProvider.Current.HasChanged(item, date);
}
public int Order
{
get
{
// After Omdb
return 1;
}
}
}
}

View File

@ -2,24 +2,31 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
using MediaBrowser.Providers.TV;
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Omdb
{
public class OmdbItemProvider : ICustomMetadataProvider<Series>,
ICustomMetadataProvider<Movie>, ICustomMetadataProvider<Trailer>
public class OmdbItemProvider : IRemoteMetadataProvider<Series, SeriesInfo>,
IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<Trailer, TrailerInfo>
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
private readonly ILogger _logger;
public OmdbItemProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient)
public OmdbItemProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger)
{
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
_logger = logger;
}
public string Name
@ -27,25 +34,110 @@ namespace MediaBrowser.Providers.Omdb
get { return "IMDb via The Open Movie Database"; }
}
public Task<ItemUpdateType> FetchAsync(Series item, IDirectoryService directoryService, CancellationToken cancellationToken)
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
{
return new OmdbProvider(_jsonSerializer, _httpClient).Fetch(item, cancellationToken);
var result = new MetadataResult<Series>
{
Item = new Series()
};
var imdbId = info.GetProviderId(MetadataProviders.Imdb);
if (string.IsNullOrEmpty(imdbId))
{
var searchResult = await GetSeriesImdbId(info, cancellationToken).ConfigureAwait(false);
imdbId = searchResult.Item1;
if (!string.IsNullOrEmpty(searchResult.Item2))
{
result.Item.SetProviderId(MetadataProviders.Tvdb, searchResult.Item2);
}
}
public Task<ItemUpdateType> FetchAsync(Movie item, IDirectoryService directoryService, CancellationToken cancellationToken)
if (!string.IsNullOrEmpty(imdbId))
{
return new OmdbProvider(_jsonSerializer, _httpClient).Fetch(item, cancellationToken);
result.Item.SetProviderId(MetadataProviders.Imdb, imdbId);
result.HasMetadata = true;
await new OmdbProvider(_jsonSerializer, _httpClient).Fetch(result.Item, imdbId, cancellationToken)
.ConfigureAwait(false);
}
private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
public Task<ItemUpdateType> FetchAsync(Trailer item, IDirectoryService directoryService, CancellationToken cancellationToken)
{
if (item.IsLocalTrailer)
{
return _cachedTask;
return result;
}
return new OmdbProvider(_jsonSerializer, _httpClient).Fetch(item, cancellationToken);
public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken)
{
return GetMovieResult<Movie>(info, cancellationToken);
}
public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult<Trailer>();
if (info.IsLocalTrailer)
{
return Task.FromResult(result);
}
return GetMovieResult<Trailer>(info, cancellationToken);
}
private async Task<MetadataResult<T>> GetMovieResult<T>(ItemLookupInfo info, CancellationToken cancellationToken)
where T : Video, new()
{
var result = new MetadataResult<T>
{
Item = new T()
};
var imdbId = info.GetProviderId(MetadataProviders.Imdb);
if (string.IsNullOrEmpty(imdbId))
{
var searchResult = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false);
imdbId = searchResult.Item1;
if (!string.IsNullOrEmpty(searchResult.Item2))
{
result.Item.SetProviderId(MetadataProviders.Tmdb, searchResult.Item2);
}
}
if (!string.IsNullOrEmpty(imdbId))
{
result.Item.SetProviderId(MetadataProviders.Imdb, imdbId);
result.HasMetadata = true;
await new OmdbProvider(_jsonSerializer, _httpClient).Fetch(result.Item, imdbId, cancellationToken)
.ConfigureAwait(false);
}
return result;
}
private async Task<Tuple<string, string>> GetMovieImdbId(ItemLookupInfo info, CancellationToken cancellationToken)
{
var result = await new GenericMovieDbInfo<Movie>(_logger, _jsonSerializer).GetMetadata(info, cancellationToken)
.ConfigureAwait(false);
var imdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Imdb) : null;
var tmdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Tmdb) : null;
return new Tuple<string, string>(imdb, tmdb);
}
private async Task<Tuple<string,string>> GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken)
{
var result = await TvdbSeriesProvider.Current.GetMetadata(info, cancellationToken)
.ConfigureAwait(false);
var imdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Imdb) : null;
var tvdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Tvdb) : null;
return new Tuple<string, string>(imdb, tvdb);
}
}
}

View File

@ -2,7 +2,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using System;
@ -16,26 +15,23 @@ namespace MediaBrowser.Providers.Omdb
{
public class OmdbProvider
{
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
internal readonly SemaphoreSlim ResourcePool = new SemaphoreSlim(1, 1);
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public static OmdbProvider Current;
public OmdbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient)
{
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
Current = this;
}
public async Task<ItemUpdateType> Fetch(BaseItem item, CancellationToken cancellationToken)
public async Task Fetch(BaseItem item, string imdbId, CancellationToken cancellationToken)
{
var imdbId = item.GetProviderId(MetadataProviders.Imdb);
if (string.IsNullOrEmpty(imdbId))
{
return ItemUpdateType.None;
}
var imdbParam = imdbId.StartsWith("tt", StringComparison.OrdinalIgnoreCase) ? imdbId : "tt" + imdbId;
var url = string.Format("http://www.omdbapi.com/?i={0}&tomatoes=true", imdbParam);
@ -43,7 +39,7 @@ namespace MediaBrowser.Providers.Omdb
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
ResourcePool = _resourcePool,
ResourcePool = ResourcePool,
CancellationToken = cancellationToken
}).ConfigureAwait(false))
@ -98,16 +94,13 @@ namespace MediaBrowser.Providers.Omdb
ParseAdditionalMetadata(item, result);
}
return ItemUpdateType.MetadataDownload;
}
private void ParseAdditionalMetadata(BaseItem item, RootObject result)
{
// Grab series genres because imdb data is better than tvdb. Leave movies alone
// But only do it if english is the preferred language because this data will not be localized
if (!item.LockedFields.Contains(MetadataFields.Genres) &&
ShouldFetchGenres(item) &&
if (ShouldFetchGenres(item) &&
!string.IsNullOrWhiteSpace(result.Genre) &&
!string.Equals(result.Genre, "n/a", StringComparison.OrdinalIgnoreCase))
{
@ -146,21 +139,10 @@ namespace MediaBrowser.Providers.Omdb
var lang = item.GetPreferredMetadataLanguage();
// The data isn't localized and so can only be used for english users
if (!string.Equals(lang, "en", StringComparison.OrdinalIgnoreCase))
{
return false;
return string.Equals(lang, "en", StringComparison.OrdinalIgnoreCase);
}
// Only fetch if other providers didn't get anything
if (item is Trailer)
{
return item.Genres.Count == 0;
}
return item is Series || item is Movie;
}
protected class RootObject
public class RootObject
{
public string Title { get; set; }
public string Year { get; set; }

View File

@ -73,7 +73,12 @@ namespace MediaBrowser.Providers.TV
if (string.IsNullOrEmpty(tmdbId))
{
tmdbId = await new MovieDbSearch(_logger, _jsonSerializer).FindSeriesId(info, cancellationToken).ConfigureAwait(false);
var searchResult = await new MovieDbSearch(_logger, _jsonSerializer).FindSeriesId(info, cancellationToken).ConfigureAwait(false);
if (searchResult != null)
{
tmdbId = searchResult.id.ToString(_usCulture);
}
}
if (!string.IsNullOrEmpty(tmdbId))
@ -434,7 +439,7 @@ namespace MediaBrowser.Providers.TV
{
get
{
// After Tvdb
// After Omdb and Tvdb
return 2;
}
}

View File

@ -22,7 +22,7 @@ using System.Xml;
namespace MediaBrowser.Providers.TV
{
public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>
public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
{
internal readonly SemaphoreSlim TvDbResourcePool = new SemaphoreSlim(2, 2);
internal static TvdbSeriesProvider Current { get; private set; }
@ -1072,5 +1072,14 @@ namespace MediaBrowser.Providers.TV
{
get { return "TheTVDB"; }
}
public int Order
{
get
{
// After Omdb
return 1;
}
}
}
}

View File

@ -154,7 +154,9 @@ namespace MediaBrowser.ServerApplication
// Add our log window if specified
if (_configurationManager.Configuration.ShowLogWindow)
{
Trace.Listeners.Add(new WindowTraceListener(new LogForm(_logManager)));
_logForm = new LogForm(_logManager);
Trace.Listeners.Add(new WindowTraceListener(_logForm));
}
else
{