added music and game genre image downloading
This commit is contained in:
parent
b50fc351a1
commit
a5be2523c5
|
@ -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")]
|
[Route("/LiveTv/Recordings/Groups/{Id}", "GET")]
|
||||||
[Api(Description = "Gets a recording group")]
|
[Api(Description = "Gets a recording group")]
|
||||||
public class GetRecordingGroup : IReturn<RecordingGroupDto>
|
public class GetRecordingGroup : IReturn<RecordingGroupDto>
|
||||||
|
@ -411,20 +397,6 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
Task.WaitAll(task);
|
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)
|
public object Get(GetRecordingGroups request)
|
||||||
{
|
{
|
||||||
var result = _liveTvManager.GetRecordingGroups(new RecordingGroupQuery
|
var result = _liveTvManager.GetRecordingGroups(new RecordingGroupQuery
|
||||||
|
|
|
@ -888,11 +888,18 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state.MediaPath = string.Format("http://localhost:{0}/mediabrowser/LiveTv/Recordings/{1}/Stream",
|
var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false);
|
||||||
ServerConfigurationManager.Configuration.HttpServerPortNumber,
|
|
||||||
request.Id);
|
|
||||||
|
|
||||||
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;
|
itemId = recording.Id;
|
||||||
|
@ -905,11 +912,18 @@ namespace MediaBrowser.Api.Playback
|
||||||
state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
||||||
state.PlayableStreamFileNames = new List<string>();
|
state.PlayableStreamFileNames = new List<string>();
|
||||||
|
|
||||||
state.MediaPath = string.Format("http://localhost:{0}/mediabrowser/LiveTv/Channels/{1}/Stream",
|
var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false);
|
||||||
ServerConfigurationManager.Configuration.HttpServerPortNumber,
|
|
||||||
request.Id);
|
|
||||||
|
|
||||||
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;
|
itemId = channel.Id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<StreamResponseInfo> GetRecordingStream(string id, CancellationToken cancellationToken);
|
Task<LiveStreamInfo> GetRecordingStream(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel stream.
|
/// Gets the channel stream.
|
||||||
|
@ -169,7 +169,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{StreamResponseInfo}.</returns>
|
/// <returns>Task{StreamResponseInfo}.</returns>
|
||||||
Task<StreamResponseInfo> GetChannelStream(string id, CancellationToken cancellationToken);
|
Task<LiveStreamInfo> GetChannelStream(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the program.
|
/// Gets the program.
|
||||||
|
|
|
@ -145,7 +145,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="recordingId">The recording identifier.</param>
|
/// <param name="recordingId">The recording identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<StreamResponseInfo> GetRecordingStream(string recordingId, CancellationToken cancellationToken);
|
Task<LiveStreamInfo> GetRecordingStream(string recordingId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel stream.
|
/// Gets the channel stream.
|
||||||
|
@ -153,6 +153,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="channelId">The channel identifier.</param>
|
/// <param name="channelId">The channel identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<StreamResponseInfo> GetChannelStream(string channelId, CancellationToken cancellationToken);
|
Task<LiveStreamInfo> GetChannelStream(string channelId, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs
Normal file
18
MediaBrowser.Controller/LiveTv/LiveStreamInfo.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class LiveStreamInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the path.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The path.</value>
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the URL.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The URL.</value>
|
||||||
|
public string Url { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -109,6 +109,7 @@
|
||||||
<Compile Include="Library\IUserDataManager.cs" />
|
<Compile Include="Library\IUserDataManager.cs" />
|
||||||
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
||||||
<Compile Include="LiveTv\ILiveTvRecording.cs" />
|
<Compile Include="LiveTv\ILiveTvRecording.cs" />
|
||||||
|
<Compile Include="LiveTv\LiveStreamInfo.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvAudioRecording.cs" />
|
<Compile Include="LiveTv\LiveTvAudioRecording.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvChannel.cs" />
|
<Compile Include="LiveTv\LiveTvChannel.cs" />
|
||||||
<Compile Include="LiveTv\ChannelInfo.cs" />
|
<Compile Include="LiveTv\ChannelInfo.cs" />
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<MonoDevelop.Ide.Workbench ActiveDocument="MediaBrowser.Server.Mono\Networking\NetworkManager.cs">
|
<MonoDevelop.Ide.Workbench ActiveDocument="MediaBrowser.Server.Mono\Networking\NetworkManager.cs">
|
||||||
<Files>
|
<Files>
|
||||||
<File FileName="MediaBrowser.Server.Mono\app.config" Line="1" Column="1" />
|
<File FileName="MediaBrowser.Server.Mono\app.config" Line="1" Column="1" />
|
||||||
<File FileName="MediaBrowser.Server.Mono\Networking\NetworkManager.cs" Line="6" Column="34" />
|
<File FileName="MediaBrowser.Server.Mono\Networking\NetworkManager.cs" Line="7" Column="26" />
|
||||||
</Files>
|
</Files>
|
||||||
</MonoDevelop.Ide.Workbench>
|
</MonoDevelop.Ide.Workbench>
|
||||||
<MonoDevelop.Ide.DebuggingService.Breakpoints>
|
<MonoDevelop.Ide.DebuggingService.Breakpoints>
|
||||||
|
|
160
MediaBrowser.Providers/ImagesByName/GameGenreImageProvider.cs
Normal file
160
MediaBrowser.Providers/ImagesByName/GameGenreImageProvider.cs
Normal file
|
@ -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<bool> 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<RemoteImageInfo> 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<RemoteImageInfo> 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return GetImages(item, imageType == ImageType.Primary, imageType == ImageType.Thumb, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return GetImages(item, true, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, bool posters, bool thumbs, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var list = new List<RemoteImageInfo>();
|
||||||
|
|
||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
161
MediaBrowser.Providers/ImagesByName/MusicGenreImageProvider.cs
Normal file
161
MediaBrowser.Providers/ImagesByName/MusicGenreImageProvider.cs
Normal file
|
@ -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<bool> 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<RemoteImageInfo> 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<RemoteImageInfo> 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, ImageType imageType, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return GetImages(item, imageType == ImageType.Primary, imageType == ImageType.Thumb, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<RemoteImageInfo>> GetAllImages(IHasImages item, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return GetImages(item, true, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, bool posters, bool thumbs, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var list = new List<RemoteImageInfo>();
|
||||||
|
|
||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,10 @@
|
||||||
<Compile Include="Games\GameSystemProviderFromXml.cs" />
|
<Compile Include="Games\GameSystemProviderFromXml.cs" />
|
||||||
<Compile Include="ImageFromMediaLocationProvider.cs" />
|
<Compile Include="ImageFromMediaLocationProvider.cs" />
|
||||||
<Compile Include="ImagesByNameProvider.cs" />
|
<Compile Include="ImagesByNameProvider.cs" />
|
||||||
|
<Compile Include="ImagesByName\MusicGenreImageProvider.cs" />
|
||||||
|
<Compile Include="ImagesByName\MusicGenresManualImageProvider.cs" />
|
||||||
|
<Compile Include="ImagesByName\GameGenreImageProvider.cs" />
|
||||||
|
<Compile Include="ImagesByName\GameGenresManualImageProvider.cs" />
|
||||||
<Compile Include="ImagesByName\GenreImageProvider.cs" />
|
<Compile Include="ImagesByName\GenreImageProvider.cs" />
|
||||||
<Compile Include="ImagesByName\GenresManualImageProvider.cs" />
|
<Compile Include="ImagesByName\GenresManualImageProvider.cs" />
|
||||||
<Compile Include="ImagesByName\ImageUtils.cs" />
|
<Compile Include="ImagesByName\ImageUtils.cs" />
|
||||||
|
|
|
@ -40,9 +40,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
//BaseItem.LibraryManager.LibraryChanged -= LibraryChanged;
|
|
||||||
|
|
||||||
//LuceneSearch.CloseAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -153,18 +153,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false);
|
return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<StreamResponseInfo> GetRecordingStream(string id, CancellationToken cancellationToken)
|
public async Task<LiveStreamInfo> GetRecordingStream(string id, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var service = ActiveService;
|
var service = ActiveService;
|
||||||
|
|
||||||
var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false);
|
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);
|
return await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<StreamResponseInfo> GetChannelStream(string id, CancellationToken cancellationToken)
|
public async Task<LiveStreamInfo> GetChannelStream(string id, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var service = ActiveService;
|
var service = ActiveService;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Common.Internal</id>
|
<id>MediaBrowser.Common.Internal</id>
|
||||||
<version>3.0.294</version>
|
<version>3.0.295</version>
|
||||||
<title>MediaBrowser.Common.Internal</title>
|
<title>MediaBrowser.Common.Internal</title>
|
||||||
<authors>Luke</authors>
|
<authors>Luke</authors>
|
||||||
<owners>ebr,Luke,scottisafool</owners>
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
|
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
|
||||||
<copyright>Copyright © Media Browser 2013</copyright>
|
<copyright>Copyright © Media Browser 2013</copyright>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MediaBrowser.Common" version="3.0.294" />
|
<dependency id="MediaBrowser.Common" version="3.0.295" />
|
||||||
<dependency id="NLog" version="2.1.0" />
|
<dependency id="NLog" version="2.1.0" />
|
||||||
<dependency id="SimpleInjector" version="2.4.0" />
|
<dependency id="SimpleInjector" version="2.4.0" />
|
||||||
<dependency id="sharpcompress" version="0.10.2" />
|
<dependency id="sharpcompress" version="0.10.2" />
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Common</id>
|
<id>MediaBrowser.Common</id>
|
||||||
<version>3.0.294</version>
|
<version>3.0.295</version>
|
||||||
<title>MediaBrowser.Common</title>
|
<title>MediaBrowser.Common</title>
|
||||||
<authors>Media Browser Team</authors>
|
<authors>Media Browser Team</authors>
|
||||||
<owners>ebr,Luke,scottisafool</owners>
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Server.Core</id>
|
<id>MediaBrowser.Server.Core</id>
|
||||||
<version>3.0.294</version>
|
<version>3.0.295</version>
|
||||||
<title>Media Browser.Server.Core</title>
|
<title>Media Browser.Server.Core</title>
|
||||||
<authors>Media Browser Team</authors>
|
<authors>Media Browser Team</authors>
|
||||||
<owners>ebr,Luke,scottisafool</owners>
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<description>Contains core components required to build plugins for Media Browser Server.</description>
|
<description>Contains core components required to build plugins for Media Browser Server.</description>
|
||||||
<copyright>Copyright © Media Browser 2013</copyright>
|
<copyright>Copyright © Media Browser 2013</copyright>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MediaBrowser.Common" version="3.0.294" />
|
<dependency id="MediaBrowser.Common" version="3.0.295" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user