From a5be2523c5d86c077175b2de347b8beb791616c1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Jan 2014 18:07:37 -0500 Subject: [PATCH] added music and game genre image downloading --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 28 --- .../Playback/BaseStreamingService.cs | 30 +++- .../LiveTv/ILiveTvManager.cs | 4 +- .../LiveTv/ILiveTvService.cs | 4 +- .../LiveTv/LiveStreamInfo.cs | 18 ++ .../MediaBrowser.Controller.csproj | 1 + MediaBrowser.Mono.userprefs | 2 +- .../ImagesByName/GameGenreImageProvider.cs | 160 +++++++++++++++++ .../GameGenresManualImageProvider.cs | 128 ++++++++++++++ .../ImagesByName/MusicGenreImageProvider.cs | 161 ++++++++++++++++++ .../MusicGenresManualImageProvider.cs | 129 ++++++++++++++ .../MediaBrowser.Providers.csproj | 4 + .../Library/LuceneSearchEngine.cs | 3 - .../LiveTv/LiveTvManager.cs | 6 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 17 files changed, 636 insertions(+), 52 deletions(-) create mode 100644 MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs create mode 100644 MediaBrowser.Providers/ImagesByName/GameGenreImageProvider.cs create mode 100644 MediaBrowser.Providers/ImagesByName/GameGenresManualImageProvider.cs create mode 100644 MediaBrowser.Providers/ImagesByName/MusicGenreImageProvider.cs create mode 100644 MediaBrowser.Providers/ImagesByName/MusicGenresManualImageProvider.cs diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 84bd291a4..6cec2118b 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -194,20 +194,6 @@ namespace MediaBrowser.Api.LiveTv { } - [Route("/LiveTv/Recordings/{Id}/Stream", "GET")] - public class GetInternalRecordingStream - { - [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - [Route("/LiveTv/Channels/{Id}/Stream", "GET")] - public class GetInternalChannelStream - { - [ApiMember(Name = "Id", Description = "Channel Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - [Route("/LiveTv/Recordings/Groups/{Id}", "GET")] [Api(Description = "Gets a recording group")] public class GetRecordingGroup : IReturn @@ -411,20 +397,6 @@ namespace MediaBrowser.Api.LiveTv Task.WaitAll(task); } - public object Get(GetInternalRecordingStream request) - { - var stream = _liveTvManager.GetRecordingStream(request.Id, CancellationToken.None).Result; - - return ToStreamResult(stream.Stream, stream.MimeType); - } - - public object Get(GetInternalChannelStream request) - { - var stream = _liveTvManager.GetChannelStream(request.Id, CancellationToken.None).Result; - - return ToStreamResult(stream.Stream, stream.MimeType); - } - public object Get(GetRecordingGroups request) { var result = _liveTvManager.GetRecordingGroups(new RecordingGroupQuery diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 718c142a4..450c0c681 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -888,11 +888,18 @@ namespace MediaBrowser.Api.Playback } else { - state.MediaPath = string.Format("http://localhost:{0}/mediabrowser/LiveTv/Recordings/{1}/Stream", - ServerConfigurationManager.Configuration.HttpServerPortNumber, - request.Id); + var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false); - state.IsRemote = true; + if (!string.IsNullOrEmpty(streamInfo.Path) && File.Exists(streamInfo.Path)) + { + state.MediaPath = streamInfo.Path; + state.IsRemote = false; + } + else if (!string.IsNullOrEmpty(streamInfo.Url)) + { + state.MediaPath = streamInfo.Url; + state.IsRemote = true; + } } itemId = recording.Id; @@ -905,11 +912,18 @@ namespace MediaBrowser.Api.Playback state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); state.PlayableStreamFileNames = new List(); - state.MediaPath = string.Format("http://localhost:{0}/mediabrowser/LiveTv/Channels/{1}/Stream", - ServerConfigurationManager.Configuration.HttpServerPortNumber, - request.Id); + var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false); - state.IsRemote = true; + if (!string.IsNullOrEmpty(streamInfo.Path) && File.Exists(streamInfo.Path)) + { + state.MediaPath = streamInfo.Path; + state.IsRemote = false; + } + else if (!string.IsNullOrEmpty(streamInfo.Url)) + { + state.MediaPath = streamInfo.Url; + state.IsRemote = true; + } itemId = channel.Id; } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 87ac0d4dc..b7acb0735 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -161,7 +161,7 @@ namespace MediaBrowser.Controller.LiveTv /// The identifier. /// The cancellation token. /// Task{Stream}. - Task GetRecordingStream(string id, CancellationToken cancellationToken); + Task GetRecordingStream(string id, CancellationToken cancellationToken); /// /// Gets the channel stream. @@ -169,7 +169,7 @@ namespace MediaBrowser.Controller.LiveTv /// The identifier. /// The cancellation token. /// Task{StreamResponseInfo}. - Task GetChannelStream(string id, CancellationToken cancellationToken); + Task GetChannelStream(string id, CancellationToken cancellationToken); /// /// Gets the program. diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs index f8efbce63..491e8cbf8 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs @@ -145,7 +145,7 @@ namespace MediaBrowser.Controller.LiveTv /// The recording identifier. /// The cancellation token. /// Task{Stream}. - Task GetRecordingStream(string recordingId, CancellationToken cancellationToken); + Task GetRecordingStream(string recordingId, CancellationToken cancellationToken); /// /// Gets the channel stream. @@ -153,6 +153,6 @@ namespace MediaBrowser.Controller.LiveTv /// The channel identifier. /// The cancellation token. /// Task{Stream}. - Task GetChannelStream(string channelId, CancellationToken cancellationToken); + Task GetChannelStream(string channelId, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs b/MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs new file mode 100644 index 000000000..ba480f685 --- /dev/null +++ b/MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs @@ -0,0 +1,18 @@ + +namespace MediaBrowser.Controller.LiveTv +{ + public class LiveStreamInfo + { + /// + /// Gets or sets the path. + /// + /// The path. + public string Path { get; set; } + + /// + /// Gets or sets the URL. + /// + /// The URL. + public string Url { get; set; } + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 25ea9979c..e08361812 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -109,6 +109,7 @@ + diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs index 51af96f9f..e5d5fa75e 100644 --- a/MediaBrowser.Mono.userprefs +++ b/MediaBrowser.Mono.userprefs @@ -3,7 +3,7 @@ - + diff --git a/MediaBrowser.Providers/ImagesByName/GameGenreImageProvider.cs b/MediaBrowser.Providers/ImagesByName/GameGenreImageProvider.cs new file mode 100644 index 000000000..a0dbb83dc --- /dev/null +++ b/MediaBrowser.Providers/ImagesByName/GameGenreImageProvider.cs @@ -0,0 +1,160 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Providers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.ImagesByName +{ + public class GameGenreImageProvider : BaseMetadataProvider + { + private readonly IProviderManager _providerManager; + private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(5, 5); + + public GameGenreImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager) + : base(logManager, configurationManager) + { + _providerManager = providerManager; + } + + public override bool Supports(BaseItem item) + { + return item is GameGenre; + } + + public override bool RequiresInternet + { + get + { + return true; + } + } + + public override ItemUpdateType ItemUpdateType + { + get + { + return ItemUpdateType.ImageUpdate; + } + } + + protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) + { + if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Thumb)) + { + return false; + } + + // Try again periodically in case new images were added + if ((DateTime.UtcNow - providerInfo.LastRefreshed).TotalDays > 7) + { + return true; + } + + return base.NeedsRefreshInternal(item, providerInfo); + } + + protected override bool RefreshOnVersionChange + { + get + { + return true; + } + } + + protected override string ProviderVersion + { + get + { + return "8"; + } + } + + public override async Task FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) + { + if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Thumb)) + { + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); + return true; + } + + var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, GameGenresManualImageProvider.ProviderName).ConfigureAwait(false); + + await DownloadImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); + + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); + return true; + } + + private async Task DownloadImages(BaseItem item, List images, CancellationToken cancellationToken) + { + if (!item.LockedFields.Contains(MetadataFields.Images)) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (!item.HasImage(ImageType.Primary)) + { + await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false); + } + cancellationToken.ThrowIfCancellationRequested(); + + if (!item.HasImage(ImageType.Thumb)) + { + await SaveImage(item, images, ImageType.Thumb, cancellationToken).ConfigureAwait(false); + } + } + + if (!item.LockedFields.Contains(MetadataFields.Backdrops)) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (item.BackdropImagePaths.Count == 0) + { + foreach (var image in images.Where(i => i.Type == ImageType.Backdrop)) + { + await _providerManager.SaveImage(item, image.Url, _resourcePool, ImageType.Backdrop, null, cancellationToken) + .ConfigureAwait(false); + + break; + } + } + } + } + + + private async Task SaveImage(BaseItem item, IEnumerable images, ImageType type, CancellationToken cancellationToken) + { + foreach (var image in images.Where(i => i.Type == type)) + { + try + { + await _providerManager.SaveImage(item, image.Url, _resourcePool, type, null, cancellationToken).ConfigureAwait(false); + break; + } + catch (HttpException ex) + { + // Sometimes fanart has bad url's in their xml + if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) + { + continue; + } + break; + } + } + } + + public override MetadataProviderPriority Priority + { + get { return MetadataProviderPriority.Third; } + } + } +} diff --git a/MediaBrowser.Providers/ImagesByName/GameGenresManualImageProvider.cs b/MediaBrowser.Providers/ImagesByName/GameGenresManualImageProvider.cs new file mode 100644 index 000000000..8207bb042 --- /dev/null +++ b/MediaBrowser.Providers/ImagesByName/GameGenresManualImageProvider.cs @@ -0,0 +1,128 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.ImagesByName +{ + public class GameGenresManualImageProvider : IImageProvider + { + private readonly IServerConfigurationManager _config; + private readonly IHttpClient _httpClient; + private readonly IFileSystem _fileSystem; + + private readonly SemaphoreSlim _listResourcePool = new SemaphoreSlim(1, 1); + + public GameGenresManualImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem) + { + _config = config; + _httpClient = httpClient; + _fileSystem = fileSystem; + } + + public string Name + { + get { return ProviderName; } + } + + public static string ProviderName + { + get { return "Media Browser"; } + } + + public bool Supports(IHasImages item) + { + return item is GameGenre; + } + + public Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) + { + return GetImages(item, imageType == ImageType.Primary, imageType == ImageType.Thumb, cancellationToken); + } + + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) + { + return GetImages(item, true, true, cancellationToken); + } + + private async Task> GetImages(IHasImages item, bool posters, bool thumbs, CancellationToken cancellationToken) + { + var list = new List(); + + if (posters) + { + var posterPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotegamegenreposters.txt"); + + await EnsurePosterList(posterPath, cancellationToken).ConfigureAwait(false); + + list.Add(GetImage(item, posterPath, ImageType.Primary, "folder")); + } + + cancellationToken.ThrowIfCancellationRequested(); + + if (thumbs) + { + var thumbsPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotegamegenrethumbs.txt"); + + await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false); + + list.Add(GetImage(item, thumbsPath, ImageType.Thumb, "thumb")); + } + + return list.Where(i => i != null); + } + + private RemoteImageInfo GetImage(IHasImages item, string filename, ImageType type, string remoteFilename) + { + var list = ImageUtils.GetAvailableImages(filename); + + var match = ImageUtils.FindMatch(item, list); + + if (!string.IsNullOrEmpty(match)) + { + var url = GetUrl(match, remoteFilename); + + return new RemoteImageInfo + { + ProviderName = Name, + Type = type, + Url = url + }; + } + + return null; + } + + private string GetUrl(string image, string filename) + { + return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/gamegenres/{0}/{1}.jpg", image, filename); + } + + private Task EnsureThumbsList(string file, CancellationToken cancellationToken) + { + const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/gamegenrethumbs.txt"; + + return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken); + } + + private Task EnsurePosterList(string file, CancellationToken cancellationToken) + { + const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/gamegenreposters.txt"; + + return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken); + } + + public int Priority + { + get { return 0; } + } + } +} diff --git a/MediaBrowser.Providers/ImagesByName/MusicGenreImageProvider.cs b/MediaBrowser.Providers/ImagesByName/MusicGenreImageProvider.cs new file mode 100644 index 000000000..5b05a7b63 --- /dev/null +++ b/MediaBrowser.Providers/ImagesByName/MusicGenreImageProvider.cs @@ -0,0 +1,161 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Providers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.ImagesByName +{ + public class MusicGenreImageProvider : BaseMetadataProvider + { + private readonly IProviderManager _providerManager; + private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(5, 5); + + public MusicGenreImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager) + : base(logManager, configurationManager) + { + _providerManager = providerManager; + } + + public override bool Supports(BaseItem item) + { + return item is MusicGenre; + } + + public override bool RequiresInternet + { + get + { + return true; + } + } + + public override ItemUpdateType ItemUpdateType + { + get + { + return ItemUpdateType.ImageUpdate; + } + } + + protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) + { + if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Thumb)) + { + return false; + } + + // Try again periodically in case new images were added + if ((DateTime.UtcNow - providerInfo.LastRefreshed).TotalDays > 7) + { + return true; + } + + return base.NeedsRefreshInternal(item, providerInfo); + } + + protected override bool RefreshOnVersionChange + { + get + { + return true; + } + } + + protected override string ProviderVersion + { + get + { + return "8"; + } + } + + public override async Task FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) + { + if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Thumb)) + { + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); + return true; + } + + var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, MusicGenresManualImageProvider.ProviderName).ConfigureAwait(false); + + await DownloadImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); + + SetLastRefreshed(item, DateTime.UtcNow, providerInfo); + return true; + } + + private async Task DownloadImages(BaseItem item, List images, CancellationToken cancellationToken) + { + if (!item.LockedFields.Contains(MetadataFields.Images)) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (!item.HasImage(ImageType.Primary)) + { + await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false); + } + cancellationToken.ThrowIfCancellationRequested(); + + if (!item.HasImage(ImageType.Thumb)) + { + await SaveImage(item, images, ImageType.Thumb, cancellationToken).ConfigureAwait(false); + } + } + + if (!item.LockedFields.Contains(MetadataFields.Backdrops)) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (item.BackdropImagePaths.Count == 0) + { + foreach (var image in images.Where(i => i.Type == ImageType.Backdrop)) + { + await _providerManager.SaveImage(item, image.Url, _resourcePool, ImageType.Backdrop, null, cancellationToken) + .ConfigureAwait(false); + + break; + } + } + } + } + + + private async Task SaveImage(BaseItem item, IEnumerable images, ImageType type, CancellationToken cancellationToken) + { + foreach (var image in images.Where(i => i.Type == type)) + { + try + { + await _providerManager.SaveImage(item, image.Url, _resourcePool, type, null, cancellationToken).ConfigureAwait(false); + break; + } + catch (HttpException ex) + { + // Sometimes fanart has bad url's in their xml + if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) + { + continue; + } + break; + } + } + } + + public override MetadataProviderPriority Priority + { + get { return MetadataProviderPriority.Third; } + } + } +} diff --git a/MediaBrowser.Providers/ImagesByName/MusicGenresManualImageProvider.cs b/MediaBrowser.Providers/ImagesByName/MusicGenresManualImageProvider.cs new file mode 100644 index 000000000..f21e867d1 --- /dev/null +++ b/MediaBrowser.Providers/ImagesByName/MusicGenresManualImageProvider.cs @@ -0,0 +1,129 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.ImagesByName +{ + public class MusicGenresManualImageProvider : IImageProvider + { + private readonly IServerConfigurationManager _config; + private readonly IHttpClient _httpClient; + private readonly IFileSystem _fileSystem; + + private readonly SemaphoreSlim _listResourcePool = new SemaphoreSlim(1, 1); + + public MusicGenresManualImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem) + { + _config = config; + _httpClient = httpClient; + _fileSystem = fileSystem; + } + + public string Name + { + get { return ProviderName; } + } + + public static string ProviderName + { + get { return "Media Browser"; } + } + + public bool Supports(IHasImages item) + { + return item is MusicGenre; + } + + public Task> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken) + { + return GetImages(item, imageType == ImageType.Primary, imageType == ImageType.Thumb, cancellationToken); + } + + public Task> GetAllImages(IHasImages item, CancellationToken cancellationToken) + { + return GetImages(item, true, true, cancellationToken); + } + + private async Task> GetImages(IHasImages item, bool posters, bool thumbs, CancellationToken cancellationToken) + { + var list = new List(); + + if (posters) + { + var posterPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotemusicgenreposters.txt"); + + await EnsurePosterList(posterPath, cancellationToken).ConfigureAwait(false); + + list.Add(GetImage(item, posterPath, ImageType.Primary, "folder")); + } + + cancellationToken.ThrowIfCancellationRequested(); + + if (thumbs) + { + var thumbsPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotemusicgenrethumbs.txt"); + + await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false); + + list.Add(GetImage(item, thumbsPath, ImageType.Thumb, "thumb")); + } + + return list.Where(i => i != null); + } + + private RemoteImageInfo GetImage(IHasImages item, string filename, ImageType type, string remoteFilename) + { + var list = ImageUtils.GetAvailableImages(filename); + + var match = ImageUtils.FindMatch(item, list); + + if (!string.IsNullOrEmpty(match)) + { + var url = GetUrl(match, remoteFilename); + + return new RemoteImageInfo + { + ProviderName = Name, + Type = type, + Url = url + }; + } + + return null; + } + + private string GetUrl(string image, string filename) + { + return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/musicgenres/{0}/{1}.jpg", image, filename); + } + + private Task EnsureThumbsList(string file, CancellationToken cancellationToken) + { + const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/musicgenrethumbs.txt"; + + return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken); + } + + private Task EnsurePosterList(string file, CancellationToken cancellationToken) + { + const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/musicgenreposters.txt"; + + return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken); + } + + public int Priority + { + get { return 0; } + } + } +} diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index b32670a91..6b87f1dfe 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -66,6 +66,10 @@ + + + + diff --git a/MediaBrowser.Server.Implementations/Library/LuceneSearchEngine.cs b/MediaBrowser.Server.Implementations/Library/LuceneSearchEngine.cs index b194b2e94..34156b509 100644 --- a/MediaBrowser.Server.Implementations/Library/LuceneSearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/LuceneSearchEngine.cs @@ -40,9 +40,6 @@ namespace MediaBrowser.Server.Implementations.Library public void Dispose() { - //BaseItem.LibraryManager.LibraryChanged -= LibraryChanged; - - //LuceneSearch.CloseAll(); } /// diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index b38ef5d55..4b3f33297 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -153,18 +153,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false); } - public async Task GetRecordingStream(string id, CancellationToken cancellationToken) + public async Task GetRecordingStream(string id, CancellationToken cancellationToken) { var service = ActiveService; var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); - var recording = recordings.FirstOrDefault(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); + var recording = recordings.First(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); return await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false); } - public async Task GetChannelStream(string id, CancellationToken cancellationToken) + public async Task GetChannelStream(string id, CancellationToken cancellationToken) { var service = ActiveService; diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 4dd9b22fe..5b8f266bc 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.294 + 3.0.295 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index ea68c2c49..334ddc8e9 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.294 + 3.0.295 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 1e3a24eee..b0d354a91 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.294 + 3.0.295 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - +