mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
Add GPL modules
This commit is contained in:
parent
9bac3ac616
commit
a86b71899e
@ -231,7 +231,7 @@ namespace Emby.Notifications
|
||||
}
|
||||
}
|
||||
|
||||
var hasSeries = item as IHasSeriesName;
|
||||
var hasSeries = item as IHasSeries;
|
||||
|
||||
if (hasSeries != null)
|
||||
{
|
||||
|
@ -318,7 +318,6 @@ namespace Emby.Server.Implementations
|
||||
private IMediaEncoder MediaEncoder { get; set; }
|
||||
private ISubtitleEncoder SubtitleEncoder { get; set; }
|
||||
|
||||
private IConnectManager ConnectManager { get; set; }
|
||||
private ISessionManager SessionManager { get; set; }
|
||||
|
||||
private ILiveTvManager LiveTvManager { get; set; }
|
||||
@ -839,8 +838,6 @@ namespace Emby.Server.Implementations
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract IConnectManager CreateConnectManager();
|
||||
|
||||
protected virtual IHttpClient CreateHttpClient()
|
||||
{
|
||||
return new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, GetDefaultUserAgent);
|
||||
@ -947,7 +944,7 @@ namespace Emby.Server.Implementations
|
||||
AuthenticationRepository = GetAuthenticationRepository();
|
||||
RegisterSingleInstance(AuthenticationRepository);
|
||||
|
||||
UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer, FileSystemManager, CryptographyProvider);
|
||||
UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, this, JsonSerializer, FileSystemManager, CryptographyProvider);
|
||||
RegisterSingleInstance(UserManager);
|
||||
|
||||
LibraryManager = new LibraryManager(this, Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
|
||||
@ -986,9 +983,6 @@ namespace Emby.Server.Implementations
|
||||
var encryptionManager = new EncryptionManager();
|
||||
RegisterSingleInstance<IEncryptionManager>(encryptionManager);
|
||||
|
||||
ConnectManager = CreateConnectManager();
|
||||
RegisterSingleInstance(ConnectManager);
|
||||
|
||||
DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
|
||||
RegisterSingleInstance(DeviceManager);
|
||||
|
||||
@ -1045,11 +1039,11 @@ namespace Emby.Server.Implementations
|
||||
RegisterSingleInstance(activityLogRepo);
|
||||
RegisterSingleInstance<IActivityManager>(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager));
|
||||
|
||||
var authContext = new AuthorizationContext(AuthenticationRepository, ConnectManager, UserManager);
|
||||
var authContext = new AuthorizationContext(AuthenticationRepository, UserManager);
|
||||
RegisterSingleInstance<IAuthorizationContext>(authContext);
|
||||
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
|
||||
|
||||
AuthService = new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, NetworkManager);
|
||||
AuthService = new AuthService(UserManager, authContext, ServerConfigurationManager, SessionManager, NetworkManager);
|
||||
RegisterSingleInstance<IAuthService>(AuthService);
|
||||
|
||||
SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, ProcessFactory, TextEncoding);
|
||||
|
@ -1086,7 +1086,7 @@ namespace Emby.Server.Implementations.Channels
|
||||
}
|
||||
item.ParentId = parentFolderId;
|
||||
|
||||
var hasSeries = item as IHasSeriesName;
|
||||
var hasSeries = item as IHasSeries;
|
||||
if (hasSeries != null)
|
||||
{
|
||||
if (!string.Equals(hasSeries.SeriesName, info.SeriesName, StringComparison.OrdinalIgnoreCase))
|
||||
@ -1215,4 +1215,4 @@ namespace Emby.Server.Implementations.Channels
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -942,7 +942,7 @@ namespace Emby.Server.Implementations.Data
|
||||
saveItemStatement.TryBind("@Album", item.Album);
|
||||
saveItemStatement.TryBind("@IsVirtualItem", item.IsVirtualItem);
|
||||
|
||||
var hasSeriesName = item as IHasSeriesName;
|
||||
var hasSeriesName = item as IHasSeries;
|
||||
if (hasSeriesName != null)
|
||||
{
|
||||
saveItemStatement.TryBind("@SeriesName", hasSeriesName.SeriesName);
|
||||
@ -1757,7 +1757,7 @@ namespace Emby.Server.Implementations.Data
|
||||
}
|
||||
index++;
|
||||
|
||||
var hasSeriesName = item as IHasSeriesName;
|
||||
var hasSeriesName = item as IHasSeries;
|
||||
if (hasSeriesName != null)
|
||||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
@ -6441,4 +6441,4 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,19 +17,17 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||
{
|
||||
private readonly IServerConfigurationManager _config;
|
||||
|
||||
public AuthService(IUserManager userManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config, IConnectManager connectManager, ISessionManager sessionManager, INetworkManager networkManager)
|
||||
public AuthService(IUserManager userManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config, ISessionManager sessionManager, INetworkManager networkManager)
|
||||
{
|
||||
AuthorizationContext = authorizationContext;
|
||||
_config = config;
|
||||
SessionManager = sessionManager;
|
||||
ConnectManager = connectManager;
|
||||
UserManager = userManager;
|
||||
NetworkManager = networkManager;
|
||||
}
|
||||
|
||||
public IUserManager UserManager { get; private set; }
|
||||
public IAuthorizationContext AuthorizationContext { get; private set; }
|
||||
public IConnectManager ConnectManager { get; private set; }
|
||||
public ISessionManager SessionManager { get; private set; }
|
||||
public INetworkManager NetworkManager { get; private set; }
|
||||
|
||||
|
@ -13,13 +13,11 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||
public class AuthorizationContext : IAuthorizationContext
|
||||
{
|
||||
private readonly IAuthenticationRepository _authRepo;
|
||||
private readonly IConnectManager _connectManager;
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
public AuthorizationContext(IAuthenticationRepository authRepo, IConnectManager connectManager, IUserManager userManager)
|
||||
public AuthorizationContext(IAuthenticationRepository authRepo, IUserManager userManager)
|
||||
{
|
||||
_authRepo = authRepo;
|
||||
_connectManager = connectManager;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
|
@ -1,46 +0,0 @@
|
||||
using MediaBrowser.Common.Events;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Connect;
|
||||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Connect;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Cryptography;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Controller.Security;
|
||||
using MediaBrowser.Controller.Devices;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
public class ConnectManager : IConnectManager
|
||||
{
|
||||
public ConnectManager()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -74,7 +74,6 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
private readonly Func<IImageProcessor> _imageProcessorFactory;
|
||||
private readonly Func<IDtoService> _dtoServiceFactory;
|
||||
private readonly Func<IConnectManager> _connectFactory;
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ICryptoProvider _cryptographyProvider;
|
||||
@ -82,7 +81,7 @@ namespace Emby.Server.Implementations.Library
|
||||
private IAuthenticationProvider[] _authenticationProviders;
|
||||
private DefaultAuthenticationProvider _defaultAuthenticationProvider;
|
||||
|
||||
public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
|
||||
public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
|
||||
{
|
||||
_logger = logger;
|
||||
UserRepository = userRepository;
|
||||
@ -90,7 +89,6 @@ namespace Emby.Server.Implementations.Library
|
||||
_networkManager = networkManager;
|
||||
_imageProcessorFactory = imageProcessorFactory;
|
||||
_dtoServiceFactory = dtoServiceFactory;
|
||||
_connectFactory = connectFactory;
|
||||
_appHost = appHost;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_fileSystem = fileSystem;
|
||||
|
@ -61,21 +61,6 @@ namespace MediaBrowser.Api
|
||||
public bool? IsAppStoreEnabled { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class GetPackageVersionUpdates
|
||||
/// </summary>
|
||||
[Route("/Packages/Updates", "GET", Summary = "Gets available package updates for currently installed packages")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetPackageVersionUpdates : IReturn<PackageVersionInfo[]>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[ApiMember(Name = "PackageType", Description = "Package type filter (System/UserInstalled)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
public string PackageType { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class InstallPackage
|
||||
/// </summary>
|
||||
@ -146,30 +131,7 @@ namespace MediaBrowser.Api
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public async Task<object> Get(GetPackageVersionUpdates request)
|
||||
{
|
||||
PackageVersionInfo[] result = null;
|
||||
|
||||
if (string.Equals(request.PackageType, "UserInstalled", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = (await _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).ConfigureAwait(false)).ToArray();
|
||||
}
|
||||
|
||||
else if (string.Equals(request.PackageType, "System", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var updateCheckResult = await _appHost
|
||||
.CheckForApplicationUpdate(CancellationToken.None, new SimpleProgress<double>()).ConfigureAwait(false);
|
||||
|
||||
if (updateCheckResult.IsUpdateAvailable)
|
||||
{
|
||||
result = new PackageVersionInfo[] { updateCheckResult.Package };
|
||||
}
|
||||
}
|
||||
|
||||
return ToOptimizedResult(result ?? new PackageVersionInfo[] { });
|
||||
}
|
||||
|
||||
///
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
/// </summary>
|
||||
|
@ -148,7 +148,6 @@ namespace MediaBrowser.Api.Playback
|
||||
DisposeTranscodingThrottler();
|
||||
DisposeLiveStream();
|
||||
DisposeLogStream();
|
||||
DisposeIsoMount();
|
||||
|
||||
TranscodingJob = null;
|
||||
}
|
||||
@ -251,9 +250,9 @@ namespace MediaBrowser.Api.Playback
|
||||
public DeviceProfile DeviceProfile { get; set; }
|
||||
|
||||
public TranscodingJob TranscodingJob;
|
||||
public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
|
||||
public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float framerate, double? percentComplete, long bytesTranscoded, int? bitRate)
|
||||
{
|
||||
ApiEntryPoint.Instance.ReportTranscodingProgress(TranscodingJob, this, transcodingPosition, framerate, percentComplete, bytesTranscoded, bitRate);
|
||||
ApiEntryPoint.Instance.ReportTranscodingProgress(TranscodingJob, this, transcodingPosition, 0, percentComplete, 0, bitRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ namespace MediaBrowser.Api
|
||||
result.StartDate = program.StartDate;
|
||||
}
|
||||
|
||||
var hasSeries = item as IHasSeriesName;
|
||||
var hasSeries = item as IHasSeries;
|
||||
if (hasSeries != null)
|
||||
{
|
||||
result.Series = hasSeries.SeriesName;
|
||||
|
@ -51,16 +51,14 @@ namespace MediaBrowser.Api
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly IConnectManager _connectManager;
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IHttpClient _httpClient;
|
||||
|
||||
public StartupWizardService(IServerConfigurationManager config, IHttpClient httpClient, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager, IMediaEncoder mediaEncoder)
|
||||
public StartupWizardService(IServerConfigurationManager config, IHttpClient httpClient, IServerApplicationHost appHost, IUserManager userManager, IMediaEncoder mediaEncoder)
|
||||
{
|
||||
_config = config;
|
||||
_appHost = appHost;
|
||||
_userManager = userManager;
|
||||
_connectManager = connectManager;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Common.Configuration
|
||||
{
|
||||
public class ConfigurationUpdateEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the key.
|
||||
/// </summary>
|
||||
/// <value>The key.</value>
|
||||
public string Key { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the new configuration.
|
||||
/// </summary>
|
||||
/// <value>The new configuration.</value>
|
||||
public object NewConfiguration { get; set; }
|
||||
}
|
||||
}
|
84
MediaBrowser.Common/Configuration/IApplicationPaths.cs
Normal file
84
MediaBrowser.Common/Configuration/IApplicationPaths.cs
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
namespace MediaBrowser.Common.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IApplicationPaths
|
||||
/// </summary>
|
||||
public interface IApplicationPaths
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the path to the program data folder
|
||||
/// </summary>
|
||||
/// <value>The program data path.</value>
|
||||
string ProgramDataPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the program system folder
|
||||
/// </summary>
|
||||
/// <value>The program data path.</value>
|
||||
string ProgramSystemPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder path to the data directory
|
||||
/// </summary>
|
||||
/// <value>The data directory.</value>
|
||||
string DataPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image cache path.
|
||||
/// </summary>
|
||||
/// <value>The image cache path.</value>
|
||||
string ImageCachePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the plugin directory
|
||||
/// </summary>
|
||||
/// <value>The plugins path.</value>
|
||||
string PluginsPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the plugin configurations directory
|
||||
/// </summary>
|
||||
/// <value>The plugin configurations path.</value>
|
||||
string PluginConfigurationsPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to where temporary update files will be stored
|
||||
/// </summary>
|
||||
/// <value>The plugin configurations path.</value>
|
||||
string TempUpdatePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the log directory
|
||||
/// </summary>
|
||||
/// <value>The log directory path.</value>
|
||||
string LogDirectoryPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the application configuration root directory
|
||||
/// </summary>
|
||||
/// <value>The configuration directory path.</value>
|
||||
string ConfigurationDirectoryPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the system configuration file
|
||||
/// </summary>
|
||||
/// <value>The system configuration file path.</value>
|
||||
string SystemConfigurationFilePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder path to the cache directory
|
||||
/// </summary>
|
||||
/// <value>The cache directory.</value>
|
||||
string CachePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder path to the temp directory within the cache folder
|
||||
/// </summary>
|
||||
/// <value>The temp directory.</value>
|
||||
string TempDirectory { get; }
|
||||
|
||||
string VirtualDataPath { get; }
|
||||
}
|
||||
|
||||
}
|
22
MediaBrowser.Common/Configuration/IConfigurationFactory.cs
Normal file
22
MediaBrowser.Common/Configuration/IConfigurationFactory.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Common.Configuration
|
||||
{
|
||||
public interface IConfigurationFactory
|
||||
{
|
||||
IEnumerable<ConfigurationStore> GetConfigurations();
|
||||
}
|
||||
|
||||
public class ConfigurationStore
|
||||
{
|
||||
public string Key { get; set; }
|
||||
|
||||
public Type ConfigurationType { get; set; }
|
||||
}
|
||||
|
||||
public interface IValidatingConfiguration
|
||||
{
|
||||
void Validate(object oldConfig, object newConfig);
|
||||
}
|
||||
}
|
82
MediaBrowser.Common/Configuration/IConfigurationManager.cs
Normal file
82
MediaBrowser.Common/Configuration/IConfigurationManager.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Common.Configuration
|
||||
{
|
||||
public interface IConfigurationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when [configuration updating].
|
||||
/// </summary>
|
||||
event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdating;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [configuration updated].
|
||||
/// </summary>
|
||||
event EventHandler<EventArgs> ConfigurationUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [named configuration updated].
|
||||
/// </summary>
|
||||
event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the application paths.
|
||||
/// </summary>
|
||||
/// <value>The application paths.</value>
|
||||
IApplicationPaths CommonApplicationPaths { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration.
|
||||
/// </summary>
|
||||
/// <value>The configuration.</value>
|
||||
BaseApplicationConfiguration CommonConfiguration { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Saves the configuration.
|
||||
/// </summary>
|
||||
void SaveConfiguration();
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the configuration.
|
||||
/// </summary>
|
||||
/// <param name="newConfiguration">The new configuration.</param>
|
||||
void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
object GetConfiguration(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the configuration.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>Type.</returns>
|
||||
Type GetConfigurationType(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the configuration.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="configuration">The configuration.</param>
|
||||
void SaveConfiguration(string key, object configuration);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the parts.
|
||||
/// </summary>
|
||||
/// <param name="factories">The factories.</param>
|
||||
void AddParts(IEnumerable<IConfigurationFactory> factories);
|
||||
}
|
||||
|
||||
public static class ConfigurationManagerExtensions
|
||||
{
|
||||
public static T GetConfiguration<T>(this IConfigurationManager manager, string key)
|
||||
{
|
||||
return (T)manager.GetConfiguration(key);
|
||||
}
|
||||
}
|
||||
}
|
108
MediaBrowser.Common/Events/EventHelper.cs
Normal file
108
MediaBrowser.Common/Events/EventHelper.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Class EventHelper
|
||||
/// </summary>
|
||||
public static class EventHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Fires the event.
|
||||
/// </summary>
|
||||
/// <param name="handler">The handler.</param>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="args">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void QueueEventIfNotNull(EventHandler handler, object sender, EventArgs args, ILogger logger)
|
||||
{
|
||||
if (handler != null)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
handler(sender, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.ErrorException("Error in event handler", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues the event.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="handler">The handler.</param>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="args">The args.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void QueueEventIfNotNull<T>(EventHandler<T> handler, object sender, T args, ILogger logger)
|
||||
{
|
||||
if (handler != null)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
handler(sender, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.ErrorException("Error in event handler", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires the event.
|
||||
/// </summary>
|
||||
/// <param name="handler">The handler.</param>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="args">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void FireEventIfNotNull(EventHandler handler, object sender, EventArgs args, ILogger logger)
|
||||
{
|
||||
if (handler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
handler(sender, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.ErrorException("Error in event handler", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires the event.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="handler">The handler.</param>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="args">The args.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void FireEventIfNotNull<T>(EventHandler<T> handler, object sender, T args, ILogger logger)
|
||||
{
|
||||
if (handler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
handler(sender, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.ErrorException("Error in event handler", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
MediaBrowser.Common/Extensions/BaseExtensions.cs
Normal file
58
MediaBrowser.Common/Extensions/BaseExtensions.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using MediaBrowser.Model.Cryptography;
|
||||
|
||||
namespace MediaBrowser.Common.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BaseExtensions
|
||||
/// </summary>
|
||||
public static class BaseExtensions
|
||||
{
|
||||
public static ICryptoProvider CryptographyProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Strips the HTML.
|
||||
/// </summary>
|
||||
/// <param name="htmlString">The HTML string.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string StripHtml(this string htmlString)
|
||||
{
|
||||
// http://stackoverflow.com/questions/1349023/how-can-i-strip-html-from-text-in-net
|
||||
const string pattern = @"<(.|\n)*?>";
|
||||
|
||||
return Regex.Replace(htmlString, pattern, string.Empty).Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the M d5.
|
||||
/// </summary>
|
||||
/// <param name="str">The STR.</param>
|
||||
/// <returns>Guid.</returns>
|
||||
public static Guid GetMD5(this string str)
|
||||
{
|
||||
return CryptographyProvider.GetMD5(str);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MB id.
|
||||
/// </summary>
|
||||
/// <param name="str">The STR.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>Guid.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">type</exception>
|
||||
[Obsolete("Use LibraryManager.GetNewItemId")]
|
||||
public static Guid GetMBId(this string str, Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException("type");
|
||||
}
|
||||
|
||||
var key = type.FullName + str.ToLower();
|
||||
|
||||
return key.GetMD5();
|
||||
}
|
||||
}
|
||||
}
|
63
MediaBrowser.Common/Extensions/ResourceNotFoundException.cs
Normal file
63
MediaBrowser.Common/Extensions/ResourceNotFoundException.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Common.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ResourceNotFoundException
|
||||
/// </summary>
|
||||
public class ResourceNotFoundException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ResourceNotFoundException" /> class.
|
||||
/// </summary>
|
||||
public ResourceNotFoundException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ResourceNotFoundException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public ResourceNotFoundException(string message)
|
||||
: base(message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoteServiceUnavailableException : Exception
|
||||
{
|
||||
public RemoteServiceUnavailableException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public RemoteServiceUnavailableException(string message)
|
||||
: base(message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class RateLimitExceededException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RateLimitExceededException" /> class.
|
||||
/// </summary>
|
||||
public RateLimitExceededException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RateLimitExceededException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public RateLimitExceededException(string message)
|
||||
: base(message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
147
MediaBrowser.Common/IApplicationHost.cs
Normal file
147
MediaBrowser.Common/IApplicationHost.cs
Normal file
@ -0,0 +1,147 @@
|
||||
using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Updates;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface to be implemented by the applications hosting a kernel
|
||||
/// </summary>
|
||||
public interface IApplicationHost
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the display name of the operating system.
|
||||
/// </summary>
|
||||
/// <value>The display name of the operating system.</value>
|
||||
string OperatingSystemDisplayName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the device identifier.
|
||||
/// </summary>
|
||||
/// <value>The device identifier.</value>
|
||||
string SystemId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [application updated].
|
||||
/// </summary>
|
||||
event EventHandler<GenericEventArgs<PackageVersionInfo>> ApplicationUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance has pending kernel reload.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance has pending kernel reload; otherwise, <c>false</c>.</value>
|
||||
bool HasPendingRestart { get; }
|
||||
|
||||
bool IsShuttingDown { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance can self restart.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
|
||||
bool CanSelfRestart { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [has pending restart changed].
|
||||
/// </summary>
|
||||
event EventHandler HasPendingRestartChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the pending restart.
|
||||
/// </summary>
|
||||
void NotifyPendingRestart();
|
||||
|
||||
/// <summary>
|
||||
/// Restarts this instance.
|
||||
/// </summary>
|
||||
void Restart();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the application version.
|
||||
/// </summary>
|
||||
/// <value>The application version.</value>
|
||||
Version ApplicationVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance can self update.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
|
||||
bool CanSelfUpdate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exports.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="manageLiftime">if set to <c>true</c> [manage liftime].</param>
|
||||
/// <returns>IEnumerable{``0}.</returns>
|
||||
IEnumerable<T> GetExports<T>(bool manageLiftime = true);
|
||||
|
||||
/// <summary>
|
||||
/// Checks for update.
|
||||
/// </summary>
|
||||
/// <returns>Task{CheckForUpdateResult}.</returns>
|
||||
Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the application.
|
||||
/// </summary>
|
||||
/// <returns>Task.</returns>
|
||||
Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress<double> progress);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves this instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns>``0.</returns>
|
||||
T Resolve<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Resolves this instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns>``0.</returns>
|
||||
T TryResolve<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down.
|
||||
/// </summary>
|
||||
Task Shutdown();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugins.
|
||||
/// </summary>
|
||||
/// <value>The plugins.</value>
|
||||
IPlugin[] Plugins { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Removes the plugin.
|
||||
/// </summary>
|
||||
/// <param name="plugin">The plugin.</param>
|
||||
void RemovePlugin(IPlugin plugin);
|
||||
|
||||
/// <summary>
|
||||
/// Inits this instance.
|
||||
/// </summary>
|
||||
void Init();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the instance.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
object CreateInstance(Type type);
|
||||
|
||||
PackageVersionClass SystemUpdateLevel { get; }
|
||||
|
||||
string GetValue(string name);
|
||||
}
|
||||
}
|
16
MediaBrowser.Common/MediaBrowser.Common.csproj
Normal file
16
MediaBrowser.Common/MediaBrowser.Common.csproj
Normal file
@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\SharedVersion.cs"/>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
157
MediaBrowser.Common/Net/HttpRequestOptions.cs
Normal file
157
MediaBrowser.Common/Net/HttpRequestOptions.cs
Normal file
@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
|
||||
namespace MediaBrowser.Common.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// Class HttpRequestOptions
|
||||
/// </summary>
|
||||
public class HttpRequestOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the URL.
|
||||
/// </summary>
|
||||
/// <value>The URL.</value>
|
||||
public string Url { get; set; }
|
||||
|
||||
public CompressionMethod? DecompressionMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the accept header.
|
||||
/// </summary>
|
||||
/// <value>The accept header.</value>
|
||||
public string AcceptHeader
|
||||
{
|
||||
get { return GetHeaderValue("Accept"); }
|
||||
set
|
||||
{
|
||||
RequestHeaders["Accept"] = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the cancellation token.
|
||||
/// </summary>
|
||||
/// <value>The cancellation token.</value>
|
||||
public CancellationToken CancellationToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the resource pool.
|
||||
/// </summary>
|
||||
/// <value>The resource pool.</value>
|
||||
public SemaphoreSlim ResourcePool { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user agent.
|
||||
/// </summary>
|
||||
/// <value>The user agent.</value>
|
||||
public string UserAgent
|
||||
{
|
||||
get { return GetHeaderValue("User-Agent"); }
|
||||
set
|
||||
{
|
||||
RequestHeaders["User-Agent"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the referrer.
|
||||
/// </summary>
|
||||
/// <value>The referrer.</value>
|
||||
public string Referer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the host.
|
||||
/// </summary>
|
||||
/// <value>The host.</value>
|
||||
public string Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the progress.
|
||||
/// </summary>
|
||||
/// <value>The progress.</value>
|
||||
public IProgress<double> Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [enable HTTP compression].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enable HTTP compression]; otherwise, <c>false</c>.</value>
|
||||
public bool EnableHttpCompression { get; set; }
|
||||
|
||||
public Dictionary<string, string> RequestHeaders { get; private set; }
|
||||
|
||||
public string RequestContentType { get; set; }
|
||||
|
||||
public string RequestContent { get; set; }
|
||||
public byte[] RequestContentBytes { get; set; }
|
||||
|
||||
public bool BufferContent { get; set; }
|
||||
|
||||
public bool LogRequest { get; set; }
|
||||
public bool LogRequestAsDebug { get; set; }
|
||||
public bool LogErrors { get; set; }
|
||||
public bool LogResponse { get; set; }
|
||||
public bool LogResponseHeaders { get; set; }
|
||||
|
||||
public bool LogErrorResponseBody { get; set; }
|
||||
public bool EnableKeepAlive { get; set; }
|
||||
|
||||
public CacheMode CacheMode { get; set; }
|
||||
public TimeSpan CacheLength { get; set; }
|
||||
|
||||
public int TimeoutMs { get; set; }
|
||||
public bool EnableDefaultUserAgent { get; set; }
|
||||
|
||||
public bool AppendCharsetToMimeType { get; set; }
|
||||
public string DownloadFilePath { get; set; }
|
||||
|
||||
private string GetHeaderValue(string name)
|
||||
{
|
||||
string value;
|
||||
|
||||
RequestHeaders.TryGetValue(name, out value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpRequestOptions"/> class.
|
||||
/// </summary>
|
||||
public HttpRequestOptions()
|
||||
{
|
||||
EnableHttpCompression = true;
|
||||
|
||||
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
LogRequest = true;
|
||||
LogErrors = true;
|
||||
CacheMode = CacheMode.None;
|
||||
|
||||
TimeoutMs = 20000;
|
||||
}
|
||||
|
||||
public void SetPostData(IDictionary<string,string> values)
|
||||
{
|
||||
var strings = values.Keys.Select(key => string.Format("{0}={1}", key, values[key]));
|
||||
var postContent = string.Join("&", strings.ToArray());
|
||||
|
||||
RequestContent = postContent;
|
||||
RequestContentType = "application/x-www-form-urlencoded";
|
||||
}
|
||||
}
|
||||
|
||||
public enum CacheMode
|
||||
{
|
||||
None = 0,
|
||||
Unconditional = 1
|
||||
}
|
||||
|
||||
public enum CompressionMethod
|
||||
{
|
||||
Deflate,
|
||||
Gzip
|
||||
}
|
||||
}
|
75
MediaBrowser.Common/Net/HttpResponseInfo.cs
Normal file
75
MediaBrowser.Common/Net/HttpResponseInfo.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
namespace MediaBrowser.Common.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// Class HttpResponseInfo
|
||||
/// </summary>
|
||||
public class HttpResponseInfo : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the content.
|
||||
/// </summary>
|
||||
/// <value>The type of the content.</value>
|
||||
public string ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the response URL.
|
||||
/// </summary>
|
||||
/// <value>The response URL.</value>
|
||||
public string ResponseUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content.
|
||||
/// </summary>
|
||||
/// <value>The content.</value>
|
||||
public Stream Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status code.
|
||||
/// </summary>
|
||||
/// <value>The status code.</value>
|
||||
public HttpStatusCode StatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the temp file path.
|
||||
/// </summary>
|
||||
/// <value>The temp file path.</value>
|
||||
public string TempFilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the length of the content.
|
||||
/// </summary>
|
||||
/// <value>The length of the content.</value>
|
||||
public long? ContentLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
/// <value>The headers.</value>
|
||||
public Dictionary<string,string> Headers { get; set; }
|
||||
|
||||
private readonly IDisposable _disposable;
|
||||
|
||||
public HttpResponseInfo(IDisposable disposable)
|
||||
{
|
||||
_disposable = disposable;
|
||||
Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
public HttpResponseInfo()
|
||||
{
|
||||
Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposable != null)
|
||||
{
|
||||
_disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
59
MediaBrowser.Common/Net/IHttpClient.cs
Normal file
59
MediaBrowser.Common/Net/IHttpClient.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IHttpClient
|
||||
/// </summary>
|
||||
public interface IHttpClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the response.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseInfo> GetResponse(HttpRequestOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified options.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>Task{Stream}.</returns>
|
||||
Task<Stream> Get(HttpRequestOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Sends the asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="httpMethod">The HTTP method.</param>
|
||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod);
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified options.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseInfo> Post(HttpRequestOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the contents of a given url into a temporary location
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>Task{System.String}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">progress</exception>
|
||||
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
|
||||
Task<string> GetTempFile(HttpRequestOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the temporary file response.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseInfo> GetTempFileResponse(HttpRequestOptions options);
|
||||
}
|
||||
}
|
66
MediaBrowser.Common/Net/INetworkManager.cs
Normal file
66
MediaBrowser.Common/Net/INetworkManager.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Net;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common.Net
|
||||
{
|
||||
public interface INetworkManager
|
||||
{
|
||||
event EventHandler NetworkChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random port number that is currently available
|
||||
/// </summary>
|
||||
/// <returns>System.Int32.</returns>
|
||||
int GetRandomUnusedTcpPort();
|
||||
|
||||
int GetRandomUnusedUdpPort();
|
||||
|
||||
Func<string[]> LocalSubnetsFn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns MAC Address from first Network Card in Computer
|
||||
/// </summary>
|
||||
/// <returns>[string] MAC Address</returns>
|
||||
List<string> GetMacAddresses();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is in private address space] [the specified endpoint].
|
||||
/// </summary>
|
||||
/// <param name="endpoint">The endpoint.</param>
|
||||
/// <returns><c>true</c> if [is in private address space] [the specified endpoint]; otherwise, <c>false</c>.</returns>
|
||||
bool IsInPrivateAddressSpace(string endpoint);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the network shares.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>IEnumerable{NetworkShare}.</returns>
|
||||
IEnumerable<NetworkShare> GetNetworkShares(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets available devices within the domain
|
||||
/// </summary>
|
||||
/// <returns>PC's in the Domain</returns>
|
||||
IEnumerable<FileSystemEntryInfo> GetNetworkDevices();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is in local network] [the specified endpoint].
|
||||
/// </summary>
|
||||
/// <param name="endpoint">The endpoint.</param>
|
||||
/// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns>
|
||||
bool IsInLocalNetwork(string endpoint);
|
||||
|
||||
IpAddressInfo[] GetLocalIpAddresses();
|
||||
|
||||
IpAddressInfo ParseIpAddress(string ipAddress);
|
||||
|
||||
bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo);
|
||||
|
||||
Task<IpAddressInfo[]> GetHostAddressesAsync(string host);
|
||||
|
||||
bool IsAddressInSubnets(string addressString, string[] subnets);
|
||||
}
|
||||
}
|
276
MediaBrowser.Common/Plugins/BasePlugin.cs
Normal file
276
MediaBrowser.Common/Plugins/BasePlugin.cs
Normal file
@ -0,0 +1,276 @@
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.Plugins;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace MediaBrowser.Common.Plugins
|
||||
{
|
||||
public abstract class BasePlugin : IPlugin, IPluginAssembly
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the plugin
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description.
|
||||
/// </summary>
|
||||
/// <value>The description.</value>
|
||||
public virtual string Description
|
||||
{
|
||||
get { return string.Empty; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique id.
|
||||
/// </summary>
|
||||
/// <value>The unique id.</value>
|
||||
public virtual Guid Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin version
|
||||
/// </summary>
|
||||
/// <value>The version.</value>
|
||||
public Version Version { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the assembly file
|
||||
/// </summary>
|
||||
/// <value>The assembly file path.</value>
|
||||
public string AssemblyFilePath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info.
|
||||
/// </summary>
|
||||
/// <returns>PluginInfo.</returns>
|
||||
public virtual PluginInfo GetPluginInfo()
|
||||
{
|
||||
var info = new PluginInfo
|
||||
{
|
||||
Name = Name,
|
||||
Version = Version.ToString(),
|
||||
Description = Description,
|
||||
Id = Id.ToString()
|
||||
};
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when just before the plugin is uninstalled from the server.
|
||||
/// </summary>
|
||||
public virtual void OnUninstalling()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion)
|
||||
{
|
||||
AssemblyFilePath = assemblyFilePath;
|
||||
DataFolderPath = dataFolderPath;
|
||||
Version = assemblyVersion;
|
||||
}
|
||||
|
||||
public void SetId(Guid assemblyId)
|
||||
{
|
||||
Id = assemblyId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to the data folder, where the plugin can store any miscellaneous files needed
|
||||
/// </summary>
|
||||
/// <value>The data folder path.</value>
|
||||
public string DataFolderPath { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a common base class for all plugins
|
||||
/// </summary>
|
||||
/// <typeparam name="TConfigurationType">The type of the T configuration type.</typeparam>
|
||||
public abstract class BasePlugin<TConfigurationType> : BasePlugin, IHasPluginConfiguration
|
||||
where TConfigurationType : BasePluginConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the application paths.
|
||||
/// </summary>
|
||||
/// <value>The application paths.</value>
|
||||
protected IApplicationPaths ApplicationPaths { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the XML serializer.
|
||||
/// </summary>
|
||||
/// <value>The XML serializer.</value>
|
||||
protected IXmlSerializer XmlSerializer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of configuration this plugin uses
|
||||
/// </summary>
|
||||
/// <value>The type of the configuration.</value>
|
||||
public Type ConfigurationType
|
||||
{
|
||||
get { return typeof(TConfigurationType); }
|
||||
}
|
||||
|
||||
private Action<string> _directoryCreateFn;
|
||||
public void SetStartupInfo(Action<string> directoryCreateFn)
|
||||
{
|
||||
// hack alert, until the .net core transition is complete
|
||||
_directoryCreateFn = directoryCreateFn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name the assembly file
|
||||
/// </summary>
|
||||
/// <value>The name of the assembly file.</value>
|
||||
protected string AssemblyFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.GetFileName(AssemblyFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The _configuration sync lock
|
||||
/// </summary>
|
||||
private readonly object _configurationSyncLock = new object();
|
||||
/// <summary>
|
||||
/// The _configuration
|
||||
/// </summary>
|
||||
private TConfigurationType _configuration;
|
||||
/// <summary>
|
||||
/// Gets the plugin's configuration
|
||||
/// </summary>
|
||||
/// <value>The configuration.</value>
|
||||
public TConfigurationType Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
// Lazy load
|
||||
if (_configuration == null)
|
||||
{
|
||||
lock (_configurationSyncLock)
|
||||
{
|
||||
if (_configuration == null)
|
||||
{
|
||||
_configuration = LoadConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _configuration;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
_configuration = value;
|
||||
}
|
||||
}
|
||||
|
||||
private TConfigurationType LoadConfiguration()
|
||||
{
|
||||
var path = ConfigurationFilePath;
|
||||
|
||||
try
|
||||
{
|
||||
return (TConfigurationType)XmlSerializer.DeserializeFromFile(typeof(TConfigurationType), path);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the configuration file. Subclasses should override
|
||||
/// </summary>
|
||||
/// <value>The name of the configuration file.</value>
|
||||
public virtual string ConfigurationFileName
|
||||
{
|
||||
get { return Path.ChangeExtension(AssemblyFileName, ".xml"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to the configuration file
|
||||
/// </summary>
|
||||
/// <value>The configuration file path.</value>
|
||||
public string ConfigurationFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(ApplicationPaths.PluginConfigurationsPath, ConfigurationFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BasePlugin{TConfigurationType}" /> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationPaths">The application paths.</param>
|
||||
/// <param name="xmlSerializer">The XML serializer.</param>
|
||||
protected BasePlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
||||
{
|
||||
ApplicationPaths = applicationPaths;
|
||||
XmlSerializer = xmlSerializer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The _save lock
|
||||
/// </summary>
|
||||
private readonly object _configurationSaveLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Saves the current configuration to the file system
|
||||
/// </summary>
|
||||
public virtual void SaveConfiguration()
|
||||
{
|
||||
lock (_configurationSaveLock)
|
||||
{
|
||||
_directoryCreateFn(Path.GetDirectoryName(ConfigurationFilePath));
|
||||
|
||||
XmlSerializer.SerializeToFile(Configuration, ConfigurationFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Completely overwrites the current configuration with a new copy
|
||||
/// Returns true or false indicating success or failure
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration.</param>
|
||||
/// <exception cref="System.ArgumentNullException">configuration</exception>
|
||||
public virtual void UpdateConfiguration(BasePluginConfiguration configuration)
|
||||
{
|
||||
if (configuration == null)
|
||||
{
|
||||
throw new ArgumentNullException("configuration");
|
||||
}
|
||||
|
||||
Configuration = (TConfigurationType)configuration;
|
||||
|
||||
SaveConfiguration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin's configuration
|
||||
/// </summary>
|
||||
/// <value>The configuration.</value>
|
||||
BasePluginConfiguration IHasPluginConfiguration.Configuration
|
||||
{
|
||||
get { return Configuration; }
|
||||
}
|
||||
|
||||
public override PluginInfo GetPluginInfo()
|
||||
{
|
||||
var info = base.GetPluginInfo();
|
||||
|
||||
info.ConfigurationFileName = ConfigurationFileName;
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPluginAssembly
|
||||
{
|
||||
void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion);
|
||||
void SetId(Guid assemblyId);
|
||||
}
|
||||
}
|
83
MediaBrowser.Common/Plugins/IPlugin.cs
Normal file
83
MediaBrowser.Common/Plugins/IPlugin.cs
Normal file
@ -0,0 +1,83 @@
|
||||
using MediaBrowser.Model.Plugins;
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Common.Plugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IPlugin
|
||||
/// </summary>
|
||||
public interface IPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the plugin
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description.
|
||||
/// </summary>
|
||||
/// <value>The description.</value>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique id.
|
||||
/// </summary>
|
||||
/// <value>The unique id.</value>
|
||||
Guid Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin version
|
||||
/// </summary>
|
||||
/// <value>The version.</value>
|
||||
Version Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the assembly file
|
||||
/// </summary>
|
||||
/// <value>The assembly file path.</value>
|
||||
string AssemblyFilePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to the data folder, where the plugin can store any miscellaneous files needed
|
||||
/// </summary>
|
||||
/// <value>The data folder path.</value>
|
||||
string DataFolderPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info.
|
||||
/// </summary>
|
||||
/// <returns>PluginInfo.</returns>
|
||||
PluginInfo GetPluginInfo();
|
||||
|
||||
/// <summary>
|
||||
/// Called when just before the plugin is uninstalled from the server.
|
||||
/// </summary>
|
||||
void OnUninstalling();
|
||||
}
|
||||
|
||||
public interface IHasPluginConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of configuration this plugin uses
|
||||
/// </summary>
|
||||
/// <value>The type of the configuration.</value>
|
||||
Type ConfigurationType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Completely overwrites the current configuration with a new copy
|
||||
/// Returns true or false indicating success or failure
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration.</param>
|
||||
/// <exception cref="System.ArgumentNullException">configuration</exception>
|
||||
void UpdateConfiguration(BasePluginConfiguration configuration);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin's configuration
|
||||
/// </summary>
|
||||
/// <value>The configuration.</value>
|
||||
BasePluginConfiguration Configuration { get; }
|
||||
|
||||
void SetStartupInfo(Action<string> directoryCreateFn);
|
||||
}
|
||||
}
|
54
MediaBrowser.Common/Progress/ActionableProgress.cs
Normal file
54
MediaBrowser.Common/Progress/ActionableProgress.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Common.Progress
|
||||
{
|
||||
/// <summary>
|
||||
/// Class ActionableProgress
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ActionableProgress<T> : IProgress<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The _actions
|
||||
/// </summary>
|
||||
private Action<T> _action;
|
||||
public event EventHandler<T> ProgressChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Registers the action.
|
||||
/// </summary>
|
||||
/// <param name="action">The action.</param>
|
||||
public void RegisterAction(Action<T> action)
|
||||
{
|
||||
_action = action;
|
||||
}
|
||||
|
||||
public void Report(T value)
|
||||
{
|
||||
if (ProgressChanged != null)
|
||||
{
|
||||
ProgressChanged(this, value);
|
||||
}
|
||||
|
||||
var action = _action;
|
||||
if (action != null)
|
||||
{
|
||||
action(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SimpleProgress<T> : IProgress<T>
|
||||
{
|
||||
public event EventHandler<T> ProgressChanged;
|
||||
|
||||
public void Report(T value)
|
||||
{
|
||||
if (ProgressChanged != null)
|
||||
{
|
||||
ProgressChanged(this, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
MediaBrowser.Common/Properties/AssemblyInfo.cs
Normal file
27
MediaBrowser.Common/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("MediaBrowser.Common")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("MediaBrowser.Common")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
15
MediaBrowser.Common/Security/IRequiresRegistration.cs
Normal file
15
MediaBrowser.Common/Security/IRequiresRegistration.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common.Security
|
||||
{
|
||||
public interface IRequiresRegistration
|
||||
{
|
||||
/// <summary>
|
||||
/// Load all registration information required for this entity.
|
||||
/// Your class should re-load all MBRegistrationRecords when this is called even if they were
|
||||
/// previously loaded.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task LoadRegistrationInfoAsync();
|
||||
}
|
||||
}
|
32
MediaBrowser.Common/Security/ISecurityManager.cs
Normal file
32
MediaBrowser.Common/Security/ISecurityManager.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common.Security
|
||||
{
|
||||
public interface ISecurityManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is MB supporter.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is MB supporter; otherwise, <c>false</c>.</value>
|
||||
Task<bool> IsSupporter();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the supporter key.
|
||||
/// </summary>
|
||||
/// <value>The supporter key.</value>
|
||||
string SupporterKey { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the registration status. Overload to support existing plug-ins.
|
||||
/// </summary>
|
||||
Task<MBRegistrationRecord> GetRegistrationStatus(string feature);
|
||||
|
||||
/// <summary>
|
||||
/// Register and app store sale with our back-end
|
||||
/// </summary>
|
||||
/// <param name="parameters">Json parameters to pass to admin server</param>
|
||||
Task RegisterAppStoreSale(string parameters);
|
||||
Task UpdateSupporterKey(string newValue);
|
||||
}
|
||||
}
|
8
MediaBrowser.Common/Security/PaymentRequiredException.cs
Normal file
8
MediaBrowser.Common/Security/PaymentRequiredException.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Common.Security
|
||||
{
|
||||
public class PaymentRequiredException : Exception
|
||||
{
|
||||
}
|
||||
}
|
278
MediaBrowser.Common/Updates/GithubUpdater.cs
Normal file
278
MediaBrowser.Common/Updates/GithubUpdater.cs
Normal file
@ -0,0 +1,278 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Common.Updates
|
||||
{
|
||||
public class GithubUpdater
|
||||
{
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
|
||||
public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
}
|
||||
|
||||
public async Task<CheckForUpdateResult> CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, TimeSpan cacheLength, CancellationToken cancellationToken)
|
||||
{
|
||||
var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);
|
||||
|
||||
var options = new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
EnableKeepAlive = false,
|
||||
CancellationToken = cancellationToken,
|
||||
UserAgent = "Emby/3.0",
|
||||
BufferContent = false
|
||||
};
|
||||
|
||||
if (cacheLength.Ticks > 0)
|
||||
{
|
||||
options.CacheMode = CacheMode.Unconditional;
|
||||
options.CacheLength = cacheLength;
|
||||
}
|
||||
|
||||
using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
|
||||
|
||||
return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename)
|
||||
{
|
||||
if (updateLevel == PackageVersionClass.Release)
|
||||
{
|
||||
// Technically all we need to do is check that it's not pre-release
|
||||
// But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly.
|
||||
obj = obj.Where(i => !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) && !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
}
|
||||
else if (updateLevel == PackageVersionClass.Beta)
|
||||
{
|
||||
obj = obj.Where(i => i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
}
|
||||
else if (updateLevel == PackageVersionClass.Dev)
|
||||
{
|
||||
obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
}
|
||||
|
||||
var availableUpdate = obj
|
||||
.Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename))
|
||||
.Where(i => i != null)
|
||||
.OrderByDescending(i => Version.Parse(i.AvailableVersion))
|
||||
.FirstOrDefault();
|
||||
|
||||
return availableUpdate ?? new CheckForUpdateResult
|
||||
{
|
||||
IsUpdateAvailable = false
|
||||
};
|
||||
}
|
||||
|
||||
private bool MatchesUpdateLevel(RootObject i, PackageVersionClass updateLevel)
|
||||
{
|
||||
if (updateLevel == PackageVersionClass.Beta)
|
||||
{
|
||||
return i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
if (updateLevel == PackageVersionClass.Dev)
|
||||
{
|
||||
return !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) ||
|
||||
i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// Technically all we need to do is check that it's not pre-release
|
||||
// But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly.
|
||||
return !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) &&
|
||||
!i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public async Task<List<RootObject>> GetLatestReleases(string organzation, string repository, string assetFilename, CancellationToken cancellationToken)
|
||||
{
|
||||
var list = new List<RootObject>();
|
||||
|
||||
var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);
|
||||
|
||||
var options = new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
EnableKeepAlive = false,
|
||||
CancellationToken = cancellationToken,
|
||||
UserAgent = "Emby/3.0",
|
||||
BufferContent = false
|
||||
};
|
||||
|
||||
using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
|
||||
{
|
||||
using (var stream = response.Content)
|
||||
{
|
||||
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
|
||||
|
||||
obj = obj.Where(i => (i.assets ?? new List<Asset>()).Any(a => IsAsset(a, assetFilename, i.tag_name))).ToArray();
|
||||
|
||||
list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Release)).OrderByDescending(GetVersion).Take(1));
|
||||
list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Beta)).OrderByDescending(GetVersion).Take(1));
|
||||
list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Dev)).OrderByDescending(GetVersion).Take(1));
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Version GetVersion(RootObject obj)
|
||||
{
|
||||
Version version;
|
||||
if (!Version.TryParse(obj.tag_name, out version))
|
||||
{
|
||||
return new Version(1, 0);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename)
|
||||
{
|
||||
Version version;
|
||||
var versionString = obj.tag_name;
|
||||
if (!Version.TryParse(versionString, out version))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (version < minVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var asset = (obj.assets ?? new List<Asset>()).FirstOrDefault(i => IsAsset(i, assetFilename, versionString));
|
||||
|
||||
if (asset == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new CheckForUpdateResult
|
||||
{
|
||||
AvailableVersion = version.ToString(),
|
||||
IsUpdateAvailable = version > minVersion,
|
||||
Package = new PackageVersionInfo
|
||||
{
|
||||
classification = obj.prerelease ?
|
||||
(obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) :
|
||||
PackageVersionClass.Release,
|
||||
name = packageName,
|
||||
sourceUrl = asset.browser_download_url,
|
||||
targetFilename = targetFilename,
|
||||
versionStr = version.ToString(),
|
||||
requiredVersionStr = "1.0.0",
|
||||
description = obj.body,
|
||||
infoUrl = obj.html_url
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private bool IsAsset(Asset asset, string assetFilename, string version)
|
||||
{
|
||||
var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty;
|
||||
|
||||
assetFilename = assetFilename.Replace("{version}", version);
|
||||
|
||||
if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public class Uploader
|
||||
{
|
||||
public string login { get; set; }
|
||||
public int id { get; set; }
|
||||
public string avatar_url { get; set; }
|
||||
public string gravatar_id { get; set; }
|
||||
public string url { get; set; }
|
||||
public string html_url { get; set; }
|
||||
public string followers_url { get; set; }
|
||||
public string following_url { get; set; }
|
||||
public string gists_url { get; set; }
|
||||
public string starred_url { get; set; }
|
||||
public string subscriptions_url { get; set; }
|
||||
public string organizations_url { get; set; }
|
||||
public string repos_url { get; set; }
|
||||
public string events_url { get; set; }
|
||||
public string received_events_url { get; set; }
|
||||
public string type { get; set; }
|
||||
public bool site_admin { get; set; }
|
||||
}
|
||||
|
||||
public class Asset
|
||||
{
|
||||
public string url { get; set; }
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
public object label { get; set; }
|
||||
public Uploader uploader { get; set; }
|
||||
public string content_type { get; set; }
|
||||
public string state { get; set; }
|
||||
public int size { get; set; }
|
||||
public int download_count { get; set; }
|
||||
public string created_at { get; set; }
|
||||
public string updated_at { get; set; }
|
||||
public string browser_download_url { get; set; }
|
||||
}
|
||||
|
||||
public class Author
|
||||
{
|
||||
public string login { get; set; }
|
||||
public int id { get; set; }
|
||||
public string avatar_url { get; set; }
|
||||
public string gravatar_id { get; set; }
|
||||
public string url { get; set; }
|
||||
public string html_url { get; set; }
|
||||
public string followers_url { get; set; }
|
||||
public string following_url { get; set; }
|
||||
public string gists_url { get; set; }
|
||||
public string starred_url { get; set; }
|
||||
public string subscriptions_url { get; set; }
|
||||
public string organizations_url { get; set; }
|
||||
public string repos_url { get; set; }
|
||||
public string events_url { get; set; }
|
||||
public string received_events_url { get; set; }
|
||||
public string type { get; set; }
|
||||
public bool site_admin { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public string url { get; set; }
|
||||
public string assets_url { get; set; }
|
||||
public string upload_url { get; set; }
|
||||
public string html_url { get; set; }
|
||||
public int id { get; set; }
|
||||
public string tag_name { get; set; }
|
||||
public string target_commitish { get; set; }
|
||||
public string name { get; set; }
|
||||
public bool draft { get; set; }
|
||||
public Author author { get; set; }
|
||||
public bool prerelease { get; set; }
|
||||
public string created_at { get; set; }
|
||||
public string published_at { get; set; }
|
||||
public List<Asset> assets { get; set; }
|
||||
public string tarball_url { get; set; }
|
||||
public string zipball_url { get; set; }
|
||||
public string body { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
121
MediaBrowser.Common/Updates/IInstallationManager.cs
Normal file
121
MediaBrowser.Common/Updates/IInstallationManager.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Updates;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common.Updates
|
||||
{
|
||||
public interface IInstallationManager : IDisposable
|
||||
{
|
||||
event EventHandler<InstallationEventArgs> PackageInstalling;
|
||||
event EventHandler<InstallationEventArgs> PackageInstallationCompleted;
|
||||
event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
|
||||
event EventHandler<InstallationEventArgs> PackageInstallationCancelled;
|
||||
|
||||
/// <summary>
|
||||
/// The current installations
|
||||
/// </summary>
|
||||
List<Tuple<InstallationInfo, CancellationTokenSource>> CurrentInstallations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The completed installations
|
||||
/// </summary>
|
||||
IEnumerable<InstallationInfo> CompletedInstallations { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [plugin uninstalled].
|
||||
/// </summary>
|
||||
event EventHandler<GenericEventArgs<IPlugin>> PluginUninstalled;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [plugin updated].
|
||||
/// </summary>
|
||||
event EventHandler<GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>>> PluginUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [plugin updated].
|
||||
/// </summary>
|
||||
event EventHandler<GenericEventArgs<PackageVersionInfo>> PluginInstalled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available packages.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="withRegistration">if set to <c>true</c> [with registration].</param>
|
||||
/// <param name="packageType">Type of the package.</param>
|
||||
/// <param name="applicationVersion">The application version.</param>
|
||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||
Task<List<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
||||
bool withRegistration = true,
|
||||
string packageType = null,
|
||||
Version applicationVersion = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available packages from a static resource.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||
Task<List<PackageInfo>> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the package.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="guid">The assembly guid</param>
|
||||
/// <param name="classification">The classification.</param>
|
||||
/// <param name="version">The version.</param>
|
||||
/// <returns>Task{PackageVersionInfo}.</returns>
|
||||
Task<PackageVersionInfo> GetPackage(string name, string guid, PackageVersionClass classification, Version version);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest compatible version.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="guid">The assembly guid</param>
|
||||
/// <param name="currentServerVersion">The current server version.</param>
|
||||
/// <param name="classification">The classification.</param>
|
||||
/// <returns>Task{PackageVersionInfo}.</returns>
|
||||
Task<PackageVersionInfo> GetLatestCompatibleVersion(string name, string guid, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest compatible version.
|
||||
/// </summary>
|
||||
/// <param name="availablePackages">The available packages.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="guid">The assembly guid</param>
|
||||
/// <param name="currentServerVersion">The current server version.</param>
|
||||
/// <param name="classification">The classification.</param>
|
||||
/// <returns>PackageVersionInfo.</returns>
|
||||
PackageVersionInfo GetLatestCompatibleVersion(IEnumerable<PackageInfo> availablePackages, string name, string guid, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available plugin updates.
|
||||
/// </summary>
|
||||
/// <param name="applicationVersion">The current server version.</param>
|
||||
/// <param name="withAutoUpdateEnabled">if set to <c>true</c> [with auto update enabled].</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{PackageVersionInfo}}.</returns>
|
||||
Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(Version applicationVersion, bool withAutoUpdateEnabled, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Installs the package.
|
||||
/// </summary>
|
||||
/// <param name="package">The package.</param>
|
||||
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">package</exception>
|
||||
Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Uninstalls a plugin
|
||||
/// </summary>
|
||||
/// <param name="plugin">The plugin.</param>
|
||||
/// <exception cref="System.ArgumentException"></exception>
|
||||
void UninstallPlugin(IPlugin plugin);
|
||||
}
|
||||
}
|
11
MediaBrowser.Common/Updates/InstallationEventArgs.cs
Normal file
11
MediaBrowser.Common/Updates/InstallationEventArgs.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace MediaBrowser.Common.Updates
|
||||
{
|
||||
public class InstallationEventArgs
|
||||
{
|
||||
public InstallationInfo InstallationInfo { get; set; }
|
||||
|
||||
public PackageVersionInfo PackageVersionInfo { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Common.Updates
|
||||
{
|
||||
public class InstallationFailedEventArgs : InstallationEventArgs
|
||||
{
|
||||
public Exception Exception { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
|
||||
namespace MediaBrowser.Controller.Authentication
|
||||
{
|
||||
public class AuthenticationResult
|
||||
{
|
||||
public UserDto User { get; set; }
|
||||
public SessionInfo SessionInfo { get; set; }
|
||||
public string AccessToken { get; set; }
|
||||
public string ServerId { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Users;
|
||||
|
||||
namespace MediaBrowser.Controller.Authentication
|
||||
{
|
||||
public interface IAuthenticationProvider
|
||||
{
|
||||
string Name { get; }
|
||||
bool IsEnabled { get; }
|
||||
Task<ProviderAuthenticationResult> Authenticate(string username, string password);
|
||||
Task<bool> HasPassword(User user);
|
||||
Task ChangePassword(User user, string newPassword);
|
||||
}
|
||||
|
||||
public interface IRequiresResolvedUser
|
||||
{
|
||||
Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser);
|
||||
}
|
||||
|
||||
public interface IHasNewUserPolicy
|
||||
{
|
||||
UserPolicy GetNewUserPolicy();
|
||||
}
|
||||
|
||||
public class ProviderAuthenticationResult
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
}
|
||||
}
|
94
MediaBrowser.Controller/Channels/Channel.cs
Normal file
94
MediaBrowser.Controller/Channels/Channel.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Progress;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public class Channel : Folder
|
||||
{
|
||||
public override bool IsVisible(User user)
|
||||
{
|
||||
if (user.Policy.BlockedChannels != null)
|
||||
{
|
||||
if (user.Policy.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!user.Policy.EnableAllChannels && !user.Policy.EnabledChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return base.IsVisible(user);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsInheritedParentImages
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override SourceType SourceType
|
||||
{
|
||||
get { return SourceType.Channel; }
|
||||
}
|
||||
|
||||
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
|
||||
{
|
||||
try
|
||||
{
|
||||
query.Parent = this;
|
||||
query.ChannelIds = new Guid[] { Id };
|
||||
|
||||
// Don't blow up here because it could cause parent screens with other content to fail
|
||||
return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).Result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Already logged at lower levels
|
||||
return new QueryResult<BaseItem>();
|
||||
}
|
||||
}
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
{
|
||||
return GetInternalMetadataPath(basePath, Id);
|
||||
}
|
||||
|
||||
public static string GetInternalMetadataPath(string basePath, Guid id)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata");
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool IsAllowTagFilterEnforced()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool IsChannelVisible(BaseItem channelItem, User user)
|
||||
{
|
||||
var channel = ChannelManager.GetChannel(channelItem.ChannelId.ToString(""));
|
||||
|
||||
return channel.IsVisible(user);
|
||||
}
|
||||
}
|
||||
}
|
82
MediaBrowser.Controller/Channels/ChannelItemInfo.cs
Normal file
82
MediaBrowser.Controller/Channels/ChannelItemInfo.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public class ChannelItemInfo : IHasProviderIds
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string SeriesName { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public DateTime DateModified { get; set; }
|
||||
|
||||
public ChannelItemType Type { get; set; }
|
||||
|
||||
public string OfficialRating { get; set; }
|
||||
|
||||
public string Overview { get; set; }
|
||||
|
||||
public List<string> Genres { get; set; }
|
||||
public List<string> Studios { get; set; }
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
public List<PersonInfo> People { get; set; }
|
||||
|
||||
public float? CommunityRating { get; set; }
|
||||
|
||||
public long? RunTimeTicks { get; set; }
|
||||
|
||||
public string ImageUrl { get; set; }
|
||||
public string OriginalTitle { get; set; }
|
||||
|
||||
public ChannelMediaType MediaType { get; set; }
|
||||
public ChannelFolderType FolderType { get; set; }
|
||||
|
||||
public ChannelMediaContentType ContentType { get; set; }
|
||||
public ExtraType ExtraType { get; set; }
|
||||
public List<TrailerType> TrailerTypes { get; set; }
|
||||
|
||||
public Dictionary<string, string> ProviderIds { get; set; }
|
||||
|
||||
public DateTime? PremiereDate { get; set; }
|
||||
public int? ProductionYear { get; set; }
|
||||
|
||||
public DateTime? DateCreated { get; set; }
|
||||
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
public int? IndexNumber { get; set; }
|
||||
public int? ParentIndexNumber { get; set; }
|
||||
|
||||
public List<MediaSourceInfo> MediaSources { get; set; }
|
||||
|
||||
public string HomePageUrl { get; set; }
|
||||
|
||||
public List<string> Artists { get; set; }
|
||||
|
||||
public List<string> AlbumArtists { get; set; }
|
||||
public bool IsLiveStream { get; set; }
|
||||
public string Etag { get; set; }
|
||||
|
||||
public ChannelItemInfo()
|
||||
{
|
||||
MediaSources = new List<MediaSourceInfo>();
|
||||
TrailerTypes = new List<TrailerType>();
|
||||
Genres = new List<string>();
|
||||
Studios = new List<string>();
|
||||
People = new List<PersonInfo>();
|
||||
Tags = new List<string>();
|
||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
Artists = new List<string>();
|
||||
AlbumArtists = new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
16
MediaBrowser.Controller/Channels/ChannelItemResult.cs
Normal file
16
MediaBrowser.Controller/Channels/ChannelItemResult.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public class ChannelItemResult
|
||||
{
|
||||
public List<ChannelItemInfo> Items { get; set; }
|
||||
|
||||
public int? TotalRecordCount { get; set; }
|
||||
|
||||
public ChannelItemResult()
|
||||
{
|
||||
Items = new List<ChannelItemInfo>();
|
||||
}
|
||||
}
|
||||
}
|
9
MediaBrowser.Controller/Channels/ChannelItemType.cs
Normal file
9
MediaBrowser.Controller/Channels/ChannelItemType.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public enum ChannelItemType
|
||||
{
|
||||
Media = 0,
|
||||
|
||||
Folder = 1
|
||||
}
|
||||
}
|
15
MediaBrowser.Controller/Channels/ChannelParentalRating.cs
Normal file
15
MediaBrowser.Controller/Channels/ChannelParentalRating.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public enum ChannelParentalRating
|
||||
{
|
||||
GeneralAudience = 0,
|
||||
|
||||
UsPG = 1,
|
||||
|
||||
UsPG13 = 2,
|
||||
|
||||
UsR = 3,
|
||||
|
||||
Adult = 4
|
||||
}
|
||||
}
|
14
MediaBrowser.Controller/Channels/ChannelSearchInfo.cs
Normal file
14
MediaBrowser.Controller/Channels/ChannelSearchInfo.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public class ChannelSearchInfo
|
||||
{
|
||||
public string SearchTerm { get; set; }
|
||||
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
|
||||
public class ChannelLatestMediaSearch
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
}
|
76
MediaBrowser.Controller/Channels/IChannel.cs
Normal file
76
MediaBrowser.Controller/Channels/IChannel.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public interface IChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description.
|
||||
/// </summary>
|
||||
/// <value>The description.</value>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data version.
|
||||
/// </summary>
|
||||
/// <value>The data version.</value>
|
||||
string DataVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the home page URL.
|
||||
/// </summary>
|
||||
/// <value>The home page URL.</value>
|
||||
string HomePageUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parental rating.
|
||||
/// </summary>
|
||||
/// <value>The parental rating.</value>
|
||||
ChannelParentalRating ParentalRating { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel information.
|
||||
/// </summary>
|
||||
/// <returns>ChannelFeatures.</returns>
|
||||
InternalChannelFeatures GetChannelFeatures();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is enabled for] [the specified user].
|
||||
/// </summary>
|
||||
/// <param name="userId">The user identifier.</param>
|
||||
/// <returns><c>true</c> if [is enabled for] [the specified user]; otherwise, <c>false</c>.</returns>
|
||||
bool IsEnabledFor(string userId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel items.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{ChannelItem}}.</returns>
|
||||
Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel image.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{DynamicImageInfo}.</returns>
|
||||
Task<DynamicImageResponse> GetChannelImage(ImageType type, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported channel images.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{ImageType}.</returns>
|
||||
IEnumerable<ImageType> GetSupportedChannelImages();
|
||||
}
|
||||
}
|
89
MediaBrowser.Controller/Channels/IChannelManager.cs
Normal file
89
MediaBrowser.Controller/Channels/IChannelManager.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public interface IChannelManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the parts.
|
||||
/// </summary>
|
||||
/// <param name="channels">The channels.</param>
|
||||
void AddParts(IEnumerable<IChannel> channels);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel features.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>ChannelFeatures.</returns>
|
||||
ChannelFeatures GetChannelFeatures(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all channel features.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{ChannelFeatures}.</returns>
|
||||
ChannelFeatures[] GetAllChannelFeatures();
|
||||
|
||||
bool EnableMediaSourceDisplay(BaseItem item);
|
||||
bool CanDelete(BaseItem item);
|
||||
|
||||
Task DeleteItem(BaseItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>Channel.</returns>
|
||||
Channel GetChannel(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channels internal.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
QueryResult<Channel> GetChannelsInternal(ChannelQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channels.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
QueryResult<BaseItemDto> GetChannels(ChannelQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest media.
|
||||
/// </summary>
|
||||
Task<QueryResult<BaseItemDto>> GetLatestChannelItems(InternalItemsQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest media.
|
||||
/// </summary>
|
||||
Task<QueryResult<BaseItem>> GetLatestChannelItemsInternal(InternalItemsQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel items.
|
||||
/// </summary>
|
||||
Task<QueryResult<BaseItemDto>> GetChannelItems(InternalItemsQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel items internal.
|
||||
/// </summary>
|
||||
Task<QueryResult<BaseItem>> GetChannelItemsInternal(InternalItemsQuery query, IProgress<double> progress, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the channel item media sources.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
|
||||
IEnumerable<MediaSourceInfo> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken);
|
||||
|
||||
bool EnableMediaProbe(BaseItem item);
|
||||
}
|
||||
}
|
13
MediaBrowser.Controller/Channels/IHasCacheKey.cs
Normal file
13
MediaBrowser.Controller/Channels/IHasCacheKey.cs
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public interface IHasCacheKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the cache key.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user identifier.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
string GetCacheKey(string userId);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public interface IRequiresMediaInfoCallback
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the channel item media information.
|
||||
/// </summary>
|
||||
Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaInfo(string id, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
50
MediaBrowser.Controller/Channels/ISearchableChannel.cs
Normal file
50
MediaBrowser.Controller/Channels/ISearchableChannel.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public interface ISearchableChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// Searches the specified search term.
|
||||
/// </summary>
|
||||
/// <param name="searchInfo">The search information.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{ChannelItemInfo}}.</returns>
|
||||
Task<IEnumerable<ChannelItemInfo>> Search(ChannelSearchInfo searchInfo, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface ISupportsLatestMedia
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the latest media.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{ChannelItemInfo}}.</returns>
|
||||
Task<IEnumerable<ChannelItemInfo>> GetLatestMedia(ChannelLatestMediaSearch request, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface ISupportsDelete
|
||||
{
|
||||
bool CanDelete(BaseItem item);
|
||||
Task DeleteItem(string id, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IDisableMediaSourceDisplay
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface ISupportsMediaProbe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IHasFolderAttributes
|
||||
{
|
||||
string[] Attributes { get; }
|
||||
}
|
||||
}
|
61
MediaBrowser.Controller/Channels/InternalChannelFeatures.cs
Normal file
61
MediaBrowser.Controller/Channels/InternalChannelFeatures.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public class InternalChannelFeatures
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the media types.
|
||||
/// </summary>
|
||||
/// <value>The media types.</value>
|
||||
public List<ChannelMediaType> MediaTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content types.
|
||||
/// </summary>
|
||||
/// <value>The content types.</value>
|
||||
public List<ChannelMediaContentType> ContentTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the maximum number of records the channel allows retrieving at a time
|
||||
/// </summary>
|
||||
public int? MaxPageSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default sort orders.
|
||||
/// </summary>
|
||||
/// <value>The default sort orders.</value>
|
||||
public List<ChannelItemSortField> DefaultSortFields { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if a sort ascending/descending toggle is supported or not.
|
||||
/// </summary>
|
||||
public bool SupportsSortOrderToggle { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the automatic refresh levels.
|
||||
/// </summary>
|
||||
/// <value>The automatic refresh levels.</value>
|
||||
public int? AutoRefreshLevels { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the daily download limit.
|
||||
/// </summary>
|
||||
/// <value>The daily download limit.</value>
|
||||
public int? DailyDownloadLimit { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [supports downloading].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [supports downloading]; otherwise, <c>false</c>.</value>
|
||||
public bool SupportsContentDownloading { get; set; }
|
||||
|
||||
public InternalChannelFeatures()
|
||||
{
|
||||
MediaTypes = new List<ChannelMediaType>();
|
||||
ContentTypes = new List<ChannelMediaContentType>();
|
||||
|
||||
DefaultSortFields = new List<ChannelItemSortField>();
|
||||
}
|
||||
}
|
||||
}
|
21
MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs
Normal file
21
MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using MediaBrowser.Model.Channels;
|
||||
using System;
|
||||
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public class InternalChannelItemQuery
|
||||
{
|
||||
public string FolderId { get; set; }
|
||||
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
public int? StartIndex { get; set; }
|
||||
|
||||
public int? Limit { get; set; }
|
||||
|
||||
public ChannelItemSortField? SortBy { get; set; }
|
||||
|
||||
public bool SortDescending { get; set; }
|
||||
}
|
||||
}
|
23
MediaBrowser.Controller/Chapters/IChapterManager.cs
Normal file
23
MediaBrowser.Controller/Chapters/IChapterManager.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Chapters
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IChapterManager
|
||||
/// </summary>
|
||||
public interface IChapterManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the chapters.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item identifier.</param>
|
||||
/// <returns>List{ChapterInfo}.</returns>
|
||||
|
||||
/// <summary>
|
||||
/// Saves the chapters.
|
||||
/// </summary>
|
||||
void SaveChapters(string itemId, List<ChapterInfo> chapters);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Collections
|
||||
{
|
||||
public class CollectionCreationOptions : IHasProviderIds
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public Guid? ParentId { get; set; }
|
||||
|
||||
public bool IsLocked { get; set; }
|
||||
|
||||
public Dictionary<string, string> ProviderIds { get; set; }
|
||||
|
||||
public string[] ItemIdList { get; set; }
|
||||
public Guid[] UserIds { get; set; }
|
||||
|
||||
public CollectionCreationOptions()
|
||||
{
|
||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
ItemIdList = new string[] {};
|
||||
UserIds = new Guid[] {};
|
||||
}
|
||||
}
|
||||
}
|
37
MediaBrowser.Controller/Collections/CollectionEvents.cs
Normal file
37
MediaBrowser.Controller/Collections/CollectionEvents.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Collections
|
||||
{
|
||||
public class CollectionCreatedEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the collection.
|
||||
/// </summary>
|
||||
/// <value>The collection.</value>
|
||||
public BoxSet Collection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public CollectionCreationOptions Options { get; set; }
|
||||
}
|
||||
|
||||
public class CollectionModifiedEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the collection.
|
||||
/// </summary>
|
||||
/// <value>The collection.</value>
|
||||
public BoxSet Collection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the items changed.
|
||||
/// </summary>
|
||||
/// <value>The items changed.</value>
|
||||
public List<BaseItem> ItemsChanged { get; set; }
|
||||
}
|
||||
}
|
57
MediaBrowser.Controller/Collections/ICollectionManager.cs
Normal file
57
MediaBrowser.Controller/Collections/ICollectionManager.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Collections
|
||||
{
|
||||
public interface ICollectionManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when [collection created].
|
||||
/// </summary>
|
||||
event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [items added to collection].
|
||||
/// </summary>
|
||||
event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [items removed from collection].
|
||||
/// </summary>
|
||||
event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the collection.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
BoxSet CreateCollection(CollectionCreationOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Adds to collection.
|
||||
/// </summary>
|
||||
/// <param name="collectionId">The collection identifier.</param>
|
||||
/// <param name="itemIds">The item ids.</param>
|
||||
void AddToCollection(Guid collectionId, IEnumerable<string> itemIds);
|
||||
|
||||
/// <summary>
|
||||
/// Removes from collection.
|
||||
/// </summary>
|
||||
/// <param name="collectionId">The collection identifier.</param>
|
||||
/// <param name="itemIds">The item ids.</param>
|
||||
void RemoveFromCollection(Guid collectionId, IEnumerable<string> itemIds);
|
||||
|
||||
void AddToCollection(Guid collectionId, IEnumerable<Guid> itemIds);
|
||||
void RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds);
|
||||
|
||||
/// <summary>
|
||||
/// Collapses the items within box sets.
|
||||
/// </summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
IEnumerable<BaseItem> CollapseItemsWithinBoxSets(IEnumerable<BaseItem> items, User user);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
|
||||
namespace MediaBrowser.Controller.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IServerConfigurationManager
|
||||
/// </summary>
|
||||
public interface IServerConfigurationManager : IConfigurationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the application paths.
|
||||
/// </summary>
|
||||
/// <value>The application paths.</value>
|
||||
IServerApplicationPaths ApplicationPaths { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration.
|
||||
/// </summary>
|
||||
/// <value>The configuration.</value>
|
||||
ServerConfiguration Configuration { get; }
|
||||
|
||||
bool SetOptimalValues();
|
||||
}
|
||||
}
|
45
MediaBrowser.Controller/Connect/IConnectManager.cs
Normal file
45
MediaBrowser.Controller/Connect/IConnectManager.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Connect;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Connect
|
||||
{
|
||||
public interface IConnectManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the wan API address.
|
||||
/// </summary>
|
||||
/// <value>The wan API address.</value>
|
||||
string WanApiAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Links the user.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user identifier.</param>
|
||||
/// <param name="connectUsername">The connect username.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task<UserLinkResult> LinkUser(string userId, string connectUsername);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the link.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user identifier.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task RemoveConnect(string userId);
|
||||
|
||||
User GetUserFromExchangeToken(string token);
|
||||
|
||||
/// <summary>
|
||||
/// Authenticates the specified username.
|
||||
/// </summary>
|
||||
Task<ConnectAuthenticationResult> Authenticate(string username, string password, string passwordMd5);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is authorization token valid] [the specified token].
|
||||
/// </summary>
|
||||
/// <param name="token">The token.</param>
|
||||
/// <returns><c>true</c> if [is authorization token valid] [the specified token]; otherwise, <c>false</c>.</returns>
|
||||
bool IsAuthorizationTokenValid(string token);
|
||||
}
|
||||
}
|
10
MediaBrowser.Controller/Connect/UserLinkResult.cs
Normal file
10
MediaBrowser.Controller/Connect/UserLinkResult.cs
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
namespace MediaBrowser.Controller.Connect
|
||||
{
|
||||
public class UserLinkResult
|
||||
{
|
||||
public bool IsPending { get; set; }
|
||||
public bool IsNewUserInvitation { get; set; }
|
||||
public string GuestDisplayName { get; set; }
|
||||
}
|
||||
}
|
10
MediaBrowser.Controller/Devices/CameraImageUploadInfo.cs
Normal file
10
MediaBrowser.Controller/Devices/CameraImageUploadInfo.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using MediaBrowser.Model.Devices;
|
||||
|
||||
namespace MediaBrowser.Controller.Devices
|
||||
{
|
||||
public class CameraImageUploadInfo
|
||||
{
|
||||
public LocalFileInfo FileInfo { get; set; }
|
||||
public DeviceInfo Device { get; set; }
|
||||
}
|
||||
}
|
73
MediaBrowser.Controller/Devices/IDeviceManager.cs
Normal file
73
MediaBrowser.Controller/Devices/IDeviceManager.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using MediaBrowser.Model.Devices;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Session;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Devices
|
||||
{
|
||||
public interface IDeviceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when [camera image uploaded].
|
||||
/// </summary>
|
||||
event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded;
|
||||
|
||||
/// <summary>
|
||||
/// Saves the capabilities.
|
||||
/// </summary>
|
||||
/// <param name="reportedId">The reported identifier.</param>
|
||||
/// <param name="capabilities">The capabilities.</param>
|
||||
/// <returns>Task.</returns>
|
||||
void SaveCapabilities(string reportedId, ClientCapabilities capabilities);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the capabilities.
|
||||
/// </summary>
|
||||
/// <param name="reportedId">The reported identifier.</param>
|
||||
/// <returns>ClientCapabilities.</returns>
|
||||
ClientCapabilities GetCapabilities(string reportedId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the device information.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>DeviceInfo.</returns>
|
||||
DeviceInfo GetDevice(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the devices.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>IEnumerable<DeviceInfo>.</returns>
|
||||
QueryResult<DeviceInfo> GetDevices(DeviceQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the upload history.
|
||||
/// </summary>
|
||||
/// <param name="deviceId">The device identifier.</param>
|
||||
/// <returns>ContentUploadHistory.</returns>
|
||||
ContentUploadHistory GetCameraUploadHistory(string deviceId);
|
||||
|
||||
/// <summary>
|
||||
/// Accepts the upload.
|
||||
/// </summary>
|
||||
/// <param name="deviceId">The device identifier.</param>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <param name="file">The file.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance [can access device] the specified user identifier.
|
||||
/// </summary>
|
||||
bool CanAccessDevice(User user, string deviceId);
|
||||
|
||||
void UpdateDeviceOptions(string deviceId, DeviceOptions options);
|
||||
DeviceOptions GetDeviceOptions(string deviceId);
|
||||
event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
|
||||
}
|
||||
}
|
76
MediaBrowser.Controller/Dlna/IDlnaManager.cs
Normal file
76
MediaBrowser.Controller/Dlna/IDlnaManager.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Dlna
|
||||
{
|
||||
public interface IDlnaManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the profile infos.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{DeviceProfileInfo}.</returns>
|
||||
IEnumerable<DeviceProfileInfo> GetProfileInfos();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the profile.
|
||||
/// </summary>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <returns>DeviceProfile.</returns>
|
||||
DeviceProfile GetProfile(IDictionary<string,string> headers);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default profile.
|
||||
/// </summary>
|
||||
/// <returns>DeviceProfile.</returns>
|
||||
DeviceProfile GetDefaultProfile();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the profile.
|
||||
/// </summary>
|
||||
/// <param name="profile">The profile.</param>
|
||||
void CreateProfile(DeviceProfile profile);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the profile.
|
||||
/// </summary>
|
||||
/// <param name="profile">The profile.</param>
|
||||
void UpdateProfile(DeviceProfile profile);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the profile.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
void DeleteProfile(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the profile.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>DeviceProfile.</returns>
|
||||
DeviceProfile GetProfile(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the profile.
|
||||
/// </summary>
|
||||
/// <param name="deviceInfo">The device information.</param>
|
||||
/// <returns>DeviceProfile.</returns>
|
||||
DeviceProfile GetProfile(DeviceIdentification deviceInfo);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server description XML.
|
||||
/// </summary>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <param name="serverUuId">The server uu identifier.</param>
|
||||
/// <param name="serverAddress">The server address.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId, string serverAddress);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the icon.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <returns>DlnaIconResponse.</returns>
|
||||
ImageStream GetIcon(string filename);
|
||||
}
|
||||
}
|
49
MediaBrowser.Controller/Drawing/IImageEncoder.cs
Normal file
49
MediaBrowser.Controller/Drawing/IImageEncoder.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
public interface IImageEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the supported input formats.
|
||||
/// </summary>
|
||||
/// <value>The supported input formats.</value>
|
||||
string[] SupportedInputFormats { get; }
|
||||
/// <summary>
|
||||
/// Gets the supported output formats.
|
||||
/// </summary>
|
||||
/// <value>The supported output formats.</value>
|
||||
ImageFormat[] SupportedOutputFormats { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the image.
|
||||
/// </summary>
|
||||
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the image collage.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
void CreateImageCollage(ImageCollageOptions options);
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [supports image collage creation].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value>
|
||||
bool SupportsImageCollageCreation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [supports image encoding].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value>
|
||||
bool SupportsImageEncoding { get; }
|
||||
|
||||
ImageSize GetImageSize(string path);
|
||||
}
|
||||
}
|
118
MediaBrowser.Controller/Drawing/IImageProcessor.cs
Normal file
118
MediaBrowser.Controller/Drawing/IImageProcessor.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IImageProcessor
|
||||
/// </summary>
|
||||
public interface IImageProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the supported input formats.
|
||||
/// </summary>
|
||||
/// <value>The supported input formats.</value>
|
||||
string[] SupportedInputFormats { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image enhancers.
|
||||
/// </summary>
|
||||
/// <value>The image enhancers.</value>
|
||||
IImageEnhancer[] ImageEnhancers { get; }
|
||||
|
||||
ImageSize GetImageSize(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the image.
|
||||
/// </summary>
|
||||
/// <param name="info">The information.</param>
|
||||
/// <returns>ImageSize.</returns>
|
||||
ImageSize GetImageSize(BaseItem item, ItemImageInfo info);
|
||||
|
||||
ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool allowSlowMethods, bool updateItem);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the parts.
|
||||
/// </summary>
|
||||
/// <param name="enhancers">The enhancers.</param>
|
||||
void AddParts(IEnumerable<IImageEnhancer> enhancers);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported enhancers.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <returns>IEnumerable{IImageEnhancer}.</returns>
|
||||
IImageEnhancer[] GetSupportedEnhancers(BaseItem item, ImageType imageType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image cache tag.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="image">The image.</param>
|
||||
/// <returns>Guid.</returns>
|
||||
string GetImageCacheTag(BaseItem item, ItemImageInfo image);
|
||||
string GetImageCacheTag(BaseItem item, ChapterInfo info);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image cache tag.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="image">The image.</param>
|
||||
/// <param name="imageEnhancers">The image enhancers.</param>
|
||||
/// <returns>Guid.</returns>
|
||||
string GetImageCacheTag(BaseItem item, ItemImageInfo image, IImageEnhancer[] imageEnhancers);
|
||||
|
||||
/// <summary>
|
||||
/// Processes the image.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="toStream">To stream.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ProcessImage(ImageProcessingOptions options, Stream toStream);
|
||||
|
||||
/// <summary>
|
||||
/// Processes the image.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task<Tuple<string, string, DateTime>> ProcessImage(ImageProcessingOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enhanced image.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <param name="imageIndex">Index of the image.</param>
|
||||
/// <returns>Task{System.String}.</returns>
|
||||
Task<string> GetEnhancedImage(BaseItem item, ImageType imageType, int imageIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported image output formats.
|
||||
/// </summary>
|
||||
/// <returns>ImageOutputFormat[].</returns>
|
||||
ImageFormat[] GetSupportedImageOutputFormats();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the image collage.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
void CreateImageCollage(ImageCollageOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [supports image collage creation].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value>
|
||||
bool SupportsImageCollageCreation { get; }
|
||||
|
||||
IImageEncoder ImageEncoder { get; set; }
|
||||
|
||||
bool SupportsTransparency(string path);
|
||||
}
|
||||
}
|
27
MediaBrowser.Controller/Drawing/ImageCollageOptions.cs
Normal file
27
MediaBrowser.Controller/Drawing/ImageCollageOptions.cs
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
public class ImageCollageOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the input paths.
|
||||
/// </summary>
|
||||
/// <value>The input paths.</value>
|
||||
public string[] InputPaths { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the output path.
|
||||
/// </summary>
|
||||
/// <value>The output path.</value>
|
||||
public string OutputPath { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the width.
|
||||
/// </summary>
|
||||
/// <value>The width.</value>
|
||||
public int Width { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the height.
|
||||
/// </summary>
|
||||
/// <value>The height.</value>
|
||||
public int Height { get; set; }
|
||||
}
|
||||
}
|
72
MediaBrowser.Controller/Drawing/ImageHelper.cs
Normal file
72
MediaBrowser.Controller/Drawing/ImageHelper.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
public static class ImageHelper
|
||||
{
|
||||
public static ImageSize GetNewImageSize(ImageProcessingOptions options, ImageSize? originalImageSize)
|
||||
{
|
||||
if (originalImageSize.HasValue)
|
||||
{
|
||||
// Determine the output size based on incoming parameters
|
||||
var newSize = DrawingUtils.Resize(originalImageSize.Value, options.Width ?? 0, options.Height ?? 0, options.MaxWidth ?? 0, options.MaxHeight ?? 0);
|
||||
|
||||
return newSize;
|
||||
}
|
||||
return GetSizeEstimate(options);
|
||||
}
|
||||
|
||||
public static IImageProcessor ImageProcessor { get; set; }
|
||||
|
||||
private static ImageSize GetSizeEstimate(ImageProcessingOptions options)
|
||||
{
|
||||
if (options.Width.HasValue && options.Height.HasValue)
|
||||
{
|
||||
return new ImageSize(options.Width.Value, options.Height.Value);
|
||||
}
|
||||
|
||||
var aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item);
|
||||
|
||||
var width = options.Width ?? options.MaxWidth;
|
||||
|
||||
if (width.HasValue)
|
||||
{
|
||||
var heightValue = width.Value / aspect;
|
||||
return new ImageSize(width.Value, heightValue);
|
||||
}
|
||||
|
||||
var height = options.Height ?? options.MaxHeight ?? 200;
|
||||
var widthValue = aspect * height;
|
||||
return new ImageSize(widthValue, height);
|
||||
}
|
||||
|
||||
private static double GetEstimatedAspectRatio(ImageType type, BaseItem item)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ImageType.Art:
|
||||
case ImageType.Backdrop:
|
||||
case ImageType.Chapter:
|
||||
case ImageType.Screenshot:
|
||||
case ImageType.Thumb:
|
||||
return 1.78;
|
||||
case ImageType.Banner:
|
||||
return 5.4;
|
||||
case ImageType.Box:
|
||||
case ImageType.BoxRear:
|
||||
case ImageType.Disc:
|
||||
case ImageType.Menu:
|
||||
return 1;
|
||||
case ImageType.Logo:
|
||||
return 2.58;
|
||||
case ImageType.Primary:
|
||||
return item.GetDefaultPrimaryImageAspectRatio();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
114
MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
Normal file
114
MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
Normal file
@ -0,0 +1,114 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
public class ImageProcessingOptions
|
||||
{
|
||||
public ImageProcessingOptions()
|
||||
{
|
||||
RequiresAutoOrientation = true;
|
||||
}
|
||||
|
||||
public Guid ItemId { get; set; }
|
||||
public BaseItem Item { get; set; }
|
||||
|
||||
public ItemImageInfo Image { get; set; }
|
||||
|
||||
public int ImageIndex { get; set; }
|
||||
|
||||
public bool CropWhiteSpace { get; set; }
|
||||
|
||||
public int? Width { get; set; }
|
||||
|
||||
public int? Height { get; set; }
|
||||
|
||||
public int? MaxWidth { get; set; }
|
||||
|
||||
public int? MaxHeight { get; set; }
|
||||
|
||||
public int Quality { get; set; }
|
||||
|
||||
public IImageEnhancer[] Enhancers { get; set; }
|
||||
|
||||
public ImageFormat[] SupportedOutputFormats { get; set; }
|
||||
|
||||
public bool AddPlayedIndicator { get; set; }
|
||||
|
||||
public int? UnplayedCount { get; set; }
|
||||
public int? Blur { get; set; }
|
||||
|
||||
public double PercentPlayed { get; set; }
|
||||
|
||||
public string BackgroundColor { get; set; }
|
||||
public string ForegroundLayer { get; set; }
|
||||
public bool RequiresAutoOrientation { get; set; }
|
||||
|
||||
private bool HasDefaultOptions(string originalImagePath)
|
||||
{
|
||||
return HasDefaultOptionsWithoutSize(originalImagePath) &&
|
||||
!Width.HasValue &&
|
||||
!Height.HasValue &&
|
||||
!MaxWidth.HasValue &&
|
||||
!MaxHeight.HasValue;
|
||||
}
|
||||
|
||||
public bool HasDefaultOptions(string originalImagePath, ImageSize? size)
|
||||
{
|
||||
if (!size.HasValue)
|
||||
{
|
||||
return HasDefaultOptions(originalImagePath);
|
||||
}
|
||||
|
||||
if (!HasDefaultOptionsWithoutSize(originalImagePath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var sizeValue = size.Value;
|
||||
|
||||
if (Width.HasValue && !sizeValue.Width.Equals(Width.Value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Height.HasValue && !sizeValue.Height.Equals(Height.Value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (MaxWidth.HasValue && sizeValue.Width > MaxWidth.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (MaxHeight.HasValue && sizeValue.Height > MaxHeight.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool HasDefaultOptionsWithoutSize(string originalImagePath)
|
||||
{
|
||||
return (Quality >= 90) &&
|
||||
IsFormatSupported(originalImagePath) &&
|
||||
!AddPlayedIndicator &&
|
||||
PercentPlayed.Equals(0) &&
|
||||
!UnplayedCount.HasValue &&
|
||||
!Blur.HasValue &&
|
||||
!CropWhiteSpace &&
|
||||
string.IsNullOrEmpty(BackgroundColor) &&
|
||||
string.IsNullOrEmpty(ForegroundLayer);
|
||||
}
|
||||
|
||||
private bool IsFormatSupported(string originalImagePath)
|
||||
{
|
||||
var ext = Path.GetExtension(originalImagePath);
|
||||
return SupportedOutputFormats.Any(outputFormat => string.Equals(ext, "." + outputFormat, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
25
MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs
Normal file
25
MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
public static class ImageProcessorExtensions
|
||||
{
|
||||
public static string GetImageCacheTag(this IImageProcessor processor, BaseItem item, ImageType imageType)
|
||||
{
|
||||
return processor.GetImageCacheTag(item, imageType, 0);
|
||||
}
|
||||
|
||||
public static string GetImageCacheTag(this IImageProcessor processor, BaseItem item, ImageType imageType, int imageIndex)
|
||||
{
|
||||
var imageInfo = item.GetImageInfo(imageType, imageIndex);
|
||||
|
||||
if (imageInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return processor.GetImageCacheTag(item, imageInfo);
|
||||
}
|
||||
}
|
||||
}
|
28
MediaBrowser.Controller/Drawing/ImageStream.cs
Normal file
28
MediaBrowser.Controller/Drawing/ImageStream.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
public class ImageStream : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the stream.
|
||||
/// </summary>
|
||||
/// <value>The stream.</value>
|
||||
public Stream Stream { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the format.
|
||||
/// </summary>
|
||||
/// <value>The format.</value>
|
||||
public ImageFormat Format { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Stream != null)
|
||||
{
|
||||
Stream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
MediaBrowser.Controller/Dto/DtoOptions.cs
Normal file
72
MediaBrowser.Controller/Dto/DtoOptions.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Controller.Dto
|
||||
{
|
||||
public class DtoOptions
|
||||
{
|
||||
private static readonly ItemFields[] DefaultExcludedFields = new []
|
||||
{
|
||||
ItemFields.SeasonUserData,
|
||||
ItemFields.RefreshState
|
||||
};
|
||||
|
||||
public ItemFields[] Fields { get; set; }
|
||||
public ImageType[] ImageTypes { get; set; }
|
||||
public int ImageTypeLimit { get; set; }
|
||||
public bool EnableImages { get; set; }
|
||||
public bool AddProgramRecordingInfo { get; set; }
|
||||
public bool EnableUserData { get; set; }
|
||||
public bool AddCurrentProgram { get; set; }
|
||||
|
||||
public DtoOptions()
|
||||
: this(true)
|
||||
{
|
||||
}
|
||||
|
||||
private static readonly ImageType[] AllImageTypes = Enum.GetNames(typeof(ImageType))
|
||||
.Select(i => (ImageType)Enum.Parse(typeof(ImageType), i, true))
|
||||
.ToArray();
|
||||
|
||||
private static readonly ItemFields[] AllItemFields = Enum.GetNames(typeof(ItemFields))
|
||||
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
|
||||
.Except(DefaultExcludedFields)
|
||||
.ToArray();
|
||||
|
||||
public bool ContainsField(ItemFields field)
|
||||
{
|
||||
return AllItemFields.Contains(field);
|
||||
}
|
||||
|
||||
public DtoOptions(bool allFields)
|
||||
{
|
||||
ImageTypeLimit = int.MaxValue;
|
||||
EnableImages = true;
|
||||
EnableUserData = true;
|
||||
AddCurrentProgram = true;
|
||||
|
||||
if (allFields)
|
||||
{
|
||||
Fields = AllItemFields;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fields = new ItemFields[] { };
|
||||
}
|
||||
|
||||
ImageTypes = AllImageTypes;
|
||||
}
|
||||
|
||||
public int GetImageLimit(ImageType type)
|
||||
{
|
||||
if (EnableImages && ImageTypes.Contains(type))
|
||||
{
|
||||
return ImageTypeLimit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
70
MediaBrowser.Controller/Dto/IDtoService.cs
Normal file
70
MediaBrowser.Controller/Dto/IDtoService.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Controller.Sync;
|
||||
|
||||
namespace MediaBrowser.Controller.Dto
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IDtoService
|
||||
/// </summary>
|
||||
public interface IDtoService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the dto id.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
string GetDtoId(BaseItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the primary image aspect ratio.
|
||||
/// </summary>
|
||||
/// <param name="dto">The dto.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary image aspect ratio.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.Nullable<System.Double>.</returns>
|
||||
double? GetPrimaryImageAspectRatio(BaseItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base item dto.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="fields">The fields.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="owner">The owner.</param>
|
||||
BaseItemDto GetBaseItemDto(BaseItem item, ItemFields[] fields, User user = null, BaseItem owner = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base item dto.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="owner">The owner.</param>
|
||||
/// <returns>BaseItemDto.</returns>
|
||||
BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base item dtos.
|
||||
/// </summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="owner">The owner.</param>
|
||||
BaseItemDto[] GetBaseItemDtos(BaseItem[] items, DtoOptions options, User user = null, BaseItem owner = null);
|
||||
|
||||
BaseItemDto[] GetBaseItemDtos(List<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item by name dto.
|
||||
/// </summary>
|
||||
BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, User user = null);
|
||||
}
|
||||
}
|
219
MediaBrowser.Controller/Entities/AggregateFolder.cs
Normal file
219
MediaBrowser.Controller/Entities/AggregateFolder.cs
Normal file
@ -0,0 +1,219 @@
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Specialized folder that can have items added to it's children by external entities.
|
||||
/// Used for our RootFolder so plug-ins can add items.
|
||||
/// </summary>
|
||||
public class AggregateFolder : Folder
|
||||
{
|
||||
public AggregateFolder()
|
||||
{
|
||||
PhysicalLocationsList = new string[] { };
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool IsPhysicalRoot
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The _virtual children
|
||||
/// </summary>
|
||||
private readonly ConcurrentBag<BaseItem> _virtualChildren = new ConcurrentBag<BaseItem>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the virtual children.
|
||||
/// </summary>
|
||||
/// <value>The virtual children.</value>
|
||||
public ConcurrentBag<BaseItem> VirtualChildren
|
||||
{
|
||||
get { return _virtualChildren; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override string[] PhysicalLocations
|
||||
{
|
||||
get
|
||||
{
|
||||
return PhysicalLocationsList;
|
||||
}
|
||||
}
|
||||
|
||||
public string[] PhysicalLocationsList { get; set; }
|
||||
|
||||
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
|
||||
{
|
||||
return CreateResolveArgs(directoryService, true).FileSystemChildren;
|
||||
}
|
||||
|
||||
private Guid[] _childrenIds = null;
|
||||
private readonly object _childIdsLock = new object();
|
||||
protected override List<BaseItem> LoadChildren()
|
||||
{
|
||||
lock (_childIdsLock)
|
||||
{
|
||||
if (_childrenIds == null || _childrenIds.Length == 0)
|
||||
{
|
||||
var list = base.LoadChildren();
|
||||
_childrenIds = list.Select(i => i.Id).ToArray();
|
||||
return list;
|
||||
}
|
||||
|
||||
return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearCache()
|
||||
{
|
||||
lock (_childIdsLock)
|
||||
{
|
||||
_childrenIds = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _requiresRefresh;
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
var changed = base.RequiresRefresh() || _requiresRefresh;
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
var locations = PhysicalLocations;
|
||||
|
||||
var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations;
|
||||
|
||||
if (!locations.SequenceEqual(newLocations))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
|
||||
{
|
||||
ClearCache();
|
||||
|
||||
var changed = base.BeforeMetadataRefresh(replaceAllMetdata) || _requiresRefresh;
|
||||
_requiresRefresh = false;
|
||||
return changed;
|
||||
}
|
||||
|
||||
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
|
||||
{
|
||||
ClearCache();
|
||||
|
||||
var path = ContainingFolderPath;
|
||||
|
||||
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService)
|
||||
{
|
||||
FileInfo = FileSystem.GetDirectoryInfo(path),
|
||||
Path = path
|
||||
};
|
||||
|
||||
// Gather child folder and files
|
||||
if (args.IsDirectory)
|
||||
{
|
||||
// When resolving the root, we need it's grandchildren (children of user views)
|
||||
var flattenFolderDepth = 2;
|
||||
|
||||
var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, CollectionFolder.ApplicationHost, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: true);
|
||||
|
||||
// Need to remove subpaths that may have been resolved from shortcuts
|
||||
// Example: if \\server\movies exists, then strip out \\server\movies\action
|
||||
files = LibraryManager.NormalizeRootPathList(files).ToArray();
|
||||
|
||||
args.FileSystemChildren = files;
|
||||
}
|
||||
|
||||
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
|
||||
if (setPhysicalLocations)
|
||||
{
|
||||
PhysicalLocationsList = args.PhysicalLocations;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
|
||||
{
|
||||
return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren);
|
||||
}
|
||||
|
||||
protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
|
||||
{
|
||||
ClearCache();
|
||||
|
||||
await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
ClearCache();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the virtual child.
|
||||
/// </summary>
|
||||
/// <param name="child">The child.</param>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public void AddVirtualChild(BaseItem child)
|
||||
{
|
||||
if (child == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
_virtualChildren.Add(child);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the virtual child.
|
||||
/// </summary>
|
||||
/// <param name="id">The id.</param>
|
||||
/// <returns>BaseItem.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">id</exception>
|
||||
public BaseItem FindVirtualChild(Guid id)
|
||||
{
|
||||
if (id.Equals(Guid.Empty))
|
||||
{
|
||||
throw new ArgumentNullException("id");
|
||||
}
|
||||
|
||||
foreach (var child in _virtualChildren)
|
||||
{
|
||||
if (child.Id == id)
|
||||
{
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
216
MediaBrowser.Controller/Entities/Audio/Audio.cs
Normal file
216
MediaBrowser.Controller/Entities/Audio/Audio.cs
Normal file
@ -0,0 +1,216 @@
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Class Audio
|
||||
/// </summary>
|
||||
public class Audio : BaseItem,
|
||||
IHasAlbumArtist,
|
||||
IHasArtist,
|
||||
IHasMusicGenres,
|
||||
IHasLookupInfo<SongInfo>,
|
||||
IHasMediaSources
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the artist.
|
||||
/// </summary>
|
||||
/// <value>The artist.</value>
|
||||
[IgnoreDataMember]
|
||||
public string[] Artists { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string[] AlbumArtists { get; set; }
|
||||
|
||||
public Audio()
|
||||
{
|
||||
Artists = new string[] {};
|
||||
AlbumArtists = new string[] {};
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAddingToPlaylist
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsInheritedParentImages
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
protected override bool SupportsOwnedItems
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override Folder LatestItemsIndexContainer
|
||||
{
|
||||
get
|
||||
{
|
||||
return AlbumEntity;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanDownload()
|
||||
{
|
||||
return IsFileProtocol;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string[] AllArtists
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = new string[AlbumArtists.Length + Artists.Length];
|
||||
|
||||
var index = 0;
|
||||
foreach (var artist in AlbumArtists)
|
||||
{
|
||||
list[index] = artist;
|
||||
index++;
|
||||
}
|
||||
foreach (var artist in Artists)
|
||||
{
|
||||
list[index] = artist;
|
||||
index++;
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public MusicAlbum AlbumEntity
|
||||
{
|
||||
get { return FindParent<MusicAlbum>(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the media.
|
||||
/// </summary>
|
||||
/// <value>The type of the media.</value>
|
||||
[IgnoreDataMember]
|
||||
public override string MediaType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Model.Entities.MediaType.Audio;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the name of the sort.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
protected override string CreateSortName()
|
||||
{
|
||||
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
|
||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
|
||||
|
||||
|
||||
if (ParentIndexNumber.HasValue)
|
||||
{
|
||||
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
|
||||
}
|
||||
songKey += Name;
|
||||
|
||||
if (!string.IsNullOrEmpty(Album))
|
||||
{
|
||||
songKey = Album + "-" + songKey;
|
||||
}
|
||||
|
||||
var albumArtist = AlbumArtists.Length == 0 ? null : AlbumArtists[0];
|
||||
if (!string.IsNullOrEmpty(albumArtist))
|
||||
{
|
||||
songKey = albumArtist + "-" + songKey;
|
||||
}
|
||||
|
||||
list.Insert(0, songKey);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
if (SourceType == SourceType.Library)
|
||||
{
|
||||
return UnratedItem.Music;
|
||||
}
|
||||
return base.GetBlockUnratedType();
|
||||
}
|
||||
|
||||
public List<MediaStream> GetMediaStreams(MediaStreamType type)
|
||||
{
|
||||
return MediaSourceManager.GetMediaStreams(new MediaStreamQuery
|
||||
{
|
||||
ItemId = Id,
|
||||
Type = type
|
||||
});
|
||||
}
|
||||
|
||||
public SongInfo GetLookupInfo()
|
||||
{
|
||||
var info = GetItemLookupInfo<SongInfo>();
|
||||
|
||||
info.AlbumArtists = AlbumArtists;
|
||||
info.Album = Album;
|
||||
info.Artists = Artists;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
protected override List<Tuple<BaseItem, MediaSourceType>> GetAllItemsForMediaSources()
|
||||
{
|
||||
var list = new List<Tuple<BaseItem, MediaSourceType>>();
|
||||
list.Add(new Tuple<BaseItem, MediaSourceType>(this, MediaSourceType.Default));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
15
MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
Normal file
15
MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
public interface IHasAlbumArtist
|
||||
{
|
||||
string[] AlbumArtists { get; set; }
|
||||
}
|
||||
|
||||
public interface IHasArtist
|
||||
{
|
||||
string[] AllArtists { get; }
|
||||
|
||||
string[] Artists { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
public interface IHasMusicGenres
|
||||
{
|
||||
string[] Genres { get; }
|
||||
}
|
||||
}
|
272
MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
Normal file
272
MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
Normal file
@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Users;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MusicAlbum
|
||||
/// </summary>
|
||||
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer
|
||||
{
|
||||
public string[] AlbumArtists { get; set; }
|
||||
public string[] Artists { get; set; }
|
||||
|
||||
public MusicAlbum()
|
||||
{
|
||||
Artists = new string[] {};
|
||||
AlbumArtists = new string[] {};
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAddingToPlaylist
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsInheritedParentImages
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public MusicArtist MusicArtist
|
||||
{
|
||||
get { return GetMusicArtist(new DtoOptions(true)); }
|
||||
}
|
||||
|
||||
public MusicArtist GetMusicArtist(DtoOptions options)
|
||||
{
|
||||
var parents = GetParents();
|
||||
foreach (var parent in parents)
|
||||
{
|
||||
var artist = parent as MusicArtist;
|
||||
if (artist != null)
|
||||
{
|
||||
return artist;
|
||||
}
|
||||
}
|
||||
|
||||
var name = AlbumArtist;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
return LibraryManager.GetArtist(name, options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsCumulativeRunTimeTicks
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string[] AllArtists
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = new string[AlbumArtists.Length + Artists.Length];
|
||||
|
||||
var index = 0;
|
||||
foreach (var artist in AlbumArtists)
|
||||
{
|
||||
list[index] = artist;
|
||||
index++;
|
||||
}
|
||||
foreach (var artist in Artists)
|
||||
{
|
||||
list[index] = artist;
|
||||
index++;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string AlbumArtist
|
||||
{
|
||||
get { return AlbumArtists.Length == 0 ? null : AlbumArtists[0]; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tracks.
|
||||
/// </summary>
|
||||
/// <value>The tracks.</value>
|
||||
[IgnoreDataMember]
|
||||
public IEnumerable<BaseItem> Tracks
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetRecursiveChildren(i => i is Audio);
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
|
||||
{
|
||||
return Tracks;
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
var albumArtist = AlbumArtist;
|
||||
if (!string.IsNullOrEmpty(albumArtist))
|
||||
{
|
||||
list.Insert(0, albumArtist + "-" + Name);
|
||||
}
|
||||
|
||||
var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
|
||||
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
list.Insert(0, "MusicAlbum-Musicbrainz-" + id);
|
||||
}
|
||||
|
||||
id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
|
||||
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Music;
|
||||
}
|
||||
|
||||
public AlbumInfo GetLookupInfo()
|
||||
{
|
||||
var id = GetItemLookupInfo<AlbumInfo>();
|
||||
|
||||
id.AlbumArtists = AlbumArtists;
|
||||
|
||||
var artist = GetMusicArtist(new DtoOptions(false));
|
||||
|
||||
if (artist != null)
|
||||
{
|
||||
id.ArtistProviderIds = artist.ProviderIds;
|
||||
}
|
||||
|
||||
id.SongInfos = GetRecursiveChildren(i => i is Audio)
|
||||
.Cast<Audio>()
|
||||
.Select(i => i.GetLookupInfo())
|
||||
.ToList();
|
||||
|
||||
var album = id.SongInfos
|
||||
.Select(i => i.Album)
|
||||
.FirstOrDefault(i => !string.IsNullOrEmpty(i));
|
||||
|
||||
if (!string.IsNullOrEmpty(album))
|
||||
{
|
||||
id.Name = album;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var items = GetRecursiveChildren();
|
||||
|
||||
var totalItems = items.Count;
|
||||
var numComplete = 0;
|
||||
|
||||
var childUpdateType = ItemUpdateType.None;
|
||||
|
||||
// Refresh songs
|
||||
foreach (var item in items)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var updateType = await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
childUpdateType = childUpdateType | updateType;
|
||||
|
||||
numComplete++;
|
||||
double percent = numComplete;
|
||||
percent /= totalItems;
|
||||
progress.Report(percent * 95);
|
||||
}
|
||||
|
||||
var parentRefreshOptions = refreshOptions;
|
||||
if (childUpdateType > ItemUpdateType.None)
|
||||
{
|
||||
parentRefreshOptions = new MetadataRefreshOptions(refreshOptions);
|
||||
parentRefreshOptions.MetadataRefreshMode = MetadataRefreshMode.FullRefresh;
|
||||
}
|
||||
|
||||
// Refresh current item
|
||||
await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!refreshOptions.IsAutomated)
|
||||
{
|
||||
await RefreshArtists(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshArtists(MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
|
||||
{
|
||||
var all = AllArtists;
|
||||
foreach (var i in all)
|
||||
{
|
||||
// This should not be necessary but we're seeing some cases of it
|
||||
if (string.IsNullOrEmpty(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var artist = LibraryManager.GetArtist(i);
|
||||
|
||||
if (!artist.IsAccessedByName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
await artist.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
275
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
Normal file
275
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
Normal file
@ -0,0 +1,275 @@
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Extensions;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MusicArtist
|
||||
/// </summary>
|
||||
public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo<ArtistInfo>
|
||||
{
|
||||
[IgnoreDataMember]
|
||||
public bool IsAccessedByName
|
||||
{
|
||||
get { return ParentId.Equals(Guid.Empty); }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool IsFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
return !IsAccessedByName;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsInheritedParentImages
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsCumulativeRunTimeTicks
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool IsDisplayedAsFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAddingToPlaylist
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return !IsAccessedByName;
|
||||
}
|
||||
|
||||
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||
{
|
||||
if (query.IncludeItemTypes.Length == 0)
|
||||
{
|
||||
query.IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name };
|
||||
query.ArtistIds = new[] { Id };
|
||||
}
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override IEnumerable<BaseItem> Children
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
return base.Children;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetChildCount(User user)
|
||||
{
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return base.GetChildCount(user);
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.IsSaveLocalMetadataEnabled();
|
||||
}
|
||||
|
||||
private readonly Task _cachedTask = Task.FromResult(true);
|
||||
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
|
||||
{
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
// Should never get in here anyway
|
||||
return _cachedTask;
|
||||
}
|
||||
|
||||
return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
list.InsertRange(0, GetUserDataKeys(this));
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the folder containing the item.
|
||||
/// If the item is a folder, it returns the folder itself
|
||||
/// </summary>
|
||||
/// <value>The containing folder path.</value>
|
||||
[IgnoreDataMember]
|
||||
public override string ContainingFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private static List<string> GetUserDataKeys(MusicArtist item)
|
||||
{
|
||||
var list = new List<string>();
|
||||
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
|
||||
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
list.Add("Artist-Musicbrainz-" + id);
|
||||
}
|
||||
|
||||
list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics());
|
||||
return list;
|
||||
}
|
||||
public override string CreatePresentationUniqueKey()
|
||||
{
|
||||
return "Artist-" + (Name ?? string.Empty).RemoveDiacritics();
|
||||
}
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Music);
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Music;
|
||||
}
|
||||
|
||||
public ArtistInfo GetLookupInfo()
|
||||
{
|
||||
var info = GetItemLookupInfo<ArtistInfo>();
|
||||
|
||||
info.SongInfos = GetRecursiveChildren(i => i is Audio)
|
||||
.Cast<Audio>()
|
||||
.Select(i => i.GetLookupInfo())
|
||||
.ToList();
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetPath(string name)
|
||||
{
|
||||
return GetPath(name, true);
|
||||
}
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName);
|
||||
}
|
||||
|
||||
private string GetRebasedPath()
|
||||
{
|
||||
return GetPath(System.IO.Path.GetFileName(Path), false);
|
||||
}
|
||||
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return base.RequiresRefresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called before any metadata refresh and returns true or false indicating if changes were made
|
||||
/// </summary>
|
||||
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
|
||||
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Path = newPath;
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasChanges;
|
||||
}
|
||||
}
|
||||
}
|
145
MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
Normal file
145
MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
Normal file
@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Extensions;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Class MusicGenre
|
||||
/// </summary>
|
||||
public class MusicGenre : BaseItem, IItemByName
|
||||
{
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||
return list;
|
||||
}
|
||||
public override string CreatePresentationUniqueKey()
|
||||
{
|
||||
return GetUserDataKeys()[0];
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAddingToPlaylist
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAncestors
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool IsDisplayedAsFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the folder containing the item.
|
||||
/// If the item is a folder, it returns the folder itself
|
||||
/// </summary>
|
||||
/// <value>The containing folder path.</value>
|
||||
[IgnoreDataMember]
|
||||
public override string ContainingFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||
{
|
||||
query.GenreIds = new[] { Id };
|
||||
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
}
|
||||
|
||||
public static string GetPath(string name)
|
||||
{
|
||||
return GetPath(name, true);
|
||||
}
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.MusicGenrePath, validName);
|
||||
}
|
||||
|
||||
private string GetRebasedPath()
|
||||
{
|
||||
return GetPath(System.IO.Path.GetFileName(Path), false);
|
||||
}
|
||||
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
|
||||
return true;
|
||||
}
|
||||
return base.RequiresRefresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called before any metadata refresh and returns true or false indicating if changes were made
|
||||
/// </summary>
|
||||
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
|
||||
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Path = newPath;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
return hasChanges;
|
||||
}
|
||||
}
|
||||
}
|
69
MediaBrowser.Controller/Entities/AudioBook.cs
Normal file
69
MediaBrowser.Controller/Entities/AudioBook.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public class AudioBook : Audio.Audio, IHasSeries, IHasLookupInfo<SongInfo>
|
||||
{
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPositionTicksResume
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string SeriesPresentationUniqueKey { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public string SeriesName { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public Guid SeriesId { get; set; }
|
||||
|
||||
public string FindSeriesSortName()
|
||||
{
|
||||
return SeriesName;
|
||||
}
|
||||
public string FindSeriesName()
|
||||
{
|
||||
return SeriesName;
|
||||
}
|
||||
public string FindSeriesPresentationUniqueKey()
|
||||
{
|
||||
return SeriesPresentationUniqueKey;
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Guid FindSeriesId()
|
||||
{
|
||||
return SeriesId;
|
||||
}
|
||||
|
||||
public override bool CanDownload()
|
||||
{
|
||||
return IsFileProtocol;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Book;
|
||||
}
|
||||
}
|
||||
}
|
2960
MediaBrowser.Controller/Entities/BaseItem.cs
Normal file
2960
MediaBrowser.Controller/Entities/BaseItem.cs
Normal file
File diff suppressed because it is too large
Load Diff
65
MediaBrowser.Controller/Entities/BaseItemExtensions.cs
Normal file
65
MediaBrowser.Controller/Entities/BaseItemExtensions.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public static class BaseItemExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the image path.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public static string GetImagePath(this BaseItem item, ImageType imageType)
|
||||
{
|
||||
return item.GetImagePath(imageType, 0);
|
||||
}
|
||||
|
||||
public static bool HasImage(this BaseItem item, ImageType imageType)
|
||||
{
|
||||
return item.HasImage(imageType, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the image path.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <param name="file">The file.</param>
|
||||
public static void SetImagePath(this BaseItem item, ImageType imageType, FileSystemMetadata file)
|
||||
{
|
||||
item.SetImagePath(imageType, 0, file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the image path.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <param name="file">The file.</param>
|
||||
public static void SetImagePath(this BaseItem item, ImageType imageType, string file)
|
||||
{
|
||||
if (file.StartsWith("http", System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = file,
|
||||
Type = imageType
|
||||
}, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SetImagePath(imageType, BaseItem.FileSystem.GetFileInfo(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
54
MediaBrowser.Controller/Entities/BasePluginFolder.cs
Normal file
54
MediaBrowser.Controller/Entities/BasePluginFolder.cs
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Plugins derive from and export this class to create a folder that will appear in the root along
|
||||
/// with all the other actual physical folders in the system.
|
||||
/// </summary>
|
||||
public abstract class BasePluginFolder : Folder, ICollectionFolder
|
||||
{
|
||||
[IgnoreDataMember]
|
||||
public virtual string CollectionType
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsInheritedParentImages
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//public override double? GetDefaultPrimaryImageAspectRatio()
|
||||
//{
|
||||
// double value = 16;
|
||||
// value /= 9;
|
||||
|
||||
// return value;
|
||||
//}
|
||||
}
|
||||
}
|
72
MediaBrowser.Controller/Entities/Book.cs
Normal file
72
MediaBrowser.Controller/Entities/Book.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries
|
||||
{
|
||||
[IgnoreDataMember]
|
||||
public override string MediaType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Model.Entities.MediaType.Book;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string SeriesPresentationUniqueKey { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public string SeriesName { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public Guid SeriesId { get; set; }
|
||||
|
||||
public string FindSeriesSortName()
|
||||
{
|
||||
return SeriesName;
|
||||
}
|
||||
public string FindSeriesName()
|
||||
{
|
||||
return SeriesName;
|
||||
}
|
||||
public string FindSeriesPresentationUniqueKey()
|
||||
{
|
||||
return SeriesPresentationUniqueKey;
|
||||
}
|
||||
|
||||
public Guid FindSeriesId()
|
||||
{
|
||||
return SeriesId;
|
||||
}
|
||||
|
||||
public override bool CanDownload()
|
||||
{
|
||||
return IsFileProtocol;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Book;
|
||||
}
|
||||
|
||||
public BookInfo GetLookupInfo()
|
||||
{
|
||||
var info = GetItemLookupInfo<BookInfo>();
|
||||
|
||||
if (string.IsNullOrEmpty(SeriesName))
|
||||
{
|
||||
info.SeriesName = GetParents().Select(i => i.Name).FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
info.SeriesName = SeriesName;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
405
MediaBrowser.Controller/Entities/CollectionFolder.cs
Normal file
405
MediaBrowser.Controller/Entities/CollectionFolder.cs
Normal file
@ -0,0 +1,405 @@
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Specialized Folder class that points to a subset of the physical folders in the system.
|
||||
/// It is created from the user-specific folders within the system root
|
||||
/// </summary>
|
||||
public class CollectionFolder : Folder, ICollectionFolder
|
||||
{
|
||||
public static IXmlSerializer XmlSerializer { get; set; }
|
||||
public static IJsonSerializer JsonSerializer { get; set; }
|
||||
public static IServerApplicationHost ApplicationHost { get; set; }
|
||||
|
||||
public CollectionFolder()
|
||||
{
|
||||
PhysicalLocationsList = new string[] { };
|
||||
PhysicalFolderIds = new Guid[] { };
|
||||
}
|
||||
|
||||
//public override double? GetDefaultPrimaryImageAspectRatio()
|
||||
//{
|
||||
// double value = 16;
|
||||
// value /= 9;
|
||||
|
||||
// return value;
|
||||
//}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsInheritedParentImages
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public string CollectionType { get; set; }
|
||||
|
||||
private static readonly Dictionary<string, LibraryOptions> LibraryOptions = new Dictionary<string, LibraryOptions>();
|
||||
public LibraryOptions GetLibraryOptions()
|
||||
{
|
||||
return GetLibraryOptions(Path);
|
||||
}
|
||||
|
||||
private static LibraryOptions LoadLibraryOptions(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions;
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
return new LibraryOptions();
|
||||
}
|
||||
|
||||
foreach (var mediaPath in result.PathInfos)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(mediaPath.Path))
|
||||
{
|
||||
mediaPath.Path = ApplicationHost.ExpandVirtualPath(mediaPath.Path);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return new LibraryOptions();
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return new LibraryOptions();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error loading library options", ex);
|
||||
|
||||
return new LibraryOptions();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetLibraryOptionsPath(string path)
|
||||
{
|
||||
return System.IO.Path.Combine(path, "options.xml");
|
||||
}
|
||||
|
||||
public void UpdateLibraryOptions(LibraryOptions options)
|
||||
{
|
||||
SaveLibraryOptions(Path, options);
|
||||
}
|
||||
|
||||
public static LibraryOptions GetLibraryOptions(string path)
|
||||
{
|
||||
lock (LibraryOptions)
|
||||
{
|
||||
LibraryOptions options;
|
||||
if (!LibraryOptions.TryGetValue(path, out options))
|
||||
{
|
||||
options = LoadLibraryOptions(path);
|
||||
LibraryOptions[path] = options;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveLibraryOptions(string path, LibraryOptions options)
|
||||
{
|
||||
lock (LibraryOptions)
|
||||
{
|
||||
LibraryOptions[path] = options;
|
||||
|
||||
var clone = JsonSerializer.DeserializeFromString<LibraryOptions>(JsonSerializer.SerializeToString(options));
|
||||
foreach (var mediaPath in clone.PathInfos)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(mediaPath.Path))
|
||||
{
|
||||
mediaPath.Path = ApplicationHost.ReverseVirtualPath(mediaPath.Path);
|
||||
}
|
||||
}
|
||||
|
||||
XmlSerializer.SerializeToFile(clone, GetLibraryOptionsPath(path));
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnCollectionFolderChange()
|
||||
{
|
||||
lock (LibraryOptions)
|
||||
{
|
||||
LibraryOptions.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow different display preferences for each collection folder
|
||||
/// </summary>
|
||||
/// <value>The display prefs id.</value>
|
||||
[IgnoreDataMember]
|
||||
public override Guid DisplayPreferencesId
|
||||
{
|
||||
get
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override string[] PhysicalLocations
|
||||
{
|
||||
get
|
||||
{
|
||||
return PhysicalLocationsList;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public string[] PhysicalLocationsList { get; set; }
|
||||
public Guid[] PhysicalFolderIds { get; set; }
|
||||
|
||||
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
|
||||
{
|
||||
return CreateResolveArgs(directoryService, true).FileSystemChildren;
|
||||
}
|
||||
|
||||
private bool _requiresRefresh;
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
var changed = base.RequiresRefresh() || _requiresRefresh;
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
var locations = PhysicalLocations;
|
||||
|
||||
var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations;
|
||||
|
||||
if (!locations.SequenceEqual(newLocations))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
var folderIds = PhysicalFolderIds;
|
||||
|
||||
var newFolderIds = GetPhysicalFolders(false).Select(i => i.Id).ToList();
|
||||
|
||||
if (!folderIds.SequenceEqual(newFolderIds))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
|
||||
{
|
||||
var changed = base.BeforeMetadataRefresh(replaceAllMetdata) || _requiresRefresh;
|
||||
_requiresRefresh = false;
|
||||
return changed;
|
||||
}
|
||||
|
||||
public override double? GetRefreshProgress()
|
||||
{
|
||||
var folders = GetPhysicalFolders(true).ToList();
|
||||
double totalProgresses = 0;
|
||||
var foldersWithProgress = 0;
|
||||
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
var progress = ProviderManager.GetRefreshProgress(folder.Id);
|
||||
if (progress.HasValue)
|
||||
{
|
||||
totalProgresses += progress.Value;
|
||||
foldersWithProgress++;
|
||||
}
|
||||
}
|
||||
|
||||
if (foldersWithProgress == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return (totalProgresses / foldersWithProgress);
|
||||
}
|
||||
|
||||
protected override bool RefreshLinkedChildren(IEnumerable<FileSystemMetadata> fileSystemChildren)
|
||||
{
|
||||
return RefreshLinkedChildrenInternal(true);
|
||||
}
|
||||
|
||||
private bool RefreshLinkedChildrenInternal(bool setFolders)
|
||||
{
|
||||
var physicalFolders = GetPhysicalFolders(false)
|
||||
.ToList();
|
||||
|
||||
var linkedChildren = physicalFolders
|
||||
.SelectMany(c => c.LinkedChildren)
|
||||
.ToList();
|
||||
|
||||
var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem));
|
||||
|
||||
LinkedChildren = linkedChildren.ToArray(linkedChildren.Count);
|
||||
|
||||
var folderIds = PhysicalFolderIds;
|
||||
var newFolderIds = physicalFolders.Select(i => i.Id).ToArray();
|
||||
|
||||
if (!folderIds.SequenceEqual(newFolderIds))
|
||||
{
|
||||
changed = true;
|
||||
if (setFolders)
|
||||
{
|
||||
PhysicalFolderIds = newFolderIds;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
|
||||
{
|
||||
var path = ContainingFolderPath;
|
||||
|
||||
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService)
|
||||
{
|
||||
FileInfo = FileSystem.GetDirectoryInfo(path),
|
||||
Path = path,
|
||||
Parent = GetParent() as Folder,
|
||||
CollectionType = CollectionType
|
||||
};
|
||||
|
||||
// Gather child folder and files
|
||||
if (args.IsDirectory)
|
||||
{
|
||||
var flattenFolderDepth = 0;
|
||||
|
||||
var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, ApplicationHost, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: true);
|
||||
|
||||
args.FileSystemChildren = files;
|
||||
}
|
||||
|
||||
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
|
||||
|
||||
if (setPhysicalLocations)
|
||||
{
|
||||
PhysicalLocationsList = args.PhysicalLocations;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes
|
||||
/// ***Currently does not contain logic to maintain items that are unavailable in the file system***
|
||||
/// </summary>
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
|
||||
/// <param name="refreshChildMetadata">if set to <c>true</c> [refresh child metadata].</param>
|
||||
/// <param name="refreshOptions">The refresh options.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
/// <returns>Task.</returns>
|
||||
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Our children are actually just references to the ones in the physical root...
|
||||
/// </summary>
|
||||
/// <value>The actual children.</value>
|
||||
[IgnoreDataMember]
|
||||
public override IEnumerable<BaseItem> Children
|
||||
{
|
||||
get { return GetActualChildren(); }
|
||||
}
|
||||
|
||||
public IEnumerable<BaseItem> GetActualChildren()
|
||||
{
|
||||
return GetPhysicalFolders(true).SelectMany(c => c.Children);
|
||||
}
|
||||
|
||||
public IEnumerable<Folder> GetPhysicalFolders()
|
||||
{
|
||||
return GetPhysicalFolders(true);
|
||||
}
|
||||
|
||||
private IEnumerable<Folder> GetPhysicalFolders(bool enableCache)
|
||||
{
|
||||
if (enableCache)
|
||||
{
|
||||
return PhysicalFolderIds.Select(i => LibraryManager.GetItemById(i)).OfType<Folder>();
|
||||
}
|
||||
|
||||
var rootChildren = LibraryManager.RootFolder.Children
|
||||
.OfType<Folder>()
|
||||
.ToList();
|
||||
|
||||
return PhysicalLocations.Where(i => !FileSystem.AreEqual(i, Path)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
|
||||
}
|
||||
|
||||
private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
|
||||
{
|
||||
var result = rootChildren
|
||||
.Where(i => FileSystem.AreEqual(i.Path, path))
|
||||
.ToList();
|
||||
|
||||
if (result.Count == 0)
|
||||
{
|
||||
var folder = LibraryManager.FindByPath(path, true) as Folder;
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
result.Add(folder);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
MediaBrowser.Controller/Entities/DayOfWeekHelper.cs
Normal file
71
MediaBrowser.Controller/Entities/DayOfWeekHelper.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public static class DayOfWeekHelper
|
||||
{
|
||||
public static List<DayOfWeek> GetDaysOfWeek(DynamicDayOfWeek day)
|
||||
{
|
||||
return GetDaysOfWeek(new List<DynamicDayOfWeek> { day });
|
||||
}
|
||||
|
||||
public static List<DayOfWeek> GetDaysOfWeek(List<DynamicDayOfWeek> days)
|
||||
{
|
||||
var list = new List<DayOfWeek>();
|
||||
|
||||
if (days.Contains(DynamicDayOfWeek.Sunday) ||
|
||||
days.Contains(DynamicDayOfWeek.Weekend) ||
|
||||
days.Contains(DynamicDayOfWeek.Everyday))
|
||||
{
|
||||
list.Add(DayOfWeek.Sunday);
|
||||
}
|
||||
|
||||
if (days.Contains(DynamicDayOfWeek.Saturday) ||
|
||||
days.Contains(DynamicDayOfWeek.Weekend) ||
|
||||
days.Contains(DynamicDayOfWeek.Everyday))
|
||||
{
|
||||
list.Add(DayOfWeek.Saturday);
|
||||
}
|
||||
|
||||
if (days.Contains(DynamicDayOfWeek.Monday) ||
|
||||
days.Contains(DynamicDayOfWeek.Weekday) ||
|
||||
days.Contains(DynamicDayOfWeek.Everyday))
|
||||
{
|
||||
list.Add(DayOfWeek.Monday);
|
||||
}
|
||||
|
||||
if (days.Contains(DynamicDayOfWeek.Tuesday) ||
|
||||
days.Contains(DynamicDayOfWeek.Weekday) ||
|
||||
days.Contains(DynamicDayOfWeek.Everyday))
|
||||
{
|
||||
list.Add(DayOfWeek.Tuesday
|
||||
);
|
||||
}
|
||||
|
||||
if (days.Contains(DynamicDayOfWeek.Wednesday) ||
|
||||
days.Contains(DynamicDayOfWeek.Weekday) ||
|
||||
days.Contains(DynamicDayOfWeek.Everyday))
|
||||
{
|
||||
list.Add(DayOfWeek.Wednesday);
|
||||
}
|
||||
|
||||
if (days.Contains(DynamicDayOfWeek.Thursday) ||
|
||||
days.Contains(DynamicDayOfWeek.Weekday) ||
|
||||
days.Contains(DynamicDayOfWeek.Everyday))
|
||||
{
|
||||
list.Add(DayOfWeek.Thursday);
|
||||
}
|
||||
|
||||
if (days.Contains(DynamicDayOfWeek.Friday) ||
|
||||
days.Contains(DynamicDayOfWeek.Weekday) ||
|
||||
days.Contains(DynamicDayOfWeek.Everyday))
|
||||
{
|
||||
list.Add(DayOfWeek.Friday);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
46
MediaBrowser.Controller/Entities/Extensions.cs
Normal file
46
MediaBrowser.Controller/Entities/Extensions.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Class Extensions
|
||||
/// </summary>
|
||||
public static class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the trailer URL.
|
||||
/// </summary>
|
||||
public static void AddTrailerUrl(this BaseItem item, string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url))
|
||||
{
|
||||
throw new ArgumentNullException("url");
|
||||
}
|
||||
|
||||
var current = item.RemoteTrailers.FirstOrDefault(i => string.Equals(i.Url, url, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (current == null)
|
||||
{
|
||||
var mediaUrl = new MediaUrl
|
||||
{
|
||||
Url = url
|
||||
};
|
||||
|
||||
if (item.RemoteTrailers.Length == 0)
|
||||
{
|
||||
item.RemoteTrailers = new[] { mediaUrl };
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = item.RemoteTrailers.ToArray(item.RemoteTrailers.Length + 1);
|
||||
list[list.Length - 1] = mediaUrl;
|
||||
|
||||
item.RemoteTrailers = list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1803
MediaBrowser.Controller/Entities/Folder.cs
Normal file
1803
MediaBrowser.Controller/Entities/Folder.cs
Normal file
File diff suppressed because it is too large
Load Diff
129
MediaBrowser.Controller/Entities/Game.cs
Normal file
129
MediaBrowser.Controller/Entities/Game.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public class Game : BaseItem, IHasTrailers, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
|
||||
{
|
||||
public Game()
|
||||
{
|
||||
MultiPartGameFiles = new string[] {};
|
||||
RemoteTrailers = EmptyMediaUrlArray;
|
||||
LocalTrailerIds = new Guid[] {};
|
||||
RemoteTrailerIds = new Guid[] {};
|
||||
}
|
||||
|
||||
public Guid[] LocalTrailerIds { get; set; }
|
||||
public Guid[] RemoteTrailerIds { get; set; }
|
||||
|
||||
public override bool CanDownload()
|
||||
{
|
||||
return IsFileProtocol;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsThemeMedia
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the remote trailers.
|
||||
/// </summary>
|
||||
/// <value>The remote trailers.</value>
|
||||
public MediaUrl[] RemoteTrailers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the media.
|
||||
/// </summary>
|
||||
/// <value>The type of the media.</value>
|
||||
[IgnoreDataMember]
|
||||
public override string MediaType
|
||||
{
|
||||
get { return Model.Entities.MediaType.Game; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the players supported.
|
||||
/// </summary>
|
||||
/// <value>The players supported.</value>
|
||||
public int? PlayersSupported { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is place holder.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is place holder; otherwise, <c>false</c>.</value>
|
||||
public bool IsPlaceHolder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the game system.
|
||||
/// </summary>
|
||||
/// <value>The game system.</value>
|
||||
public string GameSystem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is multi part.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is multi part; otherwise, <c>false</c>.</value>
|
||||
public bool IsMultiPart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the paths to the game files in the event this is a multipart game
|
||||
/// </summary>
|
||||
public string[] MultiPartGameFiles { get; set; }
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
var id = this.GetProviderId(MetadataProviders.Gamesdb);
|
||||
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
list.Insert(0, "Game-Gamesdb-" + id);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public override IEnumerable<FileSystemMetadata> GetDeletePaths()
|
||||
{
|
||||
if (!IsInMixedFolder)
|
||||
{
|
||||
return new[] {
|
||||
new FileSystemMetadata
|
||||
{
|
||||
FullName = FileSystem.GetDirectoryName(Path),
|
||||
IsDirectory = true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return base.GetDeletePaths();
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Game;
|
||||
}
|
||||
|
||||
public GameInfo GetLookupInfo()
|
||||
{
|
||||
var id = GetItemLookupInfo<GameInfo>();
|
||||
|
||||
id.GameSystem = GameSystem;
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
128
MediaBrowser.Controller/Entities/GameGenre.cs
Normal file
128
MediaBrowser.Controller/Entities/GameGenre.cs
Normal file
@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Extensions;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public class GameGenre : BaseItem, IItemByName
|
||||
{
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||
return list;
|
||||
}
|
||||
|
||||
public override string CreatePresentationUniqueKey()
|
||||
{
|
||||
return GetUserDataKeys()[0];
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the folder containing the item.
|
||||
/// If the item is a folder, it returns the folder itself
|
||||
/// </summary>
|
||||
/// <value>The containing folder path.</value>
|
||||
[IgnoreDataMember]
|
||||
public override string ContainingFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAncestors
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||
{
|
||||
query.GenreIds = new[] { Id };
|
||||
query.IncludeItemTypes = new[] { typeof(Game).Name };
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetPath(string name)
|
||||
{
|
||||
return GetPath(name, true);
|
||||
}
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GameGenrePath, validName);
|
||||
}
|
||||
|
||||
private string GetRebasedPath()
|
||||
{
|
||||
return GetPath(System.IO.Path.GetFileName(Path), false);
|
||||
}
|
||||
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
|
||||
return true;
|
||||
}
|
||||
return base.RequiresRefresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called before any metadata refresh and returns true or false indicating if changes were made
|
||||
/// </summary>
|
||||
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
|
||||
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Path = newPath;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
return hasChanges;
|
||||
}
|
||||
}
|
||||
}
|
101
MediaBrowser.Controller/Entities/GameSystem.cs
Normal file
101
MediaBrowser.Controller/Entities/GameSystem.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Users;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Class GameSystem
|
||||
/// </summary>
|
||||
public class GameSystem : Folder, IHasLookupInfo<GameSystemInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the id that should be used to key display prefs for this item.
|
||||
/// Default is based on the type for everything except actual generic folders.
|
||||
/// </summary>
|
||||
/// <value>The display prefs id.</value>
|
||||
[IgnoreDataMember]
|
||||
public override Guid DisplayPreferencesId
|
||||
{
|
||||
get
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsInheritedParentImages
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
double value = 16;
|
||||
value /= 9;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the game system.
|
||||
/// </summary>
|
||||
/// <value>The game system.</value>
|
||||
public string GameSystemName { get; set; }
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
if (!string.IsNullOrEmpty(GameSystemName))
|
||||
{
|
||||
list.Insert(0, "GameSystem-" + GameSystemName);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
{
|
||||
// Don't block. Determine by game
|
||||
return false;
|
||||
}
|
||||
|
||||
public override UnratedItem GetBlockUnratedType()
|
||||
{
|
||||
return UnratedItem.Game;
|
||||
}
|
||||
|
||||
public GameSystemInfo GetLookupInfo()
|
||||
{
|
||||
var id = GetItemLookupInfo<GameSystemInfo>();
|
||||
|
||||
id.Path = Path;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
140
MediaBrowser.Controller/Entities/Genre.cs
Normal file
140
MediaBrowser.Controller/Entities/Genre.cs
Normal file
@ -0,0 +1,140 @@
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Extensions;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Class Genre
|
||||
/// </summary>
|
||||
public class Genre : BaseItem, IItemByName
|
||||
{
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
var list = base.GetUserDataKeys();
|
||||
|
||||
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
||||
return list;
|
||||
}
|
||||
public override string CreatePresentationUniqueKey()
|
||||
{
|
||||
return GetUserDataKeys()[0];
|
||||
}
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the folder containing the item.
|
||||
/// If the item is a folder, it returns the folder itself
|
||||
/// </summary>
|
||||
/// <value>The containing folder path.</value>
|
||||
[IgnoreDataMember]
|
||||
public override string ContainingFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool IsDisplayedAsFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsAncestors
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||
{
|
||||
query.GenreIds = new[] { Id };
|
||||
query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPeople
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetPath(string name)
|
||||
{
|
||||
return GetPath(name, true);
|
||||
}
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GenrePath, validName);
|
||||
}
|
||||
|
||||
private string GetRebasedPath()
|
||||
{
|
||||
return GetPath(System.IO.Path.GetFileName(Path), false);
|
||||
}
|
||||
|
||||
public override bool RequiresRefresh()
|
||||
{
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
|
||||
return true;
|
||||
}
|
||||
return base.RequiresRefresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called before any metadata refresh and returns true or false indicating if changes were made
|
||||
/// </summary>
|
||||
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
|
||||
|
||||
var newPath = GetRebasedPath();
|
||||
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
||||
{
|
||||
Path = newPath;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
return hasChanges;
|
||||
}
|
||||
}
|
||||
}
|
27
MediaBrowser.Controller/Entities/ICollectionFolder.cs
Normal file
27
MediaBrowser.Controller/Entities/ICollectionFolder.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// This is just a marker interface to denote top level folders
|
||||
/// </summary>
|
||||
public interface ICollectionFolder : IHasCollectionType
|
||||
{
|
||||
string Path { get; }
|
||||
string Name { get; }
|
||||
Guid Id { get; }
|
||||
string[] PhysicalLocations { get; }
|
||||
}
|
||||
|
||||
public interface ISupportsUserSpecificView
|
||||
{
|
||||
bool EnableUserSpecificView { get; }
|
||||
}
|
||||
|
||||
public interface IHasCollectionType
|
||||
{
|
||||
string CollectionType { get; }
|
||||
}
|
||||
}
|
14
MediaBrowser.Controller/Entities/IHasAspectRatio.cs
Normal file
14
MediaBrowser.Controller/Entities/IHasAspectRatio.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IHasAspectRatio
|
||||
/// </summary>
|
||||
public interface IHasAspectRatio
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the aspect ratio.
|
||||
/// </summary>
|
||||
/// <value>The aspect ratio.</value>
|
||||
string AspectRatio { get; set; }
|
||||
}
|
||||
}
|
15
MediaBrowser.Controller/Entities/IHasDisplayOrder.cs
Normal file
15
MediaBrowser.Controller/Entities/IHasDisplayOrder.cs
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IHasDisplayOrder
|
||||
/// </summary>
|
||||
public interface IHasDisplayOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the display order.
|
||||
/// </summary>
|
||||
/// <value>The display order.</value>
|
||||
string DisplayOrder { get; set; }
|
||||
}
|
||||
}
|
19
MediaBrowser.Controller/Entities/IHasMediaSources.cs
Normal file
19
MediaBrowser.Controller/Entities/IHasMediaSources.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using MediaBrowser.Model.Dto;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasMediaSources
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the media sources.
|
||||
/// </summary>
|
||||
List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
|
||||
List<MediaStream> GetMediaStreams();
|
||||
Guid Id { get; set; }
|
||||
long? RunTimeTicks { get; set; }
|
||||
string Path { get; }
|
||||
}
|
||||
}
|
17
MediaBrowser.Controller/Entities/IHasProgramAttributes.cs
Normal file
17
MediaBrowser.Controller/Entities/IHasProgramAttributes.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasProgramAttributes
|
||||
{
|
||||
bool IsMovie { get; set; }
|
||||
bool IsSports { get; }
|
||||
bool IsNews { get; }
|
||||
bool IsKids { get; }
|
||||
bool IsRepeat { get; set; }
|
||||
bool IsSeries { get; set; }
|
||||
ProgramAudio? Audio { get; set; }
|
||||
string EpisodeTitle { get; set; }
|
||||
string ServiceName { get; set; }
|
||||
}
|
||||
}
|
10
MediaBrowser.Controller/Entities/IHasScreenshots.cs
Normal file
10
MediaBrowser.Controller/Entities/IHasScreenshots.cs
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IHasScreenshots
|
||||
/// </summary>
|
||||
public interface IHasScreenshots
|
||||
{
|
||||
}
|
||||
}
|
20
MediaBrowser.Controller/Entities/IHasSeries.cs
Normal file
20
MediaBrowser.Controller/Entities/IHasSeries.cs
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the series.
|
||||
/// </summary>
|
||||
/// <value>The name of the series.</value>
|
||||
string SeriesName { get; set; }
|
||||
string FindSeriesName();
|
||||
string FindSeriesSortName();
|
||||
Guid SeriesId { get; set; }
|
||||
Guid FindSeriesId();
|
||||
string SeriesPresentationUniqueKey { get; set; }
|
||||
string FindSeriesPresentationUniqueKey();
|
||||
}
|
||||
}
|
13
MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs
Normal file
13
MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasSpecialFeatures
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the special feature ids.
|
||||
/// </summary>
|
||||
/// <value>The special feature ids.</value>
|
||||
Guid[] SpecialFeatureIds { get; set; }
|
||||
}
|
||||
}
|
9
MediaBrowser.Controller/Entities/IHasStartDate.cs
Normal file
9
MediaBrowser.Controller/Entities/IHasStartDate.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasStartDate
|
||||
{
|
||||
DateTime StartDate { get; set; }
|
||||
}
|
||||
}
|
39
MediaBrowser.Controller/Entities/IHasTrailers.cs
Normal file
39
MediaBrowser.Controller/Entities/IHasTrailers.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasTrailers : IHasProviderIds
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the remote trailers.
|
||||
/// </summary>
|
||||
/// <value>The remote trailers.</value>
|
||||
MediaUrl[] RemoteTrailers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the local trailer ids.
|
||||
/// </summary>
|
||||
/// <value>The local trailer ids.</value>
|
||||
Guid[] LocalTrailerIds { get; set; }
|
||||
Guid[] RemoteTrailerIds { get; set; }
|
||||
Guid Id { get; set; }
|
||||
}
|
||||
|
||||
public static class HasTrailerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the trailer ids.
|
||||
/// </summary>
|
||||
/// <returns>List<Guid>.</returns>
|
||||
public static List<Guid> GetTrailerIds(this IHasTrailers item)
|
||||
{
|
||||
var list = item.LocalTrailerIds.ToList();
|
||||
list.AddRange(item.RemoteTrailerIds);
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user