From 07791d46a571d3d6eed23e98ec0fe1c46ea0d37f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 23 Oct 2016 15:14:57 -0400 Subject: rework scheduled tasks in preparation of common project going portable --- MediaBrowser.Server.Implementations/Library/SearchEngine.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.Server.Implementations/Library/SearchEngine.cs') diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 40cca7bab..3dff16e24 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using MediaBrowser.Controller.Extensions; namespace MediaBrowser.Server.Implementations.Library { -- cgit v1.2.3 From 0f8ccfaf496c3c761c06285574048f8866ef692c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 23 Oct 2016 15:47:34 -0400 Subject: prep for portable common --- .../ScheduledTasks/ScheduledTaskService.cs | 1 - .../ScheduledTasksWebSocketListener.cs | 3 +- .../BaseApplicationHost.cs | 32 +++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 10 +-- .../ScheduledTasks/IScheduledTaskWorker.cs | 77 -------------------- MediaBrowser.Common/ScheduledTasks/ITaskManager.cs | 81 ---------------------- MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs | 36 ---------- .../ScheduledTasks/ScheduledTaskHelpers.cs | 53 -------------- .../ScheduledTasks/TaskCompletionEventArgs.cs | 12 ---- .../Entities/Audio/MusicArtist.cs | 1 + .../Entities/Audio/MusicGenre.cs | 1 + MediaBrowser.Controller/Entities/BaseItem.cs | 1 + MediaBrowser.Controller/Entities/GameGenre.cs | 1 + MediaBrowser.Controller/Entities/Genre.cs | 1 + MediaBrowser.Controller/Entities/Person.cs | 1 + MediaBrowser.Controller/Entities/Studio.cs | 1 + .../Extensions/BaseExtensions.cs | 25 ------- .../Extensions/StringExtensions.cs | 22 ++++++ .../MediaBrowser.Controller.csproj | 2 +- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 6 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- MediaBrowser.Model/Drawing/ImageSize.cs | 6 +- MediaBrowser.Model/Extensions/BoolHelper.cs | 16 ----- MediaBrowser.Model/Extensions/DoubleHelper.cs | 21 ------ MediaBrowser.Model/Extensions/FloatHelper.cs | 18 ----- MediaBrowser.Model/MediaBrowser.Model.csproj | 8 ++- MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs | 76 ++++++++++++++++++++ MediaBrowser.Model/Tasks/ITaskManager.cs | 80 +++++++++++++++++++++ MediaBrowser.Model/Tasks/ITaskTrigger.cs | 35 ++++++++++ MediaBrowser.Model/Tasks/ScheduledTaskHelpers.cs | 52 ++++++++++++++ .../Tasks/TaskCompletionEventArgs.cs | 11 +++ .../MediaInfo/SubtitleScheduledTask.cs | 1 - MediaBrowser.Providers/TV/SeriesPostScanTask.cs | 2 +- .../EntryPoints/ServerEventNotifier.cs | 1 + .../FileOrganization/FileOrganizationNotifier.cs | 1 + .../FileOrganization/FileOrganizationService.cs | 1 + .../IO/FileRefresher.cs | 1 + .../IO/LibraryMonitor.cs | 1 + .../Library/LibraryManager.cs | 1 + .../Library/SearchEngine.cs | 1 + .../LiveTv/LiveTvManager.cs | 1 + .../Persistence/SqliteItemRepository.cs | 1 + .../Sync/SyncManager.cs | 1 + .../Migrations/DbMigration.cs | 1 + 44 files changed, 332 insertions(+), 374 deletions(-) delete mode 100644 MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs delete mode 100644 MediaBrowser.Common/ScheduledTasks/ITaskManager.cs delete mode 100644 MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs delete mode 100644 MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs delete mode 100644 MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs delete mode 100644 MediaBrowser.Controller/Extensions/BaseExtensions.cs create mode 100644 MediaBrowser.Controller/Extensions/StringExtensions.cs delete mode 100644 MediaBrowser.Model/Extensions/BoolHelper.cs delete mode 100644 MediaBrowser.Model/Extensions/DoubleHelper.cs delete mode 100644 MediaBrowser.Model/Extensions/FloatHelper.cs create mode 100644 MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs create mode 100644 MediaBrowser.Model/Tasks/ITaskManager.cs create mode 100644 MediaBrowser.Model/Tasks/ITaskTrigger.cs create mode 100644 MediaBrowser.Model/Tasks/ScheduledTaskHelpers.cs create mode 100644 MediaBrowser.Model/Tasks/TaskCompletionEventArgs.cs (limited to 'MediaBrowser.Server.Implementations/Library/SearchEngine.cs') diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index 287b87f77..29b3988ad 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Tasks; using ServiceStack; diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs index 5d3465c58..6e64345b9 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Tasks; diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index b1e6a0453..baf6d85af 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -445,20 +445,28 @@ namespace MediaBrowser.Common.Implementations private IPlugin LoadPlugin(IPlugin plugin) { - var assemblyPlugin = plugin as IPluginAssembly; - - if (assemblyPlugin != null) + try { - var assembly = plugin.GetType().Assembly; - var assemblyName = assembly.GetName(); + var assemblyPlugin = plugin as IPluginAssembly; - var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0]; - var assemblyId = new Guid(attribute.Value); + if (assemblyPlugin != null) + { + var assembly = plugin.GetType().Assembly; + var assemblyName = assembly.GetName(); - var assemblyFileName = assemblyName.Name + ".dll"; - var assemblyFilePath = Path.Combine(ApplicationPaths.PluginsPath, assemblyFileName); + var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0]; + var assemblyId = new Guid(attribute.Value); - assemblyPlugin.SetAttributes(assemblyFilePath, assemblyFileName, assemblyName.Version, assemblyId); + var assemblyFileName = assemblyName.Name + ".dll"; + var assemblyFilePath = Path.Combine(ApplicationPaths.PluginsPath, assemblyFileName); + + assemblyPlugin.SetAttributes(assemblyFilePath, assemblyFileName, assemblyName.Version, assemblyId); + } + } + catch (Exception ex) + { + Logger.ErrorException("Error loading plugin {0}", ex, plugin.GetType().FullName); + return null; } return plugin; @@ -596,7 +604,7 @@ namespace MediaBrowser.Common.Implementations } catch (Exception ex) { - Logger.ErrorException("Error creating {0}", ex, type.Name); + Logger.ErrorException("Error creating {0}", ex, type.FullName); throw; } @@ -615,7 +623,7 @@ namespace MediaBrowser.Common.Implementations } catch (Exception ex) { - Logger.ErrorException("Error creating {0}", ex, type.Name); + Logger.ErrorException("Error creating {0}", ex, type.FullName); // Don't blow up in release mode return null; } diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 94ebf8dc9..931ac7227 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -1,5 +1,5 @@  - + Debug @@ -13,7 +13,8 @@ ..\ 10.0.0 2.0 - v4.5 + v4.6 + true @@ -67,13 +68,8 @@ - - - - - diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs deleted file mode 100644 index a3a28684d..000000000 --- a/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs +++ /dev/null @@ -1,77 +0,0 @@ -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Tasks; -using System; - -namespace MediaBrowser.Common.ScheduledTasks -{ - /// - /// Interface IScheduledTaskWorker - /// - public interface IScheduledTaskWorker : IDisposable - { - /// - /// Occurs when [task progress]. - /// - event EventHandler> TaskProgress; - - /// - /// Gets or sets the scheduled task. - /// - /// The scheduled task. - IScheduledTask ScheduledTask { get; } - - /// - /// Gets the last execution result. - /// - /// The last execution result. - TaskResult LastExecutionResult { get; } - - /// - /// Gets the name. - /// - /// The name. - string Name { get; } - - /// - /// Gets the description. - /// - /// The description. - string Description { get; } - - /// - /// Gets the category. - /// - /// The category. - string Category { get; } - - /// - /// Gets the state. - /// - /// The state. - TaskState State { get; } - - /// - /// Gets the current progress. - /// - /// The current progress. - double? CurrentProgress { get; } - - /// - /// Gets the triggers that define when the task will run - /// - /// The triggers. - /// value - TaskTriggerInfo[] Triggers { get; set; } - - /// - /// Gets the unique id. - /// - /// The unique id. - string Id { get; } - - /// - /// Reloads the trigger events. - /// - void ReloadTriggerEvents(); - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs deleted file mode 100644 index e557a6b2c..000000000 --- a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediaBrowser.Model.Events; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using MediaBrowser.Model.Tasks; - -namespace MediaBrowser.Common.ScheduledTasks -{ - public interface ITaskManager : IDisposable - { - /// - /// Gets the list of Scheduled Tasks - /// - /// The scheduled tasks. - IScheduledTaskWorker[] ScheduledTasks { get; } - - /// - /// Cancels if running and queue. - /// - /// - /// Task options. - void CancelIfRunningAndQueue(TaskExecutionOptions options) - where T : IScheduledTask; - - /// - /// Cancels if running and queue. - /// - /// - void CancelIfRunningAndQueue() - where T : IScheduledTask; - - /// - /// Cancels if running. - /// - /// - void CancelIfRunning() - where T : IScheduledTask; - - /// - /// Queues the scheduled task. - /// - /// - /// Task options. - void QueueScheduledTask(TaskExecutionOptions options) - where T : IScheduledTask; - - /// - /// Queues the scheduled task. - /// - /// - void QueueScheduledTask() - where T : IScheduledTask; - - void QueueIfNotRunning() - where T : IScheduledTask; - - /// - /// Queues the scheduled task. - /// - /// The task. - /// The task run options. - void QueueScheduledTask(IScheduledTask task, TaskExecutionOptions options = null); - - /// - /// Adds the tasks. - /// - /// The tasks. - void AddTasks(IEnumerable tasks); - - void Cancel(IScheduledTaskWorker task); - Task Execute(IScheduledTaskWorker task, TaskExecutionOptions options = null); - - void Execute() - where T : IScheduledTask; - - event EventHandler> TaskExecuting; - event EventHandler TaskCompleted; - - bool SuspendTriggers { get; set; } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs b/MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs deleted file mode 100644 index d6ca63ad7..000000000 --- a/MediaBrowser.Common/ScheduledTasks/ITaskTrigger.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Tasks; -using System; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Common.ScheduledTasks -{ - /// - /// Interface ITaskTrigger - /// - public interface ITaskTrigger - { - /// - /// Fires when the trigger condition is satisfied and the task should run - /// - event EventHandler> Triggered; - - /// - /// Stars waiting for the trigger action - /// - void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup); - - /// - /// Stops waiting for the trigger action - /// - void Stop(); - - /// - /// Gets or sets the execution properties of this task. - /// - /// - /// The execution properties of this task. - /// - TaskExecutionOptions TaskOptions { get; set; } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs deleted file mode 100644 index fe45f1621..000000000 --- a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediaBrowser.Model.Tasks; -using System; -using System.Linq; - -namespace MediaBrowser.Common.ScheduledTasks -{ - /// - /// Class ScheduledTaskHelpers - /// - public static class ScheduledTaskHelpers - { - /// - /// Gets the task info. - /// - /// The task. - /// TaskInfo. - public static TaskInfo GetTaskInfo(IScheduledTaskWorker task) - { - var isHidden = false; - - var configurableTask = task.ScheduledTask as IConfigurableScheduledTask; - - if (configurableTask != null) - { - isHidden = configurableTask.IsHidden; - } - - string key = task.ScheduledTask.Key; - - var triggers = task.Triggers - .OrderBy(i => i.Type) - .ThenBy(i => i.DayOfWeek ?? DayOfWeek.Sunday) - .ThenBy(i => i.TimeOfDayTicks ?? 0) - .ToList(); - - return new TaskInfo - { - Name = task.Name, - CurrentProgressPercentage = task.CurrentProgress, - State = task.State, - Id = task.Id, - LastExecutionResult = task.LastExecutionResult, - - Triggers = triggers, - - Description = task.Description, - Category = task.Category, - IsHidden = isHidden, - Key = key - }; - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs b/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs deleted file mode 100644 index 2974806d0..000000000 --- a/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MediaBrowser.Model.Tasks; -using System; - -namespace MediaBrowser.Common.ScheduledTasks -{ - public class TaskCompletionEventArgs : EventArgs - { - public IScheduledTaskWorker Task { get; set; } - - public TaskResult Result { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 07cf43c5b..4fdd809e0 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities.Audio { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index a111166ac..cb17ea265 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Runtime.Serialization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities.Audio { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9aad91a28..4836aca8b 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -26,6 +26,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Providers; diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 2987a9a07..545bef44c 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Runtime.Serialization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index cde9c6ce4..6fefdfa55 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index d7acdb65e..6f7a32a66 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -6,6 +6,7 @@ using System.Runtime.Serialization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 773250ad9..114c14155 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Runtime.Serialization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { diff --git a/MediaBrowser.Controller/Extensions/BaseExtensions.cs b/MediaBrowser.Controller/Extensions/BaseExtensions.cs deleted file mode 100644 index 84a9b1524..000000000 --- a/MediaBrowser.Controller/Extensions/BaseExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Text; -using MediaBrowser.Model.Cryptography; - -namespace MediaBrowser.Controller.Extensions -{ - /// - /// Class BaseExtensions - /// - public static class BaseExtensions - { - public static ICryptographyProvider CryptographyProvider { get; set; } - - public static string RemoveDiacritics(this string text) - { - return String.Concat( - text.Normalize(NormalizationForm.FormD) - .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != - UnicodeCategory.NonSpacingMark) - ).Normalize(NormalizationForm.FormC); - } - } -} diff --git a/MediaBrowser.Controller/Extensions/StringExtensions.cs b/MediaBrowser.Controller/Extensions/StringExtensions.cs new file mode 100644 index 000000000..4f58d1bc5 --- /dev/null +++ b/MediaBrowser.Controller/Extensions/StringExtensions.cs @@ -0,0 +1,22 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Text; + +namespace MediaBrowser.Controller.Extensions +{ + /// + /// Class BaseExtensions + /// + public static class StringExtensions + { + public static string RemoveDiacritics(this string text) + { + return String.Concat( + text.Normalize(NormalizationForm.FormD) + .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != + UnicodeCategory.NonSpacingMark) + ).Normalize(NormalizationForm.FormC); + } + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 46277a783..670b08a3f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -165,7 +165,7 @@ - + diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index 6628e290e..1fbb4ffa1 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -171,7 +171,7 @@ namespace MediaBrowser.Model.Dlna } bool expected; - if (BoolHelper.TryParseCultureInvariant(condition.Value, out expected)) + if (bool.TryParse(condition.Value, out expected)) { switch (condition.Condition) { @@ -196,7 +196,7 @@ namespace MediaBrowser.Model.Dlna } float expected; - if (FloatHelper.TryParseCultureInvariant(condition.Value, out expected)) + if (float.TryParse(condition.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out expected)) { switch (condition.Condition) { @@ -225,7 +225,7 @@ namespace MediaBrowser.Model.Dlna } double expected; - if (DoubleHelper.TryParseCultureInvariant(condition.Value, out expected)) + if (double.TryParse(condition.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out expected)) { switch (condition.Condition) { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a3e447d04..06a883c06 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1111,7 +1111,7 @@ namespace MediaBrowser.Model.Dlna case ProfileConditionValue.VideoFramerate: { float num; - if (FloatHelper.TryParseCultureInvariant(value, out num)) + if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { item.MaxFramerate = num; } diff --git a/MediaBrowser.Model/Drawing/ImageSize.cs b/MediaBrowser.Model/Drawing/ImageSize.cs index 5ed6e7293..8cf09da18 100644 --- a/MediaBrowser.Model/Drawing/ImageSize.cs +++ b/MediaBrowser.Model/Drawing/ImageSize.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Model.Extensions; +using System.Globalization; namespace MediaBrowser.Model.Drawing { @@ -71,12 +71,12 @@ namespace MediaBrowser.Model.Drawing { double val; - if (DoubleHelper.TryParseCultureInvariant(parts[0], out val)) + if (double.TryParse(parts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out val)) { _width = val; } - if (DoubleHelper.TryParseCultureInvariant(parts[1], out val)) + if (double.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out val)) { _height = val; } diff --git a/MediaBrowser.Model/Extensions/BoolHelper.cs b/MediaBrowser.Model/Extensions/BoolHelper.cs deleted file mode 100644 index 5b61f864b..000000000 --- a/MediaBrowser.Model/Extensions/BoolHelper.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace MediaBrowser.Model.Extensions -{ - public static class BoolHelper - { - /// - /// Tries the parse culture invariant. - /// - /// The s. - /// The result. - /// true if XXXX, false otherwise. - public static bool TryParseCultureInvariant(string s, out bool result) - { - return bool.TryParse(s, out result); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/Extensions/DoubleHelper.cs b/MediaBrowser.Model/Extensions/DoubleHelper.cs deleted file mode 100644 index bcaf2d780..000000000 --- a/MediaBrowser.Model/Extensions/DoubleHelper.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Globalization; - -namespace MediaBrowser.Model.Extensions -{ - /// - /// Isolating these helpers allow this entire project to be easily converted to Java - /// - public static class DoubleHelper - { - /// - /// Tries the parse culture invariant. - /// - /// The s. - /// The result. - /// true if XXXX, false otherwise. - public static bool TryParseCultureInvariant(string s, out double result) - { - return double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out result); - } - } -} diff --git a/MediaBrowser.Model/Extensions/FloatHelper.cs b/MediaBrowser.Model/Extensions/FloatHelper.cs deleted file mode 100644 index 171eccf93..000000000 --- a/MediaBrowser.Model/Extensions/FloatHelper.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Globalization; - -namespace MediaBrowser.Model.Extensions -{ - public static class FloatHelper - { - /// - /// Tries the parse culture invariant. - /// - /// The s. - /// The result. - /// true if XXXX, false otherwise. - public static bool TryParseCultureInvariant(string s, out float result) - { - return float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out result); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index e5aac6c06..c0ff5464e 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -144,8 +144,6 @@ - - @@ -218,7 +216,6 @@ - @@ -389,6 +386,11 @@ + + + + + diff --git a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs new file mode 100644 index 000000000..415207f8f --- /dev/null +++ b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs @@ -0,0 +1,76 @@ +using System; +using MediaBrowser.Model.Events; + +namespace MediaBrowser.Model.Tasks +{ + /// + /// Interface IScheduledTaskWorker + /// + public interface IScheduledTaskWorker : IDisposable + { + /// + /// Occurs when [task progress]. + /// + event EventHandler> TaskProgress; + + /// + /// Gets or sets the scheduled task. + /// + /// The scheduled task. + IScheduledTask ScheduledTask { get; } + + /// + /// Gets the last execution result. + /// + /// The last execution result. + TaskResult LastExecutionResult { get; } + + /// + /// Gets the name. + /// + /// The name. + string Name { get; } + + /// + /// Gets the description. + /// + /// The description. + string Description { get; } + + /// + /// Gets the category. + /// + /// The category. + string Category { get; } + + /// + /// Gets the state. + /// + /// The state. + TaskState State { get; } + + /// + /// Gets the current progress. + /// + /// The current progress. + double? CurrentProgress { get; } + + /// + /// Gets the triggers that define when the task will run + /// + /// The triggers. + /// value + TaskTriggerInfo[] Triggers { get; set; } + + /// + /// Gets the unique id. + /// + /// The unique id. + string Id { get; } + + /// + /// Reloads the trigger events. + /// + void ReloadTriggerEvents(); + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs new file mode 100644 index 000000000..b6f847feb --- /dev/null +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using MediaBrowser.Model.Events; + +namespace MediaBrowser.Model.Tasks +{ + public interface ITaskManager : IDisposable + { + /// + /// Gets the list of Scheduled Tasks + /// + /// The scheduled tasks. + IScheduledTaskWorker[] ScheduledTasks { get; } + + /// + /// Cancels if running and queue. + /// + /// + /// Task options. + void CancelIfRunningAndQueue(TaskExecutionOptions options) + where T : IScheduledTask; + + /// + /// Cancels if running and queue. + /// + /// + void CancelIfRunningAndQueue() + where T : IScheduledTask; + + /// + /// Cancels if running. + /// + /// + void CancelIfRunning() + where T : IScheduledTask; + + /// + /// Queues the scheduled task. + /// + /// + /// Task options. + void QueueScheduledTask(TaskExecutionOptions options) + where T : IScheduledTask; + + /// + /// Queues the scheduled task. + /// + /// + void QueueScheduledTask() + where T : IScheduledTask; + + void QueueIfNotRunning() + where T : IScheduledTask; + + /// + /// Queues the scheduled task. + /// + /// The task. + /// The task run options. + void QueueScheduledTask(IScheduledTask task, TaskExecutionOptions options = null); + + /// + /// Adds the tasks. + /// + /// The tasks. + void AddTasks(IEnumerable tasks); + + void Cancel(IScheduledTaskWorker task); + Task Execute(IScheduledTaskWorker task, TaskExecutionOptions options = null); + + void Execute() + where T : IScheduledTask; + + event EventHandler> TaskExecuting; + event EventHandler TaskCompleted; + + bool SuspendTriggers { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Tasks/ITaskTrigger.cs b/MediaBrowser.Model/Tasks/ITaskTrigger.cs new file mode 100644 index 000000000..3beca569c --- /dev/null +++ b/MediaBrowser.Model/Tasks/ITaskTrigger.cs @@ -0,0 +1,35 @@ +using System; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.Model.Tasks +{ + /// + /// Interface ITaskTrigger + /// + public interface ITaskTrigger + { + /// + /// Fires when the trigger condition is satisfied and the task should run + /// + event EventHandler> Triggered; + + /// + /// Stars waiting for the trigger action + /// + void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup); + + /// + /// Stops waiting for the trigger action + /// + void Stop(); + + /// + /// Gets or sets the execution properties of this task. + /// + /// + /// The execution properties of this task. + /// + TaskExecutionOptions TaskOptions { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Tasks/ScheduledTaskHelpers.cs b/MediaBrowser.Model/Tasks/ScheduledTaskHelpers.cs new file mode 100644 index 000000000..66f5294e7 --- /dev/null +++ b/MediaBrowser.Model/Tasks/ScheduledTaskHelpers.cs @@ -0,0 +1,52 @@ +using System; +using System.Linq; + +namespace MediaBrowser.Model.Tasks +{ + /// + /// Class ScheduledTaskHelpers + /// + public static class ScheduledTaskHelpers + { + /// + /// Gets the task info. + /// + /// The task. + /// TaskInfo. + public static TaskInfo GetTaskInfo(IScheduledTaskWorker task) + { + var isHidden = false; + + var configurableTask = task.ScheduledTask as IConfigurableScheduledTask; + + if (configurableTask != null) + { + isHidden = configurableTask.IsHidden; + } + + string key = task.ScheduledTask.Key; + + var triggers = task.Triggers + .OrderBy(i => i.Type) + .ThenBy(i => i.DayOfWeek ?? DayOfWeek.Sunday) + .ThenBy(i => i.TimeOfDayTicks ?? 0) + .ToList(); + + return new TaskInfo + { + Name = task.Name, + CurrentProgressPercentage = task.CurrentProgress, + State = task.State, + Id = task.Id, + LastExecutionResult = task.LastExecutionResult, + + Triggers = triggers, + + Description = task.Description, + Category = task.Category, + IsHidden = isHidden, + Key = key + }; + } + } +} diff --git a/MediaBrowser.Model/Tasks/TaskCompletionEventArgs.cs b/MediaBrowser.Model/Tasks/TaskCompletionEventArgs.cs new file mode 100644 index 000000000..be9eaa613 --- /dev/null +++ b/MediaBrowser.Model/Tasks/TaskCompletionEventArgs.cs @@ -0,0 +1,11 @@ +using System; + +namespace MediaBrowser.Model.Tasks +{ + public class TaskCompletionEventArgs : EventArgs + { + public IScheduledTaskWorker Task { get; set; } + + public TaskResult Result { get; set; } + } +} diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index f05bf3ab8..eaaab22fd 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index e038a3d28..fdea1b205 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -11,9 +11,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; -using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Providers.TV { diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 3ea8417f8..9fafc561f 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -13,6 +13,7 @@ using MediaBrowser.Model.Sync; using System; using System.Collections.Generic; using System.Threading; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs index 5c3814f66..940730b3b 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs @@ -7,6 +7,7 @@ using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Logging; using System; using System.Threading; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Server.Implementations.FileOrganization { diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index a42eba6ca..9aa49946d 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -18,6 +18,7 @@ using CommonIO; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Events; using MediaBrowser.Common.Events; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Server.Implementations.FileOrganization { diff --git a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs b/MediaBrowser.Server.Implementations/IO/FileRefresher.cs index e689514c5..1c9a05753 100644 --- a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs +++ b/MediaBrowser.Server.Implementations/IO/FileRefresher.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Tasks; using MediaBrowser.Server.Implementations.ScheduledTasks; namespace MediaBrowser.Server.Implementations.IO diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 76f0e6a1d..36d912038 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -14,6 +14,7 @@ using System.Linq; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Controller; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Server.Implementations.IO { diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 6ccfa13ec..cf175f861 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -43,6 +43,7 @@ using MediaBrowser.Server.Implementations.Library.Resolvers; using SortOrder = MediaBrowser.Model.Entities.SortOrder; using VideoResolver = MediaBrowser.Naming.Video.VideoResolver; using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Server.Implementations.Library { diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 3dff16e24..c266fb191 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Server.Implementations.Library { diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 7c75abeec..3f8eb9025 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -35,6 +35,7 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Events; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Tasks; using MediaBrowser.Server.Implementations.LiveTv.Listings; namespace MediaBrowser.Server.Implementations.LiveTv diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index c76cbf8ae..e6512f4df 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -26,6 +26,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Server.Implementations.Devices; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index eaf129e63..6bdb1692e 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -31,6 +31,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.IO; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Server.Implementations.Sync { diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs index 6bcdcca87..5705b3a59 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.Tasks; using MediaBrowser.Server.Implementations.Persistence; namespace MediaBrowser.Server.Startup.Common.Migrations -- cgit v1.2.3 From 3eb4091808735858b01855d298226d239be464af Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Nov 2016 02:37:52 -0400 Subject: move additional classes to new server lib --- .../Activity/ActivityManager.cs | 56 + Emby.Server.Implementations/Dto/DtoService.cs | 1609 ++++++++++ .../Emby.Server.Implementations.csproj | 99 +- .../FileOrganization/EpisodeFileOrganizer.cs | 834 ++++++ .../FileOrganization/Extensions.cs | 33 + .../FileOrganization/FileOrganizationNotifier.cs | 80 + .../FileOrganization/FileOrganizationService.cs | 283 ++ .../FileOrganization/NameUtils.cs | 81 + .../FileOrganization/OrganizerScheduledTask.cs | 101 + .../FileOrganization/TvFolderOrganizer.cs | 210 ++ .../Library/CoreResolutionIgnoreRule.cs | 148 + .../Library/LibraryManager.cs | 3066 +++++++++++++++++++ .../Library/LocalTrailerPostScanTask.cs | 102 + .../Library/MediaSourceManager.cs | 651 +++++ .../Library/MusicManager.cs | 157 + .../Library/PathExtensions.cs | 45 + .../Library/ResolverHelper.cs | 183 ++ .../Library/Resolvers/Audio/AudioResolver.cs | 68 + .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 173 ++ .../Library/Resolvers/Audio/MusicArtistResolver.cs | 94 + .../Library/Resolvers/BaseVideoResolver.cs | 297 ++ .../Library/Resolvers/FolderResolver.cs | 56 + .../Library/Resolvers/ItemResolver.cs | 62 + .../Library/Resolvers/Movies/BoxSetResolver.cs | 77 + .../Library/Resolvers/Movies/MovieResolver.cs | 541 ++++ .../Library/Resolvers/PhotoAlbumResolver.cs | 56 + .../Library/Resolvers/PhotoResolver.cs | 103 + .../Library/Resolvers/PlaylistResolver.cs | 42 + .../Library/Resolvers/SpecialFolderResolver.cs | 85 + .../Library/Resolvers/TV/EpisodeResolver.cs | 75 + .../Library/Resolvers/TV/SeasonResolver.cs | 62 + .../Library/Resolvers/TV/SeriesResolver.cs | 251 ++ .../Library/Resolvers/VideoResolver.cs | 45 + .../Library/SearchEngine.cs | 275 ++ .../Library/UserViewManager.cs | 292 ++ .../Library/Validators/ArtistsPostScanTask.cs | 44 + .../Library/Validators/ArtistsValidator.cs | 84 + .../Library/Validators/GameGenresPostScanTask.cs | 45 + .../Library/Validators/GameGenresValidator.cs | 74 + .../Library/Validators/GenresPostScanTask.cs | 42 + .../Library/Validators/GenresValidator.cs | 75 + .../Library/Validators/MusicGenresPostScanTask.cs | 45 + .../Library/Validators/MusicGenresValidator.cs | 75 + .../Library/Validators/PeopleValidator.cs | 172 ++ .../Library/Validators/StudiosPostScanTask.cs | 45 + .../Library/Validators/StudiosValidator.cs | 74 + .../Library/Validators/YearsPostScanTask.cs | 55 + .../Logging/PatternsLogger.cs | 63 + .../Persistence/CleanDatabaseScheduledTask.cs | 361 +++ .../ScheduledTasks/RefreshMediaLibraryTask.cs | 96 + .../Sorting/AirTimeComparer.cs | 71 + .../Sorting/AiredEpisodeOrderComparer.cs | 160 + .../Sorting/AlbumArtistComparer.cs | 47 + .../Sorting/AlbumComparer.cs | 46 + .../Sorting/AlphanumComparator.cs | 99 + .../Sorting/ArtistComparer.cs | 51 + .../Sorting/BudgetComparer.cs | 39 + .../Sorting/CommunityRatingComparer.cs | 29 + .../Sorting/CriticRatingComparer.cs | 37 + .../Sorting/DateCreatedComparer.cs | 33 + .../Sorting/DateLastMediaAddedComparer.cs | 69 + .../Sorting/DatePlayedComparer.cs | 69 + .../Sorting/GameSystemComparer.cs | 54 + .../Sorting/IsFavoriteOrLikeComparer.cs | 58 + .../Sorting/IsFolderComparer.cs | 39 + .../Sorting/IsPlayedComparer.cs | 58 + .../Sorting/IsUnplayedComparer.cs | 58 + .../Sorting/MetascoreComparer.cs | 41 + .../Sorting/NameComparer.cs | 33 + .../Sorting/OfficialRatingComparer.cs | 40 + .../Sorting/PlayCountComparer.cs | 63 + .../Sorting/PlayersComparer.cs | 46 + .../Sorting/PremiereDateComparer.cs | 59 + .../Sorting/ProductionYearComparer.cs | 52 + .../Sorting/RandomComparer.cs | 33 + .../Sorting/RevenueComparer.cs | 39 + .../Sorting/RuntimeComparer.cs | 32 + .../Sorting/SeriesSortNameComparer.cs | 37 + .../Sorting/SortNameComparer.cs | 33 + .../Sorting/StartDateComparer.cs | 47 + .../Sorting/StudioComparer.cs | 30 + Emby.Server.Implementations/packages.config | 5 + .../Activity/ActivityManager.cs | 56 - .../Dto/DtoService.cs | 1609 ---------- .../FileOrganization/EpisodeFileOrganizer.cs | 831 ------ .../FileOrganization/Extensions.cs | 33 - .../FileOrganization/FileOrganizationNotifier.cs | 80 - .../FileOrganization/FileOrganizationService.cs | 283 -- .../FileOrganization/NameUtils.cs | 96 - .../FileOrganization/OrganizerScheduledTask.cs | 101 - .../FileOrganization/TvFolderOrganizer.cs | 210 -- .../IO/FileRefresher.cs | 22 +- .../IO/LibraryMonitor.cs | 9 +- .../Library/CoreResolutionIgnoreRule.cs | 148 - .../Library/LibraryManager.cs | 3067 -------------------- .../Library/LocalTrailerPostScanTask.cs | 102 - .../Library/MediaSourceManager.cs | 648 ----- .../Library/MusicManager.cs | 157 - .../Library/PathExtensions.cs | 45 - .../Library/ResolverHelper.cs | 183 -- .../Library/Resolvers/Audio/AudioResolver.cs | 68 - .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 173 -- .../Library/Resolvers/Audio/MusicArtistResolver.cs | 94 - .../Library/Resolvers/BaseVideoResolver.cs | 297 -- .../Library/Resolvers/FolderResolver.cs | 56 - .../Library/Resolvers/ItemResolver.cs | 62 - .../Library/Resolvers/Movies/BoxSetResolver.cs | 77 - .../Library/Resolvers/Movies/MovieResolver.cs | 541 ---- .../Library/Resolvers/PhotoAlbumResolver.cs | 56 - .../Library/Resolvers/PhotoResolver.cs | 103 - .../Library/Resolvers/PlaylistResolver.cs | 42 - .../Library/Resolvers/SpecialFolderResolver.cs | 85 - .../Library/Resolvers/TV/EpisodeResolver.cs | 75 - .../Library/Resolvers/TV/SeasonResolver.cs | 62 - .../Library/Resolvers/TV/SeriesResolver.cs | 251 -- .../Library/Resolvers/VideoResolver.cs | 45 - .../Library/SearchEngine.cs | 280 -- .../Library/UserViewManager.cs | 292 -- .../Library/Validators/ArtistsPostScanTask.cs | 44 - .../Library/Validators/ArtistsValidator.cs | 84 - .../Library/Validators/GameGenresPostScanTask.cs | 45 - .../Library/Validators/GameGenresValidator.cs | 74 - .../Library/Validators/GenresPostScanTask.cs | 42 - .../Library/Validators/GenresValidator.cs | 75 - .../Library/Validators/MusicGenresPostScanTask.cs | 45 - .../Library/Validators/MusicGenresValidator.cs | 75 - .../Library/Validators/PeopleValidator.cs | 172 -- .../Library/Validators/StudiosPostScanTask.cs | 45 - .../Library/Validators/StudiosValidator.cs | 74 - .../Library/Validators/YearsPostScanTask.cs | 55 - .../LiveTv/EmbyTV/EmbyTV.cs | 45 +- .../MediaBrowser.Server.Implementations.csproj | 79 - .../Persistence/CleanDatabaseScheduledTask.cs | 360 --- .../ScheduledTasks/RefreshMediaLibraryTask.cs | 96 - .../Sorting/AirTimeComparer.cs | 71 - .../Sorting/AiredEpisodeOrderComparer.cs | 160 - .../Sorting/AlbumArtistComparer.cs | 47 - .../Sorting/AlbumComparer.cs | 46 - .../Sorting/AlphanumComparator.cs | 99 - .../Sorting/ArtistComparer.cs | 51 - .../Sorting/BudgetComparer.cs | 39 - .../Sorting/CommunityRatingComparer.cs | 29 - .../Sorting/CriticRatingComparer.cs | 37 - .../Sorting/DateCreatedComparer.cs | 33 - .../Sorting/DateLastMediaAddedComparer.cs | 69 - .../Sorting/DatePlayedComparer.cs | 69 - .../Sorting/GameSystemComparer.cs | 54 - .../Sorting/IsFavoriteOrLikeComparer.cs | 58 - .../Sorting/IsFolderComparer.cs | 39 - .../Sorting/IsPlayedComparer.cs | 58 - .../Sorting/IsUnplayedComparer.cs | 58 - .../Sorting/MetascoreComparer.cs | 41 - .../Sorting/NameComparer.cs | 33 - .../Sorting/OfficialRatingComparer.cs | 40 - .../Sorting/PlayCountComparer.cs | 63 - .../Sorting/PlayersComparer.cs | 46 - .../Sorting/PremiereDateComparer.cs | 59 - .../Sorting/ProductionYearComparer.cs | 52 - .../Sorting/RandomComparer.cs | 33 - .../Sorting/RevenueComparer.cs | 39 - .../Sorting/RuntimeComparer.cs | 32 - .../Sorting/SeriesSortNameComparer.cs | 37 - .../Sorting/SortNameComparer.cs | 33 - .../Sorting/StartDateComparer.cs | 47 - .../Sorting/StudioComparer.cs | 30 - .../ApplicationHost.cs | 11 +- .../Migrations/DbMigration.cs | 1 + 167 files changed, 13394 insertions(+), 13318 deletions(-) create mode 100644 Emby.Server.Implementations/Activity/ActivityManager.cs create mode 100644 Emby.Server.Implementations/Dto/DtoService.cs create mode 100644 Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs create mode 100644 Emby.Server.Implementations/FileOrganization/Extensions.cs create mode 100644 Emby.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs create mode 100644 Emby.Server.Implementations/FileOrganization/FileOrganizationService.cs create mode 100644 Emby.Server.Implementations/FileOrganization/NameUtils.cs create mode 100644 Emby.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs create mode 100644 Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs create mode 100644 Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs create mode 100644 Emby.Server.Implementations/Library/LibraryManager.cs create mode 100644 Emby.Server.Implementations/Library/LocalTrailerPostScanTask.cs create mode 100644 Emby.Server.Implementations/Library/MediaSourceManager.cs create mode 100644 Emby.Server.Implementations/Library/MusicManager.cs create mode 100644 Emby.Server.Implementations/Library/PathExtensions.cs create mode 100644 Emby.Server.Implementations/Library/ResolverHelper.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs create mode 100644 Emby.Server.Implementations/Library/SearchEngine.cs create mode 100644 Emby.Server.Implementations/Library/UserViewManager.cs create mode 100644 Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs create mode 100644 Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs create mode 100644 Emby.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs create mode 100644 Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs create mode 100644 Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs create mode 100644 Emby.Server.Implementations/Library/Validators/GenresValidator.cs create mode 100644 Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs create mode 100644 Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs create mode 100644 Emby.Server.Implementations/Library/Validators/PeopleValidator.cs create mode 100644 Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs create mode 100644 Emby.Server.Implementations/Library/Validators/StudiosValidator.cs create mode 100644 Emby.Server.Implementations/Library/Validators/YearsPostScanTask.cs create mode 100644 Emby.Server.Implementations/Logging/PatternsLogger.cs create mode 100644 Emby.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs create mode 100644 Emby.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs create mode 100644 Emby.Server.Implementations/Sorting/AirTimeComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/AlbumComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/AlphanumComparator.cs create mode 100644 Emby.Server.Implementations/Sorting/ArtistComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/BudgetComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/CriticRatingComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/DateCreatedComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/DatePlayedComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/GameSystemComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/IsFolderComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/IsPlayedComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/MetascoreComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/NameComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/PlayCountComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/PlayersComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/PremiereDateComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/ProductionYearComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/RandomComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/RevenueComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/RuntimeComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/SortNameComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/StartDateComparer.cs create mode 100644 Emby.Server.Implementations/Sorting/StudioComparer.cs create mode 100644 Emby.Server.Implementations/packages.config delete mode 100644 MediaBrowser.Server.Implementations/Activity/ActivityManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Dto/DtoService.cs delete mode 100644 MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs delete mode 100644 MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs delete mode 100644 MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs delete mode 100644 MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs delete mode 100644 MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs delete mode 100644 MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs delete mode 100644 MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/LibraryManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/MusicManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/PathExtensions.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/ResolverHelper.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/ItemResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/SearchEngine.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/UserViewManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs delete mode 100644 MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs delete mode 100644 MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/AlbumArtistComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/AlbumComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/AlphanumComparator.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/BudgetComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/CommunityRatingComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/DateCreatedComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/GameSystemComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/IsFolderComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/MetascoreComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/NameComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/OfficialRatingComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/PlayersComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/PremiereDateComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/ProductionYearComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/RandomComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/RevenueComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/RuntimeComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs delete mode 100644 MediaBrowser.Server.Implementations/Sorting/StudioComparer.cs (limited to 'MediaBrowser.Server.Implementations/Library/SearchEngine.cs') diff --git a/Emby.Server.Implementations/Activity/ActivityManager.cs b/Emby.Server.Implementations/Activity/ActivityManager.cs new file mode 100644 index 000000000..b6095f082 --- /dev/null +++ b/Emby.Server.Implementations/Activity/ActivityManager.cs @@ -0,0 +1,56 @@ +using MediaBrowser.Common.Events; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Querying; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace Emby.Server.Implementations.Activity +{ + public class ActivityManager : IActivityManager + { + public event EventHandler> EntryCreated; + + private readonly IActivityRepository _repo; + private readonly ILogger _logger; + private readonly IUserManager _userManager; + + public ActivityManager(ILogger logger, IActivityRepository repo, IUserManager userManager) + { + _logger = logger; + _repo = repo; + _userManager = userManager; + } + + public async Task Create(ActivityLogEntry entry) + { + entry.Id = Guid.NewGuid().ToString("N"); + entry.Date = DateTime.UtcNow; + + await _repo.Create(entry).ConfigureAwait(false); + + EventHelper.FireEventIfNotNull(EntryCreated, this, new GenericEventArgs(entry), _logger); + } + + public QueryResult GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit) + { + var result = _repo.GetActivityLogEntries(minDate, startIndex, limit); + + foreach (var item in result.Items.Where(i => !string.IsNullOrWhiteSpace(i.UserId))) + { + var user = _userManager.GetUserById(item.UserId); + + if (user != null) + { + var dto = _userManager.GetUserDto(user); + item.UserPrimaryImageTag = dto.PrimaryImageTag; + } + } + + return result; + } + } +} diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs new file mode 100644 index 000000000..85549439b --- /dev/null +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -0,0 +1,1609 @@ +using MediaBrowser.Common; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Devices; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Sync; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Extensions; + +namespace Emby.Server.Implementations.Dto +{ + public class DtoService : IDtoService + { + private readonly ILogger _logger; + private readonly ILibraryManager _libraryManager; + private readonly IUserDataManager _userDataRepository; + private readonly IItemRepository _itemRepo; + + private readonly IImageProcessor _imageProcessor; + private readonly IServerConfigurationManager _config; + private readonly IFileSystem _fileSystem; + private readonly IProviderManager _providerManager; + + private readonly Func _channelManagerFactory; + private readonly ISyncManager _syncManager; + private readonly IApplicationHost _appHost; + private readonly Func _deviceManager; + private readonly Func _mediaSourceManager; + private readonly Func _livetvManager; + + public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func channelManagerFactory, ISyncManager syncManager, IApplicationHost appHost, Func deviceManager, Func mediaSourceManager, Func livetvManager) + { + _logger = logger; + _libraryManager = libraryManager; + _userDataRepository = userDataRepository; + _itemRepo = itemRepo; + _imageProcessor = imageProcessor; + _config = config; + _fileSystem = fileSystem; + _providerManager = providerManager; + _channelManagerFactory = channelManagerFactory; + _syncManager = syncManager; + _appHost = appHost; + _deviceManager = deviceManager; + _mediaSourceManager = mediaSourceManager; + _livetvManager = livetvManager; + } + + /// + /// Converts a BaseItem to a DTOBaseItem + /// + /// The item. + /// The fields. + /// The user. + /// The owner. + /// Task{DtoBaseItem}. + /// item + public BaseItemDto GetBaseItemDto(BaseItem item, List fields, User user = null, BaseItem owner = null) + { + var options = new DtoOptions + { + Fields = fields + }; + + return GetBaseItemDto(item, options, user, owner); + } + + public async Task> GetBaseItemDtos(IEnumerable items, DtoOptions options, User user = null, BaseItem owner = null) + { + if (items == null) + { + throw new ArgumentNullException("items"); + } + + if (options == null) + { + throw new ArgumentNullException("options"); + } + + var syncDictionary = GetSyncedItemProgress(options); + + var list = new List(); + var programTuples = new List>(); + var channelTuples = new List>(); + + foreach (var item in items) + { + var dto = await GetBaseItemDtoInternal(item, options, user, owner).ConfigureAwait(false); + + var tvChannel = item as LiveTvChannel; + if (tvChannel != null) + { + channelTuples.Add(new Tuple(dto, tvChannel)); + } + else if (item is LiveTvProgram) + { + programTuples.Add(new Tuple(item, dto)); + } + + var byName = item as IItemByName; + + if (byName != null) + { + if (options.Fields.Contains(ItemFields.ItemCounts)) + { + var libraryItems = byName.GetTaggedItems(new InternalItemsQuery(user) + { + Recursive = true + }); + + SetItemByNameInfo(item, dto, libraryItems.ToList(), user); + } + } + + FillSyncInfo(dto, item, options, user, syncDictionary); + + list.Add(dto); + } + + if (programTuples.Count > 0) + { + await _livetvManager().AddInfoToProgramDto(programTuples, options.Fields, user).ConfigureAwait(false); + } + + if (channelTuples.Count > 0) + { + _livetvManager().AddChannelInfo(channelTuples, options, user); + } + + return list; + } + + public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) + { + var syncDictionary = GetSyncedItemProgress(options); + + var dto = GetBaseItemDtoInternal(item, options, user, owner).Result; + var tvChannel = item as LiveTvChannel; + if (tvChannel != null) + { + var list = new List> { new Tuple(dto, tvChannel) }; + _livetvManager().AddChannelInfo(list, options, user); + } + else if (item is LiveTvProgram) + { + var list = new List> { new Tuple(item, dto) }; + var task = _livetvManager().AddInfoToProgramDto(list, options.Fields, user); + Task.WaitAll(task); + } + + var byName = item as IItemByName; + + if (byName != null) + { + if (options.Fields.Contains(ItemFields.ItemCounts)) + { + SetItemByNameInfo(item, dto, GetTaggedItems(byName, user), user); + } + + FillSyncInfo(dto, item, options, user, syncDictionary); + return dto; + } + + FillSyncInfo(dto, item, options, user, syncDictionary); + + return dto; + } + + private List GetTaggedItems(IItemByName byName, User user) + { + var items = byName.GetTaggedItems(new InternalItemsQuery(user) + { + Recursive = true + + }).ToList(); + + return items; + } + + public Dictionary GetSyncedItemProgress(DtoOptions options) + { + if (!options.Fields.Contains(ItemFields.BasicSyncInfo) && + !options.Fields.Contains(ItemFields.SyncInfo)) + { + return new Dictionary(); + } + + var deviceId = options.DeviceId; + if (string.IsNullOrWhiteSpace(deviceId)) + { + return new Dictionary(); + } + + var caps = _deviceManager().GetCapabilities(deviceId); + if (caps == null || !caps.SupportsSync) + { + return new Dictionary(); + } + + return _syncManager.GetSyncedItemProgresses(new SyncJobItemQuery + { + TargetId = deviceId, + Statuses = new[] + { + SyncJobItemStatus.Converting, + SyncJobItemStatus.Queued, + SyncJobItemStatus.Transferring, + SyncJobItemStatus.ReadyToTransfer, + SyncJobItemStatus.Synced + } + }); + } + + public void FillSyncInfo(IEnumerable> tuples, DtoOptions options, User user) + { + if (options.Fields.Contains(ItemFields.BasicSyncInfo) || + options.Fields.Contains(ItemFields.SyncInfo)) + { + var syncProgress = GetSyncedItemProgress(options); + + foreach (var tuple in tuples) + { + var item = tuple.Item1; + + FillSyncInfo(tuple.Item2, item, options, user, syncProgress); + } + } + } + + private void FillSyncInfo(IHasSyncInfo dto, BaseItem item, DtoOptions options, User user, Dictionary syncProgress) + { + var hasFullSyncInfo = options.Fields.Contains(ItemFields.SyncInfo); + + if (!options.Fields.Contains(ItemFields.BasicSyncInfo) && + !hasFullSyncInfo) + { + return; + } + + if (dto.SupportsSync ?? false) + { + SyncedItemProgress syncStatus; + if (syncProgress.TryGetValue(dto.Id, out syncStatus)) + { + if (syncStatus.Status == SyncJobItemStatus.Synced) + { + dto.SyncPercent = 100; + } + else + { + dto.SyncPercent = syncStatus.Progress; + } + + if (hasFullSyncInfo) + { + dto.HasSyncJob = true; + dto.SyncStatus = syncStatus.Status; + } + } + } + } + + private async Task GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) + { + var fields = options.Fields; + + if (item == null) + { + throw new ArgumentNullException("item"); + } + + if (fields == null) + { + throw new ArgumentNullException("fields"); + } + + var dto = new BaseItemDto + { + ServerId = _appHost.SystemId + }; + + if (item.SourceType == SourceType.Channel) + { + dto.SourceType = item.SourceType.ToString(); + } + + if (fields.Contains(ItemFields.People)) + { + AttachPeople(dto, item); + } + + if (fields.Contains(ItemFields.PrimaryImageAspectRatio)) + { + try + { + AttachPrimaryImageAspectRatio(dto, item); + } + catch (Exception ex) + { + // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions + _logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, item.Name); + } + } + + if (fields.Contains(ItemFields.DisplayPreferencesId)) + { + dto.DisplayPreferencesId = item.DisplayPreferencesId.ToString("N"); + } + + if (user != null) + { + await AttachUserSpecificInfo(dto, item, user, options).ConfigureAwait(false); + } + + var hasMediaSources = item as IHasMediaSources; + if (hasMediaSources != null) + { + if (fields.Contains(ItemFields.MediaSources)) + { + if (user == null) + { + dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true).ToList(); + } + else + { + dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user).ToList(); + } + } + } + + if (fields.Contains(ItemFields.Studios)) + { + AttachStudios(dto, item); + } + + AttachBasicFields(dto, item, owner, options); + + var collectionFolder = item as ICollectionFolder; + if (collectionFolder != null) + { + dto.OriginalCollectionType = collectionFolder.CollectionType; + + dto.CollectionType = user == null ? + collectionFolder.CollectionType : + collectionFolder.GetViewType(user); + } + + if (fields.Contains(ItemFields.CanDelete)) + { + dto.CanDelete = user == null + ? item.CanDelete() + : item.CanDelete(user); + } + + if (fields.Contains(ItemFields.CanDownload)) + { + dto.CanDownload = user == null + ? item.CanDownload() + : item.CanDownload(user); + } + + if (fields.Contains(ItemFields.Etag)) + { + dto.Etag = item.GetEtag(user); + } + + if (item is ILiveTvRecording) + { + _livetvManager().AddInfoToRecordingDto(item, dto, user); + } + + return dto; + } + + public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List taggedItems, Dictionary syncProgress, User user = null) + { + var dto = GetBaseItemDtoInternal(item, options, user).Result; + + if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts)) + { + SetItemByNameInfo(item, dto, taggedItems, user); + } + + FillSyncInfo(dto, item, options, user, syncProgress); + + return dto; + } + + private void SetItemByNameInfo(BaseItem item, BaseItemDto dto, List taggedItems, User user = null) + { + if (item is MusicArtist) + { + dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum); + dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); + dto.SongCount = taggedItems.Count(i => i is Audio); + } + else if (item is MusicGenre) + { + dto.ArtistCount = taggedItems.Count(i => i is MusicArtist); + dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum); + dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); + dto.SongCount = taggedItems.Count(i => i is Audio); + } + else if (item is GameGenre) + { + dto.GameCount = taggedItems.Count(i => i is Game); + } + else + { + // This populates them all and covers Genre, Person, Studio, Year + + dto.ArtistCount = taggedItems.Count(i => i is MusicArtist); + dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum); + dto.EpisodeCount = taggedItems.Count(i => i is Episode); + dto.GameCount = taggedItems.Count(i => i is Game); + dto.MovieCount = taggedItems.Count(i => i is Movie); + dto.TrailerCount = taggedItems.Count(i => i is Trailer); + dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); + dto.SeriesCount = taggedItems.Count(i => i is Series); + dto.ProgramCount = taggedItems.Count(i => i is LiveTvProgram); + dto.SongCount = taggedItems.Count(i => i is Audio); + } + + dto.ChildCount = taggedItems.Count; + } + + /// + /// Attaches the user specific info. + /// + private async Task AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, DtoOptions dtoOptions) + { + var fields = dtoOptions.Fields; + + if (item.IsFolder) + { + var folder = (Folder)item; + + if (dtoOptions.EnableUserData) + { + dto.UserData = await _userDataRepository.GetUserDataDto(item, dto, user).ConfigureAwait(false); + } + + if (!dto.ChildCount.HasValue && item.SourceType == SourceType.Library) + { + dto.ChildCount = GetChildCount(folder, user); + } + + if (fields.Contains(ItemFields.CumulativeRunTimeTicks)) + { + dto.CumulativeRunTimeTicks = item.RunTimeTicks; + } + + if (fields.Contains(ItemFields.DateLastMediaAdded)) + { + dto.DateLastMediaAdded = folder.DateLastMediaAdded; + } + } + + else + { + if (dtoOptions.EnableUserData) + { + dto.UserData = _userDataRepository.GetUserDataDto(item, user).Result; + } + } + + dto.PlayAccess = item.GetPlayAccess(user); + + if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo)) + { + var userCanSync = user != null && user.Policy.EnableSync; + if (userCanSync && _syncManager.SupportsSync(item)) + { + dto.SupportsSync = true; + } + } + + if (fields.Contains(ItemFields.SeasonUserData)) + { + var episode = item as Episode; + + if (episode != null) + { + var season = episode.Season; + + if (season != null) + { + dto.SeasonUserData = await _userDataRepository.GetUserDataDto(season, user).ConfigureAwait(false); + } + } + } + + var userView = item as UserView; + if (userView != null) + { + dto.HasDynamicCategories = userView.ContainsDynamicCategories(user); + } + + var collectionFolder = item as ICollectionFolder; + if (collectionFolder != null) + { + dto.HasDynamicCategories = false; + } + } + + private int GetChildCount(Folder folder, User user) + { + // Right now this is too slow to calculate for top level folders on a per-user basis + // Just return something so that apps that are expecting a value won't think the folders are empty + if (folder is ICollectionFolder || folder is UserView) + { + return new Random().Next(1, 10); + } + + return folder.GetChildCount(user); + } + + /// + /// Gets client-side Id of a server-side BaseItem + /// + /// The item. + /// System.String. + /// item + public string GetDtoId(BaseItem item) + { + if (item == null) + { + throw new ArgumentNullException("item"); + } + + return item.Id.ToString("N"); + } + + /// + /// Converts a UserItemData to a DTOUserItemData + /// + /// The data. + /// DtoUserItemData. + /// + public UserItemDataDto GetUserItemDataDto(UserItemData data) + { + if (data == null) + { + throw new ArgumentNullException("data"); + } + + return new UserItemDataDto + { + IsFavorite = data.IsFavorite, + Likes = data.Likes, + PlaybackPositionTicks = data.PlaybackPositionTicks, + PlayCount = data.PlayCount, + Rating = data.Rating, + Played = data.Played, + LastPlayedDate = data.LastPlayedDate, + Key = data.Key + }; + } + private void SetBookProperties(BaseItemDto dto, Book item) + { + dto.SeriesName = item.SeriesName; + } + private void SetPhotoProperties(BaseItemDto dto, Photo item) + { + dto.Width = item.Width; + dto.Height = item.Height; + dto.CameraMake = item.CameraMake; + dto.CameraModel = item.CameraModel; + dto.Software = item.Software; + dto.ExposureTime = item.ExposureTime; + dto.FocalLength = item.FocalLength; + dto.ImageOrientation = item.Orientation; + dto.Aperture = item.Aperture; + dto.ShutterSpeed = item.ShutterSpeed; + + dto.Latitude = item.Latitude; + dto.Longitude = item.Longitude; + dto.Altitude = item.Altitude; + dto.IsoSpeedRating = item.IsoSpeedRating; + + var album = item.AlbumEntity; + + if (album != null) + { + dto.Album = album.Name; + dto.AlbumId = album.Id.ToString("N"); + } + } + + private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item) + { + if (!string.IsNullOrEmpty(item.Album)) + { + var parentAlbum = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new[] { typeof(MusicAlbum).Name }, + Name = item.Album + + }).FirstOrDefault(); + + if (parentAlbum != null) + { + dto.AlbumId = GetDtoId(parentAlbum); + } + } + + dto.Album = item.Album; + } + + private void SetGameProperties(BaseItemDto dto, Game item) + { + dto.Players = item.PlayersSupported; + dto.GameSystem = item.GameSystem; + dto.MultiPartGameFiles = item.MultiPartGameFiles; + } + + private void SetGameSystemProperties(BaseItemDto dto, GameSystem item) + { + dto.GameSystem = item.GameSystemName; + } + + private List GetImageTags(BaseItem item, List images) + { + return images + .Select(p => GetImageCacheTag(item, p)) + .Where(i => i != null) + .ToList(); + } + + private string GetImageCacheTag(BaseItem item, ImageType type) + { + try + { + return _imageProcessor.GetImageCacheTag(item, type); + } + catch (Exception ex) + { + _logger.ErrorException("Error getting {0} image info", ex, type); + return null; + } + } + + private string GetImageCacheTag(BaseItem item, ItemImageInfo image) + { + try + { + return _imageProcessor.GetImageCacheTag(item, image); + } + catch (Exception ex) + { + _logger.ErrorException("Error getting {0} image info for {1}", ex, image.Type, image.Path); + return null; + } + } + + /// + /// Attaches People DTO's to a DTOBaseItem + /// + /// The dto. + /// The item. + /// Task. + private void AttachPeople(BaseItemDto dto, BaseItem item) + { + // Ordering by person type to ensure actors and artists are at the front. + // This is taking advantage of the fact that they both begin with A + // This should be improved in the future + var people = _libraryManager.GetPeople(item).OrderBy(i => i.SortOrder ?? int.MaxValue) + .ThenBy(i => + { + if (i.IsType(PersonType.Actor)) + { + return 0; + } + if (i.IsType(PersonType.GuestStar)) + { + return 1; + } + if (i.IsType(PersonType.Director)) + { + return 2; + } + if (i.IsType(PersonType.Writer)) + { + return 3; + } + if (i.IsType(PersonType.Producer)) + { + return 4; + } + if (i.IsType(PersonType.Composer)) + { + return 4; + } + + return 10; + }) + .ToList(); + + var list = new List(); + + var dictionary = people.Select(p => p.Name) + .Distinct(StringComparer.OrdinalIgnoreCase).Select(c => + { + try + { + return _libraryManager.GetPerson(c); + } + catch (Exception ex) + { + _logger.ErrorException("Error getting person {0}", ex, c); + return null; + } + + }).Where(i => i != null) + .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) + .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); + + for (var i = 0; i < people.Count; i++) + { + var person = people[i]; + + var baseItemPerson = new BaseItemPerson + { + Name = person.Name, + Role = person.Role, + Type = person.Type + }; + + Person entity; + + if (dictionary.TryGetValue(person.Name, out entity)) + { + baseItemPerson.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary); + baseItemPerson.Id = entity.Id.ToString("N"); + list.Add(baseItemPerson); + } + } + + dto.People = list.ToArray(); + } + + /// + /// Attaches the studios. + /// + /// The dto. + /// The item. + /// Task. + private void AttachStudios(BaseItemDto dto, BaseItem item) + { + var studios = item.Studios.ToList(); + + dto.Studios = new StudioDto[studios.Count]; + + var dictionary = studios.Distinct(StringComparer.OrdinalIgnoreCase).Select(name => + { + try + { + return _libraryManager.GetStudio(name); + } + catch (IOException ex) + { + _logger.ErrorException("Error getting studio {0}", ex, name); + return null; + } + }) + .Where(i => i != null) + .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) + .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); + + for (var i = 0; i < studios.Count; i++) + { + var studio = studios[i]; + + var studioDto = new StudioDto + { + Name = studio + }; + + Studio entity; + + if (dictionary.TryGetValue(studio, out entity)) + { + studioDto.Id = entity.Id.ToString("N"); + studioDto.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary); + } + + dto.Studios[i] = studioDto; + } + } + + /// + /// Gets the chapter info dto. + /// + /// The chapter info. + /// The item. + /// ChapterInfoDto. + private ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item) + { + var dto = new ChapterInfoDto + { + Name = chapterInfo.Name, + StartPositionTicks = chapterInfo.StartPositionTicks + }; + + if (!string.IsNullOrEmpty(chapterInfo.ImagePath)) + { + dto.ImageTag = GetImageCacheTag(item, new ItemImageInfo + { + Path = chapterInfo.ImagePath, + Type = ImageType.Chapter, + DateModified = chapterInfo.ImageDateModified + }); + } + + return dto; + } + + public List GetChapterInfoDtos(BaseItem item) + { + return _itemRepo.GetChapters(item.Id) + .Select(c => GetChapterInfoDto(c, item)) + .ToList(); + } + + /// + /// Sets simple property values on a DTOBaseItem + /// + /// The dto. + /// The item. + /// The owner. + /// The options. + private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, DtoOptions options) + { + var fields = options.Fields; + + if (fields.Contains(ItemFields.DateCreated)) + { + dto.DateCreated = item.DateCreated; + } + + if (fields.Contains(ItemFields.DisplayMediaType)) + { + dto.DisplayMediaType = item.DisplayMediaType; + } + + if (fields.Contains(ItemFields.Settings)) + { + dto.LockedFields = item.LockedFields; + dto.LockData = item.IsLocked; + dto.ForcedSortName = item.ForcedSortName; + } + dto.Container = item.Container; + + var hasBudget = item as IHasBudget; + if (hasBudget != null) + { + if (fields.Contains(ItemFields.Budget)) + { + dto.Budget = hasBudget.Budget; + } + + if (fields.Contains(ItemFields.Revenue)) + { + dto.Revenue = hasBudget.Revenue; + } + } + + dto.EndDate = item.EndDate; + + if (fields.Contains(ItemFields.HomePageUrl)) + { + dto.HomePageUrl = item.HomePageUrl; + } + + if (fields.Contains(ItemFields.ExternalUrls)) + { + dto.ExternalUrls = _providerManager.GetExternalUrls(item).ToArray(); + } + + if (fields.Contains(ItemFields.Tags)) + { + dto.Tags = item.Tags; + } + + if (fields.Contains(ItemFields.Keywords)) + { + dto.Keywords = item.Keywords; + } + + var hasAspectRatio = item as IHasAspectRatio; + if (hasAspectRatio != null) + { + dto.AspectRatio = hasAspectRatio.AspectRatio; + } + + if (fields.Contains(ItemFields.Metascore)) + { + var hasMetascore = item as IHasMetascore; + if (hasMetascore != null) + { + dto.Metascore = hasMetascore.Metascore; + } + } + + if (fields.Contains(ItemFields.AwardSummary)) + { + var hasAwards = item as IHasAwards; + if (hasAwards != null) + { + dto.AwardSummary = hasAwards.AwardSummary; + } + } + + var backdropLimit = options.GetImageLimit(ImageType.Backdrop); + if (backdropLimit > 0) + { + dto.BackdropImageTags = GetImageTags(item, item.GetImages(ImageType.Backdrop).Take(backdropLimit).ToList()); + } + + if (fields.Contains(ItemFields.ScreenshotImageTags)) + { + var screenshotLimit = options.GetImageLimit(ImageType.Screenshot); + if (screenshotLimit > 0) + { + dto.ScreenshotImageTags = GetImageTags(item, item.GetImages(ImageType.Screenshot).Take(screenshotLimit).ToList()); + } + } + + if (fields.Contains(ItemFields.Genres)) + { + dto.Genres = item.Genres; + } + + if (options.EnableImages) + { + dto.ImageTags = new Dictionary(); + + // Prevent implicitly captured closure + var currentItem = item; + foreach (var image in currentItem.ImageInfos.Where(i => !currentItem.AllowsMultipleImages(i.Type)) + .ToList()) + { + if (options.GetImageLimit(image.Type) > 0) + { + var tag = GetImageCacheTag(item, image); + + if (tag != null) + { + dto.ImageTags[image.Type] = tag; + } + } + } + } + + dto.Id = GetDtoId(item); + dto.IndexNumber = item.IndexNumber; + dto.ParentIndexNumber = item.ParentIndexNumber; + + if (item.IsFolder) + { + dto.IsFolder = true; + } + else if (item is IHasMediaSources) + { + dto.IsFolder = false; + } + + dto.MediaType = item.MediaType; + dto.LocationType = item.LocationType; + if (item.IsHD.HasValue && item.IsHD.Value) + { + dto.IsHD = item.IsHD; + } + dto.Audio = item.Audio; + + if (fields.Contains(ItemFields.Settings)) + { + dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode; + dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage; + } + + dto.CriticRating = item.CriticRating; + + if (fields.Contains(ItemFields.CriticRatingSummary)) + { + dto.CriticRatingSummary = item.CriticRatingSummary; + } + + var hasTrailers = item as IHasTrailers; + if (hasTrailers != null) + { + dto.LocalTrailerCount = hasTrailers.GetTrailerIds().Count; + } + + var hasDisplayOrder = item as IHasDisplayOrder; + if (hasDisplayOrder != null) + { + dto.DisplayOrder = hasDisplayOrder.DisplayOrder; + } + + var userView = item as UserView; + if (userView != null) + { + dto.CollectionType = userView.ViewType; + } + + if (fields.Contains(ItemFields.RemoteTrailers)) + { + dto.RemoteTrailers = hasTrailers != null ? + hasTrailers.RemoteTrailers : + new List(); + } + + dto.Name = item.Name; + dto.OfficialRating = item.OfficialRating; + + if (fields.Contains(ItemFields.Overview)) + { + dto.Overview = item.Overview; + } + + if (fields.Contains(ItemFields.OriginalTitle)) + { + dto.OriginalTitle = item.OriginalTitle; + } + + if (fields.Contains(ItemFields.ShortOverview)) + { + dto.ShortOverview = item.ShortOverview; + } + + if (fields.Contains(ItemFields.ParentId)) + { + var displayParentId = item.DisplayParentId; + if (displayParentId.HasValue) + { + dto.ParentId = displayParentId.Value.ToString("N"); + } + } + + AddInheritedImages(dto, item, options, owner); + + if (fields.Contains(ItemFields.Path)) + { + dto.Path = GetMappedPath(item); + } + + dto.PremiereDate = item.PremiereDate; + dto.ProductionYear = item.ProductionYear; + + if (fields.Contains(ItemFields.ProviderIds)) + { + dto.ProviderIds = item.ProviderIds; + } + + dto.RunTimeTicks = item.RunTimeTicks; + + if (fields.Contains(ItemFields.SortName)) + { + dto.SortName = item.SortName; + } + + if (fields.Contains(ItemFields.CustomRating)) + { + dto.CustomRating = item.CustomRating; + } + + if (fields.Contains(ItemFields.Taglines)) + { + if (!string.IsNullOrWhiteSpace(item.Tagline)) + { + dto.Taglines = new List { item.Tagline }; + } + + if (dto.Taglines == null) + { + dto.Taglines = new List(); + } + } + + dto.Type = item.GetClientTypeName(); + dto.CommunityRating = item.CommunityRating; + + if (fields.Contains(ItemFields.VoteCount)) + { + dto.VoteCount = item.VoteCount; + } + + //if (item.IsFolder) + //{ + // var folder = (Folder)item; + + // if (fields.Contains(ItemFields.IndexOptions)) + // { + // dto.IndexOptions = folder.IndexByOptionStrings.ToArray(); + // } + //} + + var supportsPlaceHolders = item as ISupportsPlaceHolders; + if (supportsPlaceHolders != null) + { + dto.IsPlaceHolder = supportsPlaceHolders.IsPlaceHolder; + } + + // Add audio info + var audio = item as Audio; + if (audio != null) + { + dto.Album = audio.Album; + dto.ExtraType = audio.ExtraType; + + var albumParent = audio.AlbumEntity; + + if (albumParent != null) + { + dto.AlbumId = GetDtoId(albumParent); + + dto.AlbumPrimaryImageTag = GetImageCacheTag(albumParent, ImageType.Primary); + } + + //if (fields.Contains(ItemFields.MediaSourceCount)) + //{ + // Songs always have one + //} + } + + var hasArtist = item as IHasArtist; + if (hasArtist != null) + { + dto.Artists = hasArtist.Artists; + + var artistItems = _libraryManager.GetArtists(new InternalItemsQuery + { + EnableTotalRecordCount = false, + ItemIds = new[] { item.Id.ToString("N") } + }); + + dto.ArtistItems = artistItems.Items + .Select(i => + { + var artist = i.Item1; + return new NameIdPair + { + Name = artist.Name, + Id = artist.Id.ToString("N") + }; + }) + .ToList(); + + // Include artists that are not in the database yet, e.g., just added via metadata editor + var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); + dto.ArtistItems.AddRange(hasArtist.Artists + .Except(foundArtists, new DistinctNameComparer()) + .Select(i => + { + // This should not be necessary but we're seeing some cases of it + if (string.IsNullOrWhiteSpace(i)) + { + return null; + } + + var artist = _libraryManager.GetArtist(i); + if (artist != null) + { + return new NameIdPair + { + Name = artist.Name, + Id = artist.Id.ToString("N") + }; + } + + return null; + + }).Where(i => i != null)); + } + + var hasAlbumArtist = item as IHasAlbumArtist; + if (hasAlbumArtist != null) + { + dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault(); + + var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery + { + EnableTotalRecordCount = false, + ItemIds = new[] { item.Id.ToString("N") } + }); + + dto.AlbumArtists = artistItems.Items + .Select(i => + { + var artist = i.Item1; + return new NameIdPair + { + Name = artist.Name, + Id = artist.Id.ToString("N") + }; + }) + .ToList(); + } + + // Add video info + var video = item as Video; + if (video != null) + { + dto.VideoType = video.VideoType; + dto.Video3DFormat = video.Video3DFormat; + dto.IsoType = video.IsoType; + + if (video.HasSubtitles) + { + dto.HasSubtitles = video.HasSubtitles; + } + + if (video.AdditionalParts.Count != 0) + { + dto.PartCount = video.AdditionalParts.Count + 1; + } + + if (fields.Contains(ItemFields.MediaSourceCount)) + { + var mediaSourceCount = video.MediaSourceCount; + if (mediaSourceCount != 1) + { + dto.MediaSourceCount = mediaSourceCount; + } + } + + if (fields.Contains(ItemFields.Chapters)) + { + dto.Chapters = GetChapterInfoDtos(item); + } + + dto.ExtraType = video.ExtraType; + } + + if (fields.Contains(ItemFields.MediaStreams)) + { + // Add VideoInfo + var iHasMediaSources = item as IHasMediaSources; + + if (iHasMediaSources != null) + { + List mediaStreams; + + if (dto.MediaSources != null && dto.MediaSources.Count > 0) + { + mediaStreams = dto.MediaSources.Where(i => new Guid(i.Id) == item.Id) + .SelectMany(i => i.MediaStreams) + .ToList(); + } + else + { + mediaStreams = _mediaSourceManager().GetStaticMediaSources(iHasMediaSources, true).First().MediaStreams; + } + + dto.MediaStreams = mediaStreams; + } + } + + var hasSpecialFeatures = item as IHasSpecialFeatures; + if (hasSpecialFeatures != null) + { + var specialFeatureCount = hasSpecialFeatures.SpecialFeatureIds.Count; + + if (specialFeatureCount > 0) + { + dto.SpecialFeatureCount = specialFeatureCount; + } + } + + // Add EpisodeInfo + var episode = item as Episode; + if (episode != null) + { + dto.IndexNumberEnd = episode.IndexNumberEnd; + dto.SeriesName = episode.SeriesName; + + if (fields.Contains(ItemFields.AlternateEpisodeNumbers)) + { + dto.DvdSeasonNumber = episode.DvdSeasonNumber; + dto.DvdEpisodeNumber = episode.DvdEpisodeNumber; + dto.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber; + } + + if (fields.Contains(ItemFields.SpecialEpisodeNumbers)) + { + dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber; + dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber; + dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber; + } + + var seasonId = episode.SeasonId; + if (seasonId.HasValue) + { + dto.SeasonId = seasonId.Value.ToString("N"); + } + + dto.SeasonName = episode.SeasonName; + + var seriesId = episode.SeriesId; + if (seriesId.HasValue) + { + dto.SeriesId = seriesId.Value.ToString("N"); + } + + Series episodeSeries = null; + + if (fields.Contains(ItemFields.SeriesGenres)) + { + episodeSeries = episodeSeries ?? episode.Series; + if (episodeSeries != null) + { + dto.SeriesGenres = episodeSeries.Genres.ToList(); + } + } + + //if (fields.Contains(ItemFields.SeriesPrimaryImage)) + { + episodeSeries = episodeSeries ?? episode.Series; + if (episodeSeries != null) + { + dto.SeriesPrimaryImageTag = GetImageCacheTag(episodeSeries, ImageType.Primary); + } + } + + if (fields.Contains(ItemFields.SeriesStudio)) + { + episodeSeries = episodeSeries ?? episode.Series; + if (episodeSeries != null) + { + dto.SeriesStudio = episodeSeries.Studios.FirstOrDefault(); + } + } + } + + // Add SeriesInfo + var series = item as Series; + if (series != null) + { + dto.AirDays = series.AirDays; + dto.AirTime = series.AirTime; + dto.SeriesStatus = series.Status; + + dto.AnimeSeriesIndex = series.AnimeSeriesIndex; + } + + // Add SeasonInfo + var season = item as Season; + if (season != null) + { + dto.SeriesName = season.SeriesName; + + var seriesId = season.SeriesId; + if (seriesId.HasValue) + { + dto.SeriesId = seriesId.Value.ToString("N"); + } + + series = null; + + if (fields.Contains(ItemFields.SeriesStudio)) + { + series = series ?? season.Series; + if (series != null) + { + dto.SeriesStudio = series.Studios.FirstOrDefault(); + } + } + + if (fields.Contains(ItemFields.SeriesPrimaryImage)) + { + series = series ?? season.Series; + if (series != null) + { + dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary); + } + } + } + + var game = item as Game; + + if (game != null) + { + SetGameProperties(dto, game); + } + + var gameSystem = item as GameSystem; + + if (gameSystem != null) + { + SetGameSystemProperties(dto, gameSystem); + } + + var musicVideo = item as MusicVideo; + if (musicVideo != null) + { + SetMusicVideoProperties(dto, musicVideo); + } + + var book = item as Book; + if (book != null) + { + SetBookProperties(dto, book); + } + + if (item.ProductionLocations.Count > 0 || item is Movie) + { + dto.ProductionLocations = item.ProductionLocations.ToArray(); + } + + var photo = item as Photo; + if (photo != null) + { + SetPhotoProperties(dto, photo); + } + + dto.ChannelId = item.ChannelId; + + if (item.SourceType == SourceType.Channel && !string.IsNullOrWhiteSpace(item.ChannelId)) + { + var channel = _libraryManager.GetItemById(item.ChannelId); + if (channel != null) + { + dto.ChannelName = channel.Name; + } + } + } + + private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner) + { + var logoLimit = options.GetImageLimit(ImageType.Logo); + var artLimit = options.GetImageLimit(ImageType.Art); + var thumbLimit = options.GetImageLimit(ImageType.Thumb); + var backdropLimit = options.GetImageLimit(ImageType.Backdrop); + + if (logoLimit == 0 && artLimit == 0 && thumbLimit == 0 && backdropLimit == 0) + { + return; + } + + BaseItem parent = null; + var isFirst = true; + + while (((!dto.HasLogo && logoLimit > 0) || (!dto.HasArtImage && artLimit > 0) || (!dto.HasThumb && thumbLimit > 0) || parent is Series) && + (parent = parent ?? (isFirst ? item.GetParent() ?? owner : parent)) != null) + { + if (parent == null) + { + break; + } + + var allImages = parent.ImageInfos; + + if (logoLimit > 0 && !dto.HasLogo && dto.ParentLogoItemId == null) + { + var image = allImages.FirstOrDefault(i => i.Type == ImageType.Logo); + + if (image != null) + { + dto.ParentLogoItemId = GetDtoId(parent); + dto.ParentLogoImageTag = GetImageCacheTag(parent, image); + } + } + if (artLimit > 0 && !dto.HasArtImage && dto.ParentArtItemId == null) + { + var image = allImages.FirstOrDefault(i => i.Type == ImageType.Art); + + if (image != null) + { + dto.ParentArtItemId = GetDtoId(parent); + dto.ParentArtImageTag = GetImageCacheTag(parent, image); + } + } + if (thumbLimit > 0 && !dto.HasThumb && (dto.ParentThumbItemId == null || parent is Series)) + { + var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb); + + if (image != null) + { + dto.ParentThumbItemId = GetDtoId(parent); + dto.ParentThumbImageTag = GetImageCacheTag(parent, image); + } + } + if (backdropLimit > 0 && !dto.HasBackdrop) + { + var images = allImages.Where(i => i.Type == ImageType.Backdrop).Take(backdropLimit).ToList(); + + if (images.Count > 0) + { + dto.ParentBackdropItemId = GetDtoId(parent); + dto.ParentBackdropImageTags = GetImageTags(parent, images); + } + } + + isFirst = false; + parent = parent.GetParent(); + } + } + + private string GetMappedPath(BaseItem item) + { + var path = item.Path; + + var locationType = item.LocationType; + + if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) + { + path = _libraryManager.GetPathAfterNetworkSubstitution(path, item); + } + + return path; + } + + /// + /// Attaches the primary image aspect ratio. + /// + /// The dto. + /// The item. + /// Task. + public void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item) + { + dto.PrimaryImageAspectRatio = GetPrimaryImageAspectRatio(item); + } + + public double? GetPrimaryImageAspectRatio(IHasImages item) + { + var imageInfo = item.GetImageInfo(ImageType.Primary, 0); + + if (imageInfo == null || !imageInfo.IsLocalFile) + { + return null; + } + + ImageSize size; + + try + { + size = _imageProcessor.GetImageSize(imageInfo); + } + catch + { + //_logger.ErrorException("Failed to determine primary image aspect ratio for {0}", ex, path); + return null; + } + + var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToList(); + + foreach (var enhancer in supportedEnhancers) + { + try + { + size = enhancer.GetEnhancedImageSize(item, ImageType.Primary, 0, size); + } + catch (Exception ex) + { + _logger.ErrorException("Error in image enhancer: {0}", ex, enhancer.GetType().Name); + } + } + + var width = size.Width; + var height = size.Height; + + if (width == 0 || height == 0) + { + return null; + } + + var photo = item as Photo; + if (photo != null && photo.Orientation.HasValue) + { + switch (photo.Orientation.Value) + { + case ImageOrientation.LeftBottom: + case ImageOrientation.LeftTop: + case ImageOrientation.RightBottom: + case ImageOrientation.RightTop: + var temp = height; + height = width; + width = temp; + break; + } + } + + return width / height; + } + } +} diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index af093d53f..11b3393c8 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -13,7 +13,7 @@ en-US 512 {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile75 + Profile7 v4.5 @@ -52,6 +52,7 @@ Properties\SharedVersion.cs + @@ -60,18 +61,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + ..\packages\MediaBrowser.Naming.1.0.0.57\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll + True + + + ..\packages\Patterns.Logging.1.0.0.4\lib\portable-net45+dnxcore50+sl4+wp71+win8+wpa81\Patterns.Logging.dll + True + + + + + + + +