diff options
| author | Luke <luke.pulverenti@gmail.com> | 2016-03-25 13:52:15 -0400 |
|---|---|---|
| committer | Luke <luke.pulverenti@gmail.com> | 2016-03-25 13:52:15 -0400 |
| commit | 72fe76ab1008f0bd38157cc37cde45797b5f6417 (patch) | |
| tree | 875b6bee7d0a634d7ef019cfb7c434823b223001 /MediaBrowser.Providers | |
| parent | 736e63241011cb9ae798bf4091cd37e097045c21 (diff) | |
| parent | f6c18200bacae6e768225a8c073418a170d349bd (diff) | |
Merge pull request #1593 from MediaBrowser/beta
Beta
Diffstat (limited to 'MediaBrowser.Providers')
41 files changed, 563 insertions, 407 deletions
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs index e82c6a1b91..ff3d5a5b24 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Providers.BoxSets { var language = item.GetPreferredMetadataLanguage(); - var mainResult = await MovieDbBoxSetProvider.Current.GetMovieDbResult(tmdbId, language, cancellationToken).ConfigureAwait(false); + var mainResult = await MovieDbBoxSetProvider.Current.GetMovieDbResult(tmdbId, null, cancellationToken).ConfigureAwait(false); if (mainResult != null) { diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index ae6199a75d..bd4078b27c 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -168,12 +168,11 @@ namespace MediaBrowser.Providers.BoxSets if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); - } + url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language)); - var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); - // Get images in english and with no language - url += "&include_image_language=" + includeImageLanguageParam; + // Get images in english and with no language + url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); + } cancellationToken.ThrowIfCancellationRequested(); @@ -196,7 +195,13 @@ namespace MediaBrowser.Providers.BoxSets { if (!string.IsNullOrEmpty(language) && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { - url = string.Format(GetCollectionInfo3, id, MovieDbSearch.ApiKey) + "&include_image_language=en,null&language=en"; + url = string.Format(GetCollectionInfo3, id, MovieDbSearch.ApiKey) + "&language=en"; + + if (!string.IsNullOrEmpty(language)) + { + // Get images in english and with no language + url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); + } using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions { @@ -239,15 +244,9 @@ namespace MediaBrowser.Providers.BoxSets private static string GetDataFilePath(IApplicationPaths appPaths, string tmdbId, string preferredLanguage) { - if (string.IsNullOrWhiteSpace(preferredLanguage)) - { - throw new ArgumentNullException("preferredLanguage"); - } - var path = GetDataPath(appPaths, tmdbId); - var filename = string.Format("all-{0}.json", - preferredLanguage); + var filename = string.Format("all-{0}.json", preferredLanguage ?? string.Empty); return Path.Combine(path, filename); } diff --git a/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs b/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs deleted file mode 100644 index 9a1a993d9c..0000000000 --- a/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using CommonIO; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Providers.Manager; - -namespace MediaBrowser.Providers.Channels -{ - public class AudioChannelItemMetadataService : MetadataService<ChannelAudioItem, ItemLookupInfo> - { - public AudioChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager) - { - } - - protected override void MergeData(MetadataResult<ChannelAudioItem> source, MetadataResult<ChannelAudioItem> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) - { - ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); - } - } -} diff --git a/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs b/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs deleted file mode 100644 index 597ae5e10c..0000000000 --- a/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Providers.Manager; -using System.Collections.Generic; -using CommonIO; - -namespace MediaBrowser.Providers.Channels -{ - public class VideoChannelItemMetadataService : MetadataService<ChannelVideoItem, ChannelItemLookupInfo> - { - public VideoChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager) - { - } - - protected override void MergeData(MetadataResult<ChannelVideoItem> source, MetadataResult<ChannelVideoItem> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) - { - ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); - } - } -} diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 64a0e6d5b2..bd1961143e 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -421,7 +421,7 @@ namespace MediaBrowser.Providers.Manager if (saveLocally) { - if (item is Episode) + if (type == ImageType.Primary && item is Episode) { path = Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename + extension); } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 416cc51bd2..b7991cb78d 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Providers.Manager var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem); var localImagesFailed = false; - var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item, refreshOptions).ToList(); + var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item, refreshOptions).ToList(); // Start by validating images try @@ -301,17 +301,23 @@ namespace MediaBrowser.Providers.Manager { if (ServerConfigurationManager.Configuration.DownloadImagesInAdvance) { - await ProviderManager.SaveImage(personEntity, imageUrl, null, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); - } - else - { - personEntity.SetImage(new ItemImageInfo + try { - Path = imageUrl, - Type = ImageType.Primary, - IsPlaceholder = true - }, 0); + await ProviderManager.SaveImage(personEntity, imageUrl, null, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); + return; + } + catch (Exception ex) + { + Logger.ErrorException("Error in AddPersonImage", ex); + } } + + personEntity.SetImage(new ItemImageInfo + { + Path = imageUrl, + Type = ImageType.Primary, + IsPlaceholder = true + }, 0); } private readonly Task _cachedTask = Task.FromResult(true); diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index b0d3f63812..a83a40bc34 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -1022,8 +1022,8 @@ namespace MediaBrowser.Providers.Manager .ToList(); var musicArtists = albums - .Select(i => i.GetParent()) - .OfType<MusicArtist>() + .Select(i => i.MusicArtist) + .Where(i => i != null) .ToList(); var musicArtistRefreshTasks = musicArtists.Select(i => i.ValidateChildren(new Progress<double>(), cancellationToken, options, true)); diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index d316d2cd8f..8927e00aae 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -50,7 +50,7 @@ </Reference> <Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath> + <HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath> </Reference> <Reference Include="DvdLib, Version=1.0.5167.21152, Culture=neutral, PublicKeyToken=7a2f3f5ec8d93575, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> @@ -90,10 +90,8 @@ <Compile Include="Chapters\ChapterManager.cs" /> <Compile Include="Folders\DefaultImageProvider.cs" /> <Compile Include="Folders\FolderMetadataService.cs" /> - <Compile Include="Channels\AudioChannelItemMetadataService.cs" /> <Compile Include="Folders\UserViewMetadataService.cs" /> <Compile Include="GameGenres\GameGenreMetadataService.cs" /> - <Compile Include="Channels\VideoChannelItemMetadataService.cs" /> <Compile Include="Games\GameMetadataService.cs" /> <Compile Include="Games\GameSystemMetadataService.cs" /> <Compile Include="Genres\GenreMetadataService.cs" /> @@ -169,26 +167,28 @@ <Compile Include="Subtitles\SubtitleManager.cs" /> <Compile Include="TV\DummySeasonProvider.cs" /> <Compile Include="TV\EpisodeMetadataService.cs" /> - <Compile Include="TV\FanArtTvUpdatesPostScanTask.cs" /> - <Compile Include="TV\FanArtSeasonProvider.cs" /> - <Compile Include="TV\FanartSeriesProvider.cs" /> + <Compile Include="TV\FanArt\FanArtTvUpdatesPostScanTask.cs" /> + <Compile Include="TV\FanArt\FanArtSeasonProvider.cs" /> + <Compile Include="TV\FanArt\FanartSeriesProvider.cs" /> <Compile Include="TV\MissingEpisodeProvider.cs" /> - <Compile Include="TV\MovieDbEpisodeImageProvider.cs" /> - <Compile Include="TV\MovieDbSeasonProvider.cs" /> - <Compile Include="TV\MovieDbSeriesImageProvider.cs" /> - <Compile Include="TV\MovieDbSeriesProvider.cs" /> - <Compile Include="TV\OmdbEpisodeProvider.cs" /> + <Compile Include="TV\TheMovieDb\MovieDbProviderBase.cs" /> + <Compile Include="TV\TheMovieDb\MovieDbEpisodeImageProvider.cs" /> + <Compile Include="TV\TheMovieDb\MovieDbSeasonProvider.cs" /> + <Compile Include="TV\TheMovieDb\MovieDbSeriesImageProvider.cs" /> + <Compile Include="TV\TheMovieDb\MovieDbSeriesProvider.cs" /> + <Compile Include="TV\TheMovieDb\MovieDbEpisodeProvider.cs" /> + <Compile Include="TV\Omdb\OmdbEpisodeProvider.cs" /> <Compile Include="TV\SeriesMetadataService.cs" /> - <Compile Include="TV\TvdbEpisodeImageProvider.cs" /> + <Compile Include="TV\TheTVDB\TvdbEpisodeImageProvider.cs" /> <Compile Include="People\TvdbPersonImageProvider.cs" /> - <Compile Include="TV\TvdbSeasonIdentityProvider.cs" /> - <Compile Include="TV\TvdbSeasonImageProvider.cs" /> - <Compile Include="TV\TvdbSeriesImageProvider.cs" /> + <Compile Include="TV\TheTVDB\TvdbSeasonIdentityProvider.cs" /> + <Compile Include="TV\TheTVDB\TvdbSeasonImageProvider.cs" /> + <Compile Include="TV\TheTVDB\TvdbSeriesImageProvider.cs" /> <Compile Include="TV\SeasonMetadataService.cs" /> - <Compile Include="TV\TvdbEpisodeProvider.cs" /> - <Compile Include="TV\TvdbSeriesProvider.cs" /> + <Compile Include="TV\TheTVDB\TvdbEpisodeProvider.cs" /> + <Compile Include="TV\TheTVDB\TvdbSeriesProvider.cs" /> <Compile Include="TV\SeriesPostScanTask.cs" /> - <Compile Include="TV\TvdbPrescanTask.cs" /> + <Compile Include="TV\TheTVDB\TvdbPrescanTask.cs" /> <Compile Include="TV\TvExternalIds.cs" /> <Compile Include="Users\UserMetadataService.cs" /> <Compile Include="Videos\VideoMetadataService.cs" /> diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index c98a67bbdb..f9108b9fda 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -107,11 +107,21 @@ namespace MediaBrowser.Providers.MediaInfo private string GetAudioImagePath(Audio item) { - var album = item.AlbumEntity; - var filename = item.Album ?? string.Empty; filename += string.Join(",", item.Artists.ToArray()); - filename += album == null ? item.Id.ToString("N") + "_primary" + item.DateModified.Ticks : album.Id.ToString("N") + album.DateModified.Ticks + "_primary"; + + if (!string.IsNullOrWhiteSpace(item.Album)) + { + filename += "_" + item.Album; + } + else if (!string.IsNullOrWhiteSpace(item.Name)) + { + filename += "_" + item.Name; + } + else + { + filename += "_" + item.Id.ToString("N"); + } filename = filename.GetMD5() + ".jpg"; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index ee05a89a85..5f556bffb4 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -532,7 +532,7 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleManager) .DownloadSubtitles(video, currentStreams.Concat(externalSubtitleStreams).ToList(), - subtitleOptions.SkipIfGraphicalSubtitlesPresent, + subtitleOptions.SkipIfEmbeddedSubtitlesPresent, subtitleOptions.SkipIfAudioTrackMatches, subtitleOptions.DownloadLanguages, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs index 6230e73475..d822890326 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.MediaInfo public async Task<List<string>> DownloadSubtitles(Video video, List<MediaStream> mediaStreams, - bool skipIfGraphicalSubtitlesPresent, + bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, IEnumerable<string> languages, CancellationToken cancellationToken) @@ -59,7 +59,7 @@ namespace MediaBrowser.Providers.MediaInfo { try { - var downloaded = await DownloadSubtitles(video, mediaStreams, skipIfGraphicalSubtitlesPresent, skipIfAudioTrackMatches, lang, mediaType, cancellationToken) + var downloaded = await DownloadSubtitles(video, mediaStreams, skipIfEmbeddedSubtitlesPresent, skipIfAudioTrackMatches, lang, mediaType, cancellationToken) .ConfigureAwait(false); if (downloaded) @@ -78,7 +78,7 @@ namespace MediaBrowser.Providers.MediaInfo private async Task<bool> DownloadSubtitles(Video video, List<MediaStream> mediaStreams, - bool skipIfGraphicalSubtitlesPresent, + bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, string language, VideoContentType mediaType, @@ -107,8 +107,8 @@ namespace MediaBrowser.Providers.MediaInfo } // There's an internal subtitle stream for this language - if (skipIfGraphicalSubtitlesPresent && - mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && !i.IsTextSubtitleStream && string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase))) + if (skipIfEmbeddedSubtitlesPresent && + mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && !i.IsExternal && string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase))) { return false; } diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 4953621f5a..b8b17cefee 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleManager) .DownloadSubtitles(video, mediaStreams, - options.SkipIfGraphicalSubtitlesPresent, + options.SkipIfEmbeddedSubtitlesPresent, options.SkipIfAudioTrackMatches, options.DownloadLanguages, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index abd4a62029..157704240a 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -179,7 +179,7 @@ namespace MediaBrowser.Providers.Movies if (movieItem != null) { - movieItem.TmdbCollectionName = movieData.belongs_to_collection.name; + movieItem.CollectionName = movieData.belongs_to_collection.name; } } diff --git a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs index b6f93392b3..6bfd9b7fa7 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs @@ -42,23 +42,6 @@ namespace MediaBrowser.Providers.Movies public bool Supports(IHasImages item) { - var channelItem = item as IChannelMediaItem; - - if (channelItem != null) - { - if (channelItem.ContentType == ChannelMediaContentType.Movie) - { - return true; - } - if (channelItem.ContentType == ChannelMediaContentType.MovieExtra) - { - if (channelItem.ExtraType == ExtraType.Trailer) - { - return true; - } - } - } - // Supports images for tv movies var tvProgram = item as LiveTvProgram; if (tvProgram != null && tvProgram.IsMovie) @@ -66,7 +49,7 @@ namespace MediaBrowser.Providers.Movies return true; } - return item is Movie || item is MusicVideo; + return item is Movie || item is MusicVideo || item is Trailer; } public IEnumerable<ImageType> GetSupportedImages(IHasImages item) @@ -82,7 +65,7 @@ namespace MediaBrowser.Providers.Movies { var list = new List<RemoteImageInfo>(); - var results = await FetchImages((BaseItem)item, _jsonSerializer, cancellationToken).ConfigureAwait(false); + var results = await FetchImages((BaseItem)item, null, _jsonSerializer, cancellationToken).ConfigureAwait(false); if (results == null) { @@ -183,14 +166,13 @@ namespace MediaBrowser.Providers.Movies /// Fetches the images. /// </summary> /// <param name="item">The item.</param> + /// <param name="language">The language.</param> /// <param name="jsonSerializer">The json serializer.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{MovieImages}.</returns> - private async Task<MovieDbProvider.Images> FetchImages(BaseItem item, IJsonSerializer jsonSerializer, - CancellationToken cancellationToken) + private async Task<MovieDbProvider.Images> FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer, CancellationToken cancellationToken) { var tmdbId = item.GetProviderId(MetadataProviders.Tmdb); - var language = item.GetPreferredMetadataLanguage(); if (string.IsNullOrWhiteSpace(tmdbId)) { diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 593c6f180e..58efc9534c 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -16,12 +16,14 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Providers.Movies { @@ -226,10 +228,6 @@ namespace MediaBrowser.Providers.Movies { throw new ArgumentNullException("tmdbId"); } - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException("language"); - } var path = GetDataFilePath(tmdbId, language); @@ -253,15 +251,15 @@ namespace MediaBrowser.Providers.Movies { throw new ArgumentNullException("tmdbId"); } - if (string.IsNullOrEmpty(preferredLanguage)) - { - throw new ArgumentNullException("preferredLanguage"); - } var path = GetMovieDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("all-{0}.json", - preferredLanguage); + if (string.IsNullOrWhiteSpace(preferredLanguage)) + { + preferredLanguage = "alllang"; + } + + var filename = string.Format("all-{0}.json", preferredLanguage); return Path.Combine(path, filename); } @@ -283,6 +281,20 @@ namespace MediaBrowser.Providers.Movies return string.Join(",", languages.ToArray()); } + public static string NormalizeLanguage(string language) + { + // They require this to be uppercase + // http://emby.media/community/index.php?/topic/32454-fr-follow-tmdbs-new-language-api-update/?p=311148 + var parts = language.Split('-'); + + if (parts.Length == 2) + { + language = parts[0] + "-" + parts[1].ToUpper(); + } + + return language; + } + /// <summary> /// Fetches the main result. /// </summary> @@ -297,12 +309,11 @@ namespace MediaBrowser.Providers.Movies if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); - } + url += string.Format("&language={0}", NormalizeLanguage(language)); - var includeImageLanguageParam = GetImageLanguagesParam(language); - // Get images in english and with no language - url += "&include_image_language=" + includeImageLanguageParam; + // Get images in english and with no language + url += "&include_image_language=" + GetImageLanguagesParam(language); + } CompleteMovieData mainResult; @@ -348,7 +359,13 @@ namespace MediaBrowser.Providers.Movies { _logger.Info("MovieDbProvider couldn't find meta for language " + language + ". Trying English..."); - url = string.Format(GetMovieInfo3, id, ApiKey) + "&include_image_language=" + includeImageLanguageParam + "&language=en"; + url = string.Format(GetMovieInfo3, id, ApiKey) + "&language=en"; + + if (!string.IsNullOrEmpty(language)) + { + // Get images in english and with no language + url += "&include_image_language=" + GetImageLanguagesParam(language); + } using (var json = await GetMovieDbResponse(new HttpRequestOptions { diff --git a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs index 2bb452df77..2b8686d5d6 100644 --- a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Movies { - public class MovieDbTrailerProvider : IHasOrder, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo> + public class MovieDbTrailerProvider : IHasOrder, IRemoteMetadataProvider<Trailer, TrailerInfo> { private readonly IHttpClient _httpClient; @@ -26,24 +26,9 @@ namespace MediaBrowser.Providers.Movies return MovieDbProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken); } - public Task<MetadataResult<ChannelVideoItem>> GetMetadata(ChannelItemLookupInfo info, CancellationToken cancellationToken) + public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken) { - if (info.ContentType != ChannelMediaContentType.MovieExtra || info.ExtraType != ExtraType.Trailer) - { - return Task.FromResult(new MetadataResult<ChannelVideoItem>()); - } - - return MovieDbProvider.Current.GetItemMetadata<ChannelVideoItem>(info, cancellationToken); - } - - public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ChannelItemLookupInfo info, CancellationToken cancellationToken) - { - if (info.ContentType != ChannelMediaContentType.MovieExtra || info.ExtraType != ExtraType.Trailer) - { - return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>()); - } - - return MovieDbProvider.Current.GetMovieSearchResults(info, cancellationToken); + return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken); } public string Name diff --git a/MediaBrowser.Providers/Movies/MovieExternalIds.cs b/MediaBrowser.Providers/Movies/MovieExternalIds.cs index c582447a9f..adaff5e771 100644 --- a/MediaBrowser.Providers/Movies/MovieExternalIds.cs +++ b/MediaBrowser.Providers/Movies/MovieExternalIds.cs @@ -28,13 +28,6 @@ namespace MediaBrowser.Providers.Movies public bool Supports(IHasProviderIds item) { - var channelItem = item as ChannelVideoItem; - - if (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra && channelItem.ExtraType == ExtraType.Trailer) - { - return true; - } - // Supports images for tv movies var tvProgram = item as LiveTvProgram; if (tvProgram != null && tvProgram.IsMovie) @@ -42,7 +35,7 @@ namespace MediaBrowser.Providers.Movies return true; } - return item is Movie || item is MusicVideo; + return item is Movie || item is MusicVideo || item is Trailer; } } @@ -88,7 +81,7 @@ namespace MediaBrowser.Providers.Movies public bool Supports(IHasProviderIds item) { - return item is Movie || item is MusicVideo; + return item is Movie || item is MusicVideo || item is Trailer; } } @@ -157,14 +150,7 @@ namespace MediaBrowser.Providers.Movies public bool Supports(IHasProviderIds item) { - var channelItem = item as ChannelVideoItem; - - if (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra && channelItem.ExtraType == ExtraType.Trailer) - { - return true; - } - - return item is Movie || item is MusicVideo || item is Series || item is Episode; + return item is Movie || item is MusicVideo || item is Series || item is Episode || item is Trailer; } } diff --git a/MediaBrowser.Providers/Movies/MovieMetadataService.cs b/MediaBrowser.Providers/Movies/MovieMetadataService.cs index 8757bdd0db..e70ec00576 100644 --- a/MediaBrowser.Providers/Movies/MovieMetadataService.cs +++ b/MediaBrowser.Providers/Movies/MovieMetadataService.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -8,6 +7,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; using System.Collections.Generic; using CommonIO; +using MediaBrowser.Controller.Entities; namespace MediaBrowser.Providers.Movies { @@ -37,10 +37,42 @@ namespace MediaBrowser.Providers.Movies var sourceItem = source.Item; var targetItem = target.Item; - if (replaceData || string.IsNullOrEmpty(targetItem.TmdbCollectionName)) + if (replaceData || string.IsNullOrEmpty(targetItem.CollectionName)) { - targetItem.TmdbCollectionName = sourceItem.TmdbCollectionName; + targetItem.CollectionName = sourceItem.CollectionName; } } } + + public class TrailerMetadataService : MetadataService<Trailer, TrailerInfo> + { + public TrailerMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager) + { + } + + protected override bool IsFullLocalMetadata(Trailer item) + { + if (string.IsNullOrWhiteSpace(item.Overview)) + { + return false; + } + if (!item.ProductionYear.HasValue) + { + return false; + } + return base.IsFullLocalMetadata(item); + } + + protected override void MergeData(MetadataResult<Trailer> source, MetadataResult<Trailer> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) + { + ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + + if (replaceData || target.Item.TrailerTypes.Count == 0) + { + target.Item.TrailerTypes = source.Item.TrailerTypes; + } + } + } + } diff --git a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs index eaebd426f6..345ed8adb8 100644 --- a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs @@ -81,23 +81,6 @@ namespace MediaBrowser.Providers.Omdb return false; } - var channelItem = item as IChannelMediaItem; - - if (channelItem != null) - { - if (channelItem.ContentType == ChannelMediaContentType.Movie) - { - return true; - } - if (channelItem.ContentType == ChannelMediaContentType.MovieExtra) - { - if (channelItem.ExtraType == ExtraType.Trailer) - { - return true; - } - } - } - // Supports images for tv movies var tvProgram = item as LiveTvProgram; if (tvProgram != null && tvProgram.IsMovie) @@ -105,7 +88,7 @@ namespace MediaBrowser.Providers.Omdb return true; } - return item is Movie; + return item is Movie || item is Trailer; } public int Order diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index ace1a8ffb9..0b092397fe 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -22,7 +22,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Omdb { public class OmdbItemProvider : IRemoteMetadataProvider<Series, SeriesInfo>, - IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>, IRemoteMetadataProvider<LiveTvProgram, LiveTvProgramLookupInfo> + IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<Trailer, TrailerInfo>, IRemoteMetadataProvider<LiveTvProgram, LiveTvProgramLookupInfo> { private readonly IJsonSerializer _jsonSerializer; private readonly IHttpClient _httpClient; @@ -100,13 +100,13 @@ namespace MediaBrowser.Providers.Omdb if (enableMultipleResults) { url += "&s=" + WebUtility.UrlEncode(name); + isSearch = true; } else { url += "&t=" + WebUtility.UrlEncode(name); } url += "&type=" + type; - isSearch = true; } else { @@ -196,23 +196,13 @@ namespace MediaBrowser.Providers.Omdb return list; } - public Task<MetadataResult<ChannelVideoItem>> GetMetadata(ChannelItemLookupInfo info, CancellationToken cancellationToken) + public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken) { - if (info.ContentType != ChannelMediaContentType.MovieExtra || info.ExtraType != ExtraType.Trailer) - { - return Task.FromResult(new MetadataResult<ChannelVideoItem>()); - } - - return GetMovieResult<ChannelVideoItem>(info, cancellationToken); + return GetMovieResult<Trailer>(info, cancellationToken); } - public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ChannelItemLookupInfo searchInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken) { - if (searchInfo.ContentType != ChannelMediaContentType.MovieExtra || searchInfo.ExtraType != ExtraType.Trailer) - { - return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>()); - } - return GetSearchResults(searchInfo, "movie", cancellationToken); } diff --git a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs index b5546683b5..2d4d484e60 100644 --- a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs @@ -59,12 +59,12 @@ namespace MediaBrowser.Providers.People // Avoid implicitly captured closure var itemName = item.Name; - var seriesWithPerson = _libraryManager.GetItems(new InternalItemsQuery + var seriesWithPerson = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Series).Name }, Person = itemName - }).Items.Cast<Series>() + }).Cast<Series>() .Where(i => TvdbSeriesProvider.IsValidSeries(i.ProviderIds)) .ToList(); diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs index d4e4b48445..3a1e05704f 100644 --- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -115,7 +115,7 @@ namespace MediaBrowser.Providers.TV { Name = seasonName, IndexNumber = seasonNumber, - Id = (series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName).GetMBId(typeof(Season)) + Id = _libraryManager.GetNewItemId((series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName), typeof(Season)) }; season.SetParent(series); diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs index 35129987d3..35129987d3 100644 --- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs b/MediaBrowser.Providers/TV/FanArt/FanArtTvUpdatesPostScanTask.cs index 71f02e028c..71f02e028c 100644 --- a/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanArtTvUpdatesPostScanTask.cs diff --git a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs index 5600c165a1..5600c165a1 100644 --- a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index ff31dbc920..248be675da 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -422,7 +422,7 @@ namespace MediaBrowser.Providers.TV Name = name, IndexNumber = episodeNumber, ParentIndexNumber = seasonNumber, - Id = (series.Id + seasonNumber.ToString(_usCulture) + name).GetMBId(typeof(Episode)) + Id = _libraryManager.GetNewItemId((series.Id + seasonNumber.ToString(_usCulture) + name), typeof(Episode)) }; episode.SetParent(season); diff --git a/MediaBrowser.Providers/TV/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs index 5a920c37fa..5a920c37fa 100644 --- a/MediaBrowser.Providers/TV/OmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs new file mode 100644 index 0000000000..9d16849482 --- /dev/null +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs @@ -0,0 +1,138 @@ +using CommonIO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Localization; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; +using MediaBrowser.Model.Serialization; +using MediaBrowser.Providers.Movies; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.TV +{ + public class MovieDbEpisodeImageProvider : + MovieDbProviderBase, + IRemoteImageProvider, + IHasOrder + { + public MovieDbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogManager logManager) + : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, logManager) + {} + + public IEnumerable<ImageType> GetSupportedImages(IHasImages item) + { + return new List<ImageType> + { + ImageType.Primary + }; + } + + public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken) + { + var episode = (Controller.Entities.TV.Episode)item; + var series = episode.Series; + + var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tmdb) : null; + + var list = new List<RemoteImageInfo>(); + + if (string.IsNullOrEmpty(seriesId)) + { + return list; + } + + var seasonNumber = episode.ParentIndexNumber; + var episodeNumber = episode.IndexNumber; + + if (!seasonNumber.HasValue || !episodeNumber.HasValue) + { + return list; + } + + var response = await GetEpisodeInfo(seriesId, seasonNumber.Value, episodeNumber.Value, + item.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false); + + var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); + + var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + + list.AddRange(GetPosters(response.images).Select(i => new RemoteImageInfo + { + Url = tmdbImageUrl + i.file_path, + CommunityRating = i.vote_average, + VoteCount = i.vote_count, + Width = i.width, + Height = i.height, + ProviderName = Name, + Type = ImageType.Primary, + RatingType = RatingType.Score + })); + + var language = item.GetPreferredMetadataLanguage(); + + var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); + + return list.OrderByDescending(i => + { + if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase)) + { + return 3; + } + if (!isLanguageEn) + { + if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase)) + { + return 2; + } + } + if (string.IsNullOrEmpty(i.Language)) + { + return isLanguageEn ? 3 : 2; + } + return 0; + }) + .ThenByDescending(i => i.CommunityRating ?? 0) + .ThenByDescending(i => i.VoteCount ?? 0) + .ToList(); + + } + + private IEnumerable<Still> GetPosters(Images images) + { + return images.stills ?? new List<Still>(); + } + + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + return GetResponse(url, cancellationToken); + } + + public string Name + { + get { return "TheMovieDb"; } + } + + public bool Supports(IHasImages item) + { + return item is Controller.Entities.TV.Episode; + } + + public int Order + { + get + { + // After tvdb + return 1; + } + } + } +} diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs new file mode 100644 index 0000000000..42254f3603 --- /dev/null +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs @@ -0,0 +1,179 @@ +using CommonIO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Localization; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Providers; +using MediaBrowser.Model.Serialization; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.TV +{ + class MovieDbEpisodeProvider : + MovieDbProviderBase, + IRemoteMetadataProvider<Episode, EpisodeInfo>, + IHasOrder + { + public MovieDbEpisodeProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogManager logManager) + : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, logManager) + { } + + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken) + { + var list = new List<RemoteSearchResult>(); + + // The search query must either provide an episode number or date + if (!searchInfo.IndexNumber.HasValue || !searchInfo.ParentIndexNumber.HasValue) + { + return list; + } + + var metadataResult = await GetMetadata(searchInfo, cancellationToken); + + if (metadataResult.HasMetadata) + { + var item = metadataResult.Item; + + list.Add(new RemoteSearchResult + { + IndexNumber = item.IndexNumber, + Name = item.Name, + ParentIndexNumber = item.ParentIndexNumber, + PremiereDate = item.PremiereDate, + ProductionYear = item.ProductionYear, + ProviderIds = item.ProviderIds, + SearchProviderName = Name, + IndexNumberEnd = item.IndexNumberEnd + }); + } + + return list; + } + + public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken) + { + var result = new MetadataResult<Episode>(); + + string seriesTmdbId; + info.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out seriesTmdbId); + + if (string.IsNullOrEmpty(seriesTmdbId)) + { + return result; + } + + var seasonNumber = info.ParentIndexNumber; + var episodeNumber = info.IndexNumber; + + if (!seasonNumber.HasValue || !episodeNumber.HasValue) + { + return result; + } + + try + { + var response = await GetEpisodeInfo(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); + + result.HasMetadata = true; + + var item = new Episode(); + result.Item = item; + + item.Name = info.Name; + item.IndexNumber = info.IndexNumber; + item.ParentIndexNumber = info.ParentIndexNumber; + item.IndexNumberEnd = info.IndexNumberEnd; + + if (response.external_ids.tvdb_id > 0) + { + item.SetProviderId(MetadataProviders.Tvdb, response.external_ids.tvdb_id.ToString(CultureInfo.InvariantCulture)); + } + + item.PremiereDate = response.air_date; + item.ProductionYear = result.Item.PremiereDate.Value.Year; + + item.Name = response.name; + item.Overview = response.overview; + + item.CommunityRating = (float)response.vote_average; + item.VoteCount = response.vote_count; + + result.ResetPeople(); + + var credits = response.credits; + if (credits != null) + { + //Actors, Directors, Writers - all in People + //actors come from cast + if (credits.cast != null) + { + foreach (var actor in credits.cast.OrderBy(a => a.order)) + { + result.AddPerson(new PersonInfo { Name = actor.name.Trim(), Role = actor.character, Type = PersonType.Actor, SortOrder = actor.order }); + } + } + + // guest stars + if (credits.guest_stars != null) + { + foreach (var guest in credits.guest_stars.OrderBy(a => a.order)) + { + result.AddPerson(new PersonInfo { Name = guest.name.Trim(), Role = guest.character, Type = PersonType.GuestStar, SortOrder = guest.order }); + } + } + + //and the rest from crew + if (credits.crew != null) + { + foreach (var person in credits.crew) + { + result.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = person.department }); + } + } + } + } + catch (HttpException ex) + { + Logger.Error("No metadata found for {0}", seasonNumber.Value); + + if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) + { + return result; + } + + throw; + } + + return result; + } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + return GetResponse(url, cancellationToken); + } + + public int Order + { + get + { + // After TheTvDb + return 1; + } + } + + public string Name + { + get { return "TheMovieDb"; } + } + } +} diff --git a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs index 115eadb96e..d22827c25e 100644 --- a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs @@ -1,148 +1,45 @@ -using MediaBrowser.Common.IO; +using CommonIO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Providers; +using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Movies; using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; -using CommonIO; namespace MediaBrowser.Providers.TV { - public class MovieDbEpisodeImageProvider : IRemoteImageProvider, IHasOrder + public abstract class MovieDbProviderBase { - private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos"; + private const string EpisodeUrlPattern = @"http://api.themoviedb.org/3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos"; private readonly IHttpClient _httpClient; private readonly IServerConfigurationManager _configurationManager; private readonly IJsonSerializer _jsonSerializer; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; + private readonly ILogger _logger; - public MovieDbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization) + public MovieDbProviderBase(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogManager logManager) { _httpClient = httpClient; _configurationManager = configurationManager; _jsonSerializer = jsonSerializer; _fileSystem = fileSystem; _localization = localization; + _logger = logManager.GetLogger(GetType().Name); } - public IEnumerable<ImageType> GetSupportedImages(IHasImages item) + protected ILogger Logger { - return new List<ImageType> - { - ImageType.Primary - }; - } - - public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken) - { - var episode = (Controller.Entities.TV.Episode)item; - var series = episode.Series; - - var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tmdb) : null; - - var list = new List<RemoteImageInfo>(); - - if (string.IsNullOrEmpty(seriesId)) - { - return list; - } - - var seasonNumber = episode.ParentIndexNumber; - var episodeNumber = episode.IndexNumber; - - if (!seasonNumber.HasValue || !episodeNumber.HasValue) - { - return list; - } - - var response = await GetEpisodeInfo(seriesId, seasonNumber.Value, episodeNumber.Value, - item.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false); - - var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; - - list.AddRange(GetPosters(response.images).Select(i => new RemoteImageInfo - { - Url = tmdbImageUrl + i.file_path, - CommunityRating = i.vote_average, - VoteCount = i.vote_count, - Width = i.width, - Height = i.height, - ProviderName = Name, - Type = ImageType.Primary, - RatingType = RatingType.Score - })); - - var language = item.GetPreferredMetadataLanguage(); - - var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); - - return list.OrderByDescending(i => - { - if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase)) - { - return 3; - } - if (!isLanguageEn) - { - if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase)) - { - return 2; - } - } - if (string.IsNullOrEmpty(i.Language)) - { - return isLanguageEn ? 3 : 2; - } - return 0; - }) - .ThenByDescending(i => i.CommunityRating ?? 0) - .ThenByDescending(i => i.VoteCount ?? 0) - .ToList(); - - } - - private IEnumerable<Still> GetPosters(Images images) - { - return images.stills ?? new List<Still>(); - } - - - public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) - { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url, - ResourcePool = MovieDbProvider.Current.MovieDbResourcePool - }); - } - - public string Name - { - get { return "TheMovieDb"; } + get { return _logger; } } - public bool Supports(IHasImages item) - { - return item is Controller.Entities.TV.Episode; - } - - private async Task<RootObject> GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage, + protected async Task<RootObject> GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage, CancellationToken cancellationToken) { await EnsureEpisodeInfo(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage, cancellationToken) @@ -203,7 +100,7 @@ namespace MediaBrowser.Providers.TV internal async Task DownloadEpisodeInfo(string id, int seasonNumber, int episodeNumber, string preferredMetadataLanguage, CancellationToken cancellationToken) { - var mainResult = await FetchMainResult(id, seasonNumber, episodeNumber, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); + var mainResult = await FetchMainResult(EpisodeUrlPattern, id, seasonNumber, episodeNumber, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); var dataFilePath = GetDataFilePath(id, seasonNumber, episodeNumber, preferredMetadataLanguage); @@ -211,9 +108,9 @@ namespace MediaBrowser.Providers.TV _jsonSerializer.SerializeToFile(mainResult, dataFilePath); } - internal async Task<RootObject> FetchMainResult(string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken) + internal async Task<RootObject> FetchMainResult(string urlPattern, string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken) { - var url = string.Format(GetTvInfo3, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, MovieDbProvider.ApiKey); + var url = string.Format(urlPattern, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, MovieDbProvider.ApiKey); if (!string.IsNullOrEmpty(language)) { @@ -238,6 +135,16 @@ namespace MediaBrowser.Providers.TV } } + protected Task<HttpResponseInfo> GetResponse(string url, CancellationToken cancellationToken) + { + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = MovieDbProvider.Current.MovieDbResourcePool + }); + } + public class Still { public double aspect_ratio { get; set; } @@ -308,7 +215,7 @@ namespace MediaBrowser.Providers.TV public class RootObject { - public string air_date { get; set; } + public DateTime air_date { get; set; } public int episode_number { get; set; } public string name { get; set; } public string overview { get; set; } @@ -323,14 +230,5 @@ namespace MediaBrowser.Providers.TV public Credits credits { get; set; } public Videos videos { get; set; } } - - public int Order - { - get - { - // After tvdb - return 1; - } - } } } diff --git a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs index 6933901927..0033c8a2ff 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs @@ -201,7 +201,7 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); + url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language)); } var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs index 3516fcbd11..f7c19988c3 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Providers.TV { var list = new List<RemoteImageInfo>(); - var results = await FetchImages((BaseItem)item, _jsonSerializer, cancellationToken).ConfigureAwait(false); + var results = await FetchImages((BaseItem)item, null, _jsonSerializer, cancellationToken).ConfigureAwait(false); if (results == null) { @@ -146,14 +146,14 @@ namespace MediaBrowser.Providers.TV /// Fetches the images. /// </summary> /// <param name="item">The item.</param> + /// <param name="language">The language.</param> /// <param name="jsonSerializer">The json serializer.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{MovieImages}.</returns> - private async Task<MovieDbSeriesProvider.Images> FetchImages(BaseItem item, IJsonSerializer jsonSerializer, + private async Task<MovieDbSeriesProvider.Images> FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer, CancellationToken cancellationToken) { var tmdbId = item.GetProviderId(MetadataProviders.Tmdb); - var language = item.GetPreferredMetadataLanguage(); if (string.IsNullOrEmpty(tmdbId)) { diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs index 994343ee24..ad2cfa12b5 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs @@ -301,12 +301,11 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); - } + url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language)); - var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); - // Get images in english and with no language - url += "&include_image_language=" + includeImageLanguageParam; + // Get images in english and with no language + url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); + } cancellationToken.ThrowIfCancellationRequested(); @@ -333,7 +332,13 @@ namespace MediaBrowser.Providers.TV { _logger.Info("MovieDbSeriesProvider couldn't find meta for language " + language + ". Trying English..."); - url = string.Format(GetTvInfo3, id, MovieDbProvider.ApiKey) + "&include_image_language=" + includeImageLanguageParam + "&language=en"; + url = string.Format(GetTvInfo3, id, MovieDbProvider.ApiKey) + "&language=en"; + + if (!string.IsNullOrEmpty(language)) + { + // Get images in english and with no language + url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); + } using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions { @@ -359,10 +364,6 @@ namespace MediaBrowser.Providers.TV { throw new ArgumentNullException("tmdbId"); } - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException("language"); - } var path = GetDataFilePath(tmdbId, language); @@ -386,15 +387,10 @@ namespace MediaBrowser.Providers.TV { throw new ArgumentNullException("tmdbId"); } - if (string.IsNullOrEmpty(preferredLanguage)) - { - throw new ArgumentNullException("preferredLanguage"); - } var path = GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("series-{0}.json", - preferredLanguage ?? string.Empty); + var filename = string.Format("series-{0}.json", preferredLanguage ?? string.Empty); return Path.Combine(path, filename); } diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs index 50ecc6bbfd..50ecc6bbfd 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs index 3920330489..291214fcd3 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs @@ -259,36 +259,36 @@ namespace MediaBrowser.Providers.TV return files; } - if (seasonNumber == null) - { - return files; - } - - var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber)); - - var fileInfo = _fileSystem.GetFileInfo(file); var usingAbsoluteData = false; - if (fileInfo.Exists) - { - files.Add(fileInfo); - } - else - { - file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber)); - fileInfo = _fileSystem.GetFileInfo(file); - if (fileInfo.Exists) - { - files.Add(fileInfo); - usingAbsoluteData = true; - } - } + if (seasonNumber.HasValue) + { + var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber)); + var fileInfo = _fileSystem.GetFileInfo(file); + + if (fileInfo.Exists) + { + files.Add(fileInfo); + } + } + else + { + usingAbsoluteData = true; + var file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber)); + var fileInfo = _fileSystem.GetFileInfo(file); + if (fileInfo.Exists) + { + files.Add(fileInfo); + } + } var end = endingEpisodeNumber ?? episodeNumber; episodeNumber++; while (episodeNumber <= end) { + string file; + if (usingAbsoluteData) { file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber)); @@ -298,7 +298,7 @@ namespace MediaBrowser.Providers.TV file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber)); } - fileInfo = _fileSystem.GetFileInfo(file); + var fileInfo = _fileSystem.GetFileInfo(file); if (fileInfo.Exists) { files.Add(fileInfo); diff --git a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs index d362ca722d..d362ca722d 100644 --- a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs diff --git a/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonIdentityProvider.cs index edeea36e44..4198430c9f 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonIdentityProvider.cs @@ -27,6 +27,11 @@ namespace MediaBrowser.Providers.TV public static TvdbSeasonIdentity? ParseIdentity(string id) { + if (id == null) + { + return null; + } + try { var parts = id.Split(':'); diff --git a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs index 7af85ecc93..7af85ecc93 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs index eae389dfb0..eae389dfb0 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs index 4a7ae57fb0..593507fb2a 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs @@ -160,19 +160,19 @@ namespace MediaBrowser.Providers.TV var series = result.Item; string id; - if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id) && !string.IsNullOrEmpty(id)) { series.SetProviderId(MetadataProviders.Tvdb, id); } - if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id) && !string.IsNullOrEmpty(id)) { series.SetProviderId(MetadataProviders.Imdb, id); } var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds); - var seriesXmlPath = GetSeriesXmlPath (seriesProviderIds, metadataLanguage); + var seriesXmlPath = GetSeriesXmlPath(seriesProviderIds, metadataLanguage); var actorsXmlPath = Path.Combine(seriesDataPath, "actors.xml"); FetchSeriesInfo(series, seriesXmlPath, cancellationToken); @@ -320,7 +320,7 @@ namespace MediaBrowser.Providers.TV internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds) { string id; - if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id) && !string.IsNullOrEmpty(id)) { // This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet. if (!string.IsNullOrWhiteSpace(id)) @@ -329,7 +329,7 @@ namespace MediaBrowser.Providers.TV } } - if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id) && !string.IsNullOrEmpty(id)) { // This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet. if (!string.IsNullOrWhiteSpace(id)) @@ -340,7 +340,7 @@ namespace MediaBrowser.Providers.TV return false; } - private SemaphoreSlim _ensureSemaphore = new SemaphoreSlim(1,1); + private SemaphoreSlim _ensureSemaphore = new SemaphoreSlim(1, 1); internal async Task<string> EnsureSeriesInfo(Dictionary<string, string> seriesProviderIds, string preferredMetadataLanguage, CancellationToken cancellationToken) { await _ensureSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -348,7 +348,7 @@ namespace MediaBrowser.Providers.TV try { string seriesId; - if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId) && !string.IsNullOrEmpty(seriesId)) { var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds); @@ -362,7 +362,7 @@ namespace MediaBrowser.Providers.TV return seriesDataPath; } - if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId) && !string.IsNullOrEmpty(seriesId)) { var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds); @@ -1300,14 +1300,14 @@ namespace MediaBrowser.Providers.TV internal static string GetSeriesDataPath(IApplicationPaths appPaths, Dictionary<string, string> seriesProviderIds) { string seriesId; - if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId) && !string.IsNullOrEmpty(seriesId)) { var seriesDataPath = Path.Combine(GetSeriesDataPath(appPaths), seriesId); return seriesDataPath; } - if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId)) + if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId) && !string.IsNullOrEmpty(seriesId)) { var seriesDataPath = Path.Combine(GetSeriesDataPath(appPaths), seriesId); @@ -1317,14 +1317,14 @@ namespace MediaBrowser.Providers.TV return null; } - public string GetSeriesXmlPath(Dictionary<string, string> seriesProviderIds, string language) - { - var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds); + public string GetSeriesXmlPath(Dictionary<string, string> seriesProviderIds, string language) + { + var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds); - var seriesXmlFilename = language.ToLower() + ".xml"; + var seriesXmlFilename = language.ToLower() + ".xml"; - return Path.Combine (seriesDataPath, seriesXmlFilename); - } + return Path.Combine(seriesDataPath, seriesXmlFilename); + } /// <summary> /// Gets the series data path. @@ -1466,4 +1466,4 @@ namespace MediaBrowser.Providers.TV }; } } -} +}
\ No newline at end of file diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config index 89172044ac..da365b0ce8 100644 --- a/MediaBrowser.Providers/packages.config +++ b/MediaBrowser.Providers/packages.config @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="CommonIO" version="1.0.0.8" targetFramework="net45" /> + <package id="CommonIO" version="1.0.0.9" targetFramework="net45" /> <package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" /> <package id="morelinq" version="1.4.0" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> |
