mirror of https://github.com/jellyfin/jellyfin.git
fixed remote control flyout
This commit is contained in:
parent
cf4ae16f18
commit
4e38c35373
|
@ -5,7 +5,6 @@ using MediaBrowser.Controller.Entities.TV;
|
|||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using ServiceStack;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
@ -94,8 +93,8 @@ namespace MediaBrowser.Api
|
|||
{
|
||||
var item = _dtoService.GetItemByDtoId(request.ItemId);
|
||||
|
||||
var newEnableInternetProviders = request.EnableInternetProviders ?? true;
|
||||
var dontFetchMetaChanged = item.DontFetchMeta != !newEnableInternetProviders;
|
||||
var newLockData = request.LockData ?? false;
|
||||
var dontFetchMetaChanged = item.DontFetchMeta != newLockData;
|
||||
|
||||
UpdateItem(request, item);
|
||||
|
||||
|
@ -107,7 +106,7 @@ namespace MediaBrowser.Api
|
|||
|
||||
foreach (var child in folder.RecursiveChildren.ToList())
|
||||
{
|
||||
child.DontFetchMeta = !newEnableInternetProviders;
|
||||
child.DontFetchMeta = newLockData;
|
||||
await _libraryManager.UpdateItem(child, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -308,15 +307,12 @@ namespace MediaBrowser.Api
|
|||
hasAspectRatio.AspectRatio = request.AspectRatio;
|
||||
}
|
||||
|
||||
item.DontFetchMeta = !(request.EnableInternetProviders ?? true);
|
||||
if (request.EnableInternetProviders ?? true)
|
||||
item.DontFetchMeta = (request.LockData ?? false);
|
||||
|
||||
if (request.LockedFields != null)
|
||||
{
|
||||
item.LockedFields = request.LockedFields;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.LockedFields.Clear();
|
||||
}
|
||||
|
||||
// Only allow this for series. Runtimes for media comes from ffprobe.
|
||||
if (item is Series)
|
||||
|
|
|
@ -240,6 +240,13 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
|
||||
responseHeaders["Accept-Ranges"] = "none";
|
||||
|
||||
var length = response.Headers["Content-Length"];
|
||||
|
||||
if (!string.IsNullOrEmpty(length))
|
||||
{
|
||||
responseHeaders["Content-Length"] = length;
|
||||
}
|
||||
|
||||
if (isHeadRequest)
|
||||
{
|
||||
using (response.Content)
|
||||
|
@ -273,13 +280,13 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
// Use the command line args with a dummy playlist path
|
||||
var outputPath = GetOutputFilePath(state);
|
||||
|
||||
responseHeaders["Accept-Ranges"] = "none";
|
||||
|
||||
var contentType = MimeTypes.GetMimeType(outputPath);
|
||||
|
||||
// Headers only
|
||||
if (isHeadRequest)
|
||||
{
|
||||
responseHeaders["Accept-Ranges"] = "none";
|
||||
|
||||
return ResultFactory.GetResult(new byte[] { }, contentType, responseHeaders);
|
||||
}
|
||||
|
||||
|
@ -294,7 +301,6 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
|
||||
var result = new ProgressiveStreamWriter(outputPath, Logger, FileSystem);
|
||||
|
||||
result.Options["Accept-Ranges"] = "none";
|
||||
result.Options["Content-Type"] = contentType;
|
||||
|
||||
// Add the response headers to the result object
|
||||
|
|
|
@ -179,7 +179,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
// Refresh all non-songs
|
||||
foreach (var item in others)
|
||||
{
|
||||
if (tasks.Count > 3)
|
||||
if (tasks.Count >= 3)
|
||||
{
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
tasks.Clear();
|
||||
|
|
|
@ -216,8 +216,18 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// Returns true if this item should not attempt to fetch metadata
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [dont fetch meta]; otherwise, <c>false</c>.</value>
|
||||
[Obsolete("Please use IsLocked instead of DontFetchMeta")]
|
||||
public bool DontFetchMeta { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsLocked
|
||||
{
|
||||
get
|
||||
{
|
||||
return DontFetchMeta;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the locked fields.
|
||||
/// </summary>
|
||||
|
|
|
@ -521,7 +521,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
foreach (var child in children)
|
||||
{
|
||||
if (tasks.Count >= 4)
|
||||
if (tasks.Count >= 3)
|
||||
{
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
tasks.Clear();
|
||||
|
|
|
@ -148,6 +148,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
|
||||
bool IsInMixedFolder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is locked.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is locked; otherwise, <c>false</c>.</value>
|
||||
bool IsLocked { get; }
|
||||
}
|
||||
|
||||
public static class HasImagesExtensions
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
// Refresh songs
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (tasks.Count >= 4)
|
||||
if (tasks.Count >= 3)
|
||||
{
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
tasks.Clear();
|
||||
|
|
|
@ -147,9 +147,11 @@
|
|||
<Compile Include="Persistence\MediaStreamQuery.cs" />
|
||||
<Compile Include="Providers\DirectoryService.cs" />
|
||||
<Compile Include="Providers\ICustomMetadataProvider.cs" />
|
||||
<Compile Include="Providers\IForcedProvider.cs" />
|
||||
<Compile Include="Providers\IHasChangeMonitor.cs" />
|
||||
<Compile Include="Entities\IHasMetadata.cs" />
|
||||
<Compile Include="Providers\IImageProvider.cs" />
|
||||
<Compile Include="Providers\IImageSaver.cs" />
|
||||
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
||||
<Compile Include="Providers\IProviderRepository.cs" />
|
||||
<Compile Include="Providers\IRemoteImageProvider.cs" />
|
||||
|
@ -216,7 +218,7 @@
|
|||
<Compile Include="Plugins\IPluginConfigurationPage.cs" />
|
||||
<Compile Include="Plugins\IServerEntryPoint.cs" />
|
||||
<Compile Include="Providers\IImageEnhancer.cs" />
|
||||
<Compile Include="Providers\BaseProviderInfo.cs" />
|
||||
<Compile Include="Providers\ProviderRefreshStatus.cs" />
|
||||
<Compile Include="Resolvers\IResolverIgnoreRule.cs" />
|
||||
<Compile Include="Resolvers\EntityResolutionHelper.cs" />
|
||||
<Compile Include="Resolvers\ResolverPriority.cs" />
|
||||
|
@ -224,7 +226,6 @@
|
|||
<Compile Include="Library\ItemResolveArgs.cs" />
|
||||
<Compile Include="IO\FileData.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Providers\BaseMetadataProvider.cs" />
|
||||
<Compile Include="Session\ISessionController.cs" />
|
||||
<Compile Include="Session\ISessionControllerFactory.cs" />
|
||||
<Compile Include="Session\PlaybackInfo.cs" />
|
||||
|
|
|
@ -719,7 +719,7 @@ namespace MediaBrowser.Controller.Providers
|
|||
}
|
||||
break;
|
||||
}
|
||||
case "TvRageId":
|
||||
case "TVRageId":
|
||||
{
|
||||
var id = reader.ReadElementContentAsString();
|
||||
if (!string.IsNullOrWhiteSpace(id))
|
||||
|
|
|
@ -1,268 +0,0 @@
|
|||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BaseMetadataProvider
|
||||
/// </summary>
|
||||
public abstract class BaseMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the logger.
|
||||
/// </summary>
|
||||
/// <value>The logger.</value>
|
||||
protected ILogger Logger { get; set; }
|
||||
|
||||
protected ILogManager LogManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration manager.
|
||||
/// </summary>
|
||||
/// <value>The configuration manager.</value>
|
||||
protected IServerConfigurationManager ConfigurationManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The _id
|
||||
/// </summary>
|
||||
public readonly Guid Id;
|
||||
|
||||
/// <summary>
|
||||
/// The true task result
|
||||
/// </summary>
|
||||
protected static readonly Task<bool> TrueTaskResult = Task.FromResult(true);
|
||||
|
||||
protected static readonly Task<bool> FalseTaskResult = Task.FromResult(false);
|
||||
|
||||
/// <summary>
|
||||
/// Supportses the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
public abstract bool Supports(BaseItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [requires internet].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [requires internet]; otherwise, <c>false</c>.</value>
|
||||
public virtual bool RequiresInternet
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the provider version.
|
||||
/// </summary>
|
||||
/// <value>The provider version.</value>
|
||||
protected virtual string ProviderVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual ItemUpdateType ItemUpdateType
|
||||
{
|
||||
get { return RequiresInternet ? ItemUpdateType.MetadataDownload : ItemUpdateType.MetadataImport; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [refresh on version change].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [refresh on version change]; otherwise, <c>false</c>.</value>
|
||||
protected virtual bool RefreshOnVersionChange
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if this provider is relatively slow and, therefore, should be skipped
|
||||
/// in certain instances. Default is whether or not it requires internet. Can be overridden
|
||||
/// for explicit designation.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is slow; otherwise, <c>false</c>.</value>
|
||||
public virtual bool IsSlow
|
||||
{
|
||||
get { return RequiresInternet; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseMetadataProvider" /> class.
|
||||
/// </summary>
|
||||
protected BaseMetadataProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
|
||||
{
|
||||
Logger = logManager.GetLogger(GetType().Name);
|
||||
LogManager = logManager;
|
||||
ConfigurationManager = configurationManager;
|
||||
Id = GetType().FullName.GetMD5();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this instance.
|
||||
/// </summary>
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the persisted last refresh date on the item for this provider.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="providerVersion">The provider version.</param>
|
||||
/// <param name="providerInfo">The provider information.</param>
|
||||
/// <param name="status">The status.</param>
|
||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||
public virtual void SetLastRefreshed(BaseItem item, DateTime value, string providerVersion,
|
||||
BaseProviderInfo providerInfo, ProviderRefreshStatus status = ProviderRefreshStatus.Success)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException("item");
|
||||
}
|
||||
|
||||
providerInfo.LastRefreshed = value;
|
||||
providerInfo.LastRefreshStatus = status;
|
||||
providerInfo.ProviderVersion = providerVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the last refreshed.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="providerInfo">The provider information.</param>
|
||||
/// <param name="status">The status.</param>
|
||||
public void SetLastRefreshed(BaseItem item, DateTime value,
|
||||
BaseProviderInfo providerInfo, ProviderRefreshStatus status = ProviderRefreshStatus.Success)
|
||||
{
|
||||
SetLastRefreshed(item, value, ProviderVersion, providerInfo, status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not this provider should be re-fetched. Default functionality can
|
||||
/// compare a provided date with a last refresh time. This can be overridden for more complex
|
||||
/// determinations.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public bool NeedsRefresh(BaseItem item, BaseProviderInfo data)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
return NeedsRefreshInternal(item, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [enforce dont fetch metadata].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enforce dont fetch metadata]; otherwise, <c>false</c>.</value>
|
||||
public virtual bool EnforceDontFetchMetadata
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Needses the refresh internal.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="providerInfo">The provider info.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
protected virtual bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException("item");
|
||||
}
|
||||
|
||||
if (providerInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException("providerInfo");
|
||||
}
|
||||
|
||||
if (providerInfo.LastRefreshed == default(DateTime))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NeedsRefreshBasedOnCompareDate(item, providerInfo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (RefreshOnVersionChange && !String.Equals(ProviderVersion, providerInfo.ProviderVersion))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (providerInfo.LastRefreshStatus != ProviderRefreshStatus.Success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Needses the refresh based on compare date.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="providerInfo">The provider info.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
protected virtual bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo)
|
||||
{
|
||||
return CompareDate(item) > providerInfo.LastRefreshed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to return the date that should be compared to the last refresh date
|
||||
/// to determine if this provider should be re-fetched.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>DateTime.</returns>
|
||||
protected virtual DateTime CompareDate(BaseItem item)
|
||||
{
|
||||
return DateTime.MinValue.AddMinutes(1); // want this to be greater than mindate so new items will refresh
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="force">if set to <c>true</c> [force].</param>
|
||||
/// <param name="providerInfo">The provider information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{System.Boolean}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public abstract Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority.
|
||||
/// </summary>
|
||||
/// <value>The priority.</value>
|
||||
public abstract MetadataProviderPriority Priority { get; }
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BaseProviderInfo
|
||||
/// </summary>
|
||||
public class BaseProviderInfo
|
||||
{
|
||||
public Guid ProviderId { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the last refreshed.
|
||||
/// </summary>
|
||||
/// <value>The last refreshed.</value>
|
||||
public DateTime LastRefreshed { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the file system stamp.
|
||||
/// </summary>
|
||||
/// <value>The file system stamp.</value>
|
||||
public Guid FileStamp { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the last refresh status.
|
||||
/// </summary>
|
||||
/// <value>The last refresh status.</value>
|
||||
public ProviderRefreshStatus LastRefreshStatus { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the provider version.
|
||||
/// </summary>
|
||||
/// <value>The provider version.</value>
|
||||
public string ProviderVersion { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum ProviderRefreshStatus
|
||||
/// </summary>
|
||||
public enum ProviderRefreshStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The success
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
/// <summary>
|
||||
/// The completed with errors
|
||||
/// </summary>
|
||||
CompletedWithErrors = 1,
|
||||
/// <summary>
|
||||
/// The failure
|
||||
/// </summary>
|
||||
Failure = 2
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a marker interface that will cause a provider to run even if IsLocked=true
|
||||
/// </summary>
|
||||
public interface IForcedProvider
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
public interface IImageSaver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
}
|
||||
|
||||
public interface IImageFileSaver : IImageSaver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the save paths.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <returns>IEnumerable{System.String}.</returns>
|
||||
IEnumerable<string> GetSavePaths(IHasImages item, ImageType type, ImageFormat format, int index);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
|
@ -26,10 +25,8 @@ namespace MediaBrowser.Controller.Providers
|
|||
}
|
||||
|
||||
public class MetadataResult<T>
|
||||
where T : IHasMetadata
|
||||
{
|
||||
public bool HasMetadata { get; set; }
|
||||
public T Item { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,8 +55,10 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <param name="metadataServices">The metadata services.</param>
|
||||
/// <param name="metadataProviders">The metadata providers.</param>
|
||||
/// <param name="savers">The savers.</param>
|
||||
/// <param name="imageSavers">The image savers.</param>
|
||||
void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders,
|
||||
IEnumerable<IMetadataSaver> savers);
|
||||
IEnumerable<IMetadataSaver> savers,
|
||||
IEnumerable<IImageSaver> imageSavers);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available remote images.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Threading;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
|
@ -8,10 +9,24 @@ namespace MediaBrowser.Controller.Providers
|
|||
{
|
||||
}
|
||||
|
||||
public interface IRemoteMetadataProvider<TItemType, in TLookupInfoType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider
|
||||
public interface IRemoteMetadataProvider<TItemType, TLookupInfoType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider
|
||||
where TItemType : IHasMetadata, IHasLookupInfo<TLookupInfoType>
|
||||
where TLookupInfoType : ItemLookupInfo, new()
|
||||
{
|
||||
Task<MetadataResult<TItemType>> GetMetadata(TLookupInfoType info, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IRemoteSearchProvider<TLookupInfoType>
|
||||
where TLookupInfoType : ItemLookupInfo
|
||||
{
|
||||
Task<IEnumerable<SearchResult<TLookupInfoType>>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public class SearchResult<T>
|
||||
where T : ItemLookupInfo
|
||||
{
|
||||
public T Item { get; set; }
|
||||
|
||||
public string ImageUrl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum ProviderRefreshStatus
|
||||
/// </summary>
|
||||
public enum ProviderRefreshStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The success
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
/// <summary>
|
||||
/// The completed with errors
|
||||
/// </summary>
|
||||
CompletedWithErrors = 1,
|
||||
/// <summary>
|
||||
/// The failure
|
||||
/// </summary>
|
||||
Failure = 2
|
||||
}
|
||||
}
|
|
@ -657,7 +657,7 @@ namespace MediaBrowser.Model.Dto
|
|||
/// Gets or sets a value indicating whether [enable internet providers].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enable internet providers]; otherwise, <c>false</c>.</value>
|
||||
public bool? EnableInternetProviders { get; set; }
|
||||
public bool? LockData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance can resume.
|
||||
|
|
|
@ -9,18 +9,18 @@ namespace MediaBrowser.Model.Entities
|
|||
/// <summary>
|
||||
/// The file system
|
||||
/// </summary>
|
||||
FileSystem = 1,
|
||||
FileSystem = 0,
|
||||
/// <summary>
|
||||
/// The remote
|
||||
/// </summary>
|
||||
Remote = 2,
|
||||
Remote = 1,
|
||||
/// <summary>
|
||||
/// The virtual
|
||||
/// </summary>
|
||||
Virtual = 3,
|
||||
Virtual = 2,
|
||||
/// <summary>
|
||||
/// The offline
|
||||
/// </summary>
|
||||
Offline = 4
|
||||
Offline = 3
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ namespace MediaBrowser.Model.Notifications
|
|||
{
|
||||
public enum NotificationLevel
|
||||
{
|
||||
Normal = 1,
|
||||
Warning = 2,
|
||||
Error = 3
|
||||
Normal = 0,
|
||||
Warning = 1,
|
||||
Error = 2
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
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.Providers.Manager;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Providers.Genres
|
||||
{
|
||||
public class GenreMetadataService : MetadataService<Genre, ItemLookupInfo>
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public GenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager)
|
||||
public GenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem)
|
||||
: base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -52,11 +52,10 @@ namespace MediaBrowser.Providers.Manager
|
|||
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
private readonly IProviderRepository _providerRepo;
|
||||
|
||||
private IMetadataService[] _metadataServices = { };
|
||||
private IMetadataProvider[] _metadataProviders = { };
|
||||
private IEnumerable<IMetadataSaver> _savers;
|
||||
private IImageSaver[] _imageSavers;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProviderManager" /> class.
|
||||
|
@ -66,15 +65,13 @@ namespace MediaBrowser.Providers.Manager
|
|||
/// <param name="libraryMonitor">The directory watchers.</param>
|
||||
/// <param name="logManager">The log manager.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="providerRepo">The provider repo.</param>
|
||||
public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IProviderRepository providerRepo)
|
||||
public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem)
|
||||
{
|
||||
_logger = logManager.GetLogger("ProviderManager");
|
||||
_httpClient = httpClient;
|
||||
ConfigurationManager = configurationManager;
|
||||
_libraryMonitor = libraryMonitor;
|
||||
_fileSystem = fileSystem;
|
||||
_providerRepo = providerRepo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -84,13 +81,16 @@ namespace MediaBrowser.Providers.Manager
|
|||
/// <param name="metadataServices">The metadata services.</param>
|
||||
/// <param name="metadataProviders">The metadata providers.</param>
|
||||
/// <param name="metadataSavers">The metadata savers.</param>
|
||||
public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers)
|
||||
/// <param name="imageSavers">The image savers.</param>
|
||||
public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers,
|
||||
IEnumerable<IImageSaver> imageSavers)
|
||||
{
|
||||
ImageProviders = imageProviders.ToArray();
|
||||
|
||||
_metadataServices = metadataServices.OrderBy(i => i.Order).ToArray();
|
||||
_metadataProviders = metadataProviders.ToArray();
|
||||
_savers = metadataSavers.ToArray();
|
||||
_imageSavers = imageSavers.ToArray();
|
||||
}
|
||||
|
||||
public Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
||||
|
@ -106,62 +106,6 @@ namespace MediaBrowser.Providers.Manager
|
|||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves to library filesystem.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="dataToSave">The data to save.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public async Task SaveToLibraryFilesystem(BaseItem item, string path, Stream dataToSave, CancellationToken cancellationToken)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (dataToSave == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
dataToSave.Dispose();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
//Tell the watchers to ignore
|
||||
_libraryMonitor.ReportFileSystemChangeBeginning(path);
|
||||
|
||||
if (dataToSave.CanSeek)
|
||||
{
|
||||
dataToSave.Position = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (dataToSave)
|
||||
{
|
||||
using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
|
||||
{
|
||||
await dataToSave.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Remove the ignore
|
||||
_libraryMonitor.ReportFileSystemChangeComplete(path, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves the image.
|
||||
/// </summary>
|
||||
|
@ -252,8 +196,13 @@ namespace MediaBrowser.Providers.Manager
|
|||
result = result.Where(i => i.Type == type.Value);
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(preferredLanguage) ? result :
|
||||
FilterImages(result, preferredLanguage);
|
||||
if (string.Equals(preferredLanguage, "en", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = result.Where(i => string.IsNullOrEmpty(i.Language) ||
|
||||
string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -262,17 +211,6 @@ namespace MediaBrowser.Providers.Manager
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<RemoteImageInfo> FilterImages(IEnumerable<RemoteImageInfo> images, string preferredLanguage)
|
||||
{
|
||||
if (string.Equals(preferredLanguage, "en", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
images = images.Where(i => string.IsNullOrEmpty(i.Language) ||
|
||||
string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported image providers.
|
||||
/// </summary>
|
||||
|
@ -294,13 +232,16 @@ namespace MediaBrowser.Providers.Manager
|
|||
|
||||
private IEnumerable<IImageProvider> GetImageProviders(IHasImages item, MetadataOptions options, bool includeDisabled)
|
||||
{
|
||||
// Avoid implicitly captured closure
|
||||
var currentOptions = options;
|
||||
|
||||
return ImageProviders.Where(i => CanRefresh(i, item, options, includeDisabled))
|
||||
.OrderBy(i =>
|
||||
{
|
||||
// See if there's a user-defined order
|
||||
if (!(i is ILocalImageProvider))
|
||||
{
|
||||
var index = Array.IndexOf(options.ImageFetcherOrder, i.Name);
|
||||
var index = Array.IndexOf(currentOptions.ImageFetcherOrder, i.Name);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
|
@ -325,36 +266,13 @@ namespace MediaBrowser.Providers.Manager
|
|||
private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled)
|
||||
where T : IHasMetadata
|
||||
{
|
||||
// Avoid implicitly captured closure
|
||||
var currentOptions = options;
|
||||
|
||||
return _metadataProviders.OfType<IMetadataProvider<T>>()
|
||||
.Where(i => CanRefresh(i, item, options, includeDisabled))
|
||||
.OrderBy(i =>
|
||||
{
|
||||
// See if there's a user-defined order
|
||||
if (i is ILocalMetadataProvider)
|
||||
{
|
||||
var index = Array.IndexOf(options.LocalMetadataReaderOrder, i.Name);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
// See if there's a user-defined order
|
||||
if (i is IRemoteMetadataProvider)
|
||||
{
|
||||
var index = Array.IndexOf(options.MetadataFetcherOrder, i.Name);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
// Not configured. Just return some high number to put it at the end.
|
||||
return 100;
|
||||
})
|
||||
.ThenBy(GetOrder);
|
||||
.Where(i => CanRefresh(i, item, currentOptions, includeDisabled))
|
||||
.OrderBy(i => GetConfiguredOrder(i, options))
|
||||
.ThenBy(GetDefaultOrder);
|
||||
}
|
||||
|
||||
private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(IHasImages item, bool includeDisabled)
|
||||
|
@ -368,6 +286,12 @@ namespace MediaBrowser.Providers.Manager
|
|||
{
|
||||
if (!includeDisabled)
|
||||
{
|
||||
// If locked only allow local providers
|
||||
if (item.IsLocked && !(provider is ILocalMetadataProvider) && !(provider is IForcedProvider))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (provider is IRemoteMetadataProvider)
|
||||
{
|
||||
if (Array.IndexOf(options.DisabledMetadataFetchers, provider.Name) != -1)
|
||||
|
@ -398,6 +322,12 @@ namespace MediaBrowser.Providers.Manager
|
|||
{
|
||||
if (!includeDisabled)
|
||||
{
|
||||
// If locked only allow local providers
|
||||
if (item.IsLocked && !(provider is ILocalImageProvider))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (provider is IRemoteImageProvider)
|
||||
{
|
||||
if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1)
|
||||
|
@ -440,12 +370,35 @@ namespace MediaBrowser.Providers.Manager
|
|||
return hasOrder.Order;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the order.
|
||||
/// </summary>
|
||||
/// <param name="provider">The provider.</param>
|
||||
/// <returns>System.Int32.</returns>
|
||||
private int GetOrder(IMetadataProvider provider)
|
||||
private int GetConfiguredOrder(IMetadataProvider provider, MetadataOptions options)
|
||||
{
|
||||
// See if there's a user-defined order
|
||||
if (provider is ILocalMetadataProvider)
|
||||
{
|
||||
var index = Array.IndexOf(options.LocalMetadataReaderOrder, provider.Name);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
// See if there's a user-defined order
|
||||
if (provider is IRemoteMetadataProvider)
|
||||
{
|
||||
var index = Array.IndexOf(options.MetadataFetcherOrder, provider.Name);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
// Not configured. Just return some high number to put it at the end.
|
||||
return 100;
|
||||
}
|
||||
|
||||
private int GetDefaultOrder(IMetadataProvider provider)
|
||||
{
|
||||
var hasOrder = provider as IHasOrder;
|
||||
|
||||
|
@ -578,6 +531,7 @@ namespace MediaBrowser.Providers.Manager
|
|||
}
|
||||
|
||||
private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
|
||||
|
||||
/// <summary>
|
||||
/// Saves the metadata.
|
||||
/// </summary>
|
||||
|
@ -658,5 +612,14 @@ namespace MediaBrowser.Providers.Manager
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//private IEnumerable<TLookupType> GetRemoteSearchResults<TLookupType>(TLookupType searchInfo,
|
||||
// CancellationToken cancellationToken)
|
||||
// where TLookupType : ItemLookupInfo
|
||||
//{
|
||||
// var providers = _metadataProviders.OfType<IRemoteSearchProvider<TLookupType>>();
|
||||
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -198,6 +198,7 @@
|
|||
<Compile Include="TV\TvdbPrescanTask.cs" />
|
||||
<Compile Include="Users\UserMetadataService.cs" />
|
||||
<Compile Include="Videos\VideoMetadataService.cs" />
|
||||
<Compile Include="Xbmc\XbmcImageSaver.cs" />
|
||||
<Compile Include="Years\YearMetadataService.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -31,7 +31,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
ICustomMetadataProvider<Video>,
|
||||
ICustomMetadataProvider<Audio>,
|
||||
IHasChangeMonitor,
|
||||
IHasOrder
|
||||
IHasOrder,
|
||||
IForcedProvider
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IIsoManager _isoManager;
|
||||
|
|
|
@ -12,6 +12,7 @@ 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;
|
||||
|
@ -41,6 +42,73 @@ namespace MediaBrowser.Providers.People
|
|||
get { return "TheMovieDb"; }
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchResult<PersonLookupInfo>>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb);
|
||||
|
||||
var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var tmdbImageUrl = tmdbSettings.images.base_url + "original";
|
||||
|
||||
if (!string.IsNullOrEmpty(tmdbId))
|
||||
{
|
||||
await EnsurePersonInfo(tmdbId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var dataFilePath = GetPersonDataFilePath(_configurationManager.ApplicationPaths, tmdbId);
|
||||
var info = _jsonSerializer.DeserializeFromFile<PersonResult>(dataFilePath);
|
||||
|
||||
var images = (info.images ?? new Images()).profiles ?? new List<Profile>();
|
||||
|
||||
var result = new SearchResult<PersonLookupInfo>
|
||||
{
|
||||
Item = new PersonLookupInfo
|
||||
{
|
||||
Name = info.name
|
||||
},
|
||||
|
||||
ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path)
|
||||
};
|
||||
|
||||
result.Item.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
|
||||
result.Item.SetProviderId(MetadataProviders.Imdb, info.imdb_id.ToString(_usCulture));
|
||||
|
||||
return new[] { result };
|
||||
}
|
||||
|
||||
var url = string.Format(@"http://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey);
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
var result = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json) ??
|
||||
new PersonSearchResults();
|
||||
|
||||
return result.Results.Select(i => GetSearchResult(i, tmdbImageUrl));
|
||||
}
|
||||
}
|
||||
|
||||
private SearchResult<PersonLookupInfo> GetSearchResult(PersonSearchResult i, string baseImageUrl)
|
||||
{
|
||||
var result = new SearchResult<PersonLookupInfo>
|
||||
{
|
||||
Item = new PersonLookupInfo
|
||||
{
|
||||
Name = i.Name
|
||||
},
|
||||
|
||||
ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : (baseImageUrl + i.Profile_Path)
|
||||
};
|
||||
|
||||
result.Item.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<MetadataResult<Person>> GetMetadata(PersonLookupInfo id, CancellationToken cancellationToken)
|
||||
{
|
||||
var tmdbId = id.GetProviderId(MetadataProviders.Tmdb);
|
||||
|
@ -48,7 +116,7 @@ namespace MediaBrowser.Providers.People
|
|||
// We don't already have an Id, need to fetch it
|
||||
if (string.IsNullOrEmpty(tmdbId))
|
||||
{
|
||||
tmdbId = await GetTmdbId(id.Name, cancellationToken).ConfigureAwait(false);
|
||||
tmdbId = await GetTmdbId(id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var result = new MetadataResult<Person>();
|
||||
|
@ -100,26 +168,14 @@ namespace MediaBrowser.Providers.People
|
|||
/// <summary>
|
||||
/// Gets the TMDB id.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{System.String}.</returns>
|
||||
private async Task<string> GetTmdbId(string name, CancellationToken cancellationToken)
|
||||
private async Task<string> GetTmdbId(PersonLookupInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
string url = string.Format(@"http://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(name), MovieDbProvider.ApiKey);
|
||||
PersonSearchResults searchResult = null;
|
||||
var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
AcceptHeader = MovieDbProvider.AcceptHeader
|
||||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
searchResult = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json);
|
||||
}
|
||||
|
||||
return searchResult != null && searchResult.Total_Results > 0 ? searchResult.Results[0].Id.ToString(_usCulture) : null;
|
||||
return results.Select(i => i.Item.GetProviderId(MetadataProviders.Tmdb)).FirstOrDefault();
|
||||
}
|
||||
|
||||
internal async Task EnsurePersonInfo(string id, CancellationToken cancellationToken)
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace MediaBrowser.Providers.Savers
|
|||
|
||||
"Added",
|
||||
"AspectRatio",
|
||||
"AudioDbAlbumId",
|
||||
"AudioDbArtistId",
|
||||
"AwardSummary",
|
||||
"BirthDate",
|
||||
"Budget",
|
||||
|
@ -73,6 +75,7 @@ namespace MediaBrowser.Providers.Savers
|
|||
"TVcomId",
|
||||
"TvDbId",
|
||||
"Type",
|
||||
"TVRageId",
|
||||
"VoteCount",
|
||||
"Website",
|
||||
"Zap2ItId"
|
||||
|
@ -477,7 +480,7 @@ namespace MediaBrowser.Providers.Savers
|
|||
|
||||
if (!string.IsNullOrEmpty(externalId))
|
||||
{
|
||||
builder.Append("<TvRageId>" + SecurityElement.Escape(externalId) + "</TvRageId>");
|
||||
builder.Append("<TVRageId>" + SecurityElement.Escape(externalId) + "</TVRageId>");
|
||||
}
|
||||
|
||||
var hasTagline = item as IHasTaglines;
|
||||
|
|
|
@ -0,0 +1,272 @@
|
|||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Providers.Xbmc
|
||||
{
|
||||
public class XbmcImageSaver : IImageFileSaver
|
||||
{
|
||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||
|
||||
public IEnumerable<string> GetSavePaths(IHasImages item, ImageType type, ImageFormat format, int index)
|
||||
{
|
||||
var season = item as Season;
|
||||
|
||||
if (!SupportsItem(item, type, season))
|
||||
{
|
||||
return new string[] { };
|
||||
}
|
||||
|
||||
var extension = "." + format.ToString().ToLower();
|
||||
|
||||
// Backdrop paths
|
||||
if (type == ImageType.Backdrop)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
if (item.IsInMixedFolder)
|
||||
{
|
||||
return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart", extension) };
|
||||
}
|
||||
|
||||
if (season != null && season.IndexNumber.HasValue)
|
||||
{
|
||||
var seriesFolder = season.SeriesPath;
|
||||
|
||||
var seasonMarker = season.IndexNumber.Value == 0
|
||||
? "-specials"
|
||||
: season.IndexNumber.Value.ToString("00", _usCulture);
|
||||
|
||||
var imageFilename = "season" + seasonMarker + "-fanart" + extension;
|
||||
|
||||
return new[] { Path.Combine(seriesFolder, imageFilename) };
|
||||
}
|
||||
|
||||
return new[]
|
||||
{
|
||||
Path.Combine(item.ContainingFolderPath, "fanart" + extension)
|
||||
};
|
||||
}
|
||||
|
||||
if (item.IsInMixedFolder)
|
||||
{
|
||||
return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart" + index.ToString(_usCulture), extension) };
|
||||
}
|
||||
|
||||
var extraFanartFilename = GetBackdropSaveFilename(item.GetImages(ImageType.Backdrop), "fanart", "fanart", index);
|
||||
|
||||
return new[]
|
||||
{
|
||||
Path.Combine(item.ContainingFolderPath, "extrafanart", extraFanartFilename + extension),
|
||||
Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + index.ToString(_usCulture) + extension)
|
||||
};
|
||||
}
|
||||
|
||||
if (type == ImageType.Primary)
|
||||
{
|
||||
if (season != null && season.IndexNumber.HasValue)
|
||||
{
|
||||
var seriesFolder = season.SeriesPath;
|
||||
|
||||
var seasonMarker = season.IndexNumber.Value == 0
|
||||
? "-specials"
|
||||
: season.IndexNumber.Value.ToString("00", _usCulture);
|
||||
|
||||
var imageFilename = "season" + seasonMarker + "-poster" + extension;
|
||||
|
||||
return new[] { Path.Combine(seriesFolder, imageFilename) };
|
||||
}
|
||||
|
||||
if (item is Episode)
|
||||
{
|
||||
var seasonFolder = Path.GetDirectoryName(item.Path);
|
||||
|
||||
var imageFilename = Path.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension;
|
||||
|
||||
return new[] { Path.Combine(seasonFolder, imageFilename) };
|
||||
}
|
||||
|
||||
if (item.IsInMixedFolder || item is MusicVideo)
|
||||
{
|
||||
return new[] { GetSavePathForItemInMixedFolder(item, type, string.Empty, extension) };
|
||||
}
|
||||
|
||||
if (item is MusicAlbum || item is MusicArtist)
|
||||
{
|
||||
return new[] { Path.Combine(item.ContainingFolderPath, "folder" + extension) };
|
||||
}
|
||||
|
||||
return new[] { Path.Combine(item.ContainingFolderPath, "poster" + extension) };
|
||||
}
|
||||
|
||||
if (type == ImageType.Banner)
|
||||
{
|
||||
if (season != null && season.IndexNumber.HasValue)
|
||||
{
|
||||
var seriesFolder = season.SeriesPath;
|
||||
|
||||
var seasonMarker = season.IndexNumber.Value == 0
|
||||
? "-specials"
|
||||
: season.IndexNumber.Value.ToString("00", _usCulture);
|
||||
|
||||
var imageFilename = "season" + seasonMarker + "-banner" + extension;
|
||||
|
||||
return new[] { Path.Combine(seriesFolder, imageFilename) };
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ImageType.Thumb)
|
||||
{
|
||||
if (season != null && season.IndexNumber.HasValue)
|
||||
{
|
||||
var seriesFolder = season.SeriesPath;
|
||||
|
||||
var seasonMarker = season.IndexNumber.Value == 0
|
||||
? "-specials"
|
||||
: season.IndexNumber.Value.ToString("00", _usCulture);
|
||||
|
||||
var imageFilename = "season" + seasonMarker + "-landscape" + extension;
|
||||
|
||||
return new[] { Path.Combine(seriesFolder, imageFilename) };
|
||||
}
|
||||
|
||||
if (item.IsInMixedFolder)
|
||||
{
|
||||
return new[] { GetSavePathForItemInMixedFolder(item, type, "landscape", extension) };
|
||||
}
|
||||
|
||||
return new[] { Path.Combine(item.ContainingFolderPath, "landscape" + extension) };
|
||||
}
|
||||
|
||||
return GetStandardSavePaths(item, type, index, extension);
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetStandardSavePaths(IHasImages item, ImageType type, int imageIndex, string extension)
|
||||
{
|
||||
string filename;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ImageType.Art:
|
||||
filename = "clearart";
|
||||
break;
|
||||
case ImageType.BoxRear:
|
||||
filename = "back";
|
||||
break;
|
||||
case ImageType.Disc:
|
||||
filename = item is MusicAlbum ? "cdart" : "disc";
|
||||
break;
|
||||
case ImageType.Screenshot:
|
||||
filename = GetBackdropSaveFilename(item.GetImages(type), "screenshot", "screenshot", imageIndex);
|
||||
break;
|
||||
default:
|
||||
filename = type.ToString().ToLower();
|
||||
break;
|
||||
}
|
||||
|
||||
string path = null;
|
||||
|
||||
if (item.IsInMixedFolder)
|
||||
{
|
||||
path = GetSavePathForItemInMixedFolder(item, type, filename, extension);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = Path.Combine(item.ContainingFolderPath, filename + extension);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return new string[] { };
|
||||
}
|
||||
|
||||
return new[] { path };
|
||||
}
|
||||
|
||||
|
||||
private string GetSavePathForItemInMixedFolder(IHasImages item, ImageType type, string imageFilename, string extension)
|
||||
{
|
||||
if (type == ImageType.Primary)
|
||||
{
|
||||
imageFilename = "poster";
|
||||
}
|
||||
var folder = Path.GetDirectoryName(item.Path);
|
||||
|
||||
return Path.Combine(folder, Path.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension);
|
||||
}
|
||||
|
||||
private bool SupportsItem(IHasImages item, ImageType type, Season season)
|
||||
{
|
||||
if (item.IsOwnedItem || item is Audio || item is User)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type != ImageType.Primary && item is Episode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!item.SupportsLocalMetadata)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var locationType = item.LocationType;
|
||||
if (locationType == LocationType.Remote || locationType == LocationType.Virtual)
|
||||
{
|
||||
var allowSaving = false;
|
||||
|
||||
// If season is virtual under a physical series, save locally if using compatible convention
|
||||
if (season != null)
|
||||
{
|
||||
var series = season.Series;
|
||||
|
||||
if (series != null && series.SupportsLocalMetadata)
|
||||
{
|
||||
allowSaving = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allowSaving)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetBackdropSaveFilename(IEnumerable<ItemImageInfo> images, string zeroIndexFilename, string numberedIndexPrefix, int? index)
|
||||
{
|
||||
if (index.HasValue && index.Value == 0)
|
||||
{
|
||||
return zeroIndexFilename;
|
||||
}
|
||||
|
||||
var filenames = images.Select(i => Path.GetFileNameWithoutExtension(i.Path)).ToList();
|
||||
|
||||
var current = 1;
|
||||
while (filenames.Contains(numberedIndexPrefix + current.ToString(_usCulture), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
current++;
|
||||
}
|
||||
|
||||
return numberedIndexPrefix + current.ToString(_usCulture);
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "MB3/Plex/Xbmc Images"; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -664,7 +664,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||
if (fields.Contains(ItemFields.Settings))
|
||||
{
|
||||
dto.LockedFields = item.LockedFields;
|
||||
dto.EnableInternetProviders = !item.DontFetchMeta;
|
||||
dto.LockData = item.DontFetchMeta;
|
||||
}
|
||||
|
||||
var hasBudget = item as IHasBudget;
|
||||
|
|
|
@ -435,10 +435,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
|||
|
||||
if (!compress || string.IsNullOrEmpty(requestedCompressionType))
|
||||
{
|
||||
var stream = await factoryFn().ConfigureAwait(false);
|
||||
|
||||
var rangeHeader = requestContext.GetHeader("Range");
|
||||
|
||||
var stream = await factoryFn().ConfigureAwait(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(rangeHeader))
|
||||
{
|
||||
return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest);
|
||||
|
@ -448,34 +448,54 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
|||
|
||||
if (isHeadRequest)
|
||||
{
|
||||
stream.Dispose();
|
||||
|
||||
return GetHttpResult(new byte[] { }, contentType);
|
||||
}
|
||||
|
||||
return new StreamWriter(stream, contentType, _logger);
|
||||
}
|
||||
|
||||
if (isHeadRequest)
|
||||
{
|
||||
return GetHttpResult(new byte[] { }, contentType);
|
||||
}
|
||||
|
||||
string content;
|
||||
long originalContentLength = 0;
|
||||
|
||||
using (var stream = await factoryFn().ConfigureAwait(false))
|
||||
{
|
||||
using (var reader = new StreamReader(stream))
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
originalContentLength = memoryStream.Length;
|
||||
|
||||
using (var reader = new StreamReader(memoryStream))
|
||||
{
|
||||
content = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!SupportsCompression)
|
||||
{
|
||||
responseHeaders["Content-Length"] = originalContentLength.ToString(UsCulture);
|
||||
|
||||
if (isHeadRequest)
|
||||
{
|
||||
return GetHttpResult(new byte[] { }, contentType);
|
||||
}
|
||||
|
||||
return new HttpResult(content, contentType);
|
||||
}
|
||||
|
||||
var contents = content.Compress(requestedCompressionType);
|
||||
|
||||
responseHeaders["Content-Length"] = contents.Length.ToString(UsCulture);
|
||||
|
||||
if (isHeadRequest)
|
||||
{
|
||||
return GetHttpResult(new byte[] { }, contentType);
|
||||
}
|
||||
|
||||
return new CompressedResult(contents, requestedCompressionType, contentType);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ using MediaBrowser.Model.Serialization;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -171,7 +170,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
|
|||
|
||||
throw;
|
||||
}
|
||||
catch (HttpListenerException ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error starting Http Server", ex);
|
||||
|
||||
|
|
|
@ -336,7 +336,7 @@ namespace MediaBrowser.ServerApplication
|
|||
LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager);
|
||||
RegisterSingleInstance(LibraryMonitor);
|
||||
|
||||
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ProviderRepository);
|
||||
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager);
|
||||
RegisterSingleInstance(ProviderManager);
|
||||
|
||||
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
|
||||
|
@ -548,7 +548,8 @@ namespace MediaBrowser.ServerApplication
|
|||
GetExports<ILibraryPostScanTask>());
|
||||
|
||||
ProviderManager.AddParts(GetExports<IImageProvider>(), GetExports<IMetadataService>(), GetExports<IMetadataProvider>(),
|
||||
GetExports<IMetadataSaver>());
|
||||
GetExports<IMetadataSaver>(),
|
||||
GetExports<IImageSaver>());
|
||||
|
||||
ImageProcessor.AddParts(GetExports<IImageEnhancer>());
|
||||
|
||||
|
|
Loading…
Reference in New Issue