Browse Source

updated mono build

Luke Pulverenti 11 years ago
parent
commit
4e81655239
23 changed files with 279 additions and 101 deletions
  1. 1 10
      MediaBrowser.Api/DisplayPreferencesService.cs
  2. 31 2
      MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
  3. 1 1
      MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs
  4. 2 2
      MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs
  5. 2 2
      MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs
  6. 14 4
      MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
  7. 20 9
      MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
  8. 84 14
      MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
  9. 7 1
      MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs
  10. 2 3
      MediaBrowser.Common/ScheduledTasks/ITaskManager.cs
  11. 1 1
      MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs
  12. 1 7
      MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
  13. 12 2
      MediaBrowser.Mono.sln
  14. 1 1
      MediaBrowser.Mono.userprefs
  15. 31 5
      MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs
  16. 2 2
      MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs
  17. 7 2
      MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
  18. 15 5
      MediaBrowser.Server.Implementations/Session/SessionManager.cs
  19. 5 0
      MediaBrowser.Server.Mono/Native/NativeApp.cs
  20. 2 23
      MediaBrowser.ServerApplication/EntryPoints/KeepServerAwake.cs
  21. 4 4
      MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs
  22. 28 1
      MediaBrowser.ServerApplication/Native/NativeApp.cs
  23. 6 0
      OpenSubtitlesHandler/OpenSubtitlesHandler.csproj

+ 1 - 10
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.Entities;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Serialization;
 using ServiceStack;
 using ServiceStack;
@@ -79,14 +78,6 @@ namespace MediaBrowser.Api
         {
         {
             var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client);
             var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client);
 
 
-            if (result == null)
-            {
-                result = new DisplayPreferences
-                {
-                    Id = request.Id
-                };
-            }
-
             return ToOptimizedSerializedResultUsingCache(result);
             return ToOptimizedSerializedResultUsingCache(result);
         }
         }
 
 

+ 31 - 2
MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Tasks;
 using MediaBrowser.Model.Tasks;
 using System.Collections.Generic;
 using System.Collections.Generic;
@@ -11,7 +12,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// <summary>
     /// Class ScheduledTasksWebSocketListener
     /// Class ScheduledTasksWebSocketListener
     /// </summary>
     /// </summary>
-    public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, object>
+    public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState>
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets the task manager.
         /// Gets or sets the task manager.
@@ -37,6 +38,26 @@ namespace MediaBrowser.Api.ScheduledTasks
             : base(logger)
             : base(logger)
         {
         {
             TaskManager = taskManager;
             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<IScheduledTaskWorker> e)
+        {
+            SendData(true);
+            e.Argument.TaskProgress += Argument_TaskProgress;
+        }
+
+        void Argument_TaskProgress(object sender, GenericEventArgs<double> e)
+        {
+            SendData(false);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -44,12 +65,20 @@ namespace MediaBrowser.Api.ScheduledTasks
         /// </summary>
         /// </summary>
         /// <param name="state">The state.</param>
         /// <param name="state">The state.</param>
         /// <returns>Task{IEnumerable{TaskInfo}}.</returns>
         /// <returns>Task{IEnumerable{TaskInfo}}.</returns>
-        protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
+        protected override Task<IEnumerable<TaskInfo>> GetDataToSend(WebSocketListenerState state)
         {
         {
             return Task.FromResult(TaskManager.ScheduledTasks
             return Task.FromResult(TaskManager.ScheduledTasks
                 .OrderBy(i => i.Name)
                 .OrderBy(i => i.Name)
                 .Select(ScheduledTaskHelpers.GetTaskInfo)
                 .Select(ScheduledTaskHelpers.GetTaskInfo)
                 .Where(i => !i.IsHidden));
                 .Where(i => !i.IsHidden));
         }
         }
+
+        protected override bool SendOnTimer
+        {
+            get
+            {
+                return false;
+            }
+        }
     }
     }
 }
 }

+ 1 - 1
MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs

@@ -133,7 +133,7 @@ namespace MediaBrowser.Api.WebSocket
     /// <summary>
     /// <summary>
     /// Class LogFileWebSocketState
     /// Class LogFileWebSocketState
     /// </summary>
     /// </summary>
-    public class LogFileWebSocketState
+    public class LogFileWebSocketState : WebSocketListenerState
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets the last log file path.
         /// Gets or sets the last log file path.

+ 2 - 2
MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs

@@ -11,7 +11,7 @@ namespace MediaBrowser.Api.WebSocket
     /// <summary>
     /// <summary>
     /// Class SessionInfoWebSocketListener
     /// Class SessionInfoWebSocketListener
     /// </summary>
     /// </summary>
-    class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfoDto>, object>
+    class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfoDto>, WebSocketListenerState>
     {
     {
         /// <summary>
         /// <summary>
         /// Gets the name.
         /// Gets the name.
@@ -43,7 +43,7 @@ namespace MediaBrowser.Api.WebSocket
         /// </summary>
         /// </summary>
         /// <param name="state">The state.</param>
         /// <param name="state">The state.</param>
         /// <returns>Task{SystemInfo}.</returns>
         /// <returns>Task{SystemInfo}.</returns>
-        protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
+        protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state)
         {
         {
             return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto));
             return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto));
         }
         }

+ 2 - 2
MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs

@@ -9,7 +9,7 @@ namespace MediaBrowser.Api.WebSocket
     /// <summary>
     /// <summary>
     /// Class SystemInfoWebSocketListener
     /// Class SystemInfoWebSocketListener
     /// </summary>
     /// </summary>
-    public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<SystemInfo, object>
+    public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<SystemInfo, WebSocketListenerState>
     {
     {
         /// <summary>
         /// <summary>
         /// Gets the name.
         /// Gets the name.
@@ -41,7 +41,7 @@ namespace MediaBrowser.Api.WebSocket
         /// </summary>
         /// </summary>
         /// <param name="state">The state.</param>
         /// <param name="state">The state.</param>
         /// <returns>Task{SystemInfo}.</returns>
         /// <returns>Task{SystemInfo}.</returns>
-        protected override Task<SystemInfo> GetDataToSend(object state)
+        protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state)
         {
         {
             return Task.FromResult(_appHost.GetSystemInfo());
             return Task.FromResult(_appHost.GetSystemInfo());
         }
         }

+ 14 - 4
MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs

@@ -1,6 +1,8 @@
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Tasks;
 using MediaBrowser.Model.Tasks;
@@ -18,6 +20,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
     /// </summary>
     /// </summary>
     public class ScheduledTaskWorker : IScheduledTaskWorker
     public class ScheduledTaskWorker : IScheduledTaskWorker
     {
     {
+        public event EventHandler<GenericEventArgs<double>> TaskProgress;
+
         /// <summary>
         /// <summary>
         /// Gets or sets the scheduled task.
         /// Gets or sets the scheduled task.
         /// </summary>
         /// </summary>
@@ -344,13 +348,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
                 throw new InvalidOperationException("Cannot execute a Task that is already running");
                 throw new InvalidOperationException("Cannot execute a Task that is already running");
             }
             }
 
 
+            var progress = new Progress<double>();
+
             CurrentCancellationTokenSource = new CancellationTokenSource();
             CurrentCancellationTokenSource = new CancellationTokenSource();
 
 
             Logger.Info("Executing {0}", Name);
             Logger.Info("Executing {0}", Name);
 
 
-            ((TaskManager)TaskManager).OnTaskExecuting(ScheduledTask);
-            
-            var progress = new Progress<double>();
+            ((TaskManager)TaskManager).OnTaskExecuting(this);
 
 
             progress.ProgressChanged += progress_ProgressChanged;
             progress.ProgressChanged += progress_ProgressChanged;
 
 
@@ -412,6 +416,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         void progress_ProgressChanged(object sender, double e)
         void progress_ProgressChanged(object sender, double e)
         {
         {
             CurrentProgress = e;
             CurrentProgress = e;
+
+            EventHelper.FireEventIfNotNull(TaskProgress, this, new GenericEventArgs<double>
+            {
+                Argument = e
+
+            }, Logger);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -546,7 +556,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
 
 
             LastExecutionResult = result;
             LastExecutionResult = result;
 
 
-            ((TaskManager) TaskManager).OnTaskCompleted(ScheduledTask, result);
+            ((TaskManager)TaskManager).OnTaskCompleted(this, result);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 20 - 9
MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs

@@ -17,8 +17,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
     /// </summary>
     /// </summary>
     public class TaskManager : ITaskManager
     public class TaskManager : ITaskManager
     {
     {
-        public event EventHandler<EventArgs> TaskExecuting;
-        public event EventHandler<GenericEventArgs<TaskResult>> TaskCompleted;
+        public event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
+        public event EventHandler<TaskCompletionEventArgs> TaskCompleted;
 
 
         /// <summary>
         /// <summary>
         /// Gets the list of Scheduled Tasks
         /// Gets the list of Scheduled Tasks
@@ -125,7 +125,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
                 // If it's idle just execute immediately
                 // If it's idle just execute immediately
                 if (task.State == TaskState.Idle)
                 if (task.State == TaskState.Idle)
                 {
                 {
-                    ((ScheduledTaskWorker)task).Execute();
+                    Execute(task);
                     return;
                     return;
                 }
                 }
 
 
@@ -149,7 +149,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         {
         {
             var myTasks = ScheduledTasks.ToList();
             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();
             ScheduledTasks = myTasks.ToArray();
         }
         }
@@ -189,9 +190,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         /// Called when [task executing].
         /// Called when [task executing].
         /// </summary>
         /// </summary>
         /// <param name="task">The task.</param>
         /// <param name="task">The task.</param>
-        internal void OnTaskExecuting(IScheduledTask task)
+        internal void OnTaskExecuting(IScheduledTaskWorker task)
         {
         {
-            EventHelper.QueueEventIfNotNull(TaskExecuting, task, EventArgs.Empty, Logger);
+            EventHelper.QueueEventIfNotNull(TaskExecuting, this, new GenericEventArgs<IScheduledTaskWorker>
+            {
+                Argument = task
+
+            }, Logger);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -199,9 +204,15 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         /// </summary>
         /// </summary>
         /// <param name="task">The task.</param>
         /// <param name="task">The task.</param>
         /// <param name="result">The result.</param>
         /// <param name="result">The result.</param>
-        internal void OnTaskCompleted(IScheduledTask task, TaskResult result)
+        internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
         {
         {
-            EventHelper.QueueEventIfNotNull(TaskCompleted, task, new GenericEventArgs<TaskResult> { Argument = result }, Logger);
+            EventHelper.QueueEventIfNotNull(TaskCompleted, task, new TaskCompletionEventArgs
+            {
+                Result = result,
+                Task = task
+
+            }, Logger);
+
             ExecuteQueuedTasks();
             ExecuteQueuedTasks();
         }
         }
 
 
@@ -219,7 +230,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
 
 
                     if (scheduledTask.State == TaskState.Idle)
                     if (scheduledTask.State == TaskState.Idle)
                     {
                     {
-                        ((ScheduledTaskWorker)scheduledTask).Execute();
+                        Execute(scheduledTask);
 
 
                         _taskQueue.Remove(type);
                         _taskQueue.Remove(type);
                     }
                     }

+ 84 - 14
MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs

@@ -15,7 +15,7 @@ namespace MediaBrowser.Common.Net
     /// <typeparam name="TReturnDataType">The type of the T return data type.</typeparam>
     /// <typeparam name="TReturnDataType">The type of the T return data type.</typeparam>
     /// <typeparam name="TStateType">The type of the T state type.</typeparam>
     /// <typeparam name="TStateType">The type of the T state type.</typeparam>
     public abstract class BasePeriodicWebSocketListener<TReturnDataType, TStateType> : IWebSocketListener, IDisposable
     public abstract class BasePeriodicWebSocketListener<TReturnDataType, TStateType> : IWebSocketListener, IDisposable
-        where TStateType : class, new()
+        where TStateType : WebSocketListenerState, new()
         where TReturnDataType : class
         where TReturnDataType : class
     {
     {
         /// <summary>
         /// <summary>
@@ -83,7 +83,15 @@ namespace MediaBrowser.Common.Net
         }
         }
 
 
         protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
         protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
-        
+
+        protected virtual bool SendOnTimer
+        {
+            get
+            {
+                return true;
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Starts sending messages over a web socket
         /// Starts sending messages over a web socket
         /// </summary>
         /// </summary>
@@ -99,9 +107,15 @@ namespace MediaBrowser.Common.Net
 
 
             Logger.Info("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name);
             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);
             var semaphore = new SemaphoreSlim(1, 1);
 
 
@@ -110,14 +124,17 @@ namespace MediaBrowser.Common.Net
                 ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>(message.Connection, cancellationTokenSource, timer, state, semaphore));
                 ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>(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));
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Timers the callback.
         /// Timers the callback.
         /// </summary>
         /// </summary>
         /// <param name="state">The state.</param>
         /// <param name="state">The state.</param>
-        private async void TimerCallback(object state)
+        private void TimerCallback(object state)
         {
         {
             var connection = (IWebSocketConnection)state;
             var connection = (IWebSocketConnection)state;
 
 
@@ -139,11 +156,50 @@ namespace MediaBrowser.Common.Net
                 return;
                 return;
             }
             }
 
 
+            SendData(tuple);
+        }
+
+        protected void SendData(bool force)
+        {
+            List<Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>> 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<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> tuple)
+        {
+            var connection = tuple.Item1;
+
             try
             try
             {
             {
                 await tuple.Item5.WaitAsync(tuple.Item2.Token).ConfigureAwait(false);
                 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)
                 if (data != null)
                 {
                 {
@@ -153,6 +209,8 @@ namespace MediaBrowser.Common.Net
                         Data = data
                         Data = data
 
 
                     }, tuple.Item2.Token).ConfigureAwait(false);
                     }, tuple.Item2.Token).ConfigureAwait(false);
+
+                    state.DateLastSendUtc = DateTime.UtcNow;
                 }
                 }
 
 
                 tuple.Item5.Release();
                 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);
             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
             try
@@ -212,7 +275,7 @@ namespace MediaBrowser.Common.Net
             }
             }
             catch (ObjectDisposedException)
             catch (ObjectDisposedException)
             {
             {
-                
+
             }
             }
 
 
             try
             try
@@ -223,7 +286,7 @@ namespace MediaBrowser.Common.Net
             {
             {
 
 
             }
             }
-            
+
             ActiveConnections.Remove(connection);
             ActiveConnections.Remove(connection);
         }
         }
 
 
@@ -253,4 +316,11 @@ namespace MediaBrowser.Common.Net
             Dispose(true);
             Dispose(true);
         }
         }
     }
     }
+
+    public class WebSocketListenerState
+    {
+        public DateTime DateLastSendUtc { get; set; }
+        public long InitialDelayMs { get; set; }
+        public long IntervalMs { get; set; }
+    }
 }
 }

+ 7 - 1
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;
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
@@ -9,6 +10,11 @@ namespace MediaBrowser.Common.ScheduledTasks
     /// </summary>
     /// </summary>
     public interface IScheduledTaskWorker : IDisposable
     public interface IScheduledTaskWorker : IDisposable
     {
     {
+        /// <summary>
+        /// Occurs when [task progress].
+        /// </summary>
+        event EventHandler<GenericEventArgs<double>> TaskProgress;
+
         /// <summary>
         /// <summary>
         /// Gets or sets the scheduled task.
         /// Gets or sets the scheduled task.
         /// </summary>
         /// </summary>

+ 2 - 3
MediaBrowser.Common/ScheduledTasks/ITaskManager.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Tasks;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
@@ -50,7 +49,7 @@ namespace MediaBrowser.Common.ScheduledTasks
         void Cancel(IScheduledTaskWorker task);
         void Cancel(IScheduledTaskWorker task);
         Task Execute(IScheduledTaskWorker task);
         Task Execute(IScheduledTaskWorker task);
 
 
-        event EventHandler<EventArgs> TaskExecuting;
-        event EventHandler<GenericEventArgs<TaskResult>> TaskCompleted;
+        event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
+        event EventHandler<TaskCompletionEventArgs> TaskCompleted;
     }
     }
 }
 }

+ 1 - 1
MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs

@@ -5,7 +5,7 @@ namespace MediaBrowser.Common.ScheduledTasks
 {
 {
     public class TaskCompletionEventArgs : EventArgs
     public class TaskCompletionEventArgs : EventArgs
     {
     {
-        public IScheduledTask Task { get; set; }
+        public IScheduledTaskWorker Task { get; set; }
 
 
         public TaskResult Result { get; set; }
         public TaskResult Result { get; set; }
     }
     }

+ 1 - 7
MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj

@@ -85,13 +85,7 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup />
   <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>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}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
-  </Target>
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">
   <Target Name="BeforeBuild">

+ 12 - 2
MediaBrowser.Mono.sln

@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaB
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}"
 EndProject
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}"
+EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|x86 = Debug|x86
 		Debug|x86 = Debug|x86
@@ -33,8 +35,8 @@ Global
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.Build.0 = Debug|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.Build.0 = Debug|Any CPU
-		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
-		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
+		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.Build.0 = Release|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.Build.0 = Release|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.ActiveCfg = Release|Any CPU
 		{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.ActiveCfg = Release|Any CPU
@@ -71,6 +73,14 @@ Global
 		{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU
 		{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU
 		{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU
 		{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU
 		{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.Build.0 = Release|Any CPU
 		{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.Build.0 = Release|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.Build.0 = Debug|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.ActiveCfg = Release|Any CPU
+		{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.Build.0 = Release|Any CPU
 		{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.Build.0 = Debug|Any CPU
 		{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.Build.0 = Debug|Any CPU
 		{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
 		{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU

+ 1 - 1
MediaBrowser.Mono.userprefs

@@ -5,7 +5,7 @@
       <File FileName="MediaBrowser.Server.Mono\app.config" Line="1" Column="1" />
       <File FileName="MediaBrowser.Server.Mono\app.config" Line="1" Column="1" />
       <File FileName="MediaBrowser.ServerApplication\ApplicationHost.cs" Line="1" Column="1" />
       <File FileName="MediaBrowser.ServerApplication\ApplicationHost.cs" Line="1" Column="1" />
       <File FileName="MediaBrowser.Server.Mono\Native\NativeApp.cs" Line="1" Column="1" />
       <File FileName="MediaBrowser.Server.Mono\Native\NativeApp.cs" Line="1" Column="1" />
-      <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="36" Column="37" />
+      <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="24" Column="15" />
     </Files>
     </Files>
   </MonoDevelop.Ide.Workbench>
   </MonoDevelop.Ide.Workbench>
   <MonoDevelop.Ide.DebuggingService.Breakpoints>
   <MonoDevelop.Ide.DebuggingService.Breakpoints>

+ 31 - 5
MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs

@@ -6,6 +6,7 @@ using MediaBrowser.Common.Updates;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Notifications;
 using MediaBrowser.Controller.Notifications;
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Plugins;
@@ -257,7 +258,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
                     NotificationType = NotificationType.NewLibraryContent.ToString()
                     NotificationType = NotificationType.NewLibraryContent.ToString()
                 };
                 };
 
 
-                notification.Variables["Name"] = item.Name;
+                notification.Variables["Name"] = GetItemName(item);
 
 
                 await SendNotification(notification).ConfigureAwait(false);
                 await SendNotification(notification).ConfigureAwait(false);
             }
             }
@@ -274,6 +275,31 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
             }
             }
         }
         }
 
 
+        private string GetItemName(BaseItem item)
+        {
+            var name = item.Name;
+
+            var hasSeries = item as IHasSeries;
+
+            if (hasSeries != null)
+            {
+                name = hasSeries.SeriesName + " - " + name;
+            }
+
+            var hasArtist = item as IHasArtist;
+            if (hasArtist != null)
+            {
+                var artists = hasArtist.AllArtists;
+
+                if (artists.Count > 0)
+                {
+                    name = hasArtist.AllArtists[0] + " - " + name;
+                }
+            }
+
+            return name;
+        }
+
         async void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
         async void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
         {
         {
             var notification = new NotificationRequest
             var notification = new NotificationRequest
@@ -286,9 +312,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
             await SendNotification(notification).ConfigureAwait(false);
             await SendNotification(notification).ConfigureAwait(false);
         }
         }
 
 
-        async void _taskManager_TaskCompleted(object sender, GenericEventArgs<TaskResult> e)
+        async void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
         {
         {
-            var result = e.Argument;
+            var result = e.Result;
 
 
             if (result.Status == TaskCompletionStatus.Failed)
             if (result.Status == TaskCompletionStatus.Failed)
             {
             {
@@ -301,8 +327,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
                     NotificationType = type
                     NotificationType = type
                 };
                 };
 
 
-                notification.Variables["Name"] = e.Argument.Name;
-                notification.Variables["ErrorMessage"] = e.Argument.ErrorMessage;
+                notification.Variables["Name"] = result.Name;
+                notification.Variables["ErrorMessage"] = result.ErrorMessage;
 
 
                 await SendNotification(notification).ConfigureAwait(false);
                 await SendNotification(notification).ConfigureAwait(false);
             }
             }

+ 2 - 2
MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs

@@ -106,9 +106,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
             _serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo);
             _serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo);
         }
         }
 
 
-        void _taskManager_TaskCompleted(object sender, GenericEventArgs<TaskResult> e)
+        void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
         {
         {
-            _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Argument);
+            _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Result);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 7 - 2
MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs

@@ -191,10 +191,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 throw new ArgumentNullException("displayPreferencesId");
                 throw new ArgumentNullException("displayPreferencesId");
             }
             }
 
 
+            var guidId = displayPreferencesId.GetMD5();
+
             var cmd = _connection.CreateCommand();
             var cmd = _connection.CreateCommand();
             cmd.CommandText = "select data from userdisplaypreferences where id = @id and userId=@userId and client=@client";
             cmd.CommandText = "select data from userdisplaypreferences where id = @id and userId=@userId and client=@client";
 
 
-            cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = displayPreferencesId.GetMD5();
+            cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = guidId;
             cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
             cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
             cmd.Parameters.Add(cmd, "@client", DbType.String).Value = client;
             cmd.Parameters.Add(cmd, "@client", DbType.String).Value = client;
 
 
@@ -209,7 +211,10 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 }
                 }
             }
             }
 
 
-            return null;
+            return new DisplayPreferences
+            {
+                Id = guidId.ToString("N")
+            };
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 15 - 5
MediaBrowser.Server.Implementations/Session/SessionManager.cs

@@ -282,7 +282,18 @@ namespace MediaBrowser.Server.Implementations.Session
 
 
             if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null)
             if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null)
             {
             {
-                info.Item = GetItemInfo(libraryItem, runtimeTicks, libraryItem, info.MediaSourceId);
+                var current = session.NowPlayingItem;
+
+                if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase))
+                {
+                    info.Item = GetItemInfo(libraryItem, libraryItem, info.MediaSourceId);
+                }
+                else
+                {
+                    info.Item = current;
+                }
+
+                info.Item.RunTimeTicks = runtimeTicks;
             }
             }
 
 
             session.NowPlayingItem = info.Item;
             session.NowPlayingItem = info.Item;
@@ -1182,12 +1193,11 @@ namespace MediaBrowser.Server.Implementations.Session
         /// Converts a BaseItem to a BaseItemInfo
         /// Converts a BaseItem to a BaseItemInfo
         /// </summary>
         /// </summary>
         /// <param name="item">The item.</param>
         /// <param name="item">The item.</param>
-        /// <param name="runtimeTicks">The now playing runtime ticks.</param>
         /// <param name="chapterOwner">The chapter owner.</param>
         /// <param name="chapterOwner">The chapter owner.</param>
         /// <param name="mediaSourceId">The media source identifier.</param>
         /// <param name="mediaSourceId">The media source identifier.</param>
         /// <returns>BaseItemInfo.</returns>
         /// <returns>BaseItemInfo.</returns>
         /// <exception cref="System.ArgumentNullException">item</exception>
         /// <exception cref="System.ArgumentNullException">item</exception>
-        private BaseItemInfo GetItemInfo(BaseItem item, long? runtimeTicks, BaseItem chapterOwner, string mediaSourceId)
+        private BaseItemInfo GetItemInfo(BaseItem item, BaseItem chapterOwner, string mediaSourceId)
         {
         {
             if (item == null)
             if (item == null)
             {
             {
@@ -1200,7 +1210,7 @@ namespace MediaBrowser.Server.Implementations.Session
                 Name = item.Name,
                 Name = item.Name,
                 MediaType = item.MediaType,
                 MediaType = item.MediaType,
                 Type = item.GetClientTypeName(),
                 Type = item.GetClientTypeName(),
-                RunTimeTicks = runtimeTicks,
+                RunTimeTicks = item.RunTimeTicks,
                 IndexNumber = item.IndexNumber,
                 IndexNumber = item.IndexNumber,
                 ParentIndexNumber = item.ParentIndexNumber,
                 ParentIndexNumber = item.ParentIndexNumber,
                 PremiereDate = item.PremiereDate,
                 PremiereDate = item.PremiereDate,
@@ -1376,7 +1386,7 @@ namespace MediaBrowser.Server.Implementations.Session
         {
         {
             var item = _libraryManager.GetItemById(new Guid(itemId));
             var item = _libraryManager.GetItemById(new Guid(itemId));
 
 
-            var info = GetItemInfo(item, item.RunTimeTicks, null, null);
+            var info = GetItemInfo(item, null, null);
 
 
             ReportNowViewingItem(sessionId, info);
             ReportNowViewingItem(sessionId, info);
         }
         }

+ 5 - 0
MediaBrowser.Server.Mono/Native/NativeApp.cs

@@ -51,5 +51,10 @@ namespace MediaBrowser.ServerApplication.Native
 		{
 		{
 			get { return false; }
 			get { return false; }
 		}
 		}
+
+        public static void PreventSystemStandby()
+        {
+            
+        }
     }
     }
 }
 }

+ 2 - 23
MediaBrowser.ServerApplication/EntryPoints/KeepServerAwake.cs

@@ -1,9 +1,9 @@
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.ServerApplication.Native;
 using System;
 using System;
 using System.Linq;
 using System.Linq;
-using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading;
 
 
 namespace MediaBrowser.ServerApplication.EntryPoints
 namespace MediaBrowser.ServerApplication.EntryPoints
@@ -37,7 +37,7 @@ namespace MediaBrowser.ServerApplication.EntryPoints
         {
         {
             try
             try
             {
             {
-                SystemHelper.ResetStandbyTimer();
+                NativeApp.PreventSystemStandby();
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
@@ -54,25 +54,4 @@ namespace MediaBrowser.ServerApplication.EntryPoints
             }
             }
         }
         }
     }
     }
-
-    internal enum EXECUTION_STATE : uint
-    {
-        ES_NONE = 0,
-        ES_SYSTEM_REQUIRED = 0x00000001,
-        ES_DISPLAY_REQUIRED = 0x00000002,
-        ES_USER_PRESENT = 0x00000004,
-        ES_AWAYMODE_REQUIRED = 0x00000040,
-        ES_CONTINUOUS = 0x80000000
-    }
-
-    public class SystemHelper
-    {
-        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
-        static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
-
-        public static void ResetStandbyTimer()
-        {
-            EXECUTION_STATE es = SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
-        }
-    }
 }
 }

+ 4 - 4
MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs

@@ -194,12 +194,12 @@ namespace MediaBrowser.ServerApplication.FFMpeg
             var uname = new Uname();
             var uname = new Uname();
 
 
 #if __MonoCS__
 #if __MonoCS__
-                Utsname uname;
-                var callResult = Syscall.uname(out uname);
+                Utsname utsname;
+                var callResult = Syscall.uname(out utsname);
                 if (callResult == 0)
                 if (callResult == 0)
                 {
                 {
-                    uname.sysname= uname.sysname;
-                    uname.machine= uname.machine;
+                    uname.sysname= utsname.sysname;
+                    uname.machine= utsname.machine;
                 }
                 }
 #endif
 #endif
             return uname;
             return uname;

+ 28 - 1
MediaBrowser.ServerApplication/Native/NativeApp.cs

@@ -1,4 +1,5 @@
-
+using System.Runtime.InteropServices;
+
 namespace MediaBrowser.ServerApplication.Native
 namespace MediaBrowser.ServerApplication.Native
 {
 {
     /// <summary>
     /// <summary>
@@ -57,5 +58,31 @@ namespace MediaBrowser.ServerApplication.Native
                 return MainStartup.CanSelfUpdate;
                 return MainStartup.CanSelfUpdate;
             }
             }
         }
         }
+
+        public static void PreventSystemStandby()
+        {
+            SystemHelper.ResetStandbyTimer();
+        }
+
+        internal enum EXECUTION_STATE : uint
+        {
+            ES_NONE = 0,
+            ES_SYSTEM_REQUIRED = 0x00000001,
+            ES_DISPLAY_REQUIRED = 0x00000002,
+            ES_USER_PRESENT = 0x00000004,
+            ES_AWAYMODE_REQUIRED = 0x00000040,
+            ES_CONTINUOUS = 0x80000000
+        }
+
+        public class SystemHelper
+        {
+            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+            static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
+
+            public static void ResetStandbyTimer()
+            {
+                EXECUTION_STATE es = SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
+            }
+        }
     }
     }
 }
 }

+ 6 - 0
OpenSubtitlesHandler/OpenSubtitlesHandler.csproj

@@ -29,6 +29,11 @@
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' ">
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Release Mono</OutputPath>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
@@ -113,6 +118,7 @@
     <Content Include="XML-RPC\Docs\XML-RPC.txt" />
     <Content Include="XML-RPC\Docs\XML-RPC.txt" />
   </ItemGroup>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">
   <Target Name="BeforeBuild">