mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-19 20:54:20 +01:00
created common startup project for mono & windows
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,57 +0,0 @@
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.ServerApplication.Native;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.EntryPoints
|
||||
{
|
||||
public class KeepServerAwake : IServerEntryPoint
|
||||
{
|
||||
private readonly ISessionManager _sessionManager;
|
||||
private readonly ILogger _logger;
|
||||
private Timer _timer;
|
||||
|
||||
public KeepServerAwake(ISessionManager sessionManager, ILogger logger)
|
||||
{
|
||||
_sessionManager = sessionManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
_timer = new Timer(obj =>
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 5))
|
||||
{
|
||||
KeepAlive();
|
||||
}
|
||||
|
||||
}, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
|
||||
}
|
||||
|
||||
private void KeepAlive()
|
||||
{
|
||||
try
|
||||
{
|
||||
NativeApp.PreventSystemStandby();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error resetting system standby timer", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_timer != null)
|
||||
{
|
||||
_timer.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.ServerApplication.Native;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.EntryPoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Class StartupWizard
|
||||
/// </summary>
|
||||
public class StartupWizard : IServerEntryPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// The _app host
|
||||
/// </summary>
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
/// <summary>
|
||||
/// The _user manager
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StartupWizard" /> class.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public StartupWizard(IServerApplicationHost appHost, ILogger logger)
|
||||
{
|
||||
_appHost = appHost;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs this instance.
|
||||
/// </summary>
|
||||
public void Run()
|
||||
{
|
||||
if (_appHost.IsFirstRun)
|
||||
{
|
||||
LaunchStartupWizard();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches the startup wizard.
|
||||
/// </summary>
|
||||
private void LaunchStartupWizard()
|
||||
{
|
||||
BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost, _logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
using Mono.Unix.Native;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
{
|
||||
public static class FFMpegDownloadInfo
|
||||
{
|
||||
// Windows builds: http://ffmpeg.zeranoe.com/builds/
|
||||
// Linux builds: http://ffmpeg.gusari.org/static/
|
||||
// OS X builds: http://ffmpegmac.net/
|
||||
// OS X x64: http://www.evermeet.cx/ffmpeg/
|
||||
|
||||
public static string Version = getFfmpegValue("Version");
|
||||
|
||||
public static string FFMpegFilename = getFfmpegValue("FFMpegFilename");
|
||||
public static string FFProbeFilename = getFfmpegValue("FFProbeFilename");
|
||||
|
||||
public static string ArchiveType = getFfmpegValue("ArchiveType");
|
||||
|
||||
private static string getFfmpegValue(string arg)
|
||||
{
|
||||
OperatingSystem os = Environment.OSVersion;
|
||||
PlatformID pid = os.Platform;
|
||||
switch (pid)
|
||||
{
|
||||
case PlatformID.Win32NT:
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20141005";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg.exe";
|
||||
case "FFProbeFilename":
|
||||
return "ffprobe.exe";
|
||||
case "ArchiveType":
|
||||
return "7z";
|
||||
}
|
||||
break;
|
||||
|
||||
case PlatformID.Unix:
|
||||
if (PlatformDetection.IsMac)
|
||||
{
|
||||
if (PlatformDetection.IsX86_64)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20140923";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg";
|
||||
case "FFProbeFilename":
|
||||
return "ffprobe";
|
||||
case "ArchiveType":
|
||||
return "7z";
|
||||
}
|
||||
}
|
||||
if (PlatformDetection.IsX86)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20140910";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg";
|
||||
case "FFProbeFilename":
|
||||
return "ffprobe";
|
||||
case "ArchiveType":
|
||||
return "7z";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PlatformDetection.IsLinux)
|
||||
{
|
||||
if (PlatformDetection.IsX86)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20140716";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg";
|
||||
case "FFProbeFilename":
|
||||
return "ffprobe";
|
||||
case "ArchiveType":
|
||||
return "gz";
|
||||
}
|
||||
}
|
||||
|
||||
else if (PlatformDetection.IsX86_64)
|
||||
{
|
||||
// Linux on x86 or x86_64
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20140716";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg";
|
||||
case "FFProbeFilename":
|
||||
return "ffprobe";
|
||||
case "ArchiveType":
|
||||
return "gz";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "path";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg";
|
||||
case "FFProbeFilename":
|
||||
return "ffprobe";
|
||||
case "ArchiveType":
|
||||
return "";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] GetDownloadUrls()
|
||||
{
|
||||
var pid = Environment.OSVersion.Platform;
|
||||
|
||||
switch (pid)
|
||||
{
|
||||
case PlatformID.Win32NT:
|
||||
if (PlatformDetection.IsX86_64)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20141005-git-e079d43-win64-static.7z",
|
||||
"https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20141005-git-e079d43-win64-static.7z"
|
||||
};
|
||||
}
|
||||
|
||||
return new[]
|
||||
{
|
||||
"http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20141005-git-e079d43-win32-static.7z",
|
||||
"https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20141005-git-e079d43-win32-static.7z"
|
||||
};
|
||||
|
||||
case PlatformID.Unix:
|
||||
if (PlatformDetection.IsMac && PlatformDetection.IsX86)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-x86-2.4.2.7z"
|
||||
};
|
||||
}
|
||||
|
||||
if (PlatformDetection.IsMac && PlatformDetection.IsX86_64)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.4.1.7z"
|
||||
};
|
||||
}
|
||||
|
||||
if (PlatformDetection.IsLinux)
|
||||
{
|
||||
if (PlatformDetection.IsX86)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.latest.tar.gz",
|
||||
"https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg.static.32bit.2014-07-16.tar.gz"
|
||||
};
|
||||
}
|
||||
|
||||
if (PlatformDetection.IsX86_64)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.latest.tar.gz",
|
||||
"https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg.static.64bit.2014-07-16.tar.gz"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// No Unix version available
|
||||
return new string[] { };
|
||||
|
||||
default:
|
||||
throw new ApplicationException("No ffmpeg download available for " + pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlatformDetection
|
||||
{
|
||||
public readonly static bool IsWindows;
|
||||
public readonly static bool IsMac;
|
||||
public readonly static bool IsLinux;
|
||||
public readonly static bool IsX86;
|
||||
public readonly static bool IsX86_64;
|
||||
public readonly static bool IsArm;
|
||||
|
||||
static PlatformDetection()
|
||||
{
|
||||
IsWindows = Path.DirectorySeparatorChar == '\\';
|
||||
|
||||
// Don't call uname on windows
|
||||
if (!IsWindows)
|
||||
{
|
||||
var uname = GetUnixName();
|
||||
|
||||
var sysName = uname.sysname ?? string.Empty;
|
||||
|
||||
IsMac = string.Equals(sysName, "Darwin", StringComparison.OrdinalIgnoreCase);
|
||||
IsLinux = string.Equals(sysName, "Linux", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var archX86 = new Regex("(i|I)[3-6]86");
|
||||
IsX86 = archX86.IsMatch(uname.machine);
|
||||
IsX86_64 = !IsX86 && uname.machine == "x86_64";
|
||||
IsArm = !IsX86 && !IsX86_64 && uname.machine.StartsWith("arm");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Environment.Is64BitOperatingSystem)
|
||||
IsX86_64 = true;
|
||||
else
|
||||
IsX86 = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static Uname GetUnixName()
|
||||
{
|
||||
var uname = new Uname();
|
||||
Utsname utsname;
|
||||
var callResult = Syscall.uname(out utsname);
|
||||
if (callResult == 0)
|
||||
{
|
||||
uname.sysname = utsname.sysname;
|
||||
uname.machine = utsname.machine;
|
||||
}
|
||||
return uname;
|
||||
}
|
||||
}
|
||||
|
||||
public class Uname
|
||||
{
|
||||
public string sysname = string.Empty;
|
||||
public string machine = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -1,416 +0,0 @@
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.ServerApplication.IO;
|
||||
using Mono.Unix.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
{
|
||||
public class FFMpegDownloader
|
||||
{
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IZipClient _zipClient;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
private readonly string[] _fontUrls =
|
||||
{
|
||||
"https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/ARIALUNI.7z"
|
||||
};
|
||||
|
||||
public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem)
|
||||
{
|
||||
_logger = logger;
|
||||
_appPaths = appPaths;
|
||||
_httpClient = httpClient;
|
||||
_zipClient = zipClient;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
public async Task<FFMpegInfo> GetFFMpegInfo(StartupOptions options, IProgress<double> progress)
|
||||
{
|
||||
var customffMpegPath = options.GetOption("-ffmpeg");
|
||||
var customffProbePath = options.GetOption("-ffprobe");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(customffMpegPath) && !string.IsNullOrWhiteSpace(customffProbePath))
|
||||
{
|
||||
return new FFMpegInfo
|
||||
{
|
||||
ProbePath = customffProbePath,
|
||||
EncoderPath = customffMpegPath,
|
||||
Version = "custom"
|
||||
};
|
||||
}
|
||||
|
||||
var version = FFMpegDownloadInfo.Version;
|
||||
|
||||
if (string.Equals(version, "path", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new FFMpegInfo
|
||||
{
|
||||
ProbePath = FFMpegDownloadInfo.FFProbeFilename,
|
||||
EncoderPath = FFMpegDownloadInfo.FFMpegFilename,
|
||||
Version = version
|
||||
};
|
||||
}
|
||||
|
||||
var rootEncoderPath = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
|
||||
var versionedDirectoryPath = Path.Combine(rootEncoderPath, version);
|
||||
|
||||
var info = new FFMpegInfo
|
||||
{
|
||||
ProbePath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFProbeFilename),
|
||||
EncoderPath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFMpegFilename),
|
||||
Version = version
|
||||
};
|
||||
|
||||
Directory.CreateDirectory(versionedDirectoryPath);
|
||||
|
||||
var excludeFromDeletions = new List<string> { versionedDirectoryPath };
|
||||
|
||||
if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath))
|
||||
{
|
||||
// ffmpeg not present. See if there's an older version we can start with
|
||||
var existingVersion = GetExistingVersion(info, rootEncoderPath);
|
||||
|
||||
// No older version. Need to download and block until complete
|
||||
if (existingVersion == null)
|
||||
{
|
||||
await DownloadFFMpeg(versionedDirectoryPath, progress).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Older version found.
|
||||
// Start with that. Download new version in the background.
|
||||
var newPath = versionedDirectoryPath;
|
||||
Task.Run(() => DownloadFFMpegInBackground(newPath));
|
||||
|
||||
info = existingVersion;
|
||||
versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath);
|
||||
|
||||
excludeFromDeletions.Add(versionedDirectoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false);
|
||||
|
||||
DeleteOlderFolders(Path.GetDirectoryName(versionedDirectoryPath), excludeFromDeletions);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private void DeleteOlderFolders(string path, IEnumerable<string> excludeFolders )
|
||||
{
|
||||
var folders = Directory.GetDirectories(path)
|
||||
.Where(i => !excludeFolders.Contains(i, StringComparer.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
DeleteFolder(folder);
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteFolder(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(path, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error deleting {0}", ex, path);
|
||||
}
|
||||
}
|
||||
|
||||
private FFMpegInfo GetExistingVersion(FFMpegInfo info, string rootEncoderPath)
|
||||
{
|
||||
var encoderFilename = Path.GetFileName(info.EncoderPath);
|
||||
var probeFilename = Path.GetFileName(info.ProbePath);
|
||||
|
||||
foreach (var directory in Directory.EnumerateDirectories(rootEncoderPath, "*", SearchOption.TopDirectoryOnly)
|
||||
.ToList())
|
||||
{
|
||||
var allFiles = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories).ToList();
|
||||
|
||||
var encoder = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), encoderFilename, StringComparison.OrdinalIgnoreCase));
|
||||
var probe = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), probeFilename, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(encoder) &&
|
||||
!string.IsNullOrWhiteSpace(probe))
|
||||
{
|
||||
return new FFMpegInfo
|
||||
{
|
||||
EncoderPath = encoder,
|
||||
ProbePath = probe,
|
||||
Version = Path.GetFileName(Path.GetDirectoryName(probe))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async void DownloadFFMpegInBackground(string directory)
|
||||
{
|
||||
try
|
||||
{
|
||||
await DownloadFFMpeg(directory, new Progress<double>()).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error downloading ffmpeg", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadFFMpeg(string directory, IProgress<double> progress)
|
||||
{
|
||||
foreach (var url in FFMpegDownloadInfo.GetDownloadUrls())
|
||||
{
|
||||
progress.Report(0);
|
||||
|
||||
try
|
||||
{
|
||||
var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = CancellationToken.None,
|
||||
Progress = progress
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
ExtractFFMpeg(tempFile, directory);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error downloading {0}", ex, url);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ApplicationException("Unable to download required components. Please try again later.");
|
||||
}
|
||||
|
||||
private void ExtractFFMpeg(string tempFile, string targetFolder)
|
||||
{
|
||||
_logger.Info("Extracting ffmpeg from {0}", tempFile);
|
||||
|
||||
var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString());
|
||||
|
||||
Directory.CreateDirectory(tempFolder);
|
||||
|
||||
try
|
||||
{
|
||||
ExtractArchive(tempFile, tempFolder);
|
||||
|
||||
var files = Directory.EnumerateFiles(tempFolder, "*", SearchOption.AllDirectories).ToList();
|
||||
|
||||
foreach (var file in files.Where(i =>
|
||||
{
|
||||
var filename = Path.GetFileName(i);
|
||||
|
||||
return
|
||||
string.Equals(filename, FFMpegDownloadInfo.FFProbeFilename, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(filename, FFMpegDownloadInfo.FFMpegFilename, StringComparison.OrdinalIgnoreCase);
|
||||
}))
|
||||
{
|
||||
File.Copy(file, Path.Combine(targetFolder, Path.GetFileName(file)), true);
|
||||
|
||||
SetFilePermissions(targetFolder, file);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
DeleteFile(tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetFilePermissions(string targetFolder, string file)
|
||||
{
|
||||
// Linux: File permission to 666, and user's execute bit
|
||||
if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
|
||||
{
|
||||
Syscall.chmod(Path.Combine(targetFolder, Path.GetFileName(file)), FilePermissions.DEFFILEMODE | FilePermissions.S_IXUSR);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtractArchive(string archivePath, string targetPath)
|
||||
{
|
||||
_logger.Info("Extracting {0} to {1}", archivePath, targetPath);
|
||||
|
||||
if (string.Equals(FFMpegDownloadInfo.ArchiveType, "7z", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_zipClient.ExtractAllFrom7z(archivePath, targetPath, true);
|
||||
}
|
||||
else if (string.Equals(FFMpegDownloadInfo.ArchiveType, "gz", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_zipClient.ExtractAllFromTar(archivePath, targetPath, true);
|
||||
}
|
||||
}
|
||||
private void Extract7zArchive(string archivePath, string targetPath)
|
||||
{
|
||||
_logger.Info("Extracting {0} to {1}", archivePath, targetPath);
|
||||
|
||||
_zipClient.ExtractAllFrom7z(archivePath, targetPath, true);
|
||||
}
|
||||
|
||||
private void DeleteFile(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.ErrorException("Error deleting temp file {0}", ex, path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the fonts.
|
||||
/// </summary>
|
||||
/// <param name="targetPath">The target path.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private async Task DownloadFonts(string targetPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fontsDirectory = Path.Combine(targetPath, "fonts");
|
||||
|
||||
Directory.CreateDirectory(fontsDirectory);
|
||||
|
||||
const string fontFilename = "ARIALUNI.TTF";
|
||||
|
||||
var fontFile = Path.Combine(fontsDirectory, fontFilename);
|
||||
|
||||
if (File.Exists(fontFile))
|
||||
{
|
||||
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Kick this off, but no need to wait on it
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await DownloadFontFile(fontsDirectory, fontFilename, new Progress<double>()).ConfigureAwait(false);
|
||||
|
||||
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
// Don't let the server crash because of this
|
||||
_logger.ErrorException("Error downloading ffmpeg font files", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Don't let the server crash because of this
|
||||
_logger.ErrorException("Error writing ffmpeg font files", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the font file.
|
||||
/// </summary>
|
||||
/// <param name="fontsDirectory">The fonts directory.</param>
|
||||
/// <param name="fontFilename">The font filename.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private async Task DownloadFontFile(string fontsDirectory, string fontFilename, IProgress<double> progress)
|
||||
{
|
||||
var existingFile = Directory
|
||||
.EnumerateFiles(_appPaths.ProgramDataPath, fontFilename, SearchOption.AllDirectories)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (existingFile != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Copy(existingFile, Path.Combine(fontsDirectory, fontFilename), true);
|
||||
return;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Log this, but don't let it fail the operation
|
||||
_logger.ErrorException("Error copying file", ex);
|
||||
}
|
||||
}
|
||||
|
||||
string tempFile = null;
|
||||
|
||||
foreach (var url in _fontUrls)
|
||||
{
|
||||
progress.Report(0);
|
||||
|
||||
try
|
||||
{
|
||||
tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
Progress = progress
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// The core can function without the font file, so handle this
|
||||
_logger.ErrorException("Failed to download ffmpeg font file from {0}", ex, url);
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tempFile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Extract7zArchive(tempFile, fontsDirectory);
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Log this, but don't let it fail the operation
|
||||
_logger.ErrorException("Error deleting temp file {0}", ex, tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the font config file.
|
||||
/// </summary>
|
||||
/// <param name="fontsDirectory">The fonts directory.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private async Task WriteFontConfigFile(string fontsDirectory)
|
||||
{
|
||||
const string fontConfigFilename = "fonts.conf";
|
||||
var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename);
|
||||
|
||||
if (!File.Exists(fontConfigFile))
|
||||
{
|
||||
var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory);
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(contents);
|
||||
|
||||
using (var fileStream = _fileSystem.GetFileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
|
||||
FileShare.Read, true))
|
||||
{
|
||||
await fileStream.WriteAsync(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
{
|
||||
/// <summary>
|
||||
/// Class FFMpegInfo
|
||||
/// </summary>
|
||||
public class FFMpegInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the path.
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
public string EncoderPath { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the probe path.
|
||||
/// </summary>
|
||||
/// <value>The probe path.</value>
|
||||
public string ProbePath { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the version.
|
||||
/// </summary>
|
||||
/// <value>The version.</value>
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.IO
|
||||
{
|
||||
public class StartupOptions
|
||||
{
|
||||
private readonly List<string> _options = Environment.GetCommandLineArgs().ToList();
|
||||
|
||||
public bool ContainsOption(string option)
|
||||
{
|
||||
return _options.Contains(option, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public string GetOption(string name)
|
||||
{
|
||||
var index = _options.IndexOf(name);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
return _options.ElementAtOrDefault(index + 1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
namespace MediaBrowser.ServerApplication.Logging
|
||||
{
|
||||
partial class LogForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LogForm));
|
||||
this.listBox1 = new System.Windows.Forms.ListBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// listBox1
|
||||
//
|
||||
this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.listBox1.Font = new System.Drawing.Font("Consolas", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.listBox1.FormattingEnabled = true;
|
||||
this.listBox1.ItemHeight = 18;
|
||||
this.listBox1.Location = new System.Drawing.Point(0, 0);
|
||||
this.listBox1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.listBox1.Name = "listBox1";
|
||||
this.listBox1.Size = new System.Drawing.Size(984, 561);
|
||||
this.listBox1.TabIndex = 0;
|
||||
//
|
||||
// LogForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(984, 561);
|
||||
this.Controls.Add(this.listBox1);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Name = "LogForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Media Browser Log";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ListBox listBox1;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using MediaBrowser.Common.Implementations.Logging;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using NLog.Targets;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.Logging
|
||||
{
|
||||
public partial class LogForm : Form
|
||||
{
|
||||
private readonly TaskScheduler _uiThread;
|
||||
private readonly ILogManager _logManager;
|
||||
|
||||
public LogForm(ILogManager logManager)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_logManager = logManager;
|
||||
_uiThread = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
|
||||
((NlogManager)_logManager).RemoveTarget("LogWindowTraceTarget");
|
||||
|
||||
((NlogManager)_logManager).AddLogTarget(new TraceTarget
|
||||
{
|
||||
Layout = "${longdate}, ${level}, ${logger}, ${message}",
|
||||
Name = "LogWindowTraceTarget"
|
||||
|
||||
}, LogSeverity.Debug);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the message.
|
||||
/// </summary>
|
||||
/// <param name="msg">The MSG.</param>
|
||||
public async void LogMessage(string msg)
|
||||
{
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
if (listBox1.Items.Count > 10000)
|
||||
{
|
||||
//I think the quickest and safest thing to do here is just clear it out
|
||||
listBox1.Items.Clear();
|
||||
}
|
||||
|
||||
foreach (var line in msg.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
listBox1.Items.Insert(0, line);
|
||||
}
|
||||
}
|
||||
|
||||
}, CancellationToken.None, TaskCreationOptions.None, _uiThread);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The log layout
|
||||
/// </summary>
|
||||
/// <value>The log layout.</value>
|
||||
public string LogLayout
|
||||
{
|
||||
get { return "${longdate}, ${level}, ${logger}, ${message}"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down.
|
||||
/// </summary>
|
||||
public async void ShutDown()
|
||||
{
|
||||
await Task.Factory.StartNew(Close, CancellationToken.None, TaskCreationOptions.None, _uiThread);
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e)
|
||||
{
|
||||
base.OnClosing(e);
|
||||
|
||||
((NlogManager)_logManager).RemoveTarget("LogWindowTraceTarget");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,75 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Class WindowTraceListener
|
||||
/// </summary>
|
||||
public class WindowTraceListener : DefaultTraceListener
|
||||
{
|
||||
/// <summary>
|
||||
/// The _window
|
||||
/// </summary>
|
||||
private readonly LogForm _window;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WindowTraceListener" /> class.
|
||||
/// </summary>
|
||||
/// <param name="window">The window.</param>
|
||||
public WindowTraceListener(LogForm window)
|
||||
{
|
||||
_window = window;
|
||||
_window.Show();
|
||||
Name = "MBLogWindow";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the value of the object's <see cref="M:System.Object.ToString" /> method to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener" /> class.
|
||||
/// </summary>
|
||||
/// <param name="o">An <see cref="T:System.Object" /> whose fully qualified class name you want to write.</param>
|
||||
public override void Write(object o)
|
||||
{
|
||||
var str = o as string;
|
||||
if (str != null)
|
||||
Write(str);
|
||||
else
|
||||
base.Write(o);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the output to the OutputDebugString function and to the <see cref="M:System.Diagnostics.Debugger.Log(System.Int32,System.String,System.String)" /> method.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to write to OutputDebugString and <see cref="M:System.Diagnostics.Debugger.Log(System.Int32,System.String,System.String)" />.</param>
|
||||
/// <PermissionSet>
|
||||
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
|
||||
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlEvidence" />
|
||||
/// </PermissionSet>
|
||||
public override void Write(string message)
|
||||
{
|
||||
_window.LogMessage(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the output to the OutputDebugString function and to the <see cref="M:System.Diagnostics.Debugger.Log(System.Int32,System.String,System.String)" /> method, followed by a carriage return and line feed (\r\n).
|
||||
/// </summary>
|
||||
/// <param name="message">The message to write to OutputDebugString and <see cref="M:System.Diagnostics.Debugger.Log(System.Int32,System.String,System.String)" />.</param>
|
||||
/// <PermissionSet>
|
||||
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
|
||||
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlEvidence" />
|
||||
/// </PermissionSet>
|
||||
public override void WriteLine(string message)
|
||||
{
|
||||
Write(message+"\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the <see cref="T:System.Diagnostics.TraceListener" /> and optionally releases the managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_window != null)
|
||||
_window.ShutDown();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
using MediaBrowser.Common.Implementations.Logging;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Server.Implementations;
|
||||
using MediaBrowser.ServerApplication.IO;
|
||||
using MediaBrowser.Server.Startup.Common;
|
||||
using MediaBrowser.Server.Startup.Common.Browser;
|
||||
using MediaBrowser.ServerApplication.Native;
|
||||
using MediaBrowser.ServerApplication.Splash;
|
||||
using MediaBrowser.ServerApplication.Updates;
|
||||
@@ -211,21 +212,25 @@ namespace MediaBrowser.ServerApplication
|
||||
{
|
||||
var fileSystem = new NativeFileSystem(logManager.GetLogger("FileSystem"), false);
|
||||
|
||||
_appHost = new ApplicationHost(appPaths,
|
||||
logManager,
|
||||
true,
|
||||
runService,
|
||||
options,
|
||||
fileSystem,
|
||||
var nativeApp = new WindowsApp
|
||||
{
|
||||
IsRunningAsService = runService
|
||||
};
|
||||
|
||||
_appHost = new ApplicationHost(appPaths,
|
||||
logManager,
|
||||
options,
|
||||
fileSystem,
|
||||
"MBServer",
|
||||
true);
|
||||
true,
|
||||
nativeApp);
|
||||
|
||||
var initProgress = new Progress<double>();
|
||||
|
||||
if (!runService)
|
||||
{
|
||||
if (!options.ContainsOption("-nosplash")) ShowSplashScreen(_appHost.ApplicationVersion, initProgress, logManager.GetLogger("Splash"));
|
||||
|
||||
|
||||
// Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes
|
||||
SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT |
|
||||
ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX);
|
||||
@@ -245,11 +250,11 @@ namespace MediaBrowser.ServerApplication
|
||||
|
||||
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
|
||||
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
|
||||
|
||||
|
||||
HideSplashScreen();
|
||||
|
||||
ShowTrayIcon();
|
||||
|
||||
|
||||
task = ApplicationTaskCompletionSource.Task;
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
@@ -260,7 +265,7 @@ namespace MediaBrowser.ServerApplication
|
||||
{
|
||||
//Application.EnableVisualStyles();
|
||||
//Application.SetCompatibleTextRenderingDefault(false);
|
||||
_serverNotifyIcon = new ServerNotifyIcon(_appHost.LogManager, _appHost, _appHost.ServerConfigurationManager, _appHost.UserManager, _appHost.LibraryManager, _appHost.JsonSerializer, _appHost.LocalizationManager, _appHost.UserViewManager);
|
||||
_serverNotifyIcon = new ServerNotifyIcon(_appHost.LogManager, _appHost, _appHost.ServerConfigurationManager, _appHost.LocalizationManager);
|
||||
Application.Run();
|
||||
}
|
||||
|
||||
@@ -274,7 +279,7 @@ namespace MediaBrowser.ServerApplication
|
||||
|
||||
_splash.ShowDialog();
|
||||
});
|
||||
|
||||
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
|
||||
@@ -63,10 +63,6 @@
|
||||
<Reference Include="MediaBrowser.IsoMounter">
|
||||
<HintPath>..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=3.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.3.1.0.0\lib\net45\NLog.dll</HintPath>
|
||||
@@ -98,28 +94,14 @@
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="ApplicationHost.cs" />
|
||||
<Compile Include="BackgroundService.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="BackgroundServiceInstaller.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="EntryPoints\KeepServerAwake.cs" />
|
||||
<Compile Include="EntryPoints\ResourceEntryPoint.cs" />
|
||||
<Compile Include="EntryPoints\StartupWizard.cs" />
|
||||
<Compile Include="FFMpeg\FFMpegDownloader.cs" />
|
||||
<Compile Include="FFMpeg\FFMpegDownloadInfo.cs" />
|
||||
<Compile Include="FFMpeg\FFMpegInfo.cs" />
|
||||
<Compile Include="IO\NativeFileSystem.cs" />
|
||||
<Compile Include="IO\StartupOptions.cs" />
|
||||
<Compile Include="Logging\LogForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Logging\LogForm.Designer.cs">
|
||||
<DependentUpon>LogForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Logging\WindowTraceListener.cs" />
|
||||
<Compile Include="Native\NativeFileSystem.cs" />
|
||||
<Compile Include="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -127,11 +109,10 @@
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MainStartup.cs" />
|
||||
<Compile Include="Native\Assemblies.cs" />
|
||||
<Compile Include="Native\Autorun.cs" />
|
||||
<Compile Include="Native\BrowserLauncher.cs" />
|
||||
<Compile Include="Native\NativeApp.cs" />
|
||||
<Compile Include="Native\Standby.cs" />
|
||||
<Compile Include="Native\ServerAuthorization.cs" />
|
||||
<Compile Include="Native\WindowsApp.cs" />
|
||||
<Compile Include="Networking\NativeMethods.cs" />
|
||||
<Compile Include="Networking\NetworkManager.cs" />
|
||||
<Compile Include="Networking\NetworkShares.cs" />
|
||||
@@ -157,9 +138,6 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Logging\LogForm.resx">
|
||||
<DependentUpon>LogForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="MainForm.resx">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@@ -232,6 +210,10 @@
|
||||
<Project>{2e781478-814d-4a48-9d80-bff206441a65}</Project>
|
||||
<Name>MediaBrowser.Server.Implementations</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\MediaBrowser.Server.Startup.Common\MediaBrowser.Server.Startup.Common.csproj">
|
||||
<Project>{b90ab8f2-1bff-4568-a3fd-2a338a435a75}</Project>
|
||||
<Name>MediaBrowser.Server.Startup.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj">
|
||||
<Project>{5624b7b5-b5a7-41d8-9f10-cc5611109619}</Project>
|
||||
<Name>MediaBrowser.WebDashboard</Name>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
using MediaBrowser.IsoMounter;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// Class Assemblies
|
||||
/// </summary>
|
||||
public static class Assemblies
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the assemblies with parts.
|
||||
/// </summary>
|
||||
/// <returns>List{Assembly}.</returns>
|
||||
public static List<Assembly> GetAssembliesWithParts()
|
||||
{
|
||||
var list = new List<Assembly>();
|
||||
|
||||
list.Add(typeof(PismoIsoManager).Assembly);
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BrowserLauncher
|
||||
/// </summary>
|
||||
public static class BrowserLauncher
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens the dashboard page.
|
||||
/// </summary>
|
||||
/// <param name="page">The page.</param>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void OpenDashboardPage(string page, IServerApplicationHost appHost, ILogger logger)
|
||||
{
|
||||
var url = "http://localhost:" + appHost.HttpServerPort + "/" +
|
||||
appHost.WebApplicationName + "/web/" + page;
|
||||
|
||||
OpenUrl(url, logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the github.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void OpenGithub(ILogger logger)
|
||||
{
|
||||
OpenUrl("https://github.com/MediaBrowser/MediaBrowser", logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the community.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void OpenCommunity(ILogger logger)
|
||||
{
|
||||
OpenUrl("http://mediabrowser.tv/community", logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the web client.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void OpenWebClient(IServerApplicationHost appHost, ILogger logger)
|
||||
{
|
||||
OpenDashboardPage("index.html", appHost, logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the dashboard.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void OpenDashboard(IServerApplicationHost appHost, ILogger logger)
|
||||
{
|
||||
OpenDashboardPage("dashboard.html", appHost, logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the swagger.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void OpenSwagger(IServerApplicationHost appHost, ILogger logger)
|
||||
{
|
||||
OpenUrl("http://localhost:" + appHost.HttpServerPort + "/" +
|
||||
appHost.WebApplicationName + "/swagger-ui/index.html", logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the URL.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
private static void OpenUrl(string url, ILogger logger)
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = url
|
||||
},
|
||||
|
||||
EnableRaisingEvents = true,
|
||||
};
|
||||
|
||||
process.Exited += ProcessExited;
|
||||
|
||||
try
|
||||
{
|
||||
process.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.ErrorException("Error launching url: {0}", ex, url);
|
||||
|
||||
Console.WriteLine("Error launching browser");
|
||||
Console.WriteLine(ex.Message);
|
||||
|
||||
//#if !__MonoCS__
|
||||
// System.Windows.Forms.MessageBox.Show("There was an error launching your web browser. Please check your default browser settings.");
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the exited.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||
private static void ProcessExited(object sender, EventArgs e)
|
||||
{
|
||||
((Process)sender).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// Class NativeApp
|
||||
/// </summary>
|
||||
public static class NativeApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Shutdowns this instance.
|
||||
/// </summary>
|
||||
public static void Shutdown()
|
||||
{
|
||||
MainStartup.Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts this instance.
|
||||
/// </summary>
|
||||
public static void Restart()
|
||||
{
|
||||
MainStartup.Restart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance [can self restart].
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this instance [can self restart]; otherwise, <c>false</c>.</returns>
|
||||
public static bool CanSelfRestart
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainStartup.CanSelfRestart;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [supports automatic run at startup].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [supports automatic run at startup]; otherwise, <c>false</c>.</value>
|
||||
public static bool SupportsAutoRunAtStartup
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance can self update.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
|
||||
public static bool CanSelfUpdate
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainStartup.CanSelfUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
public static void PreventSystemStandby()
|
||||
{
|
||||
SystemHelper.ResetStandbyTimer();
|
||||
}
|
||||
|
||||
internal enum EXECUTION_STATE : uint
|
||||
{
|
||||
ES_NONE = 0,
|
||||
ES_SYSTEM_REQUIRED = 0x00000001,
|
||||
ES_DISPLAY_REQUIRED = 0x00000002,
|
||||
ES_USER_PRESENT = 0x00000004,
|
||||
ES_AWAYMODE_REQUIRED = 0x00000040,
|
||||
ES_CONTINUOUS = 0x80000000
|
||||
}
|
||||
|
||||
public class SystemHelper
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
|
||||
|
||||
public static void ResetStandbyTimer()
|
||||
{
|
||||
EXECUTION_STATE es = SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.IO
|
||||
namespace MediaBrowser.ServerApplication.Native
|
||||
{
|
||||
public class NativeFileSystem : CommonFileSystem
|
||||
{
|
||||
36
MediaBrowser.ServerApplication/Native/Standby.cs
Normal file
36
MediaBrowser.ServerApplication/Native/Standby.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// Class NativeApp
|
||||
/// </summary>
|
||||
public static class Standby
|
||||
{
|
||||
public static void PreventSystemStandby()
|
||||
{
|
||||
SystemHelper.ResetStandbyTimer();
|
||||
}
|
||||
|
||||
internal enum EXECUTION_STATE : uint
|
||||
{
|
||||
ES_NONE = 0,
|
||||
ES_SYSTEM_REQUIRED = 0x00000001,
|
||||
ES_DISPLAY_REQUIRED = 0x00000002,
|
||||
ES_USER_PRESENT = 0x00000004,
|
||||
ES_AWAYMODE_REQUIRED = 0x00000040,
|
||||
ES_CONTINUOUS = 0x80000000
|
||||
}
|
||||
|
||||
public class SystemHelper
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
|
||||
|
||||
public static void ResetStandbyTimer()
|
||||
{
|
||||
EXECUTION_STATE es = SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
104
MediaBrowser.ServerApplication/Native/WindowsApp.cs
Normal file
104
MediaBrowser.ServerApplication/Native/WindowsApp.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.IsoMounter;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Server.Startup.Common;
|
||||
using MediaBrowser.ServerApplication.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.Native
|
||||
{
|
||||
public class WindowsApp : INativeApp
|
||||
{
|
||||
public List<Assembly> GetAssembliesWithParts()
|
||||
{
|
||||
var list = new List<Assembly>();
|
||||
|
||||
list.Add(typeof(PismoIsoManager).Assembly);
|
||||
|
||||
list.Add(GetType().Assembly);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory)
|
||||
{
|
||||
ServerAuthorization.AuthorizeServer(httpServerPort, httpServerUrlPrefix, udpPort, tempDirectory);
|
||||
}
|
||||
|
||||
public NativeEnvironment Environment
|
||||
{
|
||||
get
|
||||
{
|
||||
return new NativeEnvironment
|
||||
{
|
||||
OperatingSystem = OperatingSystem.Windows,
|
||||
SystemArchitecture = System.Environment.Is64BitOperatingSystem ? Architecture.X86_X64 : Architecture.X86
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsRunningAsService
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRunningAsService
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool CanSelfRestart
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainStartup.CanSelfRestart;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsAutoRunAtStartup
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanSelfUpdate
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainStartup.CanSelfUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
MainStartup.Shutdown();
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
MainStartup.Restart();
|
||||
}
|
||||
|
||||
public void ConfigureAutoRun(bool autorun)
|
||||
{
|
||||
Autorun.Configure(autorun);
|
||||
}
|
||||
|
||||
public INetworkManager CreateNetworkManager(ILogger logger)
|
||||
{
|
||||
return new NetworkManager(logger);
|
||||
}
|
||||
|
||||
public void PreventSystemStandby()
|
||||
{
|
||||
Standby.PreventSystemStandby();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.ServerApplication.Logging;
|
||||
using MediaBrowser.Server.Startup.Common.Browser;
|
||||
using MediaBrowser.ServerApplication.Native;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@@ -25,7 +25,6 @@ namespace MediaBrowser.ServerApplication
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
private System.Windows.Forms.ToolStripMenuItem cmdRestart;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ToolStripMenuItem cmdLogWindow;
|
||||
private System.Windows.Forms.ToolStripMenuItem cmdCommunity;
|
||||
private System.Windows.Forms.ToolStripMenuItem cmdApiDocs;
|
||||
private System.Windows.Forms.ToolStripMenuItem cmdSwagger;
|
||||
@@ -33,14 +32,8 @@ namespace MediaBrowser.ServerApplication
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly ILogManager _logManager;
|
||||
private readonly IServerConfigurationManager _configurationManager;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IUserViewManager _userViewManager;
|
||||
private readonly ILocalizationManager _localization;
|
||||
private LogForm _logForm;
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
@@ -57,20 +50,13 @@ namespace MediaBrowser.ServerApplication
|
||||
|
||||
public ServerNotifyIcon(ILogManager logManager,
|
||||
IServerApplicationHost appHost,
|
||||
IServerConfigurationManager configurationManager,
|
||||
IUserManager userManager, ILibraryManager libraryManager,
|
||||
IJsonSerializer jsonSerializer,
|
||||
ILocalizationManager localization, IUserViewManager userViewManager)
|
||||
IServerConfigurationManager configurationManager,
|
||||
ILocalizationManager localization)
|
||||
{
|
||||
_logger = logManager.GetLogger("MainWindow");
|
||||
_localization = localization;
|
||||
_userViewManager = userViewManager;
|
||||
_appHost = appHost;
|
||||
_logManager = logManager;
|
||||
_configurationManager = configurationManager;
|
||||
_userManager = userManager;
|
||||
_libraryManager = libraryManager;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
|
||||
var components = new System.ComponentModel.Container();
|
||||
|
||||
@@ -80,7 +66,6 @@ namespace MediaBrowser.ServerApplication
|
||||
|
||||
cmdExit = new System.Windows.Forms.ToolStripMenuItem();
|
||||
cmdCommunity = new System.Windows.Forms.ToolStripMenuItem();
|
||||
cmdLogWindow = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
cmdRestart = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
@@ -107,7 +92,6 @@ namespace MediaBrowser.ServerApplication
|
||||
cmdRestart,
|
||||
toolStripSeparator1,
|
||||
cmdApiDocs,
|
||||
//cmdLogWindow,
|
||||
cmdCommunity,
|
||||
cmdExit});
|
||||
contextMenuStrip1.Name = "contextMenuStrip1";
|
||||
@@ -125,12 +109,6 @@ namespace MediaBrowser.ServerApplication
|
||||
cmdCommunity.Name = "cmdCommunity";
|
||||
cmdCommunity.Size = new System.Drawing.Size(208, 22);
|
||||
//
|
||||
// cmdLogWindow
|
||||
//
|
||||
cmdLogWindow.CheckOnClick = true;
|
||||
cmdLogWindow.Name = "cmdLogWindow";
|
||||
cmdLogWindow.Size = new System.Drawing.Size(208, 22);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
@@ -176,7 +154,6 @@ namespace MediaBrowser.ServerApplication
|
||||
|
||||
cmdExit.Click += cmdExit_Click;
|
||||
cmdRestart.Click += cmdRestart_Click;
|
||||
cmdLogWindow.Click += cmdLogWindow_Click;
|
||||
cmdConfigure.Click += cmdConfigure_Click;
|
||||
cmdCommunity.Click += cmdCommunity_Click;
|
||||
cmdBrowse.Click += cmdBrowse_Click;
|
||||
@@ -184,8 +161,6 @@ namespace MediaBrowser.ServerApplication
|
||||
cmdSwagger.Click += cmdSwagger_Click;
|
||||
cmdGtihub.Click += cmdGtihub_Click;
|
||||
|
||||
LoadLogWindow(null, EventArgs.Empty);
|
||||
_logManager.LoggerLoaded += LoadLogWindow;
|
||||
_configurationManager.ConfigurationUpdated += Instance_ConfigurationUpdated;
|
||||
|
||||
LocalizeText();
|
||||
@@ -210,7 +185,6 @@ namespace MediaBrowser.ServerApplication
|
||||
cmdBrowse.Text = _localization.GetLocalizedString("LabelBrowseLibrary");
|
||||
cmdConfigure.Text = _localization.GetLocalizedString("LabelConfigureMediaBrowser");
|
||||
cmdRestart.Text = _localization.GetLocalizedString("LabelRestartServer");
|
||||
cmdLogWindow.Text = _localization.GetLocalizedString("LabelShowLogWindow");
|
||||
}
|
||||
|
||||
private string _uiCulture;
|
||||
@@ -226,62 +200,6 @@ namespace MediaBrowser.ServerApplication
|
||||
{
|
||||
LocalizeText();
|
||||
}
|
||||
|
||||
Action action = () =>
|
||||
{
|
||||
var isLogWindowOpen = _logForm != null;
|
||||
|
||||
if ((!isLogWindowOpen && _configurationManager.Configuration.ShowLogWindow) ||
|
||||
(isLogWindowOpen && !_configurationManager.Configuration.ShowLogWindow))
|
||||
{
|
||||
_logManager.ReloadLogger(_configurationManager.Configuration.EnableDebugLevelLogging
|
||||
? LogSeverity.Debug
|
||||
: LogSeverity.Info);
|
||||
}
|
||||
};
|
||||
|
||||
contextMenuStrip1.Invoke(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the log window.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="args">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||
void LoadLogWindow(object sender, EventArgs args)
|
||||
{
|
||||
CloseLogWindow();
|
||||
|
||||
Action action = () =>
|
||||
{
|
||||
// Add our log window if specified
|
||||
if (_configurationManager.Configuration.ShowLogWindow)
|
||||
{
|
||||
_logForm = new LogForm(_logManager);
|
||||
|
||||
Trace.Listeners.Add(new WindowTraceListener(_logForm));
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.Listeners.Remove("MBLogWindow");
|
||||
}
|
||||
|
||||
// Set menu option indicator
|
||||
cmdLogWindow.Checked = _configurationManager.Configuration.ShowLogWindow;
|
||||
};
|
||||
|
||||
contextMenuStrip1.Invoke(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the log window.
|
||||
/// </summary>
|
||||
void CloseLogWindow()
|
||||
{
|
||||
if (_logForm != null)
|
||||
{
|
||||
_logForm.ShutDown();
|
||||
}
|
||||
}
|
||||
|
||||
void cmdBrowse_Click(object sender, EventArgs e)
|
||||
@@ -299,13 +217,6 @@ namespace MediaBrowser.ServerApplication
|
||||
BrowserLauncher.OpenDashboard(_appHost, _logger);
|
||||
}
|
||||
|
||||
void cmdLogWindow_Click(object sender, EventArgs e)
|
||||
{
|
||||
_configurationManager.Configuration.ShowLogWindow = !_configurationManager.Configuration.ShowLogWindow;
|
||||
_configurationManager.SaveConfiguration();
|
||||
LoadLogWindow(sender, e);
|
||||
}
|
||||
|
||||
void cmdRestart_Click(object sender, EventArgs e)
|
||||
{
|
||||
_appHost.Restart();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MediaBrowser.IsoMounting" version="3.0.69" targetFramework="net45" />
|
||||
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net45" />
|
||||
<package id="NLog" version="3.1.0.0" targetFramework="net45" />
|
||||
<package id="System.Data.SQLite.Core" version="1.0.94.0" targetFramework="net45" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user