diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 31dad48be..2306fb370 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -141,7 +141,7 @@ namespace Emby.Server.Implementations return false; } - if (StartupOptions.ContainsOption("-service")) + if (StartupOptions.Service) { return false; } @@ -1747,7 +1747,7 @@ namespace Emby.Server.Implementations EncoderLocationType = MediaEncoder.EncoderLocationType, SystemArchitecture = EnvironmentInfo.SystemArchitecture, SystemUpdateLevel = SystemUpdateLevel, - PackageName = StartupOptions.GetOption("-package") + PackageName = StartupOptions.PackageName }; } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 3aa617b02..bf0546f2e 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -22,6 +22,7 @@ + diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 05c8b07ab..bb96120f4 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.EntryPoints { var options = ((ApplicationHost)_appHost).StartupOptions; - if (!options.ContainsOption("-noautorunwebapp")) + if (!options.NoAutoRunWebApp) { BrowserLauncher.OpenWebApp(_appHost); } diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs index 79a42f294..4c926b91a 100644 --- a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs +++ b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs @@ -30,8 +30,8 @@ namespace Emby.Server.Implementations.FFMpeg public FFMpegInfo GetFFMpegInfo(StartupOptions options) { - var customffMpegPath = options.GetOption("-ffmpeg"); - var customffProbePath = options.GetOption("-ffprobe"); + var customffMpegPath = options.FFmpeg; + var customffProbePath = options.FFprobe; if (!string.IsNullOrWhiteSpace(customffMpegPath) && !string.IsNullOrWhiteSpace(customffProbePath)) { diff --git a/Emby.Server.Implementations/StartupOptions.cs b/Emby.Server.Implementations/StartupOptions.cs index 221263634..fca60afb8 100644 --- a/Emby.Server.Implementations/StartupOptions.cs +++ b/Emby.Server.Implementations/StartupOptions.cs @@ -1,30 +1,43 @@ -using System; -using System.Linq; - namespace Emby.Server.Implementations { + using CommandLine; + + /// + /// Class used by CommandLine package when parsing the command line arguments. + /// public class StartupOptions { - private readonly string[] _options; + [Option('d', "programdata", Required = false, HelpText = "Path to use for program data (databases files etc.).")] + public string PathProgramData { get; set; } - public StartupOptions(string[] commandLineArgs) - { - _options = commandLineArgs; - } + [Option('c', "configdir", Required = false, HelpText = "Path to use for config data (user policies and puctures).")] + public string PathConfig { get; set; } - public bool ContainsOption(string option) - => _options.Contains(option, StringComparer.OrdinalIgnoreCase); + [Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")] + public string PathLog { get; set; } - public string GetOption(string name) - { - int index = Array.IndexOf(_options, name); - if (index == -1) - { - return null; - } + [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg exe to use in place of built-in.")] + public string FFmpeg { get; set; } - return _options.ElementAtOrDefault(index + 1); - } + [Option("ffprobe", Required = false, HelpText = "ffmpeg and ffprobe switches must be supplied together.")] + public string FFprobe { get; set; } + + + [Option("service", Required = false, HelpText = "Run as headless service.")] + public bool Service { get; set; } + + [Option("noautorunwebapp", Required = false, HelpText = "Run headless if startup wizard is complete.")] + public bool NoAutoRunWebApp { get; set; } + + [Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")] + public string PackageName { get; set; } + + + [Option("restartpath", Required = false, HelpText = "Path to reset script.")] + public string RestartPath { get; set; } + + [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")] + public string RestartArgs { get; set; } } -} + } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b580f45ca..5182ab4d7 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -16,7 +16,7 @@ namespace Jellyfin.Server { } - public override bool CanSelfRestart => StartupOptions.ContainsOption("-restartpath"); + public override bool CanSelfRestart => StartupOptions.RestartPath != null; protected override void RestartInternal() => Program.Restart(); diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 66586d4e4..dbfd59ebf 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -26,6 +26,8 @@ using ILogger = Microsoft.Extensions.Logging.ILogger; namespace Jellyfin.Server { + using CommandLine; + public static class Program { private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource(); @@ -35,14 +37,18 @@ namespace Jellyfin.Server public static async Task Main(string[] args) { - StartupOptions options = new StartupOptions(args); - Version version = Assembly.GetEntryAssembly().GetName().Version; + // For CommandLine package, change default behaviour to output errors to stdout (instead of stderr) + var parser = new Parser(config => config.HelpWriter = Console.Out); - if (options.ContainsOption("-v") || options.ContainsOption("--version")) - { - Console.WriteLine(version.ToString()); - } + // Parse the command line arguments and either start the app or exit indicating error + await parser.ParseArguments(args) + .MapResult( + options => StartApp(options), + errs => Task.FromResult(0)).ConfigureAwait(false); + } + private static async Task StartApp(StartupOptions options) + { ServerApplicationPaths appPaths = CreateApplicationPaths(options); // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager @@ -78,7 +84,7 @@ namespace Jellyfin.Server Shutdown(); }; - _logger.LogInformation("Jellyfin version: {Version}", version); + _logger.LogInformation("Jellyfin version: {Version}", Assembly.GetEntryAssembly().GetName().Version); EnvironmentInfo environmentInfo = new EnvironmentInfo(getOperatingSystem()); ApplicationHost.LogEnvironmentInfo(_logger, appPaths, environmentInfo); @@ -133,9 +139,9 @@ namespace Jellyfin.Server string programDataPath = Environment.GetEnvironmentVariable("JELLYFIN_DATA_PATH"); if (string.IsNullOrEmpty(programDataPath)) { - if (options.ContainsOption("-programdata")) + if (options.PathProgramData != null) { - programDataPath = options.GetOption("-programdata"); + programDataPath = options.PathProgramData; } else { @@ -171,9 +177,9 @@ namespace Jellyfin.Server string configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR"); if (string.IsNullOrEmpty(configDir)) { - if (options.ContainsOption("-configdir")) + if (options.PathConfig != null) { - configDir = options.GetOption("-configdir"); + configDir = options.PathConfig; } else { @@ -190,9 +196,9 @@ namespace Jellyfin.Server string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); if (string.IsNullOrEmpty(logDir)) { - if (options.ContainsOption("-logdir")) + if (options.PathLog != null) { - logDir = options.GetOption("-logdir"); + logDir = options.PathLog; } else { @@ -315,11 +321,11 @@ namespace Jellyfin.Server Shutdown(); } - private static void StartNewInstance(StartupOptions startupOptions) + private static void StartNewInstance(StartupOptions options) { _logger.LogInformation("Starting new instance"); - string module = startupOptions.GetOption("-restartpath"); + string module = options.RestartPath; if (string.IsNullOrWhiteSpace(module)) { @@ -328,9 +334,9 @@ namespace Jellyfin.Server string commandLineArgsString; - if (startupOptions.ContainsOption("-restartargs")) + if (options.RestartArgs != null) { - commandLineArgsString = startupOptions.GetOption("-restartargs") ?? string.Empty; + commandLineArgsString = options.RestartArgs ?? string.Empty; } else {