浏览代码

added IProcessManager

Luke Pulverenti 10 年之前
父节点
当前提交
3d22c48670
共有 23 个文件被更改,包括 291 次插入23 次删除
  1. 21 1
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  2. 2 1
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  3. 2 1
      MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
  4. 2 1
      MediaBrowser.Api/Playback/Hls/MpegDashService.cs
  5. 2 1
      MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
  6. 2 1
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  7. 2 1
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  8. 2 1
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  9. 21 3
      MediaBrowser.Api/Playback/StreamState.cs
  10. 42 11
      MediaBrowser.Api/Playback/TranscodingThrottler.cs
  11. 28 0
      MediaBrowser.Controller/Diagnostics/IProcessManager.cs
  12. 1 0
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  13. 5 1
      MediaBrowser.Server.Implementations/Library/UserManager.cs
  14. 1 0
      MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncProvider.cs
  15. 25 0
      MediaBrowser.Server.Mono/Diagnostics/LinuxProcessManager.cs
  16. 24 0
      MediaBrowser.Server.Mono/Diagnostics/ProcessManager.cs
  17. 2 0
      MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
  18. 13 0
      MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
  19. 2 0
      MediaBrowser.Server.Startup.Common/ApplicationHost.cs
  20. 7 0
      MediaBrowser.Server.Startup.Common/INativeApp.cs
  21. 1 0
      MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
  22. 6 0
      MediaBrowser.ServerApplication/Native/WindowsApp.cs
  23. 78 0
      MediaBrowser.ServerApplication/Native/WindowsProcessManager.cs

+ 21 - 1
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Model.Extensions;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
@@ -70,12 +71,14 @@ namespace MediaBrowser.Api.Playback
         protected IDeviceManager DeviceManager { get; private set; }
         protected IChannelManager ChannelManager { get; private set; }
         protected ISubtitleEncoder SubtitleEncoder { get; private set; }
+        protected IProcessManager ProcessManager { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
         /// </summary>
-        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager)
+        protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager)
         {
+            ProcessManager = processManager;
             DeviceManager = deviceManager;
             SubtitleEncoder = subtitleEncoder;
             ChannelManager = channelManager;
@@ -1093,9 +1096,26 @@ namespace MediaBrowser.Api.Playback
                 }
             }
 
+            StartThrottler(state, transcodingJob);
+
             return transcodingJob;
         }
 
+        private void StartThrottler(StreamState state, TranscodingJob transcodingJob)
+        {
+            if (state.InputProtocol == MediaProtocol.File &&
+                           state.RunTimeTicks.HasValue &&
+                           state.VideoType == VideoType.VideoFile &&
+                           !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
+            {
+                if (state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks && state.IsInputVideo)
+                {
+                    state.TranscodingThrottler = new TranscodingThrottler(transcodingJob, Logger, ProcessManager);
+                    state.TranscodingThrottler.Start();
+                }
+            }
+        }
+
         private async void StartStreamingLog(TranscodingJob transcodingJob, StreamState state, Stream source, Stream target)
         {
             try

+ 2 - 1
MediaBrowser.Api/Playback/Hls/BaseHlsService.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
@@ -23,7 +24,7 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public abstract class BaseHlsService : BaseStreamingService
     {
-        protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager)
+        protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
         {
         }
 

+ 2 - 1
MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Model.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
@@ -63,7 +64,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
     public class DynamicHlsService : BaseHlsService
     {
-        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager)
+        public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
         {
             NetworkManager = networkManager;
         }

+ 2 - 1
MediaBrowser.Api/Playback/Hls/MpegDashService.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
@@ -51,7 +52,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
     public class MpegDashService : BaseHlsService
     {
-        public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager)
+        public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
         {
             NetworkManager = networkManager;
         }

+ 2 - 1
MediaBrowser.Api/Playback/Hls/VideoHlsService.cs

@@ -2,6 +2,7 @@ using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.LiveTv;
@@ -57,7 +58,7 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public class VideoHlsService : BaseHlsService
     {
-        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager)
+        public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
         {
         }
 

+ 2 - 1
MediaBrowser.Api/Playback/Progressive/AudioService.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Library;
@@ -32,7 +33,7 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class AudioService : BaseProgressiveStreamingService
     {
-        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, imageProcessor, httpClient)
+        public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager, imageProcessor, httpClient)
         {
         }
 

+ 2 - 1
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Library;
@@ -29,7 +30,7 @@ namespace MediaBrowser.Api.Playback.Progressive
         protected readonly IImageProcessor ImageProcessor;
         protected readonly IHttpClient HttpClient;
 
-        protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager)
+        protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager)
         {
             ImageProcessor = imageProcessor;
             HttpClient = httpClient;

+ 2 - 1
MediaBrowser.Api/Playback/Progressive/VideoService.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Library;
@@ -63,7 +64,7 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class VideoService : BaseProgressiveStreamingService
     {
-        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, imageProcessor, httpClient)
+        public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IProcessManager processManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder, deviceManager, processManager, imageProcessor, httpClient)
         {
         }
 

+ 21 - 3
MediaBrowser.Api/Playback/StreamState.cs

@@ -1,17 +1,16 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Net;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Threading;
-using MediaBrowser.Model.Net;
 
 namespace MediaBrowser.Api.Playback
 {
@@ -23,6 +22,7 @@ namespace MediaBrowser.Api.Playback
         public string RequestedUrl { get; set; }
 
         public StreamRequest Request { get; set; }
+        public TranscodingThrottler TranscodingThrottler { get; set; }
 
         public VideoStreamRequest VideoRequest
         {
@@ -125,6 +125,7 @@ namespace MediaBrowser.Api.Playback
 
         public void Dispose()
         {
+            DisposeTranscodingThrottler();
             DisposeLiveStream();
             DisposeLogStream();
             DisposeIsoMount();
@@ -147,6 +148,23 @@ namespace MediaBrowser.Api.Playback
             }
         }
 
+        private void DisposeTranscodingThrottler()
+        {
+            if (TranscodingThrottler != null)
+            {
+                try
+                {
+                    TranscodingThrottler.Dispose();
+                }
+                catch (Exception ex)
+                {
+                    _logger.ErrorException("Error disposing TranscodingThrottler", ex);
+                }
+
+                TranscodingThrottler = null;
+            }
+        }
+
         private void DisposeIsoMount()
         {
             if (IsoMount != null)

+ 42 - 11
MediaBrowser.Api/Playback/TranscodingThrottler.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Logging;
+using MediaBrowser.Controller.Diagnostics;
+using MediaBrowser.Model.Logging;
 using System;
 using System.IO;
 using System.Threading;
@@ -9,11 +10,16 @@ namespace MediaBrowser.Api.Playback
     {
         private readonly TranscodingJob _job;
         private readonly ILogger _logger;
+        private readonly IProcessManager _processManager;
         private Timer _timer;
+        private bool _isPaused;
 
         public void Start()
         {
-            _timer = new Timer(TimerCallback, null, 5000, 5000);
+            if (_processManager.SupportsSuspension)
+            {
+                _timer = new Timer(TimerCallback, null, 5000, 5000);
+            }
         }
 
         private void TimerCallback(object state)
@@ -36,22 +42,49 @@ namespace MediaBrowser.Api.Playback
 
         private void PauseTranscoding()
         {
-            _logger.Debug("Sending pause command to ffmpeg");
-            _job.Process.StandardInput.WriteLine("p");
+            if (!_isPaused)
+            {
+                _logger.Debug("Sending pause command to ffmpeg");
+            }
+
+            try
+            {
+                //_job.Process.StandardInput.WriteLine("p");
+                _processManager.SuspendProcess(_job.Process);
+                _isPaused = true;
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error pausing transcoding", ex);
+            }
         }
 
         private void UnpauseTranscoding()
         {
-            _logger.Debug("Sending unpause command to ffmpeg");
-            _job.Process.StandardInput.WriteLine("u");
+            if (_isPaused)
+            {
+                _logger.Debug("Sending unpause command to ffmpeg");
+            }
+
+            try
+            {
+                //_job.Process.StandardInput.WriteLine("u");
+                _processManager.ResumeProcess(_job.Process);
+                _isPaused = false;
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error unpausing transcoding", ex);
+            }
         }
 
         private readonly long _gapLengthInTicks = TimeSpan.FromMinutes(2).Ticks;
 
-        public TranscodingThrottler(TranscodingJob job, ILogger logger)
+        public TranscodingThrottler(TranscodingJob job, ILogger logger, IProcessManager processManager)
         {
             _job = job;
             _logger = logger;
+            _processManager = processManager;
         }
 
         private bool IsThrottleAllowed(TranscodingJob job)
@@ -106,13 +139,11 @@ namespace MediaBrowser.Api.Playback
                 catch
                 {
                     //_logger.Error("Error getting output size");
+                    return false;
                 }
             }
-            else
-            {
-                //_logger.Debug("No throttle data for " + path);
-            }
 
+            //_logger.Debug("No throttle data for " + path);
             return false;
         }
 

+ 28 - 0
MediaBrowser.Controller/Diagnostics/IProcessManager.cs

@@ -0,0 +1,28 @@
+using System.Diagnostics;
+
+namespace MediaBrowser.Controller.Diagnostics
+{
+    /// <summary>
+    /// Interface IProcessManager
+    /// </summary>
+    public interface IProcessManager
+    {
+        /// <summary>
+        /// Gets a value indicating whether [supports suspension].
+        /// </summary>
+        /// <value><c>true</c> if [supports suspension]; otherwise, <c>false</c>.</value>
+        bool SupportsSuspension { get; }
+
+        /// <summary>
+        /// Suspends the process.
+        /// </summary>
+        /// <param name="process">The process.</param>
+        void SuspendProcess(Process process);
+
+        /// <summary>
+        /// Resumes the process.
+        /// </summary>
+        /// <param name="process">The process.</param>
+        void ResumeProcess(Process process);
+    }
+}

+ 1 - 0
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -104,6 +104,7 @@
     <Compile Include="Devices\CameraImageUploadInfo.cs" />
     <Compile Include="Devices\IDeviceManager.cs" />
     <Compile Include="Devices\IDeviceRepository.cs" />
+    <Compile Include="Diagnostics\IProcessManager.cs" />
     <Compile Include="Dlna\ControlRequest.cs" />
     <Compile Include="Dlna\ControlResponse.cs" />
     <Compile Include="Dlna\EventSubscriptionResponse.cs" />

+ 5 - 1
MediaBrowser.Server.Implementations/Library/UserManager.cs

@@ -277,7 +277,11 @@ namespace MediaBrowser.Server.Implementations.Library
             {
                 user.Policy.InvalidLoginAttemptCount = newValue;
 
-                if (newValue >= 3)
+                var maxCount = user.Policy.IsAdministrator ? 
+                    3 : 
+                    5;
+
+                if (newValue >= maxCount)
                 {
                     _logger.Debug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture));
                     user.Policy.IsDisabled = true;

+ 1 - 0
MediaBrowser.Server.Implementations/Sync/FolderSync/FolderSyncProvider.cs

@@ -113,6 +113,7 @@ namespace MediaBrowser.Server.Implementations.Sync.FolderSync
 
         private IEnumerable<SyncAccount> GetSyncAccounts()
         {
+            return new List<SyncAccount>();
             // Dummy this up
             return _userManager
                 .Users

+ 25 - 0
MediaBrowser.Server.Mono/Diagnostics/LinuxProcessManager.cs

@@ -0,0 +1,25 @@
+using MediaBrowser.Controller.Diagnostics;
+using System.Diagnostics;
+
+namespace MediaBrowser.Server.Mono.Diagnostics
+{
+    public class LinuxProcessManager : IProcessManager
+    {
+        public bool SupportsSuspension
+        {
+            get { return true; }
+        }
+
+        public void SuspendProcess(Process process)
+        {
+            // http://jumptuck.com/2011/11/23/quick-tip-pause-process-linux/
+            process.StandardInput.WriteLine("^Z");
+        }
+
+        public void ResumeProcess(Process process)
+        {
+            // http://jumptuck.com/2011/11/23/quick-tip-pause-process-linux/
+            process.StandardInput.WriteLine("fg");
+        }
+    }
+}

+ 24 - 0
MediaBrowser.Server.Mono/Diagnostics/ProcessManager.cs

@@ -0,0 +1,24 @@
+using MediaBrowser.Controller.Diagnostics;
+using System;
+using System.Diagnostics;
+
+namespace MediaBrowser.Server.Mono.Diagnostics
+{
+    public class ProcessManager : IProcessManager
+    {
+        public void SuspendProcess(Process process)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void ResumeProcess(Process process)
+        {
+            throw new NotImplementedException();
+        }
+
+        public bool SupportsSuspension
+        {
+            get { return false; }
+        }
+    }
+}

+ 2 - 0
MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj

@@ -74,6 +74,8 @@
     <Compile Include="..\SharedVersion.cs">
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
+    <Compile Include="Diagnostics\LinuxProcessManager.cs" />
+    <Compile Include="Diagnostics\ProcessManager.cs" />
     <Compile Include="Native\BaseMonoApp.cs" />
     <Compile Include="Networking\CertificateGenerator.cs" />
     <Compile Include="Program.cs" />

+ 13 - 0
MediaBrowser.Server.Mono/Native/BaseMonoApp.cs

@@ -1,6 +1,8 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.IsoMounter;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Server.Mono.Diagnostics;
 using MediaBrowser.Server.Mono.Networking;
 using MediaBrowser.Server.Startup.Common;
 using Mono.Unix.Native;
@@ -189,5 +191,16 @@ namespace MediaBrowser.Server.Mono.Native
             public string sysname = string.Empty;
             public string machine = string.Empty;
         }
+
+
+        public IProcessManager GetProcessManager()
+        {
+            if (Environment.OperatingSystem == Startup.Common.OperatingSystem.Linux)
+            {
+                return new LinuxProcessManager();
+            }
+
+            return new ProcessManager();
+        }
     }
 }

+ 2 - 0
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -380,6 +380,8 @@ namespace MediaBrowser.Server.Startup.Common
 
             RegisterSingleInstance(ServerConfigurationManager);
 
+            RegisterSingleInstance(NativeApp.GetProcessManager());
+
             LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer);
             RegisterSingleInstance(LocalizationManager);
 

+ 7 - 0
MediaBrowser.Server.Startup.Common/INativeApp.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.Model.Logging;
 using System.Collections.Generic;
 using System.Reflection;
@@ -84,5 +85,11 @@ namespace MediaBrowser.Server.Startup.Common
         /// Prevents the system stand by.
         /// </summary>
         void PreventSystemStandby();
+
+        /// <summary>
+        /// Gets the process manager.
+        /// </summary>
+        /// <returns>IProcessManager.</returns>
+        IProcessManager GetProcessManager();
     }
 }

+ 1 - 0
MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj

@@ -113,6 +113,7 @@
     <Compile Include="Native\Standby.cs" />
     <Compile Include="Native\ServerAuthorization.cs" />
     <Compile Include="Native\WindowsApp.cs" />
+    <Compile Include="Native\WindowsProcessManager.cs" />
     <Compile Include="Networking\CertificateGenerator.cs" />
     <Compile Include="Networking\NativeMethods.cs" />
     <Compile Include="Networking\NetworkManager.cs" />

+ 6 - 0
MediaBrowser.ServerApplication/Native/WindowsApp.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Diagnostics;
 using MediaBrowser.IsoMounter;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Server.Startup.Common;
@@ -109,5 +110,10 @@ namespace MediaBrowser.ServerApplication.Native
         {
             Standby.PreventSystemStandby();
         }
+
+        public IProcessManager GetProcessManager()
+        {
+            return new WindowsProcessManager();
+        }
     }
 }

+ 78 - 0
MediaBrowser.ServerApplication/Native/WindowsProcessManager.cs

@@ -0,0 +1,78 @@
+using MediaBrowser.Controller.Diagnostics;
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace MediaBrowser.ServerApplication.Native
+{
+    public class WindowsProcessManager : IProcessManager
+    {
+        public void SuspendProcess(Process process)
+        {
+            process.Suspend();
+        }
+
+        public void ResumeProcess(Process process)
+        {
+            process.Resume();
+        }
+
+        public bool SupportsSuspension
+        {
+            get { return true; }
+        }
+    }
+
+    public static class ProcessExtension
+    {
+        [DllImport("kernel32.dll")]
+        static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
+        [DllImport("kernel32.dll")]
+        static extern uint SuspendThread(IntPtr hThread);
+        [DllImport("kernel32.dll")]
+        static extern int ResumeThread(IntPtr hThread);
+
+        public static void Suspend(this Process process)
+        {
+            foreach (ProcessThread thread in process.Threads)
+            {
+                var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
+                if (pOpenThread == IntPtr.Zero)
+                {
+                    break;
+                }
+                SuspendThread(pOpenThread);
+            }
+        }
+        public static void Resume(this Process process)
+        {
+            foreach (ProcessThread thread in process.Threads)
+            {
+                var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
+                if (pOpenThread == IntPtr.Zero)
+                {
+                    break;
+                }
+                ResumeThread(pOpenThread);
+            }
+        }
+        public static void Print(this Process process)
+        {
+            Console.WriteLine("{0,8}    {1}", process.Id, process.ProcessName);
+        }
+    }
+
+    [Flags]
+    public enum ThreadAccess : int
+    {
+        TERMINATE = (0x0001),
+        SUSPEND_RESUME = (0x0002),
+        GET_CONTEXT = (0x0008),
+        SET_CONTEXT = (0x0010),
+        SET_INFORMATION = (0x0020),
+        QUERY_INFORMATION = (0x0040),
+        SET_THREAD_TOKEN = (0x0080),
+        IMPERSONATE = (0x0100),
+        DIRECT_IMPERSONATION = (0x0200)
+    }
+}