From 4e816552395c1b57868ccd29f6f2e9b70d7272a5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 10 May 2014 13:28:03 -0400 Subject: [PATCH] updated mono build --- MediaBrowser.Api/DisplayPreferencesService.cs | 11 +-- .../ScheduledTasksWebSocketListener.cs | 33 ++++++- .../WebSocket/LogFileWebSocketListener.cs | 2 +- .../WebSocket/SessionInfoWebSocketListener.cs | 4 +- .../WebSocket/SystemInfoWebSocketListener.cs | 4 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 18 +++- .../ScheduledTasks/TaskManager.cs | 29 ++++-- .../Net/BasePeriodicWebSocketListener.cs | 98 ++++++++++++++++--- .../ScheduledTasks/IScheduledTaskWorker.cs | 8 +- .../ScheduledTasks/ITaskManager.cs | 5 +- .../ScheduledTasks/TaskCompletionEventArgs.cs | 2 +- .../MediaBrowser.MediaEncoding.csproj | 8 +- MediaBrowser.Mono.sln | 14 ++- MediaBrowser.Mono.userprefs | 2 +- .../Notifications/Notifications.cs | 36 ++++++- .../EntryPoints/ServerEventNotifier.cs | 4 +- .../SqliteDisplayPreferencesRepository.cs | 9 +- .../Session/SessionManager.cs | 20 +++- MediaBrowser.Server.Mono/Native/NativeApp.cs | 5 + .../EntryPoints/KeepServerAwake.cs | 25 +---- .../FFMpeg/FFMpegDownloadInfo.cs | 8 +- .../Native/NativeApp.cs | 29 +++++- .../OpenSubtitlesHandler.csproj | 6 ++ 23 files changed, 279 insertions(+), 101 deletions(-) diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs index 16aafafb0e..206f5bf7b7 100644 --- a/MediaBrowser.Api/DisplayPreferencesService.cs +++ b/MediaBrowser.Api/DisplayPreferencesService.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Serialization; using ServiceStack; @@ -79,14 +78,6 @@ namespace MediaBrowser.Api { var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client); - if (result == null) - { - result = new DisplayPreferences - { - Id = request.Id - }; - } - return ToOptimizedSerializedResultUsingCache(result); } diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs index c143635bfa..0d61c2ce12 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Tasks; using System.Collections.Generic; @@ -11,7 +12,7 @@ namespace MediaBrowser.Api.ScheduledTasks /// /// Class ScheduledTasksWebSocketListener /// - public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener, object> + public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> { /// /// Gets or sets the task manager. @@ -37,6 +38,26 @@ namespace MediaBrowser.Api.ScheduledTasks : base(logger) { TaskManager = taskManager; + + TaskManager.TaskExecuting += TaskManager_TaskExecuting; + TaskManager.TaskCompleted += TaskManager_TaskCompleted; + } + + void TaskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) + { + SendData(true); + e.Task.TaskProgress -= Argument_TaskProgress; + } + + void TaskManager_TaskExecuting(object sender, GenericEventArgs e) + { + SendData(true); + e.Argument.TaskProgress += Argument_TaskProgress; + } + + void Argument_TaskProgress(object sender, GenericEventArgs e) + { + SendData(false); } /// @@ -44,12 +65,20 @@ namespace MediaBrowser.Api.ScheduledTasks /// /// The state. /// Task{IEnumerable{TaskInfo}}. - protected override Task> GetDataToSend(object state) + protected override Task> GetDataToSend(WebSocketListenerState state) { return Task.FromResult(TaskManager.ScheduledTasks .OrderBy(i => i.Name) .Select(ScheduledTaskHelpers.GetTaskInfo) .Where(i => !i.IsHidden)); } + + protected override bool SendOnTimer + { + get + { + return false; + } + } } } diff --git a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs index 7fbea2f401..46dabb0420 100644 --- a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs +++ b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Api.WebSocket /// /// Class LogFileWebSocketState /// - public class LogFileWebSocketState + public class LogFileWebSocketState : WebSocketListenerState { /// /// Gets or sets the last log file path. diff --git a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs index 721d8976b2..a16ea863f0 100644 --- a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs +++ b/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Api.WebSocket /// /// Class SessionInfoWebSocketListener /// - class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, object> + class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> { /// /// Gets the name. @@ -43,7 +43,7 @@ namespace MediaBrowser.Api.WebSocket /// /// The state. /// Task{SystemInfo}. - protected override Task> GetDataToSend(object state) + protected override Task> GetDataToSend(WebSocketListenerState state) { return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto)); } diff --git a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs index 62e642c927..2940bcef06 100644 --- a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs +++ b/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Api.WebSocket /// /// Class SystemInfoWebSocketListener /// - public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener + public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener { /// /// Gets the name. @@ -41,7 +41,7 @@ namespace MediaBrowser.Api.WebSocket /// /// The state. /// Task{SystemInfo}. - protected override Task GetDataToSend(object state) + protected override Task GetDataToSend(WebSocketListenerState state) { return Task.FromResult(_appHost.GetSystemInfo()); } diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index d7d0cb886e..68222d8436 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -1,6 +1,8 @@ using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Tasks; @@ -18,6 +20,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// public class ScheduledTaskWorker : IScheduledTaskWorker { + public event EventHandler> TaskProgress; + /// /// Gets or sets the scheduled task. /// @@ -344,13 +348,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks throw new InvalidOperationException("Cannot execute a Task that is already running"); } + var progress = new Progress(); + CurrentCancellationTokenSource = new CancellationTokenSource(); Logger.Info("Executing {0}", Name); - ((TaskManager)TaskManager).OnTaskExecuting(ScheduledTask); - - var progress = new Progress(); + ((TaskManager)TaskManager).OnTaskExecuting(this); progress.ProgressChanged += progress_ProgressChanged; @@ -412,6 +416,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks void progress_ProgressChanged(object sender, double e) { CurrentProgress = e; + + EventHelper.FireEventIfNotNull(TaskProgress, this, new GenericEventArgs + { + Argument = e + + }, Logger); } /// @@ -546,7 +556,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks LastExecutionResult = result; - ((TaskManager) TaskManager).OnTaskCompleted(ScheduledTask, result); + ((TaskManager)TaskManager).OnTaskCompleted(this, result); } /// diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs index cead5de04b..5aec39b89c 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs @@ -17,8 +17,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// public class TaskManager : ITaskManager { - public event EventHandler TaskExecuting; - public event EventHandler> TaskCompleted; + public event EventHandler> TaskExecuting; + public event EventHandler TaskCompleted; /// /// Gets the list of Scheduled Tasks @@ -125,7 +125,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks // If it's idle just execute immediately if (task.State == TaskState.Idle) { - ((ScheduledTaskWorker)task).Execute(); + Execute(task); return; } @@ -149,7 +149,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks { var myTasks = ScheduledTasks.ToList(); - myTasks.AddRange(tasks.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger))); + var list = tasks.ToList(); + myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger))); ScheduledTasks = myTasks.ToArray(); } @@ -189,9 +190,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// Called when [task executing]. /// /// The task. - internal void OnTaskExecuting(IScheduledTask task) + internal void OnTaskExecuting(IScheduledTaskWorker task) { - EventHelper.QueueEventIfNotNull(TaskExecuting, task, EventArgs.Empty, Logger); + EventHelper.QueueEventIfNotNull(TaskExecuting, this, new GenericEventArgs + { + Argument = task + + }, Logger); } /// @@ -199,9 +204,15 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// /// The task. /// The result. - internal void OnTaskCompleted(IScheduledTask task, TaskResult result) + internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result) { - EventHelper.QueueEventIfNotNull(TaskCompleted, task, new GenericEventArgs { Argument = result }, Logger); + EventHelper.QueueEventIfNotNull(TaskCompleted, task, new TaskCompletionEventArgs + { + Result = result, + Task = task + + }, Logger); + ExecuteQueuedTasks(); } @@ -219,7 +230,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks if (scheduledTask.State == TaskState.Idle) { - ((ScheduledTaskWorker)scheduledTask).Execute(); + Execute(scheduledTask); _taskQueue.Remove(type); } diff --git a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs index 33d3f368b6..a2af3707be 100644 --- a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Common.Net /// The type of the T return data type. /// The type of the T state type. public abstract class BasePeriodicWebSocketListener : IWebSocketListener, IDisposable - where TStateType : class, new() + where TStateType : WebSocketListenerState, new() where TReturnDataType : class { /// @@ -83,7 +83,15 @@ namespace MediaBrowser.Common.Net } protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - + + protected virtual bool SendOnTimer + { + get + { + return true; + } + } + /// /// Starts sending messages over a web socket /// @@ -99,9 +107,15 @@ namespace MediaBrowser.Common.Net Logger.Info("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name); - var timer = new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite); + var timer = SendOnTimer ? + new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) : + null; - var state = new TStateType(); + var state = new TStateType + { + IntervalMs = periodMs, + InitialDelayMs = dueTimeMs + }; var semaphore = new SemaphoreSlim(1, 1); @@ -110,14 +124,17 @@ namespace MediaBrowser.Common.Net ActiveConnections.Add(new Tuple(message.Connection, cancellationTokenSource, timer, state, semaphore)); } - timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs)); + if (timer != null) + { + timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs)); + } } /// /// Timers the callback. /// /// The state. - private async void TimerCallback(object state) + private void TimerCallback(object state) { var connection = (IWebSocketConnection)state; @@ -139,11 +156,50 @@ namespace MediaBrowser.Common.Net return; } + SendData(tuple); + } + + protected void SendData(bool force) + { + List> tuples; + + lock (ActiveConnections) + { + tuples = ActiveConnections + .Where(c => + { + if (c.Item1.State == WebSocketState.Open && !c.Item2.IsCancellationRequested) + { + var state = c.Item4; + + if (force || (DateTime.UtcNow - state.DateLastSendUtc).TotalMilliseconds >= state.IntervalMs) + { + return true; + } + } + + return false; + }) + .ToList(); + } + + foreach (var tuple in tuples) + { + SendData(tuple); + } + } + + private async void SendData(Tuple tuple) + { + var connection = tuple.Item1; + try { await tuple.Item5.WaitAsync(tuple.Item2.Token).ConfigureAwait(false); - var data = await GetDataToSend(tuple.Item4).ConfigureAwait(false); + var state = tuple.Item4; + + var data = await GetDataToSend(state).ConfigureAwait(false); if (data != null) { @@ -153,6 +209,8 @@ namespace MediaBrowser.Common.Net Data = data }, tuple.Item2.Token).ConfigureAwait(false); + + state.DateLastSendUtc = DateTime.UtcNow; } tuple.Item5.Release(); @@ -196,13 +254,18 @@ namespace MediaBrowser.Common.Net { Logger.Info("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name); - try - { - connection.Item3.Dispose(); - } - catch (ObjectDisposedException) + var timer = connection.Item3; + + if (timer != null) { + try + { + timer.Dispose(); + } + catch (ObjectDisposedException) + { + } } try @@ -212,7 +275,7 @@ namespace MediaBrowser.Common.Net } catch (ObjectDisposedException) { - + } try @@ -223,7 +286,7 @@ namespace MediaBrowser.Common.Net { } - + ActiveConnections.Remove(connection); } @@ -253,4 +316,11 @@ namespace MediaBrowser.Common.Net Dispose(true); } } + + public class WebSocketListenerState + { + public DateTime DateLastSendUtc { get; set; } + public long InitialDelayMs { get; set; } + public long IntervalMs { get; set; } + } } diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs index d0d363df76..f50bd9e76e 100644 --- a/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs +++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Tasks; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Tasks; using System; using System.Collections.Generic; @@ -9,6 +10,11 @@ namespace MediaBrowser.Common.ScheduledTasks /// public interface IScheduledTaskWorker : IDisposable { + /// + /// Occurs when [task progress]. + /// + event EventHandler> TaskProgress; + /// /// Gets or sets the scheduled task. /// diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs index 38548801b2..01dc355c33 100644 --- a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs +++ b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Events; -using MediaBrowser.Model.Tasks; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -50,7 +49,7 @@ namespace MediaBrowser.Common.ScheduledTasks void Cancel(IScheduledTaskWorker task); Task Execute(IScheduledTaskWorker task); - event EventHandler TaskExecuting; - event EventHandler> TaskCompleted; + event EventHandler> TaskExecuting; + event EventHandler TaskCompleted; } } \ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs b/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs index 8aab6b50d4..2974806d02 100644 --- a/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs +++ b/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs @@ -5,7 +5,7 @@ namespace MediaBrowser.Common.ScheduledTasks { public class TaskCompletionEventArgs : EventArgs { - public IScheduledTask Task { get; set; } + public IScheduledTaskWorker Task { get; set; } public TaskResult Result { get; set; } } diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 19287b0cbb..a67d69f79f 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -85,13 +85,7 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - +