commit
8b1b775caa
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -13,6 +13,8 @@ tmp/
|
||||||
*.bak
|
*.bak
|
||||||
*.swp
|
*.swp
|
||||||
*~.nib
|
*~.nib
|
||||||
|
project.fragment.lock.json
|
||||||
|
project.lock.json
|
||||||
local.properties
|
local.properties
|
||||||
.classpath
|
.classpath
|
||||||
.settings/
|
.settings/
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -27,11 +27,16 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using Emby.Common.Implementations.Cryptography;
|
using Emby.Common.Implementations.Cryptography;
|
||||||
|
using Emby.Common.Implementations.Diagnostics;
|
||||||
|
using Emby.Common.Implementations.Threading;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Model.Cryptography;
|
using MediaBrowser.Model.Cryptography;
|
||||||
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
#if NETSTANDARD1_6
|
#if NETSTANDARD1_6
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
#endif
|
#endif
|
||||||
|
@ -146,6 +151,9 @@ namespace Emby.Common.Implementations
|
||||||
|
|
||||||
protected ISystemEvents SystemEvents { get; private set; }
|
protected ISystemEvents SystemEvents { get; private set; }
|
||||||
|
|
||||||
|
protected IProcessFactory ProcessFactory { get; private set; }
|
||||||
|
protected ITimerFactory TimerFactory { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name.
|
/// Gets the name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -535,6 +543,12 @@ return null;
|
||||||
IsoManager = new IsoManager();
|
IsoManager = new IsoManager();
|
||||||
RegisterSingleInstance(IsoManager);
|
RegisterSingleInstance(IsoManager);
|
||||||
|
|
||||||
|
ProcessFactory = new ProcessFactory();
|
||||||
|
RegisterSingleInstance(ProcessFactory);
|
||||||
|
|
||||||
|
TimerFactory = new TimerFactory();
|
||||||
|
RegisterSingleInstance(TimerFactory);
|
||||||
|
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
108
Emby.Common.Implementations/Diagnostics/CommonProcess.cs
Normal file
108
Emby.Common.Implementations/Diagnostics/CommonProcess.cs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Diagnostics;
|
||||||
|
|
||||||
|
namespace Emby.Common.Implementations.Diagnostics
|
||||||
|
{
|
||||||
|
public class CommonProcess : IProcess
|
||||||
|
{
|
||||||
|
public event EventHandler Exited;
|
||||||
|
|
||||||
|
private readonly ProcessOptions _options;
|
||||||
|
private readonly Process _process;
|
||||||
|
|
||||||
|
public CommonProcess(ProcessOptions options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
|
||||||
|
var startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
Arguments = options.Arguments,
|
||||||
|
FileName = options.FileName,
|
||||||
|
WorkingDirectory = options.WorkingDirectory,
|
||||||
|
UseShellExecute = options.UseShellExecute,
|
||||||
|
CreateNoWindow = options.CreateNoWindow,
|
||||||
|
RedirectStandardError = options.RedirectStandardError,
|
||||||
|
RedirectStandardInput = options.RedirectStandardInput,
|
||||||
|
RedirectStandardOutput = options.RedirectStandardOutput
|
||||||
|
};
|
||||||
|
|
||||||
|
#if NET46
|
||||||
|
startInfo.ErrorDialog = options.ErrorDialog;
|
||||||
|
|
||||||
|
if (options.IsHidden)
|
||||||
|
{
|
||||||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = startInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.EnableRaisingEvents)
|
||||||
|
{
|
||||||
|
_process.EnableRaisingEvents = true;
|
||||||
|
_process.Exited += _process_Exited;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _process_Exited(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (Exited != null)
|
||||||
|
{
|
||||||
|
Exited(_process, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessOptions StartInfo
|
||||||
|
{
|
||||||
|
get { return _options; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamWriter StandardInput
|
||||||
|
{
|
||||||
|
get { return _process.StandardInput; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamReader StandardError
|
||||||
|
{
|
||||||
|
get { return _process.StandardError; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamReader StandardOutput
|
||||||
|
{
|
||||||
|
get { return _process.StandardOutput; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ExitCode
|
||||||
|
{
|
||||||
|
get { return _process.ExitCode; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
_process.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Kill()
|
||||||
|
{
|
||||||
|
_process.Kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WaitForExit(int timeMs)
|
||||||
|
{
|
||||||
|
return _process.WaitForExit(timeMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_process.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Emby.Common.Implementations/Diagnostics/ProcessFactory.cs
Normal file
12
Emby.Common.Implementations/Diagnostics/ProcessFactory.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using MediaBrowser.Model.Diagnostics;
|
||||||
|
|
||||||
|
namespace Emby.Common.Implementations.Diagnostics
|
||||||
|
{
|
||||||
|
public class ProcessFactory : IProcessFactory
|
||||||
|
{
|
||||||
|
public IProcess Create(ProcessOptions options)
|
||||||
|
{
|
||||||
|
return new CommonProcess(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -577,6 +577,23 @@ namespace Emby.Common.Implementations.IO
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<FileSystemMetadata> GetDrives()
|
||||||
|
{
|
||||||
|
// Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout
|
||||||
|
return DriveInfo.GetDrives().Where(d => d.IsReady).Select(d => new FileSystemMetadata
|
||||||
|
{
|
||||||
|
Name = GetName(d),
|
||||||
|
FullName = d.RootDirectory.FullName,
|
||||||
|
IsDirectory = true
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetName(DriveInfo drive)
|
||||||
|
{
|
||||||
|
return drive.Name;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
|
public IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
|
||||||
{
|
{
|
||||||
var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||||
|
|
39
Emby.Common.Implementations/Threading/CommonTimer.cs
Normal file
39
Emby.Common.Implementations/Threading/CommonTimer.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
|
namespace Emby.Common.Implementations.Threading
|
||||||
|
{
|
||||||
|
public class CommonTimer : ITimer
|
||||||
|
{
|
||||||
|
private readonly Timer _timer;
|
||||||
|
|
||||||
|
public CommonTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
|
||||||
|
{
|
||||||
|
_timer = new Timer(new TimerCallback(callback), state, dueTime, period);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonTimer(Action<object> callback, object state, int dueTimeMs, int periodMs)
|
||||||
|
{
|
||||||
|
_timer = new Timer(new TimerCallback(callback), state, dueTimeMs, periodMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Change(TimeSpan dueTime, TimeSpan period)
|
||||||
|
{
|
||||||
|
_timer.Change(dueTime, period);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Change(int dueTimeMs, int periodMs)
|
||||||
|
{
|
||||||
|
_timer.Change(dueTimeMs, periodMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_timer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
Emby.Common.Implementations/Threading/TimerFactory.cs
Normal file
21
Emby.Common.Implementations/Threading/TimerFactory.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
|
namespace Emby.Common.Implementations.Threading
|
||||||
|
{
|
||||||
|
public class TimerFactory : ITimerFactory
|
||||||
|
{
|
||||||
|
public ITimer Create(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
|
||||||
|
{
|
||||||
|
return new CommonTimer(callback, state, dueTime, period);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITimer Create(Action<object> callback, object state, int dueTimeMs, int periodMs)
|
||||||
|
{
|
||||||
|
return new CommonTimer(callback, state, dueTimeMs, periodMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,10 @@
|
||||||
"MediaBrowser.Model": {
|
"MediaBrowser.Model": {
|
||||||
"target": "project"
|
"target": "project"
|
||||||
},
|
},
|
||||||
"System.Net.Requests": "4.0.11",
|
"System.IO.FileSystem.DriveInfo": "4.0.0",
|
||||||
|
"System.Diagnostics.Process": "4.1.0",
|
||||||
|
"System.Threading.Timer": "4.0.1",
|
||||||
|
"System.Net.Requests": "4.0.11",
|
||||||
"System.Xml.XmlSerializer": "4.0.11",
|
"System.Xml.XmlSerializer": "4.0.11",
|
||||||
"System.Net.Http": "4.1.0",
|
"System.Net.Http": "4.1.0",
|
||||||
"System.Net.Primitives": "4.0.11",
|
"System.Net.Primitives": "4.0.11",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -42,6 +42,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Emby.Dlna", "Emby.Dlna\Emby
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -145,6 +149,18 @@ Global
|
||||||
{89AB4548-770D-41FD-A891-8DAFF44F452C}.Release Mono|Any CPU.Build.0 = Release|Any CPU
|
{89AB4548-770D-41FD-A891-8DAFF44F452C}.Release Mono|Any CPU.Build.0 = Release|Any CPU
|
||||||
{89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.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.Build.0 = Release Mono|Any CPU
|
||||||
|
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.Build.0 = Debug|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.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -166,5 +182,7 @@ Global
|
||||||
{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
{C227ADB7-E256-4E70-A8B9-22B9E0CF4F55} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||||
{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||||
{89AB4548-770D-41FD-A891-8DAFF44F452C} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
{89AB4548-770D-41FD-A891-8DAFF44F452C} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||||
|
{4FD51AC5-2C16-4308-A993-C3A84F3B4582} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||||
|
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451} = {8ADD772F-F0A4-4A53-9B2F-AF4A4C585839}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -16,9 +16,10 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
|
@ -46,6 +47,8 @@ namespace MediaBrowser.Api
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
public readonly ITimerFactory TimerFactory;
|
||||||
|
public readonly IProcessFactory ProcessFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The active transcoding jobs
|
/// The active transcoding jobs
|
||||||
|
@ -63,13 +66,15 @@ namespace MediaBrowser.Api
|
||||||
/// <param name="config">The configuration.</param>
|
/// <param name="config">The configuration.</param>
|
||||||
/// <param name="fileSystem">The file system.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <param name="mediaSourceManager">The media source manager.</param>
|
/// <param name="mediaSourceManager">The media source manager.</param>
|
||||||
public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager)
|
public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager, ITimerFactory timerFactory, IProcessFactory processFactory)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
|
TimerFactory = timerFactory;
|
||||||
|
ProcessFactory = processFactory;
|
||||||
|
|
||||||
Instance = this;
|
Instance = this;
|
||||||
_sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress;
|
_sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress;
|
||||||
|
@ -116,7 +121,7 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
DeleteEncodedMediaCache();
|
DeleteEncodedMediaCache();
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
// Don't clutter the log
|
// Don't clutter the log
|
||||||
}
|
}
|
||||||
|
@ -168,7 +173,8 @@ namespace MediaBrowser.Api
|
||||||
// Try to allow for some time to kill the ffmpeg processes and delete the partial stream files
|
// Try to allow for some time to kill the ffmpeg processes and delete the partial stream files
|
||||||
if (jobCount > 0)
|
if (jobCount > 0)
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
var task = Task.Delay(1000);
|
||||||
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,14 +196,14 @@ namespace MediaBrowser.Api
|
||||||
string liveStreamId,
|
string liveStreamId,
|
||||||
string transcodingJobId,
|
string transcodingJobId,
|
||||||
TranscodingJobType type,
|
TranscodingJobType type,
|
||||||
Process process,
|
IProcess process,
|
||||||
string deviceId,
|
string deviceId,
|
||||||
StreamState state,
|
StreamState state,
|
||||||
CancellationTokenSource cancellationTokenSource)
|
CancellationTokenSource cancellationTokenSource)
|
||||||
{
|
{
|
||||||
lock (_activeTranscodingJobs)
|
lock (_activeTranscodingJobs)
|
||||||
{
|
{
|
||||||
var job = new TranscodingJob(Logger)
|
var job = new TranscodingJob(Logger, TimerFactory)
|
||||||
{
|
{
|
||||||
Type = type,
|
Type = type,
|
||||||
Path = path,
|
Path = path,
|
||||||
|
@ -599,10 +605,6 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
DeleteHlsPartialStreamFiles(path);
|
DeleteHlsPartialStreamFiles(path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (DirectoryNotFoundException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
|
@ -650,10 +652,6 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
//Logger.Debug("Deleting HLS file {0}", file);
|
//Logger.Debug("Deleting HLS file {0}", file);
|
||||||
_fileSystem.DeleteFile(file);
|
_fileSystem.DeleteFile(file);
|
||||||
}
|
|
||||||
catch (DirectoryNotFoundException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
|
@ -706,7 +704,7 @@ namespace MediaBrowser.Api
|
||||||
/// Gets or sets the process.
|
/// Gets or sets the process.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The process.</value>
|
/// <value>The process.</value>
|
||||||
public Process Process { get; set; }
|
public IProcess Process { get; set; }
|
||||||
public ILogger Logger { get; private set; }
|
public ILogger Logger { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the active request count.
|
/// Gets or sets the active request count.
|
||||||
|
@ -717,7 +715,9 @@ namespace MediaBrowser.Api
|
||||||
/// Gets or sets the kill timer.
|
/// Gets or sets the kill timer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The kill timer.</value>
|
/// <value>The kill timer.</value>
|
||||||
private Timer KillTimer { get; set; }
|
private ITimer KillTimer { get; set; }
|
||||||
|
|
||||||
|
private readonly ITimerFactory _timerFactory;
|
||||||
|
|
||||||
public string DeviceId { get; set; }
|
public string DeviceId { get; set; }
|
||||||
|
|
||||||
|
@ -747,9 +747,10 @@ namespace MediaBrowser.Api
|
||||||
public DateTime LastPingDate { get; set; }
|
public DateTime LastPingDate { get; set; }
|
||||||
public int PingTimeout { get; set; }
|
public int PingTimeout { get; set; }
|
||||||
|
|
||||||
public TranscodingJob(ILogger logger)
|
public TranscodingJob(ILogger logger, ITimerFactory timerFactory)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
|
_timerFactory = timerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopKillTimer()
|
public void StopKillTimer()
|
||||||
|
@ -775,12 +776,12 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartKillTimer(TimerCallback callback)
|
public void StartKillTimer(Action<object> callback)
|
||||||
{
|
{
|
||||||
StartKillTimer(callback, PingTimeout);
|
StartKillTimer(callback, PingTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartKillTimer(TimerCallback callback, int intervalMs)
|
public void StartKillTimer(Action<object> callback, int intervalMs)
|
||||||
{
|
{
|
||||||
if (HasExited)
|
if (HasExited)
|
||||||
{
|
{
|
||||||
|
@ -792,7 +793,7 @@ namespace MediaBrowser.Api
|
||||||
if (KillTimer == null)
|
if (KillTimer == null)
|
||||||
{
|
{
|
||||||
//Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
//Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||||
KillTimer = new Timer(callback, this, intervalMs, Timeout.Infinite);
|
KillTimer = _timerFactory.Create(callback, this, intervalMs, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
|
@ -22,8 +23,8 @@ namespace MediaBrowser.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _active connections
|
/// The _active connections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly List<Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>> ActiveConnections =
|
protected readonly List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>> ActiveConnections =
|
||||||
new List<Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>>();
|
new List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name.
|
/// Gets the name.
|
||||||
|
@ -43,12 +44,9 @@ namespace MediaBrowser.Api
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ILogger Logger;
|
protected ILogger Logger;
|
||||||
|
|
||||||
/// <summary>
|
protected ITimerFactory TimerFactory { get; private set; }
|
||||||
/// Initializes a new instance of the <see cref="BasePeriodicWebSocketListener{TStateType}" /> class.
|
|
||||||
/// </summary>
|
protected BasePeriodicWebSocketListener(ILogger logger, ITimerFactory timerFactory)
|
||||||
/// <param name="logger">The logger.</param>
|
|
||||||
/// <exception cref="System.ArgumentNullException">logger</exception>
|
|
||||||
protected BasePeriodicWebSocketListener(ILogger logger)
|
|
||||||
{
|
{
|
||||||
if (logger == null)
|
if (logger == null)
|
||||||
{
|
{
|
||||||
|
@ -56,6 +54,7 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
|
TimerFactory = timerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -124,7 +123,7 @@ namespace MediaBrowser.Api
|
||||||
Logger.Debug("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name);
|
Logger.Debug("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name);
|
||||||
|
|
||||||
var timer = SendOnTimer ?
|
var timer = SendOnTimer ?
|
||||||
new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) :
|
TimerFactory.Create(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
var state = new TStateType
|
var state = new TStateType
|
||||||
|
@ -137,7 +136,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
lock (ActiveConnections)
|
lock (ActiveConnections)
|
||||||
{
|
{
|
||||||
ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>(message.Connection, cancellationTokenSource, timer, state, semaphore));
|
ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>(message.Connection, cancellationTokenSource, timer, state, semaphore));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timer != null)
|
if (timer != null)
|
||||||
|
@ -154,7 +153,7 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
var connection = (IWebSocketConnection)state;
|
var connection = (IWebSocketConnection)state;
|
||||||
|
|
||||||
Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> tuple;
|
Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim> tuple;
|
||||||
|
|
||||||
lock (ActiveConnections)
|
lock (ActiveConnections)
|
||||||
{
|
{
|
||||||
|
@ -177,7 +176,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
protected void SendData(bool force)
|
protected void SendData(bool force)
|
||||||
{
|
{
|
||||||
List<Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>> tuples;
|
List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>> tuples;
|
||||||
|
|
||||||
lock (ActiveConnections)
|
lock (ActiveConnections)
|
||||||
{
|
{
|
||||||
|
@ -205,7 +204,7 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SendData(Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> tuple)
|
private async void SendData(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim> tuple)
|
||||||
{
|
{
|
||||||
var connection = tuple.Item1;
|
var connection = tuple.Item1;
|
||||||
|
|
||||||
|
@ -266,7 +265,7 @@ namespace MediaBrowser.Api
|
||||||
/// Disposes the connection.
|
/// Disposes the connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connection">The connection.</param>
|
/// <param name="connection">The connection.</param>
|
||||||
private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> connection)
|
private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim> connection)
|
||||||
{
|
{
|
||||||
Logger.Debug("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name);
|
Logger.Debug("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name);
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,8 @@ using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Controller.IO;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
|
@ -110,6 +106,7 @@ namespace MediaBrowser.Api
|
||||||
public class EnvironmentService : BaseApiService
|
public class EnvironmentService : BaseApiService
|
||||||
{
|
{
|
||||||
const char UncSeparator = '\\';
|
const char UncSeparator = '\\';
|
||||||
|
const string UncSeparatorString = "\\";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _network manager
|
/// The _network manager
|
||||||
|
@ -139,7 +136,7 @@ namespace MediaBrowser.Api
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var qnap = "/share/CACHEDEV1_DATA";
|
var qnap = "/share/CACHEDEV1_DATA";
|
||||||
if (Directory.Exists(qnap))
|
if (_fileSystem.DirectoryExists(qnap))
|
||||||
{
|
{
|
||||||
result.Path = qnap;
|
result.Path = qnap;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +163,7 @@ namespace MediaBrowser.Api
|
||||||
throw new ArgumentNullException("Path");
|
throw new ArgumentNullException("Path");
|
||||||
}
|
}
|
||||||
|
|
||||||
var networkPrefix = UncSeparator.ToString(CultureInfo.InvariantCulture) + UncSeparator.ToString(CultureInfo.InvariantCulture);
|
var networkPrefix = UncSeparatorString + UncSeparatorString;
|
||||||
|
|
||||||
if (path.StartsWith(networkPrefix, StringComparison.OrdinalIgnoreCase) && path.LastIndexOf(UncSeparator) == 1)
|
if (path.StartsWith(networkPrefix, StringComparison.OrdinalIgnoreCase) && path.LastIndexOf(UncSeparator) == 1)
|
||||||
{
|
{
|
||||||
|
@ -203,13 +200,11 @@ namespace MediaBrowser.Api
|
||||||
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
|
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
|
||||||
private IEnumerable<FileSystemEntryInfo> GetDrives()
|
private IEnumerable<FileSystemEntryInfo> GetDrives()
|
||||||
{
|
{
|
||||||
// Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout
|
return _fileSystem.GetDrives().Select(d => new FileSystemEntryInfo
|
||||||
return DriveInfo.GetDrives().Where(d => d.IsReady).Select(d => new FileSystemEntryInfo
|
|
||||||
{
|
{
|
||||||
Name = GetName(d),
|
Name = d.Name,
|
||||||
Path = d.RootDirectory.FullName,
|
Path = d.FullName,
|
||||||
Type = FileSystemEntryType.Directory
|
Type = FileSystemEntryType.Directory
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,16 +222,6 @@ namespace MediaBrowser.Api
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="drive">The drive.</param>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
private string GetName(DriveInfo drive)
|
|
||||||
{
|
|
||||||
return drive.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the network shares.
|
/// Gets the network shares.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Api.Images
|
||||||
.OrderBy(i => i.Name)
|
.OrderBy(i => i.Name)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
return new List<ImageByNameInfo>();
|
return new List<ImageByNameInfo>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,7 +320,7 @@ namespace MediaBrowser.Api.Images
|
||||||
{
|
{
|
||||||
if (info.IsLocalFile)
|
if (info.IsLocalFile)
|
||||||
{
|
{
|
||||||
var fileInfo = new FileInfo(info.Path);
|
var fileInfo = _fileSystem.GetFileInfo(info.Path);
|
||||||
length = fileInfo.Length;
|
length = fileInfo.Length;
|
||||||
|
|
||||||
var size = _imageProcessor.GetImageSize(info);
|
var size = _imageProcessor.GetImageSize(info);
|
||||||
|
|
|
@ -234,21 +234,18 @@ namespace MediaBrowser.Api.Images
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(pointerCachePath))
|
contentPath = _fileSystem.ReadAllText(pointerCachePath);
|
||||||
{
|
|
||||||
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_fileSystem.FileExists(contentPath))
|
if (_fileSystem.FileExists(contentPath))
|
||||||
{
|
{
|
||||||
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
// Means the file isn't cached yet
|
// Means the file isn't cached yet
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
// Means the file isn't cached yet
|
// Means the file isn't cached yet
|
||||||
}
|
}
|
||||||
|
@ -256,10 +253,7 @@ namespace MediaBrowser.Api.Images
|
||||||
await DownloadImage(request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
|
await DownloadImage(request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
|
||||||
|
|
||||||
// Read the pointer file again
|
// Read the pointer file again
|
||||||
using (var reader = new StreamReader(pointerCachePath))
|
contentPath = _fileSystem.ReadAllText(pointerCachePath);
|
||||||
{
|
|
||||||
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -294,10 +288,7 @@ namespace MediaBrowser.Api.Images
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
|
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
|
||||||
using (var writer = new StreamWriter(pointerCachePath))
|
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
|
||||||
{
|
|
||||||
await writer.WriteAsync(fullCachePath).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -247,21 +247,18 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(pointerCachePath))
|
contentPath = _fileSystem.ReadAllText(pointerCachePath);
|
||||||
{
|
|
||||||
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_fileSystem.FileExists(contentPath))
|
if (_fileSystem.FileExists(contentPath))
|
||||||
{
|
{
|
||||||
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
// Means the file isn't cached yet
|
// Means the file isn't cached yet
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
// Means the file isn't cached yet
|
// Means the file isn't cached yet
|
||||||
}
|
}
|
||||||
|
@ -269,10 +266,7 @@ namespace MediaBrowser.Api
|
||||||
await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
|
await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
|
||||||
|
|
||||||
// Read the pointer file again
|
// Read the pointer file again
|
||||||
using (var reader = new StreamReader(pointerCachePath))
|
contentPath = _fileSystem.ReadAllText(pointerCachePath);
|
||||||
{
|
|
||||||
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -303,10 +297,7 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
|
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
|
||||||
using (var writer = new StreamWriter(pointerCachePath))
|
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
|
||||||
{
|
|
||||||
await writer.WriteAsync(fullCachePath).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -204,10 +204,10 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
public void Post(DeleteSmartMatchEntry request)
|
public void Post(DeleteSmartMatchEntry request)
|
||||||
{
|
{
|
||||||
request.Entries.ForEach(entry =>
|
foreach (var entry in request.Entries)
|
||||||
{
|
{
|
||||||
_iFileOrganizationService.DeleteSmartMatchEntry(entry.Name, entry.Value);
|
_iFileOrganizationService.DeleteSmartMatchEntry(entry.Name, entry.Value);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,7 +259,7 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
if (!_fileSystem.DirectoryExists(currentPath))
|
if (!_fileSystem.DirectoryExists(currentPath))
|
||||||
{
|
{
|
||||||
throw new DirectoryNotFoundException("The media collection does not exist");
|
throw new FileNotFoundException("The media collection does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && _fileSystem.DirectoryExists(newPath))
|
if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && _fileSystem.DirectoryExists(newPath))
|
||||||
|
|
|
@ -22,7 +22,6 @@ using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
using MediaBrowser.Server.Implementations.LiveTv.EmbyTV;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.LiveTv
|
namespace MediaBrowser.Api.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -708,11 +707,11 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetLiveRecordingFile request)
|
public object Get(GetLiveRecordingFile request)
|
||||||
{
|
{
|
||||||
var path = EmbyTV.Current.GetActiveRecordingPath(request.Id);
|
var path = _liveTvManager.GetEmbyTvActiveRecordingPath(request.Id);
|
||||||
|
|
||||||
if (path == null)
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
{
|
{
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
}
|
}
|
||||||
|
@ -729,7 +728,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
public async Task<object> Get(GetLiveStreamFile request)
|
public async Task<object> Get(GetLiveStreamFile request)
|
||||||
{
|
{
|
||||||
var directStreamProvider = (await EmbyTV.Current.GetLiveStream(request.Id).ConfigureAwait(false)) as IDirectStreamProvider;
|
var directStreamProvider = (await _liveTvManager.GetEmbyTvLiveStream(request.Id).ConfigureAwait(false)) as IDirectStreamProvider;
|
||||||
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file." + request.Container);
|
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file." + request.Container);
|
||||||
|
|
|
@ -11,10 +11,9 @@
|
||||||
<AssemblyName>MediaBrowser.Api</AssemblyName>
|
<AssemblyName>MediaBrowser.Api</AssemblyName>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
<ReleaseVersion>
|
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
|
||||||
</ReleaseVersion>
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
<TargetFrameworkProfile />
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -45,13 +44,6 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
<Link>Properties\SharedVersion.cs</Link>
|
<Link>Properties\SharedVersion.cs</Link>
|
||||||
|
@ -183,12 +175,8 @@
|
||||||
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
|
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
|
||||||
<Name>MediaBrowser.Model</Name>
|
<Name>MediaBrowser.Model</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\MediaBrowser.Server.Implementations\MediaBrowser.Server.Implementations.csproj">
|
|
||||||
<Project>{2e781478-814d-4a48-9d80-bff206441a65}</Project>
|
|
||||||
<Name>MediaBrowser.Server.Implementations</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
|
|
6
MediaBrowser.Api/MediaBrowser.Api.nuget.targets
Normal file
6
MediaBrowser.Api/MediaBrowser.Api.nuget.targets
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="EmitMSBuildWarning" BeforeTargets="Build">
|
||||||
|
<Warning Text="Packages containing MSBuild targets and props files cannot be fully installed in projects targeting multiple frameworks. The MSBuild targets and props files have been ignored." />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
|
@ -2,7 +2,6 @@
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Devices;
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
@ -14,18 +13,15 @@ using MediaBrowser.Model.MediaInfo;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback
|
namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
|
@ -536,7 +532,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-pix_fmt yuv420p " + param;
|
param = "-pix_fmt yuv420p " + param;
|
||||||
|
@ -1159,32 +1154,24 @@ namespace MediaBrowser.Api.Playback
|
||||||
var transcodingId = Guid.NewGuid().ToString("N");
|
var transcodingId = Guid.NewGuid().ToString("N");
|
||||||
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
||||||
|
|
||||||
var process = new Process
|
var process = ApiEntryPoint.Instance.ProcessFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
|
|
||||||
// Must consume both stdout and stderr or deadlocks may occur
|
// Must consume both stdout and stderr or deadlocks may occur
|
||||||
//RedirectStandardOutput = true,
|
//RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
RedirectStandardInput = true,
|
RedirectStandardInput = true,
|
||||||
|
|
||||||
FileName = MediaEncoder.EncoderPath,
|
FileName = MediaEncoder.EncoderPath,
|
||||||
Arguments = commandLineArgs,
|
Arguments = commandLineArgs,
|
||||||
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
IsHidden = true,
|
||||||
ErrorDialog = false
|
ErrorDialog = false,
|
||||||
},
|
EnableRaisingEvents = true,
|
||||||
|
WorkingDirectory = !string.IsNullOrWhiteSpace(workingDirectory) ? workingDirectory : null
|
||||||
EnableRaisingEvents = true
|
});
|
||||||
};
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(workingDirectory))
|
|
||||||
{
|
|
||||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath,
|
var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath,
|
||||||
state.Request.PlaySessionId,
|
state.Request.PlaySessionId,
|
||||||
|
@ -1269,7 +1256,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
if (EnableThrottling(state))
|
if (EnableThrottling(state))
|
||||||
{
|
{
|
||||||
transcodingJob.TranscodingThrottler = state.TranscodingThrottler = new TranscodingThrottler(transcodingJob, Logger, ServerConfigurationManager);
|
transcodingJob.TranscodingThrottler = state.TranscodingThrottler = new TranscodingThrottler(transcodingJob, Logger, ServerConfigurationManager, ApiEntryPoint.Instance.TimerFactory, FileSystem);
|
||||||
state.TranscodingThrottler.Start();
|
state.TranscodingThrottler.Start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1521,7 +1508,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
/// <param name="process">The process.</param>
|
/// <param name="process">The process.</param>
|
||||||
/// <param name="job">The job.</param>
|
/// <param name="job">The job.</param>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
private void OnFfMpegProcessExited(Process process, TranscodingJob job, StreamState state)
|
private void OnFfMpegProcessExited(IProcess process, TranscodingJob job, StreamState state)
|
||||||
{
|
{
|
||||||
if (job != null)
|
if (job != null)
|
||||||
{
|
{
|
||||||
|
@ -2409,97 +2396,98 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
return Task.FromResult(true);
|
||||||
|
|
||||||
var dict = new Dictionary<string, string>();
|
//var dict = new Dictionary<string, string>();
|
||||||
|
|
||||||
var outputAudio = GetAudioEncoder(state);
|
//var outputAudio = GetAudioEncoder(state);
|
||||||
if (!string.IsNullOrWhiteSpace(outputAudio))
|
//if (!string.IsNullOrWhiteSpace(outputAudio))
|
||||||
{
|
//{
|
||||||
dict["outputAudio"] = outputAudio;
|
// dict["outputAudio"] = outputAudio;
|
||||||
}
|
//}
|
||||||
|
|
||||||
var outputVideo = GetVideoEncoder(state);
|
//var outputVideo = GetVideoEncoder(state);
|
||||||
if (!string.IsNullOrWhiteSpace(outputVideo))
|
//if (!string.IsNullOrWhiteSpace(outputVideo))
|
||||||
{
|
//{
|
||||||
dict["outputVideo"] = outputVideo;
|
// dict["outputVideo"] = outputVideo;
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
|
//if (ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
|
||||||
ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
// ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
return Task.FromResult(true);
|
// return Task.FromResult(true);
|
||||||
}
|
//}
|
||||||
|
|
||||||
dict["id"] = AppHost.SystemId;
|
//dict["id"] = AppHost.SystemId;
|
||||||
dict["type"] = state.VideoRequest == null ? "Audio" : "Video";
|
//dict["type"] = state.VideoRequest == null ? "Audio" : "Video";
|
||||||
|
|
||||||
var audioStream = state.AudioStream;
|
//var audioStream = state.AudioStream;
|
||||||
if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
|
//if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
|
||||||
{
|
//{
|
||||||
dict["inputAudio"] = audioStream.Codec;
|
// dict["inputAudio"] = audioStream.Codec;
|
||||||
}
|
//}
|
||||||
|
|
||||||
var videoStream = state.VideoStream;
|
//var videoStream = state.VideoStream;
|
||||||
if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
|
//if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
|
||||||
{
|
//{
|
||||||
dict["inputVideo"] = videoStream.Codec;
|
// dict["inputVideo"] = videoStream.Codec;
|
||||||
}
|
//}
|
||||||
|
|
||||||
var cert = GetType().Assembly.GetModules().First().GetSignerCertificate();
|
//var cert = GetType().Assembly.GetModules().First().GetSignerCertificate();
|
||||||
if (cert != null)
|
//if (cert != null)
|
||||||
{
|
//{
|
||||||
dict["assemblySig"] = cert.GetCertHashString();
|
// dict["assemblySig"] = cert.GetCertHashString();
|
||||||
dict["certSubject"] = cert.Subject ?? string.Empty;
|
// dict["certSubject"] = cert.Subject ?? string.Empty;
|
||||||
dict["certIssuer"] = cert.Issuer ?? string.Empty;
|
// dict["certIssuer"] = cert.Issuer ?? string.Empty;
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
return Task.FromResult(true);
|
// return Task.FromResult(true);
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (state.SupportedAudioCodecs.Count > 0)
|
//if (state.SupportedAudioCodecs.Count > 0)
|
||||||
{
|
//{
|
||||||
dict["supportedAudioCodecs"] = string.Join(",", state.SupportedAudioCodecs.ToArray());
|
// dict["supportedAudioCodecs"] = string.Join(",", state.SupportedAudioCodecs.ToArray());
|
||||||
}
|
//}
|
||||||
|
|
||||||
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
|
//var auth = AuthorizationContext.GetAuthorizationInfo(Request);
|
||||||
|
|
||||||
dict["appName"] = auth.Client ?? string.Empty;
|
//dict["appName"] = auth.Client ?? string.Empty;
|
||||||
dict["appVersion"] = auth.Version ?? string.Empty;
|
//dict["appVersion"] = auth.Version ?? string.Empty;
|
||||||
dict["device"] = auth.Device ?? string.Empty;
|
//dict["device"] = auth.Device ?? string.Empty;
|
||||||
dict["deviceId"] = auth.DeviceId ?? string.Empty;
|
//dict["deviceId"] = auth.DeviceId ?? string.Empty;
|
||||||
dict["context"] = "streaming";
|
//dict["context"] = "streaming";
|
||||||
|
|
||||||
//Logger.Info(JsonSerializer.SerializeToString(dict));
|
////Logger.Info(JsonSerializer.SerializeToString(dict));
|
||||||
if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
//if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
|
// var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
|
||||||
list.Add(outputAudio);
|
// list.Add(outputAudio);
|
||||||
ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
|
// ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
//if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
|
// var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
|
||||||
list.Add(outputVideo);
|
// list.Add(outputVideo);
|
||||||
ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
|
// ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
|
||||||
}
|
//}
|
||||||
|
|
||||||
ServerConfigurationManager.SaveConfiguration();
|
//ServerConfigurationManager.SaveConfiguration();
|
||||||
|
|
||||||
//Logger.Info(JsonSerializer.SerializeToString(dict));
|
////Logger.Info(JsonSerializer.SerializeToString(dict));
|
||||||
var options = new HttpRequestOptions()
|
//var options = new HttpRequestOptions()
|
||||||
{
|
//{
|
||||||
Url = "https://mb3admin.com/admin/service/transcoding/report",
|
// Url = "https://mb3admin.com/admin/service/transcoding/report",
|
||||||
CancellationToken = CancellationToken.None,
|
// CancellationToken = CancellationToken.None,
|
||||||
LogRequest = false,
|
// LogRequest = false,
|
||||||
LogErrors = false,
|
// LogErrors = false,
|
||||||
BufferContent = false
|
// BufferContent = false
|
||||||
};
|
//};
|
||||||
options.RequestContent = JsonSerializer.SerializeToString(dict);
|
//options.RequestContent = JsonSerializer.SerializeToString(dict);
|
||||||
options.RequestContentType = "application/json";
|
//options.RequestContentType = "application/json";
|
||||||
|
|
||||||
return HttpClient.Post(options);
|
//return HttpClient.Post(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -356,7 +356,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, file.FullName);
|
Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, file.FullName);
|
||||||
|
|
||||||
Thread.Sleep(100);
|
var task = Task.Delay(100);
|
||||||
|
Task.WaitAll(task);
|
||||||
DeleteFile(file, retryCount + 1);
|
DeleteFile(file, retryCount + 1);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -378,7 +379,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
.OrderByDescending(fileSystem.GetLastWriteTimeUtc)
|
.OrderByDescending(fileSystem.GetLastWriteTimeUtc)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -881,7 +882,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
if (state.IsOutputVideo && !EnableCopyTs(state) && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
if (state.IsOutputVideo && !EnableCopyTs(state) && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
||||||
{
|
{
|
||||||
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0).ToString(CultureInfo.InvariantCulture);
|
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
||||||
|
|
|
@ -79,11 +79,13 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
private readonly IServerApplicationPaths _appPaths;
|
private readonly IServerApplicationPaths _appPaths;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public HlsSegmentService(IServerApplicationPaths appPaths, IServerConfigurationManager config)
|
public HlsSegmentService(IServerApplicationPaths appPaths, IServerConfigurationManager config, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<object> Get(GetHlsPlaylistLegacy request)
|
public Task<object> Get(GetHlsPlaylistLegacy request)
|
||||||
|
@ -111,7 +113,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
var normalizedPlaylistId = request.PlaylistId;
|
var normalizedPlaylistId = request.PlaylistId;
|
||||||
|
|
||||||
var playlistPath = Directory.EnumerateFiles(_config.ApplicationPaths.TranscodingTempPath, "*")
|
var playlistPath = _fileSystem.GetFilePaths(_config.ApplicationPaths.TranscodingTempPath)
|
||||||
.FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1);
|
.FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1);
|
||||||
|
|
||||||
return GetFileResult(file, playlistPath);
|
return GetFileResult(file, playlistPath);
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using System.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback
|
namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,19 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
private readonly TranscodingJob _job;
|
private readonly TranscodingJob _job;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private Timer _timer;
|
private ITimer _timer;
|
||||||
private bool _isPaused;
|
private bool _isPaused;
|
||||||
private readonly IConfigurationManager _config;
|
private readonly IConfigurationManager _config;
|
||||||
|
private readonly ITimerFactory _timerFactory;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public TranscodingThrottler(TranscodingJob job, ILogger logger, IConfigurationManager config)
|
public TranscodingThrottler(TranscodingJob job, ILogger logger, IConfigurationManager config, ITimerFactory timerFactory, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_job = job;
|
_job = job;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
_timerFactory = timerFactory;
|
||||||
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EncodingOptions GetOptions()
|
private EncodingOptions GetOptions()
|
||||||
|
@ -29,7 +33,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
_timer = new Timer(TimerCallback, null, 5000, 5000);
|
_timer = _timerFactory.Create(TimerCallback, null, 5000, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TimerCallback(object state)
|
private void TimerCallback(object state)
|
||||||
|
@ -120,7 +124,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var bytesTranscoded = job.BytesTranscoded ?? new FileInfo(path).Length;
|
var bytesTranscoded = job.BytesTranscoded ?? _fileSystem.GetFileInfo(path).Length;
|
||||||
|
|
||||||
// Estimate the bytes the transcoder should be ahead
|
// Estimate the bytes the transcoder should be ahead
|
||||||
double gapFactor = gapLengthInTicks;
|
double gapFactor = gapLengthInTicks;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Model.Events;
|
||||||
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;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.ScheduledTasks
|
namespace MediaBrowser.Api.ScheduledTasks
|
||||||
{
|
{
|
||||||
|
@ -31,10 +31,8 @@ namespace MediaBrowser.Api.ScheduledTasks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ScheduledTasksWebSocketListener" /> class.
|
/// Initializes a new instance of the <see cref="ScheduledTasksWebSocketListener" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">The logger.</param>
|
public ScheduledTasksWebSocketListener(ILogger logger, ITaskManager taskManager, ITimerFactory timerFactory)
|
||||||
/// <param name="taskManager">The task manager.</param>
|
: base(logger, timerFactory)
|
||||||
public ScheduledTasksWebSocketListener(ILogger logger, ITaskManager taskManager)
|
|
||||||
: base(logger)
|
|
||||||
{
|
{
|
||||||
TaskManager = taskManager;
|
TaskManager = taskManager;
|
||||||
|
|
||||||
|
@ -84,7 +82,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
||||||
{
|
{
|
||||||
TaskManager.TaskExecuting -= TaskManager_TaskExecuting;
|
TaskManager.TaskExecuting -= TaskManager_TaskExecuting;
|
||||||
TaskManager.TaskCompleted -= TaskManager_TaskCompleted;
|
TaskManager.TaskCompleted -= TaskManager_TaskCompleted;
|
||||||
|
|
||||||
base.Dispose(dispose);
|
base.Dispose(dispose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ using MediaBrowser.Model.Session;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Session
|
namespace MediaBrowser.Api.Session
|
||||||
{
|
{
|
||||||
|
@ -31,10 +32,8 @@ namespace MediaBrowser.Api.Session
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SessionInfoWebSocketListener"/> class.
|
/// Initializes a new instance of the <see cref="SessionInfoWebSocketListener"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">The logger.</param>
|
public SessionInfoWebSocketListener(ILogger logger, ISessionManager sessionManager, ITimerFactory timerFactory)
|
||||||
/// <param name="sessionManager">The session manager.</param>
|
: base(logger, timerFactory)
|
||||||
public SessionInfoWebSocketListener(ILogger logger, ISessionManager sessionManager)
|
|
||||||
: base(logger)
|
|
||||||
{
|
{
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
|
|
||||||
|
|
|
@ -215,20 +215,22 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
return await ResultFactory.GetStaticFileResult(Request, subtitleStream.Path).ConfigureAwait(false);
|
return await ResultFactory.GetStaticFileResult(Request, subtitleStream.Path).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var stream = await GetSubtitles(request).ConfigureAwait(false))
|
if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(stream))
|
using (var stream = await GetSubtitles(request).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
var text = reader.ReadToEnd();
|
using (var reader = new StreamReader(stream))
|
||||||
|
|
||||||
if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
|
|
||||||
{
|
{
|
||||||
text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
|
var text = reader.ReadToEnd();
|
||||||
}
|
|
||||||
|
|
||||||
return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format));
|
text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
|
||||||
|
|
||||||
|
return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ResultFactory.GetResult(await GetSubtitles(request).ConfigureAwait(false), MimeTypes.GetMimeType("file." + request.Format));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<Stream> GetSubtitles(GetSubtitle request)
|
private Task<Stream> GetSubtitles(GetSubtitle request)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Sync;
|
||||||
using MediaBrowser.Controller.Sync;
|
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Sync;
|
using MediaBrowser.Model.Sync;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Sync
|
namespace MediaBrowser.Api.Sync
|
||||||
{
|
{
|
||||||
|
@ -26,8 +26,8 @@ namespace MediaBrowser.Api.Sync
|
||||||
private readonly ISyncManager _syncManager;
|
private readonly ISyncManager _syncManager;
|
||||||
private string _jobId;
|
private string _jobId;
|
||||||
|
|
||||||
public SyncJobWebSocketListener(ILogger logger, ISyncManager syncManager)
|
public SyncJobWebSocketListener(ILogger logger, ISyncManager syncManager, ITimerFactory timerFactory)
|
||||||
: base(logger)
|
: base(logger, timerFactory)
|
||||||
{
|
{
|
||||||
_syncManager = syncManager;
|
_syncManager = syncManager;
|
||||||
_syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled;
|
_syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Sync;
|
||||||
using MediaBrowser.Controller.Sync;
|
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Sync;
|
using MediaBrowser.Model.Sync;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Sync
|
namespace MediaBrowser.Api.Sync
|
||||||
{
|
{
|
||||||
|
@ -25,8 +25,8 @@ namespace MediaBrowser.Api.Sync
|
||||||
private string _userId;
|
private string _userId;
|
||||||
private string _targetId;
|
private string _targetId;
|
||||||
|
|
||||||
public SyncJobsWebSocketListener(ILogger logger, ISyncManager syncManager)
|
public SyncJobsWebSocketListener(ILogger logger, ISyncManager syncManager, ITimerFactory timerFactory)
|
||||||
: base(logger)
|
: base(logger, timerFactory)
|
||||||
{
|
{
|
||||||
_syncManager = syncManager;
|
_syncManager = syncManager;
|
||||||
_syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled;
|
_syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Model.Activity;
|
||||||
using MediaBrowser.Model.Activity;
|
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.System
|
namespace MediaBrowser.Api.System
|
||||||
{
|
{
|
||||||
|
@ -26,8 +26,7 @@ namespace MediaBrowser.Api.System
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IActivityManager _activityManager;
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
public ActivityLogWebSocketListener(ILogger logger, IActivityManager activityManager)
|
public ActivityLogWebSocketListener(ILogger logger, ITimerFactory timerFactory, IActivityManager activityManager) : base(logger, timerFactory)
|
||||||
: base(logger)
|
|
||||||
{
|
{
|
||||||
_activityManager = activityManager;
|
_activityManager = activityManager;
|
||||||
_activityManager.EntryCreated += _activityManager_EntryCreated;
|
_activityManager.EntryCreated += _activityManager_EntryCreated;
|
||||||
|
|
|
@ -3,6 +3,7 @@ using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.System
|
namespace MediaBrowser.Api.System
|
||||||
{
|
{
|
||||||
|
@ -28,10 +29,8 @@ namespace MediaBrowser.Api.System
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SystemInfoWebSocketListener" /> class.
|
/// Initializes a new instance of the <see cref="SystemInfoWebSocketListener" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">The logger.</param>
|
public SystemInfoWebSocketListener(ILogger logger, IServerApplicationHost appHost, ITimerFactory timerFactory)
|
||||||
/// <param name="appHost">The app host.</param>
|
: base(logger, timerFactory)
|
||||||
public SystemInfoWebSocketListener(ILogger logger, IServerApplicationHost appHost)
|
|
||||||
: base(logger)
|
|
||||||
{
|
{
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ namespace MediaBrowser.Api.System
|
||||||
.Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
catch (DirectoryNotFoundException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
files = new List<FileSystemMetadata>();
|
files = new List<FileSystemMetadata>();
|
||||||
}
|
}
|
||||||
|
|
17
MediaBrowser.Api/project.json
Normal file
17
MediaBrowser.Api/project.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"frameworks":{
|
||||||
|
"netstandard1.6":{
|
||||||
|
"dependencies":{
|
||||||
|
"NETStandard.Library":"1.6.0",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||||
|
"buildOptions": {
|
||||||
|
"define": [ ]
|
||||||
|
},
|
||||||
|
"frameworkAssemblies":{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,7 +116,6 @@ namespace MediaBrowser.Common.Net
|
||||||
public HttpRequestOptions()
|
public HttpRequestOptions()
|
||||||
{
|
{
|
||||||
EnableHttpCompression = true;
|
EnableHttpCompression = true;
|
||||||
BufferContent = true;
|
|
||||||
|
|
||||||
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -393,5 +393,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
||||||
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
|
||||||
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
|
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
|
||||||
|
|
||||||
|
string GetEmbyTvActiveRecordingPath(string id);
|
||||||
|
Task<LiveStream> GetEmbyTvLiveStream(string id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -391,39 +391,39 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//var hasTrailers = item as IHasTrailers;
|
var hasTrailers = item as IHasTrailers;
|
||||||
//if (hasTrailers != null)
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
|
if (hasTrailers.RemoteTrailers.Count > 0)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement("Trailers");
|
||||||
|
|
||||||
|
foreach (var trailer in hasTrailers.RemoteTrailers)
|
||||||
|
{
|
||||||
|
writer.WriteElementString("Trailer", trailer.Url);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (hasProductionLocations.ProductionLocations.Count > 0)
|
||||||
//{
|
//{
|
||||||
// if (hasTrailers.RemoteTrailers.Count > 0)
|
// builder.Append("<Countries>");
|
||||||
|
|
||||||
|
// foreach (var name in hasProductionLocations.ProductionLocations)
|
||||||
// {
|
// {
|
||||||
// builder.Append("<Trailers>");
|
// builder.Append("<Country>" + SecurityElement.Escape(name) + "</Country>");
|
||||||
|
|
||||||
// foreach (var trailer in hasTrailers.RemoteTrailers)
|
|
||||||
// {
|
|
||||||
// builder.Append("<Trailer>" + SecurityElement.Escape(trailer.Url) + "</Trailer>");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// builder.Append("</Trailers>");
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// builder.Append("</Countries>");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
////if (hasProductionLocations.ProductionLocations.Count > 0)
|
var hasDisplayOrder = item as IHasDisplayOrder;
|
||||||
////{
|
if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
|
||||||
//// builder.Append("<Countries>");
|
{
|
||||||
|
writer.WriteElementString("DisplayOrder", hasDisplayOrder.DisplayOrder);
|
||||||
//// foreach (var name in hasProductionLocations.ProductionLocations)
|
}
|
||||||
//// {
|
|
||||||
//// builder.Append("<Country>" + SecurityElement.Escape(name) + "</Country>");
|
|
||||||
//// }
|
|
||||||
|
|
||||||
//// builder.Append("</Countries>");
|
|
||||||
////}
|
|
||||||
|
|
||||||
//var hasDisplayOrder = item as IHasDisplayOrder;
|
|
||||||
//if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
|
|
||||||
//{
|
|
||||||
// builder.Append("<DisplayOrder>" + SecurityElement.Escape(hasDisplayOrder.DisplayOrder) + "</DisplayOrder>");
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var hasMetascore = item as IHasMetascore;
|
//var hasMetascore = item as IHasMetascore;
|
||||||
//if (hasMetascore != null && hasMetascore.Metascore.HasValue)
|
//if (hasMetascore != null && hasMetascore.Metascore.HasValue)
|
||||||
|
@ -437,19 +437,19 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
// builder.Append("<AwardSummary>" + SecurityElement.Escape(hasAwards.AwardSummary) + "</AwardSummary>");
|
// builder.Append("<AwardSummary>" + SecurityElement.Escape(hasAwards.AwardSummary) + "</AwardSummary>");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//var hasBudget = item as IHasBudget;
|
var hasBudget = item as IHasBudget;
|
||||||
//if (hasBudget != null)
|
if (hasBudget != null)
|
||||||
//{
|
{
|
||||||
// if (hasBudget.Budget.HasValue)
|
if (hasBudget.Budget.HasValue)
|
||||||
// {
|
{
|
||||||
// builder.Append("<Budget>" + SecurityElement.Escape(hasBudget.Budget.Value.ToString(UsCulture)) + "</Budget>");
|
writer.WriteElementString("Budget", hasBudget.Budget.Value.ToString(UsCulture));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (hasBudget.Revenue.HasValue)
|
if (hasBudget.Revenue.HasValue)
|
||||||
// {
|
{
|
||||||
// builder.Append("<Revenue>" + SecurityElement.Escape(hasBudget.Revenue.Value.ToString(UsCulture)) + "</Revenue>");
|
writer.WriteElementString("Revenue", hasBudget.Revenue.Value.ToString(UsCulture));
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
//if (item.CommunityRating.HasValue)
|
//if (item.CommunityRating.HasValue)
|
||||||
//{
|
//{
|
||||||
|
@ -460,15 +460,15 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
// builder.Append("<VoteCount>" + SecurityElement.Escape(item.VoteCount.Value.ToString(UsCulture)) + "</VoteCount>");
|
// builder.Append("<VoteCount>" + SecurityElement.Escape(item.VoteCount.Value.ToString(UsCulture)) + "</VoteCount>");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//if (item.ProductionYear.HasValue && !(item is Person))
|
if (item.ProductionYear.HasValue && !(item is Person))
|
||||||
//{
|
{
|
||||||
// builder.Append("<ProductionYear>" + SecurityElement.Escape(item.ProductionYear.Value.ToString(UsCulture)) + "</ProductionYear>");
|
writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(UsCulture));
|
||||||
//}
|
}
|
||||||
|
|
||||||
//if (!string.IsNullOrEmpty(item.HomePageUrl))
|
if (!string.IsNullOrEmpty(item.HomePageUrl))
|
||||||
//{
|
{
|
||||||
// builder.Append("<Website>" + SecurityElement.Escape(item.HomePageUrl) + "</Website>");
|
writer.WriteElementString("Website", item.HomePageUrl);
|
||||||
//}
|
}
|
||||||
|
|
||||||
//var hasAspectRatio = item as IHasAspectRatio;
|
//var hasAspectRatio = item as IHasAspectRatio;
|
||||||
//if (hasAspectRatio != null)
|
//if (hasAspectRatio != null)
|
||||||
|
@ -541,29 +541,29 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
// builder.Append("</Studios>");
|
// builder.Append("</Studios>");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//if (item.Tags.Count > 0)
|
if (item.Tags.Count > 0)
|
||||||
//{
|
{
|
||||||
// builder.Append("<Tags>");
|
writer.WriteStartElement("Tags");
|
||||||
|
|
||||||
// foreach (var tag in item.Tags)
|
foreach (var tag in item.Tags)
|
||||||
// {
|
{
|
||||||
// builder.Append("<Tag>" + SecurityElement.Escape(tag) + "</Tag>");
|
writer.WriteElementString("Tag", tag);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// builder.Append("</Tags>");
|
writer.WriteEndElement();
|
||||||
//}
|
}
|
||||||
|
|
||||||
//if (item.Keywords.Count > 0)
|
if (item.Keywords.Count > 0)
|
||||||
//{
|
{
|
||||||
// builder.Append("<PlotKeywords>");
|
writer.WriteStartElement("PlotKeywords");
|
||||||
|
|
||||||
// foreach (var tag in item.Keywords)
|
foreach (var tag in item.Keywords)
|
||||||
// {
|
{
|
||||||
// builder.Append("<PlotKeyword>" + SecurityElement.Escape(tag) + "</PlotKeyword>");
|
writer.WriteElementString("PlotKeyword", tag);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// builder.Append("</PlotKeywords>");
|
writer.WriteEndElement();
|
||||||
//}
|
}
|
||||||
|
|
||||||
//var people = libraryManager.GetPeople(item);
|
//var people = libraryManager.GetPeople(item);
|
||||||
|
|
||||||
|
@ -589,42 +589,42 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
// builder.Append("</Persons>");
|
// builder.Append("</Persons>");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//var boxset = item as BoxSet;
|
var boxset = item as BoxSet;
|
||||||
//if (boxset != null)
|
if (boxset != null)
|
||||||
//{
|
{
|
||||||
// AddLinkedChildren(boxset, builder, "CollectionItems", "CollectionItem");
|
AddLinkedChildren(boxset, writer, "CollectionItems", "CollectionItem");
|
||||||
//}
|
}
|
||||||
|
|
||||||
//var playlist = item as Playlist;
|
var playlist = item as Playlist;
|
||||||
//if (playlist != null)
|
if (playlist != null)
|
||||||
//{
|
{
|
||||||
// AddLinkedChildren(playlist, builder, "PlaylistItems", "PlaylistItem");
|
AddLinkedChildren(playlist, writer, "PlaylistItems", "PlaylistItem");
|
||||||
//}
|
}
|
||||||
|
|
||||||
//var hasShares = item as IHasShares;
|
var hasShares = item as IHasShares;
|
||||||
//if (hasShares != null)
|
if (hasShares != null)
|
||||||
//{
|
{
|
||||||
// AddShares(hasShares, builder);
|
AddShares(hasShares, writer);
|
||||||
//}
|
}
|
||||||
|
|
||||||
AddMediaInfo(item, writer);
|
AddMediaInfo(item, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddShares(IHasShares item, StringBuilder builder)
|
public static void AddShares(IHasShares item, XmlWriter writer)
|
||||||
{
|
{
|
||||||
//builder.Append("<Shares>");
|
writer.WriteStartElement("Shares");
|
||||||
|
|
||||||
//foreach (var share in item.Shares)
|
foreach (var share in item.Shares)
|
||||||
//{
|
{
|
||||||
// builder.Append("<Share>");
|
writer.WriteStartElement("Share");
|
||||||
|
|
||||||
// builder.Append("<UserId>" + SecurityElement.Escape(share.UserId) + "</UserId>");
|
writer.WriteElementString("UserId", share.UserId);
|
||||||
// builder.Append("<CanEdit>" + SecurityElement.Escape(share.CanEdit.ToString().ToLower()) + "</CanEdit>");
|
writer.WriteElementString("CanEdit", share.CanEdit.ToString().ToLower());
|
||||||
|
|
||||||
// builder.Append("</Share>");
|
writer.WriteEndElement();
|
||||||
//}
|
}
|
||||||
|
|
||||||
//builder.Append("</Shares>");
|
writer.WriteEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -662,30 +662,30 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddLinkedChildren(Folder item, StringBuilder builder, string pluralNodeName, string singularNodeName)
|
public static void AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName)
|
||||||
{
|
{
|
||||||
//var items = item.LinkedChildren
|
var items = item.LinkedChildren
|
||||||
// .Where(i => i.Type == LinkedChildType.Manual)
|
.Where(i => i.Type == LinkedChildType.Manual)
|
||||||
// .ToList();
|
.ToList();
|
||||||
|
|
||||||
//if (items.Count == 0)
|
if (items.Count == 0)
|
||||||
//{
|
{
|
||||||
// return;
|
return;
|
||||||
//}
|
}
|
||||||
|
|
||||||
//builder.Append("<" + pluralNodeName + ">");
|
writer.WriteStartElement(pluralNodeName);
|
||||||
//foreach (var link in items)
|
|
||||||
//{
|
|
||||||
// builder.Append("<" + singularNodeName + ">");
|
|
||||||
|
|
||||||
// if (!string.IsNullOrWhiteSpace(link.Path))
|
foreach (var link in items)
|
||||||
// {
|
{
|
||||||
// builder.Append("<Path>" + SecurityElement.Escape((link.Path)) + "</Path>");
|
if (!string.IsNullOrWhiteSpace(link.Path))
|
||||||
// }
|
{
|
||||||
|
writer.WriteStartElement(singularNodeName);
|
||||||
|
writer.WriteElementString("Path", link.Path);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// builder.Append("</" + singularNodeName + ">");
|
writer.WriteEndElement();
|
||||||
//}
|
|
||||||
//builder.Append("</" + pluralNodeName + ">");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsPersonType(PersonInfo person, string type)
|
private static bool IsPersonType(PersonInfo person, string type)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,15 +7,13 @@ using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Controller.IO;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
|
|
||||||
namespace MediaBrowser.MediaEncoding.Encoder
|
namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
{
|
{
|
||||||
public class AudioEncoder : BaseEncoder
|
public class AudioEncoder : BaseEncoder
|
||||||
{
|
{
|
||||||
public AudioEncoder(MediaEncoder mediaEncoder, ILogger logger, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IIsoManager isoManager, ILibraryManager libraryManager, ISessionManager sessionManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager) : base(mediaEncoder, logger, configurationManager, fileSystem, isoManager, libraryManager, sessionManager, subtitleEncoder, mediaSourceManager)
|
public AudioEncoder(MediaEncoder mediaEncoder, ILogger logger, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IIsoManager isoManager, ILibraryManager libraryManager, ISessionManager sessionManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProcessFactory processFactory) : base(mediaEncoder, logger, configurationManager, fileSystem, isoManager, libraryManager, sessionManager, subtitleEncoder, mediaSourceManager, processFactory)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,5 +114,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
{
|
{
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,12 @@ using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Controller.IO;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.MediaEncoding.Encoder
|
namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
@ -35,6 +32,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
protected readonly ISessionManager SessionManager;
|
protected readonly ISessionManager SessionManager;
|
||||||
protected readonly ISubtitleEncoder SubtitleEncoder;
|
protected readonly ISubtitleEncoder SubtitleEncoder;
|
||||||
protected readonly IMediaSourceManager MediaSourceManager;
|
protected readonly IMediaSourceManager MediaSourceManager;
|
||||||
|
protected IProcessFactory ProcessFactory;
|
||||||
|
|
||||||
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
|
@ -46,7 +44,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
ISubtitleEncoder subtitleEncoder,
|
ISubtitleEncoder subtitleEncoder,
|
||||||
IMediaSourceManager mediaSourceManager)
|
IMediaSourceManager mediaSourceManager, IProcessFactory processFactory)
|
||||||
{
|
{
|
||||||
MediaEncoder = mediaEncoder;
|
MediaEncoder = mediaEncoder;
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
|
@ -57,6 +55,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
SessionManager = sessionManager;
|
SessionManager = sessionManager;
|
||||||
SubtitleEncoder = subtitleEncoder;
|
SubtitleEncoder = subtitleEncoder;
|
||||||
MediaSourceManager = mediaSourceManager;
|
MediaSourceManager = mediaSourceManager;
|
||||||
|
ProcessFactory = processFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EncodingJob> Start(EncodingJobOptions options,
|
public async Task<EncodingJob> Start(EncodingJobOptions options,
|
||||||
|
@ -75,27 +74,23 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
var commandLineArgs = await GetCommandLineArguments(encodingJob).ConfigureAwait(false);
|
var commandLineArgs = await GetCommandLineArguments(encodingJob).ConfigureAwait(false);
|
||||||
|
|
||||||
var process = new Process
|
var process = ProcessFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
|
|
||||||
// Must consume both stdout and stderr or deadlocks may occur
|
// Must consume both stdout and stderr or deadlocks may occur
|
||||||
//RedirectStandardOutput = true,
|
//RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
RedirectStandardInput = true,
|
RedirectStandardInput = true,
|
||||||
|
|
||||||
FileName = MediaEncoder.EncoderPath,
|
FileName = MediaEncoder.EncoderPath,
|
||||||
Arguments = commandLineArgs,
|
Arguments = commandLineArgs,
|
||||||
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
|
||||||
ErrorDialog = false
|
|
||||||
},
|
|
||||||
|
|
||||||
|
IsHidden = true,
|
||||||
|
ErrorDialog = false,
|
||||||
EnableRaisingEvents = true
|
EnableRaisingEvents = true
|
||||||
};
|
});
|
||||||
|
|
||||||
var workingDirectory = GetWorkingDirectory(options);
|
var workingDirectory = GetWorkingDirectory(options);
|
||||||
if (!string.IsNullOrWhiteSpace(workingDirectory))
|
if (!string.IsNullOrWhiteSpace(workingDirectory))
|
||||||
|
@ -149,7 +144,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
return encodingJob;
|
return encodingJob;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Cancel(Process process, EncodingJob job)
|
private void Cancel(IProcess process, EncodingJob job)
|
||||||
{
|
{
|
||||||
Logger.Info("Killing ffmpeg process for {0}", job.OutputFilePath);
|
Logger.Info("Killing ffmpeg process for {0}", job.OutputFilePath);
|
||||||
|
|
||||||
|
@ -164,7 +159,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="process">The process.</param>
|
/// <param name="process">The process.</param>
|
||||||
/// <param name="job">The job.</param>
|
/// <param name="job">The job.</param>
|
||||||
private void OnFfMpegProcessExited(Process process, EncodingJob job)
|
private void OnFfMpegProcessExited(IProcess process, EncodingJob job)
|
||||||
{
|
{
|
||||||
job.HasExited = true;
|
job.HasExited = true;
|
||||||
|
|
||||||
|
@ -775,7 +770,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-pix_fmt yuv420p " + param;
|
param = "-pix_fmt yuv420p " + param;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.MediaEncoding.Encoder
|
namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
@ -8,10 +9,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
public class EncoderValidator
|
public class EncoderValidator
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly IProcessFactory _processFactory;
|
||||||
|
|
||||||
public EncoderValidator(ILogger logger)
|
public EncoderValidator(ILogger logger, IProcessFactory processFactory)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_processFactory = processFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tuple<List<string>, List<string>> Validate(string encoderPath)
|
public Tuple<List<string>, List<string>> Validate(string encoderPath)
|
||||||
|
@ -145,19 +148,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
private string GetProcessOutput(string path, string arguments)
|
private string GetProcessOutput(string path, string arguments)
|
||||||
{
|
{
|
||||||
var process = new Process
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
FileName = path,
|
||||||
UseShellExecute = false,
|
Arguments = arguments,
|
||||||
FileName = path,
|
IsHidden = true,
|
||||||
Arguments = arguments,
|
ErrorDialog = false,
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
RedirectStandardOutput = true
|
||||||
ErrorDialog = false,
|
});
|
||||||
RedirectStandardOutput = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.Info("Running {0} {1}", path, arguments);
|
_logger.Info("Running {0} {1}", path, arguments);
|
||||||
|
|
||||||
|
|
|
@ -88,9 +88,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
private async Task DownloadFontFile(string fontsDirectory, string fontFilename, IProgress<double> progress)
|
private async Task DownloadFontFile(string fontsDirectory, string fontFilename, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
var existingFile = Directory
|
var existingFile = _fileSystem
|
||||||
.EnumerateFiles(_appPaths.ProgramDataPath, fontFilename, SearchOption.AllDirectories)
|
.GetFilePaths(_appPaths.ProgramDataPath, true)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault(i => string.Equals(fontFilename, Path.GetFileName(i), StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (existingFile != null)
|
if (existingFile != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,19 +14,16 @@ using MediaBrowser.Model.MediaInfo;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
|
|
||||||
namespace MediaBrowser.MediaEncoding.Encoder
|
namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
{
|
{
|
||||||
|
@ -81,14 +78,19 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
protected readonly Func<IMediaSourceManager> MediaSourceManager;
|
protected readonly Func<IMediaSourceManager> MediaSourceManager;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IZipClient _zipClient;
|
private readonly IZipClient _zipClient;
|
||||||
|
private readonly IProcessFactory _processFactory;
|
||||||
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
||||||
|
|
||||||
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
|
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
|
||||||
private readonly bool _hasExternalEncoder;
|
private readonly bool _hasExternalEncoder;
|
||||||
private string _originalFFMpegPath;
|
private readonly string _originalFFMpegPath;
|
||||||
private string _originalFFProbePath;
|
private readonly string _originalFFProbePath;
|
||||||
|
private readonly int DefaultImageExtractionTimeoutMs;
|
||||||
|
private readonly bool EnableEncoderFontFile;
|
||||||
|
|
||||||
public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamProvider memoryStreamProvider)
|
public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamProvider memoryStreamProvider, IProcessFactory processFactory,
|
||||||
|
int defaultImageExtractionTimeoutMs,
|
||||||
|
bool enableEncoderFontFile)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
|
@ -104,6 +106,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_zipClient = zipClient;
|
_zipClient = zipClient;
|
||||||
_memoryStreamProvider = memoryStreamProvider;
|
_memoryStreamProvider = memoryStreamProvider;
|
||||||
|
_processFactory = processFactory;
|
||||||
|
DefaultImageExtractionTimeoutMs = defaultImageExtractionTimeoutMs;
|
||||||
|
EnableEncoderFontFile = enableEncoderFontFile;
|
||||||
FFProbePath = ffProbePath;
|
FFProbePath = ffProbePath;
|
||||||
FFMpegPath = ffMpegPath;
|
FFMpegPath = ffMpegPath;
|
||||||
_originalFFProbePath = ffProbePath;
|
_originalFFProbePath = ffProbePath;
|
||||||
|
@ -158,12 +163,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(FFMpegPath))
|
if (!string.IsNullOrWhiteSpace(FFMpegPath))
|
||||||
{
|
{
|
||||||
var result = new EncoderValidator(_logger).Validate(FFMpegPath);
|
var result = new EncoderValidator(_logger, _processFactory).Validate(FFMpegPath);
|
||||||
|
|
||||||
SetAvailableDecoders(result.Item1);
|
SetAvailableDecoders(result.Item1);
|
||||||
SetAvailableEncoders(result.Item2);
|
SetAvailableEncoders(result.Item2);
|
||||||
|
|
||||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
if (EnableEncoderFontFile)
|
||||||
{
|
{
|
||||||
var directory = Path.GetDirectoryName(FFMpegPath);
|
var directory = Path.GetDirectoryName(FFMpegPath);
|
||||||
|
|
||||||
|
@ -255,7 +260,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
private bool ValidateVersion(string path, bool logOutput)
|
private bool ValidateVersion(string path, bool logOutput)
|
||||||
{
|
{
|
||||||
return new EncoderValidator(_logger).ValidateVersion(path, logOutput);
|
return new EncoderValidator(_logger, _processFactory).ValidateVersion(path, logOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigureEncoderPaths()
|
private void ConfigureEncoderPaths()
|
||||||
|
@ -509,27 +514,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format"
|
? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format"
|
||||||
: "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format";
|
: "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format";
|
||||||
|
|
||||||
var process = new Process
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
|
|
||||||
// Must consume both or ffmpeg may hang due to deadlocks. See comments below.
|
// Must consume both or ffmpeg may hang due to deadlocks. See comments below.
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
//RedirectStandardError = true,
|
//RedirectStandardError = true,
|
||||||
RedirectStandardInput = false,
|
RedirectStandardInput = false,
|
||||||
FileName = FFProbePath,
|
FileName = FFProbePath,
|
||||||
Arguments = string.Format(args,
|
Arguments = string.Format(args, probeSizeArgument, inputPath).Trim(),
|
||||||
probeSizeArgument, inputPath).Trim(),
|
|
||||||
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
|
||||||
ErrorDialog = false
|
|
||||||
},
|
|
||||||
|
|
||||||
|
IsHidden = true,
|
||||||
|
ErrorDialog = false,
|
||||||
EnableRaisingEvents = true
|
EnableRaisingEvents = true
|
||||||
};
|
});
|
||||||
|
|
||||||
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
|
|
||||||
|
@ -644,26 +644,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
var args = "{0} -i {1} -map 0:v:{2} -an -filter:v idet -frames:v 500 -an -f null /dev/null";
|
var args = "{0} -i {1} -map 0:v:{2} -an -filter:v idet -frames:v 500 -an -f null /dev/null";
|
||||||
|
|
||||||
var process = new Process
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
|
|
||||||
// Must consume both or ffmpeg may hang due to deadlocks. See comments below.
|
// Must consume both or ffmpeg may hang due to deadlocks. See comments below.
|
||||||
//RedirectStandardOutput = true,
|
//RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
RedirectStandardInput = false,
|
RedirectStandardInput = false,
|
||||||
FileName = FFMpegPath,
|
FileName = FFMpegPath,
|
||||||
Arguments = string.Format(args, probeSizeArgument, inputPath, videoStream.Index.ToString(CultureInfo.InvariantCulture)).Trim(),
|
Arguments = string.Format(args, probeSizeArgument, inputPath, videoStream.Index.ToString(CultureInfo.InvariantCulture)).Trim(),
|
||||||
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
|
||||||
ErrorDialog = false
|
|
||||||
},
|
|
||||||
|
|
||||||
|
IsHidden = true,
|
||||||
|
ErrorDialog = false,
|
||||||
EnableRaisingEvents = true
|
EnableRaisingEvents = true
|
||||||
};
|
});
|
||||||
|
|
||||||
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
var idetFoundInterlaced = false;
|
var idetFoundInterlaced = false;
|
||||||
|
@ -916,18 +912,15 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args;
|
args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args;
|
||||||
}
|
}
|
||||||
|
|
||||||
var process = new Process
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
FileName = FFMpegPath,
|
||||||
UseShellExecute = false,
|
Arguments = args,
|
||||||
FileName = FFMpegPath,
|
IsHidden = true,
|
||||||
Arguments = args,
|
ErrorDialog = false
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
});
|
||||||
ErrorDialog = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
|
|
||||||
|
@ -944,7 +937,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
var timeoutMs = ConfigurationManager.Configuration.ImageExtractionTimeoutMs;
|
var timeoutMs = ConfigurationManager.Configuration.ImageExtractionTimeoutMs;
|
||||||
if (timeoutMs <= 0)
|
if (timeoutMs <= 0)
|
||||||
{
|
{
|
||||||
timeoutMs = Environment.Is64BitOperatingSystem ? (Environment.ProcessorCount > 2 ? 14000 : 20000) : 40000;
|
timeoutMs = DefaultImageExtractionTimeoutMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
ranToCompletion = process.WaitForExit(timeoutMs);
|
ranToCompletion = process.WaitForExit(timeoutMs);
|
||||||
|
@ -1022,19 +1015,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
args = probeSize + " " + args;
|
args = probeSize + " " + args;
|
||||||
}
|
}
|
||||||
|
|
||||||
var process = new Process
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
FileName = FFMpegPath,
|
||||||
UseShellExecute = false,
|
Arguments = args,
|
||||||
FileName = FFMpegPath,
|
IsHidden = true,
|
||||||
Arguments = args,
|
ErrorDialog = false,
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
RedirectStandardInput = true
|
||||||
ErrorDialog = false,
|
});
|
||||||
RedirectStandardInput = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
|
_logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
|
||||||
|
|
||||||
|
@ -1107,7 +1097,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
LibraryManager,
|
LibraryManager,
|
||||||
SessionManager,
|
SessionManager,
|
||||||
SubtitleEncoder(),
|
SubtitleEncoder(),
|
||||||
MediaSourceManager())
|
MediaSourceManager(),
|
||||||
|
_processFactory)
|
||||||
.Start(options, progress, cancellationToken).ConfigureAwait(false);
|
.Start(options, progress, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await job.TaskCompletionSource.Task.ConfigureAwait(false);
|
await job.TaskCompletionSource.Task.ConfigureAwait(false);
|
||||||
|
@ -1127,7 +1118,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
LibraryManager,
|
LibraryManager,
|
||||||
SessionManager,
|
SessionManager,
|
||||||
SubtitleEncoder(),
|
SubtitleEncoder(),
|
||||||
MediaSourceManager())
|
MediaSourceManager(),
|
||||||
|
_processFactory)
|
||||||
.Start(options, progress, cancellationToken).ConfigureAwait(false);
|
.Start(options, progress, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await job.TaskCompletionSource.Task.ConfigureAwait(false);
|
await job.TaskCompletionSource.Task.ConfigureAwait(false);
|
||||||
|
@ -1231,14 +1223,14 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
private class ProcessWrapper : IDisposable
|
private class ProcessWrapper : IDisposable
|
||||||
{
|
{
|
||||||
public readonly Process Process;
|
public readonly IProcess Process;
|
||||||
public bool HasExited;
|
public bool HasExited;
|
||||||
public int? ExitCode;
|
public int? ExitCode;
|
||||||
private readonly MediaEncoder _mediaEncoder;
|
private readonly MediaEncoder _mediaEncoder;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
public bool IsRedirectingStdin { get; private set; }
|
public bool IsRedirectingStdin { get; private set; }
|
||||||
|
|
||||||
public ProcessWrapper(Process process, MediaEncoder mediaEncoder, ILogger logger, bool isRedirectingStdin)
|
public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder, ILogger logger, bool isRedirectingStdin)
|
||||||
{
|
{
|
||||||
Process = process;
|
Process = process;
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
|
@ -1249,7 +1241,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
void Process_Exited(object sender, EventArgs e)
|
void Process_Exited(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var process = (Process)sender;
|
var process = (IProcess)sender;
|
||||||
|
|
||||||
HasExited = true;
|
HasExited = true;
|
||||||
|
|
||||||
|
@ -1269,7 +1261,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
DisposeProcess(process);
|
DisposeProcess(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisposeProcess(Process process)
|
private void DisposeProcess(IProcess process)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,15 +8,13 @@ using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Controller.IO;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
|
|
||||||
namespace MediaBrowser.MediaEncoding.Encoder
|
namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
{
|
{
|
||||||
public class VideoEncoder : BaseEncoder
|
public class VideoEncoder : BaseEncoder
|
||||||
{
|
{
|
||||||
public VideoEncoder(MediaEncoder mediaEncoder, ILogger logger, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IIsoManager isoManager, ILibraryManager libraryManager, ISessionManager sessionManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager) : base(mediaEncoder, logger, configurationManager, fileSystem, isoManager, libraryManager, sessionManager, subtitleEncoder, mediaSourceManager)
|
public VideoEncoder(MediaEncoder mediaEncoder, ILogger logger, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IIsoManager isoManager, ILibraryManager libraryManager, ISessionManager sessionManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProcessFactory processFactory) : base(mediaEncoder, logger, configurationManager, fileSystem, isoManager, libraryManager, sessionManager, subtitleEncoder, mediaSourceManager, processFactory)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,5 +191,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
{
|
{
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,10 +9,10 @@
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>MediaBrowser.MediaEncoding</RootNamespace>
|
<RootNamespace>MediaBrowser.MediaEncoding</RootNamespace>
|
||||||
<AssemblyName>MediaBrowser.MediaEncoding</AssemblyName>
|
<AssemblyName>MediaBrowser.MediaEncoding</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
<TargetFrameworkProfile />
|
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
|
||||||
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -37,13 +37,6 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="UniversalDetector, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="UniversalDetector, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll</HintPath>
|
<HintPath>..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
|
@ -108,7 +101,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||||
<!-- 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">
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="EmitMSBuildWarning" BeforeTargets="Build">
|
||||||
|
<Warning Text="Packages containing MSBuild targets and props files cannot be fully installed in projects targeting multiple frameworks. The MSBuild targets and props files have been ignored." />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
|
@ -14,6 +14,7 @@ using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Controller.Subtitles;
|
using MediaBrowser.Controller.Subtitles;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
@ -31,14 +32,16 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
private readonly IEncryptionManager _encryption;
|
private readonly IEncryptionManager _encryption;
|
||||||
|
|
||||||
private readonly IJsonSerializer _json;
|
private readonly IJsonSerializer _json;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption, IJsonSerializer json)
|
public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption, IJsonSerializer json, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_logger = logManager.GetLogger(GetType().Name);
|
_logger = logManager.GetLogger(GetType().Name);
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_config = config;
|
_config = config;
|
||||||
_encryption = encryption;
|
_encryption = encryption;
|
||||||
_json = json;
|
_json = json;
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
|
||||||
_config.NamedConfigurationUpdating += _config_NamedConfigurationUpdating;
|
_config.NamedConfigurationUpdating += _config_NamedConfigurationUpdating;
|
||||||
|
|
||||||
|
@ -133,7 +136,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
|
|
||||||
if ((DateTime.UtcNow - _lastRateLimitException).TotalHours < 1)
|
if ((DateTime.UtcNow - _lastRateLimitException).TotalHours < 1)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("OpenSubtitles rate limit reached");
|
throw new Exception("OpenSubtitles rate limit reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
|
var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
|
||||||
|
@ -141,12 +144,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
if ((resultDownLoad.Status ?? string.Empty).IndexOf("407", StringComparison.OrdinalIgnoreCase) != -1)
|
if ((resultDownLoad.Status ?? string.Empty).IndexOf("407", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
_lastRateLimitException = DateTime.UtcNow;
|
_lastRateLimitException = DateTime.UtcNow;
|
||||||
throw new ApplicationException("OpenSubtitles rate limit reached");
|
throw new Exception("OpenSubtitles rate limit reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(resultDownLoad is MethodResponseSubtitleDownload))
|
if (!(resultDownLoad is MethodResponseSubtitleDownload))
|
||||||
{
|
{
|
||||||
throw new ApplicationException("Invalid response type");
|
throw new Exception("Invalid response type");
|
||||||
}
|
}
|
||||||
|
|
||||||
var results = ((MethodResponseSubtitleDownload)resultDownLoad).Results;
|
var results = ((MethodResponseSubtitleDownload)resultDownLoad).Results;
|
||||||
|
@ -269,11 +272,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
var subLanguageId = NormalizeLanguage(request.Language);
|
var subLanguageId = NormalizeLanguage(request.Language);
|
||||||
string hash;
|
string hash;
|
||||||
|
|
||||||
using (var fileStream = File.OpenRead(request.MediaPath))
|
using (var fileStream = _fileSystem.OpenRead(request.MediaPath))
|
||||||
{
|
{
|
||||||
hash = Utilities.ComputeHash(fileStream);
|
hash = Utilities.ComputeHash(fileStream);
|
||||||
}
|
}
|
||||||
var fileInfo = new FileInfo(request.MediaPath);
|
var fileInfo = _fileSystem.GetFileInfo(request.MediaPath);
|
||||||
var movieByteSize = fileInfo.Length;
|
var movieByteSize = fileInfo.Length;
|
||||||
var searchImdbId = request.ContentType == VideoContentType.Movie ? imdbId.ToString(_usCulture) : "";
|
var searchImdbId = request.ContentType == VideoContentType.Movie ? imdbId.ToString(_usCulture) : "";
|
||||||
var subtitleSearchParameters = request.ContentType == VideoContentType.Episode
|
var subtitleSearchParameters = request.ContentType == VideoContentType.Episode
|
||||||
|
|
|
@ -18,9 +18,8 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Model.TextEncoding;
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using UniversalDetector;
|
using UniversalDetector;
|
||||||
|
|
||||||
namespace MediaBrowser.MediaEncoding.Subtitles
|
namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
|
@ -36,8 +35,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
||||||
|
private readonly IProcessFactory _processFactory;
|
||||||
|
private readonly IEncoding _textEncoding;
|
||||||
|
|
||||||
public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamProvider memoryStreamProvider)
|
public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamProvider memoryStreamProvider, IProcessFactory processFactory, IEncoding textEncoding)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -48,6 +49,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_memoryStreamProvider = memoryStreamProvider;
|
_memoryStreamProvider = memoryStreamProvider;
|
||||||
|
_processFactory = processFactory;
|
||||||
|
_textEncoding = textEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string SubtitleCachePath
|
private string SubtitleCachePath
|
||||||
|
@ -418,7 +421,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
/// or
|
/// or
|
||||||
/// outputPath
|
/// outputPath
|
||||||
/// </exception>
|
/// </exception>
|
||||||
/// <exception cref="System.ApplicationException"></exception>
|
|
||||||
private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken)
|
private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(inputPath))
|
if (string.IsNullOrEmpty(inputPath))
|
||||||
|
@ -440,23 +442,20 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
encodingParam = " -sub_charenc " + encodingParam;
|
encodingParam = " -sub_charenc " + encodingParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
var process = new Process
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
RedirectStandardOutput = false,
|
||||||
{
|
RedirectStandardError = true,
|
||||||
RedirectStandardOutput = false,
|
RedirectStandardInput = true,
|
||||||
RedirectStandardError = true,
|
|
||||||
RedirectStandardInput = true,
|
|
||||||
|
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
FileName = _mediaEncoder.EncoderPath,
|
FileName = _mediaEncoder.EncoderPath,
|
||||||
Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath),
|
Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath),
|
||||||
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
IsHidden = true,
|
||||||
ErrorDialog = false
|
ErrorDialog = false
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
_logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
_logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
|
|
||||||
|
@ -538,7 +537,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
|
|
||||||
_logger.Error(msg);
|
_logger.Error(msg);
|
||||||
|
|
||||||
throw new ApplicationException(msg);
|
throw new Exception(msg);
|
||||||
}
|
}
|
||||||
await SetAssFont(outputPath).ConfigureAwait(false);
|
await SetAssFont(outputPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -593,23 +592,20 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath,
|
var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath,
|
||||||
subtitleStreamIndex, outputCodec, outputPath);
|
subtitleStreamIndex, outputCodec, outputPath);
|
||||||
|
|
||||||
var process = new Process
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
CreateNoWindow = true,
|
||||||
{
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
|
|
||||||
RedirectStandardOutput = false,
|
RedirectStandardOutput = false,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
RedirectStandardInput = true,
|
RedirectStandardInput = true,
|
||||||
|
|
||||||
FileName = _mediaEncoder.EncoderPath,
|
FileName = _mediaEncoder.EncoderPath,
|
||||||
Arguments = processArgs,
|
Arguments = processArgs,
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
IsHidden = true,
|
||||||
ErrorDialog = false
|
ErrorDialog = false
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
_logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
_logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
|
|
||||||
|
@ -674,10 +670,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
catch (FileNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
catch (DirectoryNotFoundException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
|
@ -695,7 +687,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
|
|
||||||
_logger.Error(msg);
|
_logger.Error(msg);
|
||||||
|
|
||||||
throw new ApplicationException(msg);
|
throw new Exception(msg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -749,20 +741,26 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
string text;
|
string text;
|
||||||
Encoding encoding;
|
Encoding encoding;
|
||||||
|
|
||||||
using (var reader = new StreamReader(file, true))
|
using (var fileStream = _fileSystem.OpenRead(file))
|
||||||
{
|
{
|
||||||
encoding = reader.CurrentEncoding;
|
using (var reader = new StreamReader(fileStream, true))
|
||||||
|
{
|
||||||
|
encoding = reader.CurrentEncoding;
|
||||||
|
|
||||||
text = await reader.ReadToEndAsync().ConfigureAwait(false);
|
text = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var newText = text.Replace(",Arial,", ",Arial Unicode MS,");
|
var newText = text.Replace(",Arial,", ",Arial Unicode MS,");
|
||||||
|
|
||||||
if (!string.Equals(text, newText))
|
if (!string.Equals(text, newText))
|
||||||
{
|
{
|
||||||
using (var writer = new StreamWriter(file, false, encoding))
|
using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||||
{
|
{
|
||||||
writer.Write(newText);
|
using (var writer = new StreamWriter(fileStream, encoding))
|
||||||
|
{
|
||||||
|
writer.Write(newText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -795,7 +793,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
{
|
{
|
||||||
if (protocol == MediaProtocol.File)
|
if (protocol == MediaProtocol.File)
|
||||||
{
|
{
|
||||||
if (GetFileEncoding(path).Equals(Encoding.UTF8))
|
if (_textEncoding.GetFileEncoding(path).Equals(Encoding.UTF8))
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
@ -902,29 +900,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Encoding GetFileEncoding(string srcFile)
|
|
||||||
{
|
|
||||||
// *** Detect byte order mark if any - otherwise assume default
|
|
||||||
var buffer = new byte[5];
|
|
||||||
|
|
||||||
using (var file = _fileSystem.GetFileStream(srcFile, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite))
|
|
||||||
{
|
|
||||||
file.Read(buffer, 0, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
|
|
||||||
return Encoding.UTF8;
|
|
||||||
if (buffer[0] == 0xfe && buffer[1] == 0xff)
|
|
||||||
return Encoding.Unicode;
|
|
||||||
if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
|
|
||||||
return Encoding.UTF32;
|
|
||||||
if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
|
|
||||||
return Encoding.UTF7;
|
|
||||||
|
|
||||||
// It's ok - anything aside from utf is ok since that's what we're looking for
|
|
||||||
return Encoding.Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken)
|
private async Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (protocol == MediaProtocol.Http)
|
if (protocol == MediaProtocol.Http)
|
||||||
|
|
17
MediaBrowser.MediaEncoding/project.json
Normal file
17
MediaBrowser.MediaEncoding/project.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"frameworks":{
|
||||||
|
"netstandard1.6":{
|
||||||
|
"dependencies":{
|
||||||
|
"NETStandard.Library":"1.6.0",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".NETPortable,Version=v4.5,Profile=Profile7":{
|
||||||
|
"buildOptions": {
|
||||||
|
"define": [ ]
|
||||||
|
},
|
||||||
|
"frameworkAssemblies":{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
MediaBrowser.Model/Diagnostics/IProcess.cs
Normal file
19
MediaBrowser.Model/Diagnostics/IProcess.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Model.Diagnostics
|
||||||
|
{
|
||||||
|
public interface IProcess : IDisposable
|
||||||
|
{
|
||||||
|
event EventHandler Exited;
|
||||||
|
|
||||||
|
void Kill();
|
||||||
|
bool WaitForExit(int timeMs);
|
||||||
|
int ExitCode { get; }
|
||||||
|
void Start();
|
||||||
|
StreamWriter StandardInput { get; }
|
||||||
|
StreamReader StandardError { get; }
|
||||||
|
StreamReader StandardOutput { get; }
|
||||||
|
ProcessOptions StartInfo { get; }
|
||||||
|
}
|
||||||
|
}
|
24
MediaBrowser.Model/Diagnostics/IProcessFactory.cs
Normal file
24
MediaBrowser.Model/Diagnostics/IProcessFactory.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Model.Diagnostics
|
||||||
|
{
|
||||||
|
public interface IProcessFactory
|
||||||
|
{
|
||||||
|
IProcess Create(ProcessOptions options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProcessOptions
|
||||||
|
{
|
||||||
|
public String FileName { get; set; }
|
||||||
|
public String Arguments { get; set; }
|
||||||
|
public String WorkingDirectory { get; set; }
|
||||||
|
public bool CreateNoWindow { get; set; }
|
||||||
|
public bool UseShellExecute { get; set; }
|
||||||
|
public bool EnableRaisingEvents { get; set; }
|
||||||
|
public bool ErrorDialog { get; set; }
|
||||||
|
public bool RedirectStandardError { get; set; }
|
||||||
|
public bool RedirectStandardInput { get; set; }
|
||||||
|
public bool RedirectStandardOutput { get; set; }
|
||||||
|
public bool IsHidden { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -305,6 +305,8 @@ namespace MediaBrowser.Model.IO
|
||||||
char DirectorySeparatorChar { get; }
|
char DirectorySeparatorChar { get; }
|
||||||
|
|
||||||
string GetFullPath(string path);
|
string GetFullPath(string path);
|
||||||
|
|
||||||
|
List<FileSystemMetadata> GetDrives();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum FileOpenMode
|
public enum FileOpenMode
|
||||||
|
|
|
@ -106,6 +106,8 @@
|
||||||
<Compile Include="Devices\LocalFileInfo.cs" />
|
<Compile Include="Devices\LocalFileInfo.cs" />
|
||||||
<Compile Include="Devices\DeviceInfo.cs" />
|
<Compile Include="Devices\DeviceInfo.cs" />
|
||||||
<Compile Include="Devices\DevicesOptions.cs" />
|
<Compile Include="Devices\DevicesOptions.cs" />
|
||||||
|
<Compile Include="Diagnostics\IProcess.cs" />
|
||||||
|
<Compile Include="Diagnostics\IProcessFactory.cs" />
|
||||||
<Compile Include="Dlna\CodecProfile.cs" />
|
<Compile Include="Dlna\CodecProfile.cs" />
|
||||||
<Compile Include="Dlna\ContainerProfile.cs" />
|
<Compile Include="Dlna\ContainerProfile.cs" />
|
||||||
<Compile Include="Dlna\DeviceProfile.cs" />
|
<Compile Include="Dlna\DeviceProfile.cs" />
|
||||||
|
@ -422,6 +424,8 @@
|
||||||
<Compile Include="Tasks\ScheduledTaskHelpers.cs" />
|
<Compile Include="Tasks\ScheduledTaskHelpers.cs" />
|
||||||
<Compile Include="Tasks\TaskCompletionEventArgs.cs" />
|
<Compile Include="Tasks\TaskCompletionEventArgs.cs" />
|
||||||
<Compile Include="Tasks\TaskExecutionOptions.cs" />
|
<Compile Include="Tasks\TaskExecutionOptions.cs" />
|
||||||
|
<Compile Include="Threading\ITimer.cs" />
|
||||||
|
<Compile Include="Threading\ITimerFactory.cs" />
|
||||||
<Compile Include="Updates\CheckForUpdateResult.cs" />
|
<Compile Include="Updates\CheckForUpdateResult.cs" />
|
||||||
<Compile Include="Updates\PackageTargetSystem.cs" />
|
<Compile Include="Updates\PackageTargetSystem.cs" />
|
||||||
<Compile Include="Updates\InstallationInfo.cs" />
|
<Compile Include="Updates\InstallationInfo.cs" />
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.TextEncoding
|
namespace MediaBrowser.Model.TextEncoding
|
||||||
{
|
{
|
||||||
public interface IEncoding
|
public interface IEncoding
|
||||||
{
|
{
|
||||||
byte[] GetASCIIBytes(string text);
|
byte[] GetASCIIBytes(string text);
|
||||||
string GetASCIIString(byte[] bytes, int startIndex, int length);
|
string GetASCIIString(byte[] bytes, int startIndex, int length);
|
||||||
|
|
||||||
|
Encoding GetFileEncoding(string path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
MediaBrowser.Model/Threading/ITimer.cs
Normal file
10
MediaBrowser.Model/Threading/ITimer.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Model.Threading
|
||||||
|
{
|
||||||
|
public interface ITimer : IDisposable
|
||||||
|
{
|
||||||
|
void Change(TimeSpan dueTime, TimeSpan period);
|
||||||
|
void Change(int dueTimeMs, int periodMs);
|
||||||
|
}
|
||||||
|
}
|
10
MediaBrowser.Model/Threading/ITimerFactory.cs
Normal file
10
MediaBrowser.Model/Threading/ITimerFactory.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Model.Threading
|
||||||
|
{
|
||||||
|
public interface ITimerFactory
|
||||||
|
{
|
||||||
|
ITimer Create(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period);
|
||||||
|
ITimer Create(Action<object> callback, object state, int dueTimeMs, int periodMs);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -162,8 +162,7 @@ namespace MediaBrowser.Providers.BoxSets
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,8 +319,7 @@ namespace MediaBrowser.Providers.BoxSets
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -556,7 +556,7 @@ namespace MediaBrowser.Providers.Manager
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ImageType.Primary:
|
case ImageType.Primary:
|
||||||
return !(item is Movie || item is Series || item is Season || item is Game);
|
return !(item is Movie || item is Series || item is Game);
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,8 @@ namespace MediaBrowser.Providers.Manager
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
ResourcePool = resourcePool,
|
ResourcePool = resourcePool,
|
||||||
Url = url
|
Url = url,
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -222,8 +222,7 @@ namespace MediaBrowser.Providers.Movies
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +285,8 @@ namespace MediaBrowser.Providers.Movies
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
|
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = true
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
|
@ -220,8 +220,7 @@ namespace MediaBrowser.Providers.Movies
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -434,6 +434,7 @@ namespace MediaBrowser.Providers.Movies
|
||||||
options.ResourcePool = MovieDbResourcePool;
|
options.ResourcePool = MovieDbResourcePool;
|
||||||
_lastRequestTicks = DateTime.UtcNow.Ticks;
|
_lastRequestTicks = DateTime.UtcNow.Ticks;
|
||||||
|
|
||||||
|
options.BufferContent = true;
|
||||||
options.UserAgent = "Emby/" + _appHost.ApplicationVersion;
|
options.UserAgent = "Emby/" + _appHost.ApplicationVersion;
|
||||||
|
|
||||||
return await _httpClient.Get(options).ConfigureAwait(false);
|
return await _httpClient.Get(options).ConfigureAwait(false);
|
||||||
|
|
|
@ -46,8 +46,7 @@ namespace MediaBrowser.Providers.Movies
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = AudioDbArtistProvider.Current.AudioDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,6 @@ namespace MediaBrowser.Providers.Music
|
||||||
using (var response = await _httpClient.Get(new HttpRequestOptions
|
using (var response = await _httpClient.Get(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = AudioDbArtistProvider.Current.AudioDbResourcePool,
|
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
|
|
|
@ -129,8 +129,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = AudioDbArtistProvider.Current.AudioDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,8 @@ namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = AudioDbResourcePool,
|
ResourcePool = AudioDbResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = true
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
|
@ -211,8 +211,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,8 @@ namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = FanArtResourcePool,
|
ResourcePool = FanArtResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = true
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@ using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@ -266,7 +267,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
// Loop through each element
|
// Loop through each element
|
||||||
while (reader.Read())
|
while (!reader.EOF)
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
|
@ -287,6 +288,10 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
@ -299,7 +304,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
// Loop through each element
|
// Loop through each element
|
||||||
while (reader.Read())
|
while (!reader.EOF)
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
|
@ -326,6 +331,10 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
@ -421,7 +430,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
// Loop through each element
|
// Loop through each element
|
||||||
while (reader.Read())
|
while (!reader.EOF)
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
|
@ -441,6 +450,10 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -453,7 +466,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
// Loop through each element
|
// Loop through each element
|
||||||
while (reader.Read())
|
while (!reader.EOF)
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
|
@ -470,6 +483,10 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -517,7 +534,9 @@ namespace MediaBrowser.Providers.Music
|
||||||
|
|
||||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
list = _json.DeserializeFromStream<List<MbzUrl>>(stream);
|
var results = _json.DeserializeFromStream<List<MbzUrl>>(stream);
|
||||||
|
|
||||||
|
list = results;
|
||||||
}
|
}
|
||||||
_lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
|
_lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
|
||||||
}
|
}
|
||||||
|
@ -550,11 +569,13 @@ namespace MediaBrowser.Providers.Music
|
||||||
internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var urlInfo = await GetMbzUrl().ConfigureAwait(false);
|
var urlInfo = await GetMbzUrl().ConfigureAwait(false);
|
||||||
|
var throttleMs = urlInfo.throttleMs;
|
||||||
|
|
||||||
if (urlInfo.throttleMs > 0)
|
if (throttleMs > 0)
|
||||||
{
|
{
|
||||||
// MusicBrainz is extremely adamant about limiting to one request per second
|
// MusicBrainz is extremely adamant about limiting to one request per second
|
||||||
await Task.Delay(urlInfo.throttleMs, cancellationToken).ConfigureAwait(false);
|
_logger.Debug("Throttling MusicBrainz by {0}ms", throttleMs.ToString(CultureInfo.InvariantCulture));
|
||||||
|
await Task.Delay(throttleMs, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
url = urlInfo.url.TrimEnd('/') + url;
|
url = urlInfo.url.TrimEnd('/') + url;
|
||||||
|
@ -564,7 +585,8 @@ namespace MediaBrowser.Providers.Music
|
||||||
Url = url,
|
Url = url,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion,
|
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion,
|
||||||
ResourcePool = _musicBrainzResourcePool
|
ResourcePool = _musicBrainzResourcePool,
|
||||||
|
BufferContent = throttleMs > 0
|
||||||
};
|
};
|
||||||
|
|
||||||
return await _httpClient.Get(options).ConfigureAwait(false);
|
return await _httpClient.Get(options).ConfigureAwait(false);
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
// Loop through each element
|
// Loop through each element
|
||||||
while (reader.Read())
|
while (!reader.EOF)
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
|
@ -108,6 +108,10 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new List<RemoteSearchResult>();
|
return new List<RemoteSearchResult>();
|
||||||
|
@ -122,7 +126,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
// Loop through each element
|
// Loop through each element
|
||||||
while (reader.Read())
|
while (!reader.EOF)
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
|
@ -149,6 +153,10 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
|
|
@ -70,9 +70,7 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = OmdbProvider.ResourcePool
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,8 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = OmdbProvider.ResourcePool,
|
ResourcePool = OmdbProvider.ResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = true
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -296,8 +297,7 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = OmdbProvider.ResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,8 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = ResourcePool,
|
ResourcePool = ResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = true
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -340,7 +341,8 @@ namespace MediaBrowser.Providers.Omdb
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = ResourcePool,
|
ResourcePool = ResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = true
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,8 +135,7 @@ namespace MediaBrowser.Providers.People
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,8 +408,7 @@ namespace MediaBrowser.Providers.People
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,8 +216,7 @@ namespace MediaBrowser.Providers.People
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,8 +224,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,7 +320,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
|
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = true
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
|
@ -121,8 +121,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,8 +194,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,8 +656,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url
|
||||||
ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -88,8 +88,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
Headers["Content-Length"] = source.Length.ToString(UsCulture);
|
Headers["Content-Length"] = source.Length.ToString(UsCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int BufferSize = 81920;
|
|
||||||
|
|
||||||
public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)
|
public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -102,7 +100,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
{
|
{
|
||||||
using (var src = SourceStream)
|
using (var src = SourceStream)
|
||||||
{
|
{
|
||||||
await src.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false);
|
await src.CopyToAsync(responseStream).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
public event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
|
public event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
|
||||||
public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
|
public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
|
||||||
|
|
||||||
|
public string GetEmbyTvActiveRecordingPath(string id)
|
||||||
|
{
|
||||||
|
return EmbyTV.EmbyTV.Current.GetActiveRecordingPath(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<LiveStream> GetEmbyTvLiveStream(string id)
|
||||||
|
{
|
||||||
|
return EmbyTV.EmbyTV.Current.GetLiveStream(id);
|
||||||
|
}
|
||||||
|
|
||||||
public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem, ISecurityManager security)
|
public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem, ISecurityManager security)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
|
@ -70,6 +70,9 @@
|
||||||
<Reference Include="ServiceStack.Api.Swagger">
|
<Reference Include="ServiceStack.Api.Swagger">
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="ServiceStack.Common">
|
||||||
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="SharpCompress, Version=0.10.3.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="SharpCompress, Version=0.10.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||||
|
@ -79,7 +82,6 @@
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Configuration" />
|
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
|
@ -87,16 +89,12 @@
|
||||||
<Reference Include="System.Net" />
|
<Reference Include="System.Net" />
|
||||||
<Reference Include="System.Runtime.Serialization" />
|
<Reference Include="System.Runtime.Serialization" />
|
||||||
<Reference Include="System.Security" />
|
<Reference Include="System.Security" />
|
||||||
<Reference Include="System.ServiceModel" />
|
|
||||||
<Reference Include="System.Transactions" />
|
<Reference Include="System.Transactions" />
|
||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="ServiceStack">
|
<Reference Include="ServiceStack">
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Common">
|
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Common.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ServiceStack.Interfaces">
|
<Reference Include="ServiceStack.Interfaces">
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.TextEncoding;
|
using MediaBrowser.Model.TextEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.TextEncoding
|
namespace MediaBrowser.Server.Implementations.TextEncoding
|
||||||
{
|
{
|
||||||
public class TextEncoding : IEncoding
|
public class TextEncoding : IEncoding
|
||||||
{
|
{
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
|
public TextEncoding(IFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] GetASCIIBytes(string text)
|
public byte[] GetASCIIBytes(string text)
|
||||||
{
|
{
|
||||||
return Encoding.ASCII.GetBytes(text);
|
return Encoding.ASCII.GetBytes(text);
|
||||||
|
@ -14,5 +22,28 @@ namespace MediaBrowser.Server.Implementations.TextEncoding
|
||||||
{
|
{
|
||||||
return Encoding.ASCII.GetString(bytes, 0, bytes.Length);
|
return Encoding.ASCII.GetString(bytes, 0, bytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Encoding GetFileEncoding(string srcFile)
|
||||||
|
{
|
||||||
|
// *** Detect byte order mark if any - otherwise assume default
|
||||||
|
var buffer = new byte[5];
|
||||||
|
|
||||||
|
using (var file = _fileSystem.OpenRead(srcFile))
|
||||||
|
{
|
||||||
|
file.Read(buffer, 0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
|
||||||
|
return Encoding.UTF8;
|
||||||
|
if (buffer[0] == 0xfe && buffer[1] == 0xff)
|
||||||
|
return Encoding.Unicode;
|
||||||
|
if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
|
||||||
|
return Encoding.UTF32;
|
||||||
|
if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
|
||||||
|
return Encoding.UTF7;
|
||||||
|
|
||||||
|
// It's ok - anything aside from utf is ok since that's what we're looking for
|
||||||
|
return Encoding.Default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -547,7 +547,7 @@ namespace MediaBrowser.Server.Startup.Common
|
||||||
StringExtensions.LocalizationManager = LocalizationManager;
|
StringExtensions.LocalizationManager = LocalizationManager;
|
||||||
RegisterSingleInstance(LocalizationManager);
|
RegisterSingleInstance(LocalizationManager);
|
||||||
|
|
||||||
IEncoding textEncoding = new TextEncoding();
|
IEncoding textEncoding = new TextEncoding(FileSystemManager);
|
||||||
RegisterSingleInstance(textEncoding);
|
RegisterSingleInstance(textEncoding);
|
||||||
Utilities.EncodingHelper = textEncoding;
|
Utilities.EncodingHelper = textEncoding;
|
||||||
RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer(FileSystemManager, textEncoding));
|
RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer(FileSystemManager, textEncoding));
|
||||||
|
@ -697,7 +697,7 @@ namespace MediaBrowser.Server.Startup.Common
|
||||||
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
|
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
|
||||||
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager));
|
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager));
|
||||||
|
|
||||||
SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, MemoryStreamProvider);
|
SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, MemoryStreamProvider, ProcessFactory, textEncoding);
|
||||||
RegisterSingleInstance(SubtitleEncoder);
|
RegisterSingleInstance(SubtitleEncoder);
|
||||||
|
|
||||||
await displayPreferencesRepo.Initialize().ConfigureAwait(false);
|
await displayPreferencesRepo.Initialize().ConfigureAwait(false);
|
||||||
|
@ -789,7 +789,10 @@ namespace MediaBrowser.Server.Startup.Common
|
||||||
() => SubtitleEncoder,
|
() => SubtitleEncoder,
|
||||||
() => MediaSourceManager,
|
() => MediaSourceManager,
|
||||||
HttpClient,
|
HttpClient,
|
||||||
ZipClient, MemoryStreamProvider);
|
ZipClient, MemoryStreamProvider,
|
||||||
|
ProcessFactory,
|
||||||
|
Environment.Is64BitOperatingSystem ? (Environment.ProcessorCount > 2 ? 14000 : 20000) : 40000,
|
||||||
|
Environment.OSVersion.Platform == PlatformID.Win32NT);
|
||||||
|
|
||||||
MediaEncoder = mediaEncoder;
|
MediaEncoder = mediaEncoder;
|
||||||
RegisterSingleInstance(MediaEncoder);
|
RegisterSingleInstance(MediaEncoder);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user