From 6c50734131604d98f7637693ebcb91dedaac506e Mon Sep 17 00:00:00 2001 From: softworkz Date: Thu, 3 Mar 2016 02:56:51 +0100 Subject: [PATCH 001/140] Created new Metadata provider for TheMovieDB: MovieDbEpisodeProvider Most of the required logic already existed in MovieDbEpisodeImageProvider. In order to avoid duplicated code, I have moved all common code to a new base class "MovieDbProviderBase" from which MovieDbEpisodeProvider and MovieDbEpisodeImageProvider are inheriting now. --- .../MediaBrowser.Providers.csproj | 2 + .../TV/MovieDbEpisodeImageProvider.cs | 218 +--------------- .../TV/MovieDbEpisodeProvider.cs | 152 ++++++++++++ .../TV/MovieDbProviderBase.cs | 234 ++++++++++++++++++ 4 files changed, 398 insertions(+), 208 deletions(-) create mode 100644 MediaBrowser.Providers/TV/MovieDbEpisodeProvider.cs create mode 100644 MediaBrowser.Providers/TV/MovieDbProviderBase.cs diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 24397dd5a0..aeaf263c26 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -173,10 +173,12 @@ + + diff --git a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs index 115eadb96e..9d16849482 100644 --- a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.IO; +using CommonIO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -6,37 +6,26 @@ 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.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 class MovieDbEpisodeImageProvider : + MovieDbProviderBase, + IRemoteImageProvider, + IHasOrder { - 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 readonly IHttpClient _httpClient; - private readonly IServerConfigurationManager _configurationManager; - private readonly IJsonSerializer _jsonSerializer; - private readonly IFileSystem _fileSystem; - private readonly ILocalizationManager _localization; - - public MovieDbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization) - { - _httpClient = httpClient; - _configurationManager = configurationManager; - _jsonSerializer = jsonSerializer; - _fileSystem = fileSystem; - _localization = localization; - } + public MovieDbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogManager logManager) + : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, logManager) + {} public IEnumerable GetSupportedImages(IHasImages item) { @@ -124,12 +113,7 @@ namespace MediaBrowser.Providers.TV public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url, - ResourcePool = MovieDbProvider.Current.MovieDbResourcePool - }); + return GetResponse(url, cancellationToken); } public string Name @@ -142,188 +126,6 @@ namespace MediaBrowser.Providers.TV return item is Controller.Entities.TV.Episode; } - private async Task GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage, - CancellationToken cancellationToken) - { - await EnsureEpisodeInfo(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage, cancellationToken) - .ConfigureAwait(false); - - var dataFilePath = GetDataFilePath(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage); - - return _jsonSerializer.DeserializeFromFile(dataFilePath); - } - - internal Task EnsureEpisodeInfo(string tmdbId, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken) - { - if (string.IsNullOrEmpty(tmdbId)) - { - throw new ArgumentNullException("tmdbId"); - } - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException("language"); - } - - var path = GetDataFilePath(tmdbId, seasonNumber, episodeNumber, language); - - var fileInfo = _fileSystem.GetFileSystemInfo(path); - - if (fileInfo.Exists) - { - // If it's recent or automatic updates are enabled, don't re-download - if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 3) - { - return Task.FromResult(true); - } - } - - return DownloadEpisodeInfo(tmdbId, seasonNumber, episodeNumber, language, cancellationToken); - } - - internal string GetDataFilePath(string tmdbId, int seasonNumber, int episodeNumber, string preferredLanguage) - { - if (string.IsNullOrEmpty(tmdbId)) - { - throw new ArgumentNullException("tmdbId"); - } - if (string.IsNullOrEmpty(preferredLanguage)) - { - throw new ArgumentNullException("preferredLanguage"); - } - - var path = MovieDbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - - var filename = string.Format("season-{0}-episode-{1}-{2}.json", - seasonNumber.ToString(CultureInfo.InvariantCulture), - episodeNumber.ToString(CultureInfo.InvariantCulture), - preferredLanguage); - - return Path.Combine(path, filename); - } - - 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 dataFilePath = GetDataFilePath(id, seasonNumber, episodeNumber, preferredMetadataLanguage); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath)); - _jsonSerializer.SerializeToFile(mainResult, dataFilePath); - } - - internal async Task FetchMainResult(string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken) - { - var url = string.Format(GetTvInfo3, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, MovieDbProvider.ApiKey); - - if (!string.IsNullOrEmpty(language)) - { - url += string.Format("&language={0}", language); - } - - var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); - // Get images in english and with no language - url += "&include_image_language=" + includeImageLanguageParam; - - cancellationToken.ThrowIfCancellationRequested(); - - using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - AcceptHeader = MovieDbProvider.AcceptHeader - - }).ConfigureAwait(false)) - { - return _jsonSerializer.DeserializeFromStream(json); - } - } - - public class Still - { - public double aspect_ratio { get; set; } - public string file_path { get; set; } - public int height { get; set; } - public string id { get; set; } - public object iso_639_1 { get; set; } - public double vote_average { get; set; } - public int vote_count { get; set; } - public int width { get; set; } - } - - public class Images - { - public List stills { get; set; } - } - - public class ExternalIds - { - public string imdb_id { get; set; } - public object freebase_id { get; set; } - public string freebase_mid { get; set; } - public int tvdb_id { get; set; } - public int tvrage_id { get; set; } - } - - public class Cast - { - public string character { get; set; } - public string credit_id { get; set; } - public int id { get; set; } - public string name { get; set; } - public string profile_path { get; set; } - public int order { get; set; } - } - - public class Crew - { - public int id { get; set; } - public string credit_id { get; set; } - public string name { get; set; } - public string department { get; set; } - public string job { get; set; } - public string profile_path { get; set; } - } - - public class GuestStar - { - public int id { get; set; } - public string name { get; set; } - public string credit_id { get; set; } - public string character { get; set; } - public int order { get; set; } - public string profile_path { get; set; } - } - - public class Credits - { - public List cast { get; set; } - public List crew { get; set; } - public List guest_stars { get; set; } - } - - public class Videos - { - public List results { get; set; } - } - - public class RootObject - { - public string air_date { get; set; } - public int episode_number { get; set; } - public string name { get; set; } - public string overview { get; set; } - public int id { get; set; } - public object production_code { get; set; } - public int season_number { get; set; } - public string still_path { get; set; } - public double vote_average { get; set; } - public int vote_count { get; set; } - public Images images { get; set; } - public ExternalIds external_ids { get; set; } - public Credits credits { get; set; } - public Videos videos { get; set; } - } - public int Order { get diff --git a/MediaBrowser.Providers/TV/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/TV/MovieDbEpisodeProvider.cs new file mode 100644 index 0000000000..6a98fcf612 --- /dev/null +++ b/MediaBrowser.Providers/TV/MovieDbEpisodeProvider.cs @@ -0,0 +1,152 @@ +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, + IHasOrder + { + public MovieDbEpisodeProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogManager logManager) + : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, logManager) + { } + + public Task> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken) + { + return Task.FromResult>(new List()); + } + + public async Task> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken) + { + var result = new MetadataResult(); + + 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 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/MovieDbProviderBase.cs b/MediaBrowser.Providers/TV/MovieDbProviderBase.cs new file mode 100644 index 0000000000..d22827c25e --- /dev/null +++ b/MediaBrowser.Providers/TV/MovieDbProviderBase.cs @@ -0,0 +1,234 @@ +using CommonIO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Localization; +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.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.TV +{ + public abstract class MovieDbProviderBase + { + 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 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); + } + + protected ILogger Logger + { + get { return _logger; } + } + + protected async Task GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage, + CancellationToken cancellationToken) + { + await EnsureEpisodeInfo(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage, cancellationToken) + .ConfigureAwait(false); + + var dataFilePath = GetDataFilePath(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage); + + return _jsonSerializer.DeserializeFromFile(dataFilePath); + } + + internal Task EnsureEpisodeInfo(string tmdbId, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(tmdbId)) + { + throw new ArgumentNullException("tmdbId"); + } + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException("language"); + } + + var path = GetDataFilePath(tmdbId, seasonNumber, episodeNumber, language); + + var fileInfo = _fileSystem.GetFileSystemInfo(path); + + if (fileInfo.Exists) + { + // If it's recent or automatic updates are enabled, don't re-download + if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 3) + { + return Task.FromResult(true); + } + } + + return DownloadEpisodeInfo(tmdbId, seasonNumber, episodeNumber, language, cancellationToken); + } + + internal string GetDataFilePath(string tmdbId, int seasonNumber, int episodeNumber, string preferredLanguage) + { + if (string.IsNullOrEmpty(tmdbId)) + { + throw new ArgumentNullException("tmdbId"); + } + if (string.IsNullOrEmpty(preferredLanguage)) + { + throw new ArgumentNullException("preferredLanguage"); + } + + var path = MovieDbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); + + var filename = string.Format("season-{0}-episode-{1}-{2}.json", + seasonNumber.ToString(CultureInfo.InvariantCulture), + episodeNumber.ToString(CultureInfo.InvariantCulture), + preferredLanguage); + + return Path.Combine(path, filename); + } + + internal async Task DownloadEpisodeInfo(string id, int seasonNumber, int episodeNumber, string preferredMetadataLanguage, CancellationToken cancellationToken) + { + var mainResult = await FetchMainResult(EpisodeUrlPattern, id, seasonNumber, episodeNumber, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); + + var dataFilePath = GetDataFilePath(id, seasonNumber, episodeNumber, preferredMetadataLanguage); + + _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath)); + _jsonSerializer.SerializeToFile(mainResult, dataFilePath); + } + + internal async Task FetchMainResult(string urlPattern, string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken) + { + var url = string.Format(urlPattern, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, MovieDbProvider.ApiKey); + + if (!string.IsNullOrEmpty(language)) + { + url += string.Format("&language={0}", language); + } + + var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language); + // Get images in english and with no language + url += "&include_image_language=" + includeImageLanguageParam; + + cancellationToken.ThrowIfCancellationRequested(); + + using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions + { + Url = url, + CancellationToken = cancellationToken, + AcceptHeader = MovieDbProvider.AcceptHeader + + }).ConfigureAwait(false)) + { + return _jsonSerializer.DeserializeFromStream(json); + } + } + + protected Task 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; } + public string file_path { get; set; } + public int height { get; set; } + public string id { get; set; } + public object iso_639_1 { get; set; } + public double vote_average { get; set; } + public int vote_count { get; set; } + public int width { get; set; } + } + + public class Images + { + public List stills { get; set; } + } + + public class ExternalIds + { + public string imdb_id { get; set; } + public object freebase_id { get; set; } + public string freebase_mid { get; set; } + public int tvdb_id { get; set; } + public int tvrage_id { get; set; } + } + + public class Cast + { + public string character { get; set; } + public string credit_id { get; set; } + public int id { get; set; } + public string name { get; set; } + public string profile_path { get; set; } + public int order { get; set; } + } + + public class Crew + { + public int id { get; set; } + public string credit_id { get; set; } + public string name { get; set; } + public string department { get; set; } + public string job { get; set; } + public string profile_path { get; set; } + } + + public class GuestStar + { + public int id { get; set; } + public string name { get; set; } + public string credit_id { get; set; } + public string character { get; set; } + public int order { get; set; } + public string profile_path { get; set; } + } + + public class Credits + { + public List cast { get; set; } + public List crew { get; set; } + public List guest_stars { get; set; } + } + + public class Videos + { + public List results { get; set; } + } + + public class RootObject + { + public DateTime air_date { get; set; } + public int episode_number { get; set; } + public string name { get; set; } + public string overview { get; set; } + public int id { get; set; } + public object production_code { get; set; } + public int season_number { get; set; } + public string still_path { get; set; } + public double vote_average { get; set; } + public int vote_count { get; set; } + public Images images { get; set; } + public ExternalIds external_ids { get; set; } + public Credits credits { get; set; } + public Videos videos { get; set; } + } + } +} From 86de8e27b9b636d2a55d705820cca269f699ea6a Mon Sep 17 00:00:00 2001 From: softworkz Date: Thu, 3 Mar 2016 05:10:15 +0100 Subject: [PATCH 002/140] Added migration task for new MovieDbEpisodeProvider Ensures that the new provider is disabled by default --- .../ApplicationHost.cs | 1 + .../MediaBrowser.Server.Startup.Common.csproj | 1 + .../MovieDbEpisodeProviderMigration.cs | 47 +++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 MediaBrowser.Server.Startup.Common/Migrations/MovieDbEpisodeProviderMigration.cs diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index a543808504..b71fe365d3 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -374,6 +374,7 @@ namespace MediaBrowser.Server.Startup.Common var migrations = new List { new OmdbEpisodeProviderMigration(ServerConfigurationManager), + new MovieDbEpisodeProviderMigration(ServerConfigurationManager), new DbMigration(ServerConfigurationManager, TaskManager) }; diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index a4028d5b03..9321c311b4 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -73,6 +73,7 @@ + diff --git a/MediaBrowser.Server.Startup.Common/Migrations/MovieDbEpisodeProviderMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/MovieDbEpisodeProviderMigration.cs new file mode 100644 index 0000000000..c2ed0c9818 --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Migrations/MovieDbEpisodeProviderMigration.cs @@ -0,0 +1,47 @@ +using MediaBrowser.Controller.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Startup.Common.Migrations +{ + class MovieDbEpisodeProviderMigration : IVersionMigration + { + private readonly IServerConfigurationManager _config; + private const string _providerName = "TheMovieDb"; + + public MovieDbEpisodeProviderMigration(IServerConfigurationManager config) + { + _config = config; + } + + public void Run() + { + var migrationKey = this.GetType().FullName; + var migrationKeyList = _config.Configuration.Migrations.ToList(); + + if (!migrationKeyList.Contains(migrationKey)) + { + foreach (var metaDataOption in _config.Configuration.MetadataOptions) + { + if (metaDataOption.ItemType == "Episode") + { + var disabledFetchers = metaDataOption.DisabledMetadataFetchers.ToList(); + if (!disabledFetchers.Contains(_providerName)) + { + disabledFetchers.Add(_providerName); + metaDataOption.DisabledMetadataFetchers = disabledFetchers.ToArray(); + } + } + } + + migrationKeyList.Add(migrationKey); + _config.Configuration.Migrations = migrationKeyList.ToArray(); + _config.SaveConfiguration(); + } + + } + } +} From fa8d79a191701170f5443ede7d15b62374f717a7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Mar 2016 21:52:41 -0500 Subject: [PATCH 003/140] add path to table creation --- .../Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index cd439d1f27..18a41d82a6 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] queries = { - "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID)", + "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", "create index if not exists idx_TypedBaseItems on TypedBaseItems(guid)", "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)", "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)", From 22377f2516b78d9eb6a2e5bf4e99958590bd5788 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Mar 2016 12:07:14 -0500 Subject: [PATCH 004/140] auto-organize fixes --- .../TV/TvdbSeasonIdentityProvider.cs | 5 +++ .../TV/TvdbSeriesProvider.cs | 34 +++++++++---------- .../FileOrganization/TvFolderOrganizer.cs | 8 ++--- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs index edeea36e44..4198430c9f 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs +++ b/MediaBrowser.Providers/TV/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/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 4a7ae57fb0..593507fb2a 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/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 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 EnsureSeriesInfo(Dictionary 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 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 seriesProviderIds, string language) - { - var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds); + public string GetSeriesXmlPath(Dictionary 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); + } /// /// Gets the series data path. @@ -1466,4 +1466,4 @@ namespace MediaBrowser.Providers.TV }; } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index 845fcdff27..43bd2f29cf 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } catch (Exception ex) { - _logger.ErrorException("Error organizing episode {0}", ex, file); + _logger.ErrorException("Error organizing episode {0}", ex, file.FullName); } numComplete++; @@ -132,7 +132,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { try { - return _fileSystem.GetFiles(path, true) + return _fileSystem.GetFiles(path, true) .ToList(); } catch (IOException ex) @@ -150,7 +150,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization /// The extensions. private void DeleteLeftOverFiles(string path, IEnumerable extensions) { - var eligibleFiles = _fileSystem.GetFiles(path, true) + var eligibleFiles = _fileSystem.GetFiles(path, true) .Where(i => extensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)) .ToList(); @@ -206,4 +206,4 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return watchLocations.Contains(path, StringComparer.OrdinalIgnoreCase); } } -} +} \ No newline at end of file From 21ebd05a0ef72c0b4c8f5d0c3d84077e0579b5ba Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Mar 2016 12:38:51 -0500 Subject: [PATCH 005/140] update MovieDb providers to search for images using all languages --- .../BoxSets/MovieDbBoxSetImageProvider.cs | 2 +- .../BoxSets/MovieDbBoxSetProvider.cs | 23 +++++++------- .../Movies/MovieDbImageProvider.cs | 7 ++--- .../Movies/MovieDbProvider.cs | 31 ++++++++++--------- .../TV/MovieDbSeriesImageProvider.cs | 6 ++-- .../TV/MovieDbSeriesProvider.cs | 26 +++++++--------- 6 files changed, 45 insertions(+), 50 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..37aaf038ff 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -169,11 +169,10 @@ namespace MediaBrowser.Providers.BoxSets if (!string.IsNullOrEmpty(language)) { url += string.Format("&language={0}", 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/Movies/MovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs index b6f93392b3..e86ae4b047 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Providers.Movies { var list = new List(); - 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 +183,13 @@ namespace MediaBrowser.Providers.Movies /// Fetches the images. /// /// The item. + /// The language. /// The json serializer. /// The cancellation token. /// Task{MovieImages}. - private async Task FetchImages(BaseItem item, IJsonSerializer jsonSerializer, - CancellationToken cancellationToken) + private async Task 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..9ab9e44fca 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -226,10 +226,6 @@ namespace MediaBrowser.Providers.Movies { throw new ArgumentNullException("tmdbId"); } - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException("language"); - } var path = GetDataFilePath(tmdbId, language); @@ -253,15 +249,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); } @@ -298,11 +294,10 @@ namespace MediaBrowser.Providers.Movies if (!string.IsNullOrEmpty(language)) { url += string.Format("&language={0}", 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 +343,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/TV/MovieDbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesImageProvider.cs index 3516fcbd11..f7c19988c3 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeriesImageProvider.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Providers.TV { var list = new List(); - 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. /// /// The item. + /// The language. /// The json serializer. /// The cancellation token. /// Task{MovieImages}. - private async Task FetchImages(BaseItem item, IJsonSerializer jsonSerializer, + private async Task 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/MovieDbSeriesProvider.cs index 994343ee24..5b4153760d 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs @@ -302,11 +302,10 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(language)) { url += string.Format("&language={0}", 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); } From ca83644e1cf936d3f95572cad8a35fba0148e1b7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Mar 2016 23:16:55 -0500 Subject: [PATCH 006/140] handle no subs setting --- .../Library/MediaSourceManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index e4a085f421..dfc6fc1259 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -17,6 +17,7 @@ using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.IO; +using MediaBrowser.Model.Configuration; namespace MediaBrowser.Server.Implementations.Library { @@ -276,7 +277,7 @@ namespace MediaBrowser.Server.Implementations.Library private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user) { - if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections) + if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None) { var index = userData.SubtitleStreamIndex.Value; // Make sure the saved index is still valid From 63efe6ae987b363ca6c7789f576de4907debaab9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Mar 2016 23:17:02 -0500 Subject: [PATCH 007/140] handle people image failures --- .../Manager/MetadataService.cs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) 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); From 62023e986aeba762caf9c9f2a2dbe5f5d3177a09 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 5 Mar 2016 13:29:14 -0500 Subject: [PATCH 008/140] re-enable sat/ip --- .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 378 +++++++++--------- .../LiveTv/TunerHosts/SatIp/SatIpHost.cs | 254 ++++++------ 2 files changed, 316 insertions(+), 316 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index f6db2f5a8d..6781e498ac 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -21,225 +21,225 @@ using MediaBrowser.Model.Serialization; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { - //public class SatIpDiscovery : IServerEntryPoint - //{ - // private readonly IDeviceDiscovery _deviceDiscovery; - // private readonly IServerConfigurationManager _config; - // private readonly ILogger _logger; - // private readonly ILiveTvManager _liveTvManager; - // private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); - // private readonly IHttpClient _httpClient; - // private readonly IJsonSerializer _json; + public class SatIpDiscovery : IServerEntryPoint + { + private readonly IDeviceDiscovery _deviceDiscovery; + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly ILiveTvManager _liveTvManager; + private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); + private readonly IHttpClient _httpClient; + private readonly IJsonSerializer _json; - // public static SatIpDiscovery Current; + public static SatIpDiscovery Current; - // private readonly List _discoveredHosts = new List(); + private readonly List _discoveredHosts = new List(); - // public List DiscoveredHosts - // { - // get { return _discoveredHosts.ToList(); } - // } + public List DiscoveredHosts + { + get { return _discoveredHosts.ToList(); } + } - // public SatIpDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json) - // { - // _deviceDiscovery = deviceDiscovery; - // _config = config; - // _logger = logger; - // _liveTvManager = liveTvManager; - // _httpClient = httpClient; - // _json = json; - // Current = this; - // } + public SatIpDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json) + { + _deviceDiscovery = deviceDiscovery; + _config = config; + _logger = logger; + _liveTvManager = liveTvManager; + _httpClient = httpClient; + _json = json; + Current = this; + } - // public void Run() - // { - // _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; - // } + public void Run() + { + _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; + } - // void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) - // { - // string st = null; - // string nt = null; - // e.Headers.TryGetValue("ST", out st); - // e.Headers.TryGetValue("NT", out nt); + void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) + { + string st = null; + string nt = null; + e.Headers.TryGetValue("ST", out st); + e.Headers.TryGetValue("NT", out nt); - // if (string.Equals(st, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase) || - // string.Equals(nt, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase)) - // { - // string location; - // if (e.Headers.TryGetValue("Location", out location) && !string.IsNullOrWhiteSpace(location)) - // { - // _logger.Debug("SAT IP found at {0}", location); + if (string.Equals(st, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase) || + string.Equals(nt, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase)) + { + string location; + if (e.Headers.TryGetValue("Location", out location) && !string.IsNullOrWhiteSpace(location)) + { + _logger.Debug("SAT IP found at {0}", location); - // // Just get the beginning of the url - // AddDevice(location); - // } - // } - // } + // Just get the beginning of the url + AddDevice(location); + } + } + } - // private async void AddDevice(string location) - // { - // await _semaphore.WaitAsync().ConfigureAwait(false); + private async void AddDevice(string location) + { + await _semaphore.WaitAsync().ConfigureAwait(false); - // try - // { - // if (_discoveredHosts.Any(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(location, i.Url, StringComparison.OrdinalIgnoreCase))) - // { - // return; - // } + try + { + if (_discoveredHosts.Any(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(location, i.Url, StringComparison.OrdinalIgnoreCase))) + { + return; + } - // _logger.Debug("Will attempt to add SAT device {0}", location); - // var info = await GetInfo(location, CancellationToken.None).ConfigureAwait(false); + _logger.Debug("Will attempt to add SAT device {0}", location); + var info = await GetInfo(location, CancellationToken.None).ConfigureAwait(false); - // _discoveredHosts.Add(info); - // } - // catch (OperationCanceledException) - // { + _discoveredHosts.Add(info); + } + catch (OperationCanceledException) + { - // } - // catch (NotImplementedException) - // { + } + catch (NotImplementedException) + { - // } - // catch (Exception ex) - // { - // _logger.ErrorException("Error saving device", ex); - // } - // finally - // { - // _semaphore.Release(); - // } - // } + } + catch (Exception ex) + { + _logger.ErrorException("Error saving device", ex); + } + finally + { + _semaphore.Release(); + } + } - // public void Dispose() - // { - // } + public void Dispose() + { + } - // public async Task GetInfo(string url, CancellationToken cancellationToken) - // { - // var result = new SatIpTunerHostInfo - // { - // Url = url, - // IsEnabled = true, - // Type = SatIpHost.DeviceType, - // Tuners = 1, - // TunersAvailable = 1 - // }; + public async Task GetInfo(string url, CancellationToken cancellationToken) + { + var result = new SatIpTunerHostInfo + { + Url = url, + IsEnabled = true, + Type = SatIpHost.DeviceType, + Tuners = 1, + TunersAvailable = 1 + }; - // using (var stream = await _httpClient.Get(url, cancellationToken).ConfigureAwait(false)) - // { - // using (var streamReader = new StreamReader(stream)) - // { - // // Use XmlReader for best performance - // using (var reader = XmlReader.Create(streamReader)) - // { - // reader.MoveToContent(); + using (var stream = await _httpClient.Get(url, cancellationToken).ConfigureAwait(false)) + { + using (var streamReader = new StreamReader(stream)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader)) + { + reader.MoveToContent(); - // // Loop through each element - // while (reader.Read()) - // { - // if (reader.NodeType == XmlNodeType.Element) - // { - // switch (reader.Name) - // { - // case "device": - // using (var subtree = reader.ReadSubtree()) - // { - // FillFromDeviceNode(result, subtree); - // } - // break; - // default: - // reader.Skip(); - // break; - // } - // } - // } - // } - // } - // } + // Loop through each element + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "device": + using (var subtree = reader.ReadSubtree()) + { + FillFromDeviceNode(result, subtree); + } + break; + default: + reader.Skip(); + break; + } + } + } + } + } + } - // if (string.IsNullOrWhiteSpace(result.Id)) - // { - // throw new NotImplementedException(); - // } + if (string.IsNullOrWhiteSpace(result.Id)) + { + throw new NotImplementedException(); + } - // // Device hasn't implemented an m3u list - // if (string.IsNullOrWhiteSpace(result.M3UUrl)) - // { - // result.IsEnabled = false; - // } + // Device hasn't implemented an m3u list + if (string.IsNullOrWhiteSpace(result.M3UUrl)) + { + result.IsEnabled = false; + } - // else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - // { - // var fullM3uUrl = url.Substring(0, url.LastIndexOf('/')); - // result.M3UUrl = fullM3uUrl + "/" + result.M3UUrl.TrimStart('/'); - // } + else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + var fullM3uUrl = url.Substring(0, url.LastIndexOf('/')); + result.M3UUrl = fullM3uUrl + "/" + result.M3UUrl.TrimStart('/'); + } - // _logger.Debug("SAT device result: {0}", _json.SerializeToString(result)); + _logger.Debug("SAT device result: {0}", _json.SerializeToString(result)); - // return result; - // } + return result; + } - // private void FillFromDeviceNode(SatIpTunerHostInfo info, XmlReader reader) - // { - // reader.MoveToContent(); + private void FillFromDeviceNode(SatIpTunerHostInfo info, XmlReader reader) + { + reader.MoveToContent(); - // while (reader.Read()) - // { - // if (reader.NodeType == XmlNodeType.Element) - // { - // switch (reader.LocalName) - // { - // case "UDN": - // { - // info.Id = reader.ReadElementContentAsString(); - // break; - // } + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.LocalName) + { + case "UDN": + { + info.Id = reader.ReadElementContentAsString(); + break; + } - // case "friendlyName": - // { - // info.FriendlyName = reader.ReadElementContentAsString(); - // break; - // } + case "friendlyName": + { + info.FriendlyName = reader.ReadElementContentAsString(); + break; + } - // case "satip:X_SATIPCAP": - // case "X_SATIPCAP": - // { - // // DVBS2-2 - // var value = reader.ReadElementContentAsString() ?? string.Empty; - // var parts = value.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries); - // if (parts.Length == 2) - // { - // int intValue; - // if (int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - // { - // info.TunersAvailable = intValue; - // } + case "satip:X_SATIPCAP": + case "X_SATIPCAP": + { + // DVBS2-2 + var value = reader.ReadElementContentAsString() ?? string.Empty; + var parts = value.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length == 2) + { + int intValue; + if (int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) + { + info.TunersAvailable = intValue; + } - // if (int.TryParse(parts[0].Substring(parts[0].Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - // { - // info.Tuners = intValue; - // } - // } - // break; - // } + if (int.TryParse(parts[0].Substring(parts[0].Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) + { + info.Tuners = intValue; + } + } + break; + } - // case "satip:X_SATIPM3U": - // case "X_SATIPM3U": - // { - // // /channellist.lua?select=m3u - // info.M3UUrl = reader.ReadElementContentAsString(); - // break; - // } + case "satip:X_SATIPM3U": + case "X_SATIPM3U": + { + // /channellist.lua?select=m3u + info.M3UUrl = reader.ReadElementContentAsString(); + break; + } - // default: - // reader.Skip(); - // break; - // } - // } - // } - // } - //} + default: + reader.Skip(); + break; + } + } + } + } + } public class SatIpTunerHostInfo : TunerHostInfo { diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs index 11213be232..d305a886a6 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs @@ -19,153 +19,153 @@ using MediaBrowser.Model.Serialization; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { - //public class SatIpHost : BaseTunerHost, ITunerHost - //{ - // private readonly IFileSystem _fileSystem; - // private readonly IHttpClient _httpClient; - - // public SatIpHost(IConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient) - // : base(config, logger, jsonSerializer, mediaEncoder) - // { - // _fileSystem = fileSystem; - // _httpClient = httpClient; - // } + public class SatIpHost : BaseTunerHost, ITunerHost + { + private readonly IFileSystem _fileSystem; + private readonly IHttpClient _httpClient; - // private const string ChannelIdPrefix = "sat_"; - - // protected override async Task> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) - // { - // var satInfo = (SatIpTunerHostInfo) tuner; + public SatIpHost(IConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient) + : base(config, logger, jsonSerializer, mediaEncoder) + { + _fileSystem = fileSystem; + _httpClient = httpClient; + } - // return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(satInfo.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); - // } + private const string ChannelIdPrefix = "sat_"; - // public static string DeviceType - // { - // get { return "satip"; } - // } + protected override async Task> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) + { + var satInfo = (SatIpTunerHostInfo)tuner; - // public override string Type - // { - // get { return DeviceType; } - // } + return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(satInfo.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); + } - // protected override async Task> GetChannelStreamMediaSources(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) - // { - // var urlHash = tuner.Url.GetMD5().ToString("N"); - // var prefix = ChannelIdPrefix + urlHash; - // if (!channelId.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - // { - // return null; - // } + public static string DeviceType + { + get { return "satip"; } + } - // var channels = await GetChannels(tuner, true, cancellationToken).ConfigureAwait(false); - // var m3uchannels = channels.Cast(); - // var channel = m3uchannels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase)); - // if (channel != null) - // { - // var path = channel.Path; - // MediaProtocol protocol = MediaProtocol.File; - // if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - // { - // protocol = MediaProtocol.Http; - // } - // else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase)) - // { - // protocol = MediaProtocol.Rtmp; - // } - // else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase)) - // { - // protocol = MediaProtocol.Rtsp; - // } + public override string Type + { + get { return DeviceType; } + } - // var mediaSource = new MediaSourceInfo - // { - // Path = channel.Path, - // Protocol = protocol, - // MediaStreams = new List - // { - // new MediaStream - // { - // Type = MediaStreamType.Video, - // // Set the index to -1 because we don't know the exact index of the video stream within the container - // Index = -1, - // IsInterlaced = true - // }, - // new MediaStream - // { - // Type = MediaStreamType.Audio, - // // Set the index to -1 because we don't know the exact index of the audio stream within the container - // Index = -1 + protected override async Task> GetChannelStreamMediaSources(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) + { + var urlHash = tuner.Url.GetMD5().ToString("N"); + var prefix = ChannelIdPrefix + urlHash; + if (!channelId.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + { + return null; + } - // } - // }, - // RequiresOpening = false, - // RequiresClosing = false - // }; + var channels = await GetChannels(tuner, true, cancellationToken).ConfigureAwait(false); + var m3uchannels = channels.Cast(); + var channel = m3uchannels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase)); + if (channel != null) + { + var path = channel.Path; + MediaProtocol protocol = MediaProtocol.File; + if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + protocol = MediaProtocol.Http; + } + else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase)) + { + protocol = MediaProtocol.Rtmp; + } + else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase)) + { + protocol = MediaProtocol.Rtsp; + } - // return new List { mediaSource }; - // } - // return new List { }; - // } + var mediaSource = new MediaSourceInfo + { + Path = channel.Path, + Protocol = protocol, + MediaStreams = new List + { + new MediaStream + { + Type = MediaStreamType.Video, + // Set the index to -1 because we don't know the exact index of the video stream within the container + Index = -1, + IsInterlaced = true + }, + new MediaStream + { + Type = MediaStreamType.Audio, + // Set the index to -1 because we don't know the exact index of the audio stream within the container + Index = -1 - // protected override async Task GetChannelStream(TunerHostInfo tuner, string channelId, string streamId, CancellationToken cancellationToken) - // { - // var sources = await GetChannelStreamMediaSources(tuner, channelId, cancellationToken).ConfigureAwait(false); + } + }, + RequiresOpening = false, + RequiresClosing = false + }; - // return sources.First(); - // } + return new List { mediaSource }; + } + return new List { }; + } - // protected override async Task IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) - // { - // var updatedInfo = await SatIpDiscovery.Current.GetInfo(tuner.Url, cancellationToken).ConfigureAwait(false); + protected override async Task GetChannelStream(TunerHostInfo tuner, string channelId, string streamId, CancellationToken cancellationToken) + { + var sources = await GetChannelStreamMediaSources(tuner, channelId, cancellationToken).ConfigureAwait(false); - // return updatedInfo.TunersAvailable > 0; - // } + return sources.First(); + } - // protected override bool IsValidChannelId(string channelId) - // { - // return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase); - // } + protected override async Task IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) + { + var updatedInfo = await SatIpDiscovery.Current.GetInfo(tuner.Url, cancellationToken).ConfigureAwait(false); - // protected override List GetTunerHosts() - // { - // return SatIpDiscovery.Current.DiscoveredHosts; - // } + return updatedInfo.TunersAvailable > 0; + } - // public string Name - // { - // get { return "Sat IP"; } - // } + protected override bool IsValidChannelId(string channelId) + { + return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase); + } - // public Task> GetTunerInfos(CancellationToken cancellationToken) - // { - // var list = GetTunerHosts() - // .SelectMany(i => GetTunerInfos(i, cancellationToken)) - // .ToList(); + protected override List GetTunerHosts() + { + return SatIpDiscovery.Current.DiscoveredHosts; + } - // return Task.FromResult(list); - // } + public string Name + { + get { return "Sat IP"; } + } - // public List GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) - // { - // var satInfo = (SatIpTunerHostInfo) info; + public Task> GetTunerInfos(CancellationToken cancellationToken) + { + var list = GetTunerHosts() + .SelectMany(i => GetTunerInfos(i, cancellationToken)) + .ToList(); - // var list = new List(); + return Task.FromResult(list); + } - // for (var i = 0; i < satInfo.Tuners; i++) - // { - // list.Add(new LiveTvTunerInfo - // { - // Name = satInfo.FriendlyName ?? Name, - // SourceType = Type, - // Status = LiveTvTunerStatus.Available, - // Id = info.Url.GetMD5().ToString("N") + i.ToString(CultureInfo.InvariantCulture), - // Url = info.Url - // }); - // } + public List GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) + { + var satInfo = (SatIpTunerHostInfo)info; - // return list; - // } - //} + var list = new List(); + + for (var i = 0; i < satInfo.Tuners; i++) + { + list.Add(new LiveTvTunerInfo + { + Name = satInfo.FriendlyName ?? Name, + SourceType = Type, + Status = LiveTvTunerStatus.Available, + Id = info.Url.GetMD5().ToString("N") + i.ToString(CultureInfo.InvariantCulture), + Url = info.Url + }); + } + + return list; + } + } } From 0aecb6e2963245c2d43d3450915a9d7561d94a8a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 5 Mar 2016 13:29:32 -0500 Subject: [PATCH 009/140] fix opus transcoding --- MediaBrowser.Api/Playback/Progressive/AudioService.cs | 8 ++++++-- MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index ada4761c75..1d8f5003f1 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -73,9 +73,13 @@ namespace MediaBrowser.Api.Playback.Progressive audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture)); } - if (state.OutputAudioSampleRate.HasValue) + // opus will fail on 44100 + if (!string.Equals(state.OutputAudioCodec, "opus", global::System.StringComparison.OrdinalIgnoreCase)) { - audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture)); + if (state.OutputAudioSampleRate.HasValue) + { + audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture)); + } } const string vn = " -vn"; diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs index a4d4797ebc..c2754217f6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs @@ -35,9 +35,13 @@ namespace MediaBrowser.MediaEncoding.Encoder audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture)); } - if (state.OutputAudioSampleRate.HasValue) + // opus will fail on 44100 + if (!string.Equals(state.OutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase)) { - audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture)); + if (state.OutputAudioSampleRate.HasValue) + { + audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture)); + } } const string vn = " -vn"; From c481daeb204d66f3ce543b2b862a9bc9c7159ca1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 5 Mar 2016 13:51:19 -0500 Subject: [PATCH 010/140] use shared globalize --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index b8bb397fc4..77365315c8 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -143,6 +143,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -281,9 +284,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From 0e39f672b42291bdb06343b2fc8d0ba27d411cf2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 5 Mar 2016 13:54:36 -0500 Subject: [PATCH 011/140] 3.0.5897 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ab7f18aa3c..fd1c720325 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5896")] +[assembly: AssemblyVersion("3.0.5897")] From 44723dd076e057a0862c0df373ab3a6d0107dfd7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 5 Mar 2016 16:02:43 -0500 Subject: [PATCH 012/140] ipv6 fix --- .../MediaBrowser.Server.Implementations.csproj | 4 ++-- MediaBrowser.Server.Implementations/packages.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index f1fbafc76f..0ad345a2a5 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -65,9 +65,9 @@ ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll - + False - ..\packages\SocketHttpListener.1.0.0.28\lib\net45\SocketHttpListener.dll + ..\packages\SocketHttpListener.1.0.0.29\lib\net45\SocketHttpListener.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index bbabeda6d1..456f1a4c50 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,5 +7,5 @@ - + \ No newline at end of file From 5954e53d2e2f7b9e0d1458df8e946233281b7be7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 6 Mar 2016 13:43:39 -0500 Subject: [PATCH 013/140] remove fody from full model --- MediaBrowser.Model/FodyWeavers.xml | 4 ---- MediaBrowser.Model/MediaBrowser.Model.csproj | 9 +-------- MediaBrowser.Model/packages.config | 5 ----- 3 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 MediaBrowser.Model/FodyWeavers.xml delete mode 100644 MediaBrowser.Model/packages.config diff --git a/MediaBrowser.Model/FodyWeavers.xml b/MediaBrowser.Model/FodyWeavers.xml deleted file mode 100644 index 7369928101..0000000000 --- a/MediaBrowser.Model/FodyWeavers.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index fda2402496..2500a27a82 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -14,6 +14,7 @@ v4.5 + 60e95275 true @@ -441,7 +442,6 @@ - @@ -458,13 +458,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - "); } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 77365315c8..be8dbaeae1 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -284,6 +284,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -859,9 +862,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From 99833681c318fe83c911023f60a28e6c00302d74 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Mar 2016 10:14:17 -0500 Subject: [PATCH 029/140] update MovieDbProvider --- .../Movies/MovieDbProvider.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 9ab9e44fca..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 { @@ -279,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; + } + /// /// Fetches the main result. /// @@ -293,7 +309,7 @@ namespace MediaBrowser.Providers.Movies if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); + url += string.Format("&language={0}", NormalizeLanguage(language)); // Get images in english and with no language url += "&include_image_language=" + GetImageLanguagesParam(language); From 734ebdab9519fb7a8611412ff6d2e8ab8364895f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Mar 2016 10:19:35 -0500 Subject: [PATCH 030/140] update moviedb providers --- MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs | 2 +- MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs | 2 +- MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index 37aaf038ff..bd4078b27c 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -168,7 +168,7 @@ namespace MediaBrowser.Providers.BoxSets if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); + url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language)); // Get images in english and with no language url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); diff --git a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs index 6933901927..0033c8a2ff 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/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/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs index 5b4153760d..ad2cfa12b5 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs @@ -301,7 +301,7 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); + url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language)); // Get images in english and with no language url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); From ccba42c0061915e35963bd4b2bf175a1d719e7a9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Mar 2016 10:20:37 -0500 Subject: [PATCH 031/140] 3.0.5902 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index c9f25adc08..9dcde44265 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5901")] +[assembly: AssemblyVersion("3.0.5902")] From 24fcde7d917d3991bcdf51dde8fb4437bc378888 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Mar 2016 15:16:42 -0500 Subject: [PATCH 032/140] update fonts --- .../MediaBrowser.WebDashboard.csproj | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index be8dbaeae1..5b8e2932a9 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1609,84 +1609,9 @@ - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest From 146547b02e80b9224fa414238cd0e737c2a482d6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Mar 2016 22:30:23 -0500 Subject: [PATCH 033/140] add error handling to recording parsing --- MediaBrowser.Api/TvShowsService.cs | 2 +- .../LiveTv/EmbyTV/ItemDataProvider.cs | 17 ++++++++++++++++- .../MediaBrowser.WebDashboard.csproj | 3 --- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 2dad9533fe..2873dd8b46 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -273,7 +273,7 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime(); + var minPremiereDate = DateTime.Now.Date.ToUniversalTime(); var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId }; diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 68b3f1f71e..a4eb23d993 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV try { - return _jsonSerializer.DeserializeFromFile>(jsonFile); + return _jsonSerializer.DeserializeFromFile>(jsonFile) ?? new List(); } catch (FileNotFoundException) { @@ -69,6 +69,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private void UpdateList(List newList) { + if (newList == null) + { + throw new ArgumentNullException("newList"); + } + var file = _dataPath + ".json"; _fileSystem.CreateDirectory(Path.GetDirectoryName(file)); @@ -81,6 +86,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public virtual void Update(T item) { + if (item == null) + { + throw new ArgumentNullException("item"); + } + var list = GetAll().ToList(); var index = list.FindIndex(i => EqualityComparer(i, item)); @@ -97,6 +107,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public virtual void Add(T item) { + if (item == null) + { + throw new ArgumentNullException("item"); + } + var list = GetAll().ToList(); if (list.Any(i => EqualityComparer(i, item))) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 5b8e2932a9..74bc05fe82 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -341,9 +341,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From dd6a4eefe5b1ea65b284d07f2f5aed3527b66f24 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Mar 2016 22:30:42 -0500 Subject: [PATCH 034/140] support single tmdb urls in nfo --- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 30243ff57c..7362ee58f7 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -195,8 +195,20 @@ namespace MediaBrowser.XbmcMetadata.Parsers item.SetProviderId(MetadataProviders.Imdb, m.Value); } - // TODO: Support Tmdb + // Support Tmdb // http://www.themoviedb.org/movie/36557 + var srch = "themoviedb.org/movie/"; + var index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase); + + if (index != -1) + { + var tmdbId = xml.Substring(index + srch.Length).TrimEnd('/'); + int value; + if (!string.IsNullOrWhiteSpace(tmdbId) && int.TryParse(tmdbId, NumberStyles.Any, CultureInfo.InvariantCulture, out value)) + { + item.SetProviderId(MetadataProviders.Tmdb, tmdbId); + } + } } protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult itemResult) From 749037eb4a73c9ae4b66c787a381737427dd6eca Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Mar 2016 03:34:17 -0400 Subject: [PATCH 035/140] update sat/ip discovery --- .../ApiClient/ServerCredentials.cs | 5 -- MediaBrowser.Model/ApiClient/ServerInfo.cs | 1 - MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 3 + .../LiveTv/EmbyTV/EmbyTV.cs | 13 ++++ .../LiveTv/EmbyTV/ItemDataProvider.cs | 5 +- .../HdHomerun/HdHomerunDiscovery.cs | 5 +- .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 72 ++++++++++++++----- .../LiveTv/TunerHosts/SatIp/SatIpHost.cs | 15 +--- .../MediaBrowser.WebDashboard.csproj | 6 ++ 9 files changed, 86 insertions(+), 39 deletions(-) diff --git a/MediaBrowser.Model/ApiClient/ServerCredentials.cs b/MediaBrowser.Model/ApiClient/ServerCredentials.cs index f9af0fa4ef..0f0ab65d4a 100644 --- a/MediaBrowser.Model/ApiClient/ServerCredentials.cs +++ b/MediaBrowser.Model/ApiClient/ServerCredentials.cs @@ -41,11 +41,6 @@ namespace MediaBrowser.Model.ApiClient { existing.DateLastAccessed = server.DateLastAccessed; } - - if (server.DateLastLocalConnection > existing.DateLastLocalConnection) - { - existing.DateLastLocalConnection = server.DateLastLocalConnection; - } existing.UserLinkType = server.UserLinkType; diff --git a/MediaBrowser.Model/ApiClient/ServerInfo.cs b/MediaBrowser.Model/ApiClient/ServerInfo.cs index 53ae5be528..e1fa581d7b 100644 --- a/MediaBrowser.Model/ApiClient/ServerInfo.cs +++ b/MediaBrowser.Model/ApiClient/ServerInfo.cs @@ -19,7 +19,6 @@ namespace MediaBrowser.Model.ApiClient public String AccessToken { get; set; } public List WakeOnLanInfos { get; set; } public DateTime DateLastAccessed { get; set; } - public DateTime DateLastLocalConnection { get; set; } public String ExchangeToken { get; set; } public UserLinkType? UserLinkType { get; set; } public ConnectionMode? LastConnectionMode { get; set; } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index c6b8385b0f..78c6830642 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -32,6 +32,9 @@ namespace MediaBrowser.Model.LiveTv public string DeviceId { get; set; } public bool ImportFavoritesOnly { get; set; } public bool IsEnabled { get; set; } + public string M3UUrl { get; set; } + public string FriendlyName { get; set; } + public int Tuners { get; set; } public int DataVersion { get; set; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index aa4583ef8c..e00a68e32b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1008,6 +1008,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private IEnumerable GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable allPrograms, IReadOnlyList currentRecordings) { + if (seriesTimer == null) + { + throw new ArgumentNullException("seriesTimer"); + } + if (allPrograms == null) + { + throw new ArgumentNullException("allPrograms"); + } + if (currentRecordings == null) + { + throw new ArgumentNullException("currentRecordings"); + } + // Exclude programs that have already ended allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow && i.StartDate > DateTime.UtcNow); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index a4eb23d993..79b26468e6 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using CommonIO; -using MediaBrowser.Common.IO; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { @@ -35,9 +34,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { if (_items == null) { + Logger.Info("Loading live tv data from {0}", _dataPath); _items = GetItemsFromFile(_dataPath); } - return _items; + return _items.ToList(); } } @@ -58,7 +58,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV catch (IOException ex) { Logger.ErrorException("Error deserializing {0}", ex, jsonFile); - throw; } catch (Exception ex) { diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs index aa4030b813..9ba1c60cc9 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs @@ -22,15 +22,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly ILiveTvManager _liveTvManager; private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); private readonly IHttpClient _httpClient; - private IJsonSerializer _json; + private readonly IJsonSerializer _json; - public HdHomerunDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient) + public HdHomerunDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json) { _deviceDiscovery = deviceDiscovery; _config = config; _logger = logger; _liveTvManager = liveTvManager; _httpClient = httpClient; + _json = json; } public void Run() diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index 6781e498ac..9a02413cd6 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -33,13 +32,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public static SatIpDiscovery Current; - private readonly List _discoveredHosts = new List(); - - public List DiscoveredHosts - { - get { return _discoveredHosts.ToList(); } - } - public SatIpDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json) { _deviceDiscovery = deviceDiscovery; @@ -83,15 +75,43 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp try { - if (_discoveredHosts.Any(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(location, i.Url, StringComparison.OrdinalIgnoreCase))) + var options = GetConfiguration(); + + if (options.TunerHosts.Any(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && UriEquals(i.Url, location))) { return; } - + _logger.Debug("Will attempt to add SAT device {0}", location); var info = await GetInfo(location, CancellationToken.None).ConfigureAwait(false); - _discoveredHosts.Add(info); + var existing = GetConfiguration().TunerHosts + .FirstOrDefault(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(i.DeviceId, info.DeviceId, StringComparison.OrdinalIgnoreCase)); + + if (existing == null) + { + await _liveTvManager.SaveTunerHost(new TunerHostInfo + { + Type = SatIpHost.DeviceType, + Url = location, + DataVersion = 1, + DeviceId = info.DeviceId, + FriendlyName = info.FriendlyName, + Tuners = info.Tuners + + }).ConfigureAwait(false); + } + else + { + if (!string.Equals(existing.Url, location, StringComparison.OrdinalIgnoreCase)) + { + existing.Url = location; + existing.M3UUrl = info.M3UUrl; + existing.FriendlyName = info.FriendlyName; + existing.Tuners = info.Tuners; + await _liveTvManager.SaveTunerHost(existing).ConfigureAwait(false); + } + } } catch (OperationCanceledException) { @@ -111,6 +131,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp } } + private bool UriEquals(string savedUri, string location) + { + return string.Equals(NormalizeUrl(location), NormalizeUrl(savedUri), StringComparison.OrdinalIgnoreCase); + } + + private string NormalizeUrl(string url) + { + if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + url = "http://" + url; + } + + url = url.TrimEnd('/'); + + // Strip off the port + return new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped); + } + + private LiveTvOptions GetConfiguration() + { + return _config.GetConfiguration("livetv"); + } + public void Dispose() { } @@ -158,7 +201,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp } } - if (string.IsNullOrWhiteSpace(result.Id)) + if (string.IsNullOrWhiteSpace(result.DeviceId)) { throw new NotImplementedException(); } @@ -192,7 +235,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { case "UDN": { - info.Id = reader.ReadElementContentAsString(); + info.DeviceId = reader.ReadElementContentAsString(); break; } @@ -243,9 +286,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public class SatIpTunerHostInfo : TunerHostInfo { - public int Tuners { get; set; } public int TunersAvailable { get; set; } - public string M3UUrl { get; set; } - public string FriendlyName { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs index d305a886a6..4bbb7e85ca 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs @@ -35,9 +35,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp protected override async Task> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) { - var satInfo = (SatIpTunerHostInfo)tuner; - - return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(satInfo.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); + return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); } public static string DeviceType @@ -128,11 +126,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase); } - protected override List GetTunerHosts() - { - return SatIpDiscovery.Current.DiscoveredHosts; - } - public string Name { get { return "Sat IP"; } @@ -149,15 +142,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public List GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) { - var satInfo = (SatIpTunerHostInfo)info; - var list = new List(); - for (var i = 0; i < satInfo.Tuners; i++) + for (var i = 0; i < info.Tuners; i++) { list.Add(new LiveTvTunerInfo { - Name = satInfo.FriendlyName ?? Name, + Name = info.FriendlyName ?? Name, SourceType = Type, Status = LiveTvTunerStatus.Available, Id = info.Url.GetMD5().ToString("N") + i.ToString(CultureInfo.InvariantCulture), diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 74bc05fe82..fb52b58b75 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -272,6 +272,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -302,6 +305,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 7fb2109bcce80fa16d7749db5a288201d9ef3f1f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Mar 2016 16:00:57 -0400 Subject: [PATCH 036/140] 3.0.5903 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 9dcde44265..8572ec0044 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5902")] +[assembly: AssemblyVersion("3.0.5903")] From d683f3061979d786efc574f1073af4e77da11772 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Mar 2016 21:34:24 -0400 Subject: [PATCH 037/140] update music user data key --- MediaBrowser.Api/StartupWizardService.cs | 1 + .../Entities/Audio/Audio.cs | 25 +++++++++++++++++++ .../Entities/Audio/MusicAlbum.cs | 23 +++++++++++++++-- .../Entities/Movies/Movie.cs | 8 ++++++ .../Parsers/MovieXmlParser.cs | 2 +- .../Configuration/ServerConfiguration.cs | 3 ++- MediaBrowser.Model/Dto/BaseItemDto.cs | 6 ----- MediaBrowser.Model/Querying/ItemFields.cs | 5 ---- .../Manager/ProviderManager.cs | 4 +-- .../MediaInfo/AudioImageProvider.cs | 16 +++++++++--- .../Movies/GenericMovieDbInfo.cs | 2 +- .../Movies/MovieMetadataService.cs | 4 +-- .../Dto/DtoService.cs | 10 -------- .../Library/LibraryManager.cs | 5 ---- .../Parsers/BaseNfoParser.cs | 5 ++-- .../Parsers/MovieNfoParser.cs | 13 +++++++--- .../Savers/MovieNfoSaver.cs | 4 +-- 17 files changed, 91 insertions(+), 45 deletions(-) diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 06db1de745..10f9ec0223 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -68,6 +68,7 @@ namespace MediaBrowser.Api _config.Configuration.EnableLocalizedGuids = true; _config.Configuration.EnableCustomPathSubFolders = true; _config.Configuration.EnableDateLastRefresh = true; + _config.Configuration.EnableStandaloneMusicKeys = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 766f1e5ed8..dc37dcceab 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -153,6 +153,31 @@ namespace MediaBrowser.Controller.Entities.Audio /// System.String. protected override string CreateUserDataKey() { + if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) + { + var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty; + + + if (ParentIndexNumber.HasValue) + { + songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey; + } + songKey+= Name; + + if (!string.IsNullOrWhiteSpace(Album)) + { + songKey = Album + "-" + songKey; + } + + var albumArtist = AlbumArtists.FirstOrDefault(); + if (!string.IsNullOrWhiteSpace(albumArtist)) + { + songKey = albumArtist + "-" + songKey; + } + + return songKey; + } + var parent = AlbumEntity; if (parent != null) diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index c5ce6a2f7b..e6178c183b 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -34,7 +34,17 @@ namespace MediaBrowser.Controller.Entities.Audio { get { - return GetParents().OfType().FirstOrDefault(); + var artist = GetParents().OfType().FirstOrDefault(); + + if (artist == null) + { + var name = AlbumArtist; + if (!string.IsNullOrWhiteSpace(name)) + { + artist = LibraryManager.GetArtist(name); + } + } + return artist; } } @@ -106,6 +116,15 @@ namespace MediaBrowser.Controller.Entities.Audio return "MusicAlbum-Musicbrainz-" + id; } + if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) + { + var albumArtist = AlbumArtist; + if (!string.IsNullOrWhiteSpace(albumArtist)) + { + return albumArtist + "-" + Name; + } + } + return base.CreateUserDataKey(); } @@ -125,7 +144,7 @@ namespace MediaBrowser.Controller.Entities.Audio id.AlbumArtists = AlbumArtists; - var artist = GetParents().OfType().FirstOrDefault(); + var artist = MusicArtist; if (artist != null) { diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 749d562ac1..6f99e77ec4 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using CommonIO; @@ -85,6 +86,13 @@ namespace MediaBrowser.Controller.Entities.Movies /// The name of the TMDB collection. public string TmdbCollectionName { get; set; } + [IgnoreDataMember] + public string CollectionName + { + get { return TmdbCollectionName; } + set { TmdbCollectionName = value; } + } + /// /// Gets the trailer ids. /// diff --git a/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs index 0b434231fd..1c1bbe71e1 100644 --- a/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(val) && movie != null) { - movie.TmdbCollectionName = val; + movie.CollectionName = val; } break; diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 64edbdea9c..009068deae 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -207,7 +207,8 @@ namespace MediaBrowser.Model.Configuration public bool DownloadImagesInAdvance { get; set; } public bool EnableAnonymousUsageReporting { get; set; } - + public bool EnableStandaloneMusicKeys { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index ef2de5d789..8e3284152b 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -206,12 +206,6 @@ namespace MediaBrowser.Model.Dto /// The short overview. public string ShortOverview { get; set; } - /// - /// Gets or sets the name of the TMDB collection. - /// - /// The name of the TMDB collection. - public string TmdbCollectionName { get; set; } - /// /// Gets or sets the taglines. /// diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 97fec8fdd3..1540f178a4 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -235,11 +235,6 @@ /// VoteCount, - /// - /// The TMDB collection name - /// - TmdbCollectionName, - /// /// The trailer url of the item /// 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() + .Select(i => i.MusicArtist) + .Where(i => i != null) .ToList(); var musicArtistRefreshTasks = musicArtists.Select(i => i.ValidateChildren(new Progress(), cancellationToken, options, true)); 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/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/MovieMetadataService.cs b/MediaBrowser.Providers/Movies/MovieMetadataService.cs index 8757bdd0db..f4cad837a1 100644 --- a/MediaBrowser.Providers/Movies/MovieMetadataService.cs +++ b/MediaBrowser.Providers/Movies/MovieMetadataService.cs @@ -37,9 +37,9 @@ 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; } } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index a19a122c38..fb202b7980 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1378,16 +1378,6 @@ namespace MediaBrowser.Server.Implementations.Dto } } - // Add MovieInfo - var movie = item as Movie; - if (movie != null) - { - if (fields.Contains(ItemFields.TmdbCollectionName)) - { - dto.TmdbCollectionName = movie.TmdbCollectionName; - } - } - var hasSpecialFeatures = item as IHasSpecialFeatures; if (hasSpecialFeatures != null) { diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 721603efec..3c56af9e6a 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1044,11 +1044,6 @@ namespace MediaBrowser.Server.Implementations.Library return names; } - private void SetPropertiesFromSongs(MusicArtist artist, IEnumerable items) - { - - } - /// /// Validate and refresh the People sub-set of the IBN. /// The items are stored in the db but not loaded into memory until actually requested by an operation. diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 7362ee58f7..cb74d4dd77 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -180,7 +180,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers } catch (XmlException) { - + } } } @@ -661,7 +661,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { val = val.Replace("plugin://plugin.video.youtube/?action=play_video&videoid=", "http://www.youtube.com/watch?v=", StringComparison.OrdinalIgnoreCase); - + hasTrailer.AddTrailerUrl(val, false); } } @@ -860,6 +860,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers break; case "collectionnumber": + case "tmdbcolid": var tmdbCollection = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(tmdbCollection)) { diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index 8d5c2bf20e..14c214f043 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -11,7 +11,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers { class MovieNfoParser : BaseNfoParser