fixed remote control flyout

pull/702/head
Luke Pulverenti 10 years ago
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);
}
}
@ -307,16 +306,13 @@ 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
{
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;
}
}
// Avoid implicitly captured closure
var currentOptions = options;
// Not configured. Just return some high number to put it at the end.
return 100;
})
.ThenBy(GetOrder);
return _metadataProviders.OfType<IMetadataProvider<T>>()
.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;
@ -21,9 +22,9 @@ namespace MediaBrowser.Providers.People
public class MovieDbPersonProvider : IRemoteMetadataProvider<Person, PersonLookupInfo>
{
const string DataFileName = "info.json";
internal static MovieDbPersonProvider Current { get; private set; }
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
@ -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;
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
AcceptHeader = MovieDbProvider.AcceptHeader
}).ConfigureAwait(false))
{
searchResult = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json);
}
var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
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())
{
content = await reader.ReadToEndAsync().ConfigureAwait(false);
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);
}

@ -69,7 +69,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var response = (HttpListenerResponse)res.OriginalResponse;
response.ContentLength64 = length;
// Disable chunked encoding. Technically this is only needed when using Content-Range, but
// anytime we know the content length there's no need for it
response.SendChunked = false;

@ -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…
Cancel
Save