aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.drone.yml28
-rw-r--r--.editorconfig133
-rw-r--r--.gitignore2
-rw-r--r--Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs25
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs117
-rw-r--r--Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs65
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs20
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs30
-rw-r--r--Emby.Server.Implementations/ServerApplicationPaths.cs9
-rw-r--r--Emby.Server.Implementations/Session/FirebaseSessionController.cs131
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs13
-rw-r--r--Emby.Server.Implementations/Udp/UdpServer.cs1
-rw-r--r--Jellyfin.Server/CoreAppHost.cs4
-rw-r--r--Jellyfin.Server/Jellyfin.Server.csproj1
-rw-r--r--Jellyfin.Server/PowerManagement.cs23
-rw-r--r--Jellyfin.Server/Program.cs73
-rw-r--r--Jellyfin.Server/Resources/Configuration/logging.json19
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs18
-rw-r--r--MediaBrowser.Common/IApplicationHost.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs13
-rw-r--r--MediaBrowser.Model/Session/ClientCapabilities.cs2
-rw-r--r--MediaBrowser.Model/System/IPowerManagement.cs11
-rw-r--r--MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs84
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbProvider.cs16
-rw-r--r--README.md49
-rw-r--r--SharedVersion.cs2
-rw-r--r--debian/changelog23
-rw-r--r--debian/conf/jellyfin8
-rw-r--r--debian/conf/logging.json29
-rw-r--r--debian/control3
-rw-r--r--debian/install1
-rw-r--r--debian/jellyfin.service2
-rw-r--r--debian/postinst29
-rw-r--r--debian/postrm29
-rw-r--r--debian/preinst20
-rw-r--r--debian/prerm12
-rw-r--r--debian/source/options1
38 files changed, 432 insertions, 620 deletions
diff --git a/.drone.yml b/.drone.yml
index 13762ba0a..c6d41b555 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -1,32 +1,12 @@
kind: pipeline
-name: build:debian
+name: build
steps:
- name: submodules
image: docker:git
commands:
- git submodule update --init --recursive
-- name: build:debian
- image: plugins/docker
- group: build
- settings:
- repo: jellyfin/jellyfin
- dry_run: true
- dockerfile: Dockerfile.debian_package
-
-
----
-kind: pipeline
-name: build:docker
-
-steps:
-- name: submodules
- image: docker:git
+- name: build
+ image: microsoft/dotnet:2-sdk
commands:
- - git submodule update --init --recursive
-- name: build:docker
- image: plugins/docker
- group: build
- settings:
- repo: jellyfin/jellyfin
- dry_run: true
+ - dotnet publish --configuration release --output /release
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..a3b72c9af
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,133 @@
+# With more recent updates Visual Studio 2017 supports EditorConfig files out of the box
+# Visual Studio Code needs an extension: https://github.com/editorconfig/editorconfig-vscode
+# For emacs, vim, np++ and other editors, see here: https://github.com/editorconfig
+###############################
+# Core EditorConfig Options #
+###############################
+# All files
+[*]
+indent_style = space
+root = true
+indent_size = 4
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+end_of_line = lf
+max_line_length = null
+
+# Code files
+[*.{cs,csx,vb,vbx}]
+indent_size = 4
+insert_final_newline = true
+charset = utf-8
+###############################
+# .NET Coding Conventions #
+###############################
+[*.{cs,vb}]
+# Organize usings
+dotnet_sort_system_directives_first = true
+# this. preferences
+dotnet_style_qualification_for_field = false:silent
+dotnet_style_qualification_for_property = false:silent
+dotnet_style_qualification_for_method = false:silent
+dotnet_style_qualification_for_event = false:silent
+# Language keywords vs BCL types preferences
+dotnet_style_predefined_type_for_locals_parameters_members = true:silent
+dotnet_style_predefined_type_for_member_access = true:silent
+# Parentheses preferences
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+# Modifier preferences
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+dotnet_style_readonly_field = true:suggestion
+# Expression-level preferences
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
+dotnet_prefer_inferred_tuple_names = true:suggestion
+dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+###############################
+# Naming Conventions #
+###############################
+# Style Definitions
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+# Use PascalCase for constant fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
+dotnet_naming_symbols.constant_fields.required_modifiers = const
+###############################
+# C# Coding Conventions #
+###############################
+[*.cs]
+# var preferences
+csharp_style_var_for_built_in_types = true:silent
+csharp_style_var_when_type_is_apparent = true:silent
+csharp_style_var_elsewhere = true:silent
+# Expression-bodied members
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+# Pattern matching preferences
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+# Null-checking preferences
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+# Modifier preferences
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+# Expression-level preferences
+csharp_prefer_braces = true:silent
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+###############################
+# C# Formatting Rules #
+###############################
+# New line preferences
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+# Indentation preferences
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = flush_left
+# Space preferences
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+# Wrapping preferences
+csharp_preserve_single_line_statements = true
+csharp_preserve_single_line_blocks = true
+###############################
+# VB Coding Conventions #
+###############################
+[*.vb]
+# Modifier preferences
+visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
diff --git a/.gitignore b/.gitignore
index 9bbfd9b74..befba5a20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -247,6 +247,8 @@ MediaBrowser.WebDashboard/dashboard-ui/.idea/
#########################
debian/.debhelper/
+debian/*.debhelper
+debian/debhelper-build-stamp
debian/files
debian/jellyfin.substvars
debian/jellyfin/
diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs
index 76d0076a6..3e12bc0b6 100644
--- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs
+++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs
@@ -12,11 +12,16 @@ namespace Emby.Server.Implementations.AppBase
/// <summary>
/// Initializes a new instance of the <see cref="BaseApplicationPaths"/> class.
/// </summary>
- protected BaseApplicationPaths(string programDataPath, string appFolderPath, string logDirectoryPath)
+ protected BaseApplicationPaths(
+ string programDataPath,
+ string appFolderPath,
+ string logDirectoryPath = null,
+ string configurationDirectoryPath = null)
{
ProgramDataPath = programDataPath;
ProgramSystemPath = appFolderPath;
LogDirectoryPath = logDirectoryPath;
+ ConfigurationDirectoryPath = configurationDirectoryPath;
}
public string ProgramDataPath { get; private set; }
@@ -135,6 +140,11 @@ namespace Emby.Server.Implementations.AppBase
}
/// <summary>
+ /// The _config directory
+ /// </summary>
+ private string _configurationDirectoryPath;
+
+ /// <summary>
/// Gets the path to the application configuration root directory
/// </summary>
/// <value>The configuration directory path.</value>
@@ -142,7 +152,18 @@ namespace Emby.Server.Implementations.AppBase
{
get
{
- return Path.Combine(ProgramDataPath, "config");
+ if (string.IsNullOrEmpty(_configurationDirectoryPath))
+ {
+ _configurationDirectoryPath = Path.Combine(ProgramDataPath, "config");
+
+ Directory.CreateDirectory(_configurationDirectoryPath);
+ }
+
+ return _configurationDirectoryPath;
+ }
+ set
+ {
+ _configurationDirectoryPath = value;
}
}
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 236851968..950ae10c7 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -369,7 +369,6 @@ namespace Emby.Server.Implementations
public StartupOptions StartupOptions { get; private set; }
- internal IPowerManagement PowerManagement { get; private set; }
internal IImageEncoder ImageEncoder { get; private set; }
protected IProcessFactory ProcessFactory { get; private set; }
@@ -391,7 +390,6 @@ namespace Emby.Server.Implementations
ILoggerFactory loggerFactory,
StartupOptions options,
IFileSystem fileSystem,
- IPowerManagement powerManagement,
IEnvironmentInfo environmentInfo,
IImageEncoder imageEncoder,
ISystemEvents systemEvents,
@@ -417,12 +415,9 @@ namespace Emby.Server.Implementations
Logger = LoggerFactory.CreateLogger("App");
StartupOptions = options;
- PowerManagement = powerManagement;
ImageEncoder = imageEncoder;
- //SetBaseExceptionMessage();
-
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
NetworkManager.NetworkChanged += NetworkManager_NetworkChanged;
@@ -687,18 +682,6 @@ namespace Emby.Server.Implementations
return parts;
}
- // TODO: @bond
- /*
- private void SetBaseExceptionMessage()
- {
- var builder = GetBaseExceptionMessage(ApplicationPaths);
-
- builder.Insert(0, string.Format("Version: {0}{1}", ApplicationVersion, Environment.NewLine));
- builder.Insert(0, "*** Error Report ***" + Environment.NewLine);
-
- LoggerFactory.ExceptionMessagePrefix = builder.ToString();
- }*/
-
/// <summary>
/// Runs the startup tasks.
/// </summary>
@@ -734,8 +717,6 @@ namespace Emby.Server.Implementations
RunEntryPoints(entryPoints, false);
Logger.LogInformation("All entry points have started");
- //LoggerFactory.RemoveConsoleOutput();
-
return Task.CompletedTask;
}
@@ -749,7 +730,7 @@ namespace Emby.Server.Implementations
}
var name = entryPoint.GetType().FullName;
- Logger.LogInformation("Starting entry point {0}", name);
+ Logger.LogInformation("Starting entry point {Name}", name);
var now = DateTime.UtcNow;
try
{
@@ -757,9 +738,9 @@ namespace Emby.Server.Implementations
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error in {name}", name);
+ Logger.LogError(ex, "Error while running entrypoint {Name}", name);
}
- Logger.LogInformation("Entry point completed: {0}. Duration: {1} seconds", name, (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture), "ImageInfos");
+ Logger.LogInformation("Entry point completed: {Name}. Duration: {Duration} seconds", name, (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture), "ImageInfos");
}
}
@@ -873,8 +854,6 @@ namespace Emby.Server.Implementations
SocketFactory = new SocketFactory(LoggerFactory.CreateLogger("SocketFactory"));
RegisterSingleInstance(SocketFactory);
- RegisterSingleInstance(PowerManagement);
-
SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LoggerFactory, FileSystemManager, CryptographyProvider);
RegisterSingleInstance(SecurityManager);
@@ -1310,7 +1289,6 @@ namespace Emby.Server.Implementations
{
if (!ServerConfigurationManager.Configuration.IsPortAuthorized)
{
- RegisterServerWithAdministratorAccess();
ServerConfigurationManager.Configuration.IsPortAuthorized = true;
ConfigurationManager.SaveConfiguration();
}
@@ -1381,12 +1359,11 @@ namespace Emby.Server.Implementations
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error getting plugin Id from {pluginName}.", plugin.GetType().FullName);
+ Logger.LogError(ex, "Error getting plugin Id from {PluginName}.", plugin.GetType().FullName);
}
}
- var hasPluginConfiguration = plugin as IHasPluginConfiguration;
- if (hasPluginConfiguration != null)
+ if (plugin is IHasPluginConfiguration hasPluginConfiguration)
{
hasPluginConfiguration.SetStartupInfo(s => Directory.CreateDirectory(s));
}
@@ -1805,13 +1782,13 @@ namespace Emby.Server.Implementations
{
var result = Version.Parse(FileVersionInfo.GetVersionInfo(path).FileVersion);
- Logger.LogInformation("File {0} has version {1}", path, result);
+ Logger.LogInformation("File {Path} has version {Version}", path, result);
return result;
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error getting version number from {path}", path);
+ Logger.LogError(ex, "Error getting version number from {Path}", path);
return new Version(1, 0);
}
@@ -2225,32 +2202,6 @@ namespace Emby.Server.Implementations
protected abstract void ShutdownInternal();
- /// <summary>
- /// Registers the server with administrator access.
- /// </summary>
- private void RegisterServerWithAdministratorAccess()
- {
- Logger.LogInformation("Requesting administrative access to authorize http server");
-
- try
- {
- AuthorizeServer();
- }
- catch (NotImplementedException)
- {
-
- }
- catch (Exception ex)
- {
- Logger.LogError(ex, "Error authorizing server");
- }
- }
-
- protected virtual void AuthorizeServer()
- {
- throw new NotImplementedException();
- }
-
public event EventHandler HasUpdateAvailableChanged;
private bool _hasUpdateAvailable;
@@ -2413,15 +2364,14 @@ namespace Emby.Server.Implementations
{
var type = GetType();
- //LoggerFactory.AddConsoleOutput();
- Logger.LogInformation("Disposing " + type.Name);
+ Logger.LogInformation("Disposing {Type}", type.Name);
var parts = DisposableParts.Distinct().Where(i => i.GetType() != type).ToList();
DisposableParts.Clear();
foreach (var part in parts)
{
- Logger.LogInformation("Disposing " + part.GetType().Name);
+ Logger.LogInformation("Disposing {Type}", part.GetType().Name);
try
{
@@ -2429,58 +2379,11 @@ namespace Emby.Server.Implementations
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error disposing {0}", part.GetType().Name);
+ Logger.LogError(ex, "Error disposing {Type}", part.GetType().Name);
}
}
}
}
-
- private Dictionary<string, string> _values;
- public string GetValue(string name)
- {
- if (_values == null)
- {
- _values = LoadValues();
- }
-
- string value;
-
- if (_values.TryGetValue(name, out value))
- {
- return value;
- }
-
- return null;
- }
-
- // TODO: @bond Remove?
- private Dictionary<string, string> LoadValues()
- {
- Dictionary<string, string> values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
- using (var stream = typeof(ApplicationHost).Assembly.GetManifestResourceStream(typeof(ApplicationHost).Namespace + ".values.txt"))
- {
- using (var reader = new StreamReader(stream))
- {
- while (!reader.EndOfStream)
- {
- var line = reader.ReadLine();
- if (string.IsNullOrEmpty(line))
- {
- continue;
- }
-
- var index = line.IndexOf('=');
- if (index != -1)
- {
- values[line.Substring(0, index)] = line.Substring(index + 1);
- }
- }
- }
- }
-
- return values;
- }
}
internal class CertificateInfo
diff --git a/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs b/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs
deleted file mode 100644
index a6dadcef0..000000000
--- a/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Plugins;
-using MediaBrowser.Controller.Session;
-using Microsoft.Extensions.Logging;
-using System;
-using System.Linq;
-using MediaBrowser.Model.System;
-using MediaBrowser.Model.Threading;
-
-namespace Emby.Server.Implementations.EntryPoints
-{
- public class KeepServerAwake : IServerEntryPoint
- {
- private readonly ISessionManager _sessionManager;
- private readonly ILogger _logger;
- private ITimer _timer;
- private readonly IServerApplicationHost _appHost;
- private readonly ITimerFactory _timerFactory;
- private readonly IPowerManagement _powerManagement;
-
- public KeepServerAwake(ISessionManager sessionManager, ILogger logger, IServerApplicationHost appHost, ITimerFactory timerFactory, IPowerManagement powerManagement)
- {
- _sessionManager = sessionManager;
- _logger = logger;
- _appHost = appHost;
- _timerFactory = timerFactory;
- _powerManagement = powerManagement;
- }
-
- public void Run()
- {
- _timer = _timerFactory.Create(OnTimerCallback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
- }
-
- private void OnTimerCallback(object state)
- {
- var now = DateTime.UtcNow;
-
- try
- {
- if (_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 15))
- {
- _powerManagement.PreventSystemStandby();
- }
- else
- {
- _powerManagement.AllowSystemStandby();
- }
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error resetting system standby timer");
- }
- }
-
- public void Dispose()
- {
- if (_timer != null)
- {
- _timer.Dispose();
- _timer = null;
- }
- }
- }
-}
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index e5fd28997..ddda4b2c3 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -160,9 +160,9 @@ namespace Emby.Server.Implementations.Library
list.Add(source);
}
- foreach (var source in list)
+ if (user != null)
{
- if (user != null)
+ foreach (var source in list)
{
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 59f9fe86f..81a47bfea 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -75,7 +75,23 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly IStreamHelper _streamHelper;
- public EmbyTV(IServerApplicationHost appHost, IStreamHelper streamHelper, IMediaSourceManager mediaSourceManager, IAssemblyInfo assemblyInfo, ILogger logger, IJsonSerializer jsonSerializer, IPowerManagement powerManagement, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory, IProcessFactory processFactory, ISystemEvents systemEvents)
+ public EmbyTV(IServerApplicationHost appHost,
+ IStreamHelper streamHelper,
+ IMediaSourceManager mediaSourceManager,
+ IAssemblyInfo assemblyInfo,
+ ILogger logger,
+ IJsonSerializer jsonSerializer,
+ IHttpClient httpClient,
+ IServerConfigurationManager config,
+ ILiveTvManager liveTvManager,
+ IFileSystem fileSystem,
+ ILibraryManager libraryManager,
+ ILibraryMonitor libraryMonitor,
+ IProviderManager providerManager,
+ IMediaEncoder mediaEncoder,
+ ITimerFactory timerFactory,
+ IProcessFactory processFactory,
+ ISystemEvents systemEvents)
{
Current = this;
@@ -97,7 +113,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_streamHelper = streamHelper;
_seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers"));
- _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger, timerFactory, powerManagement);
+ _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger, timerFactory);
_timerProvider.TimerFired += _timerProvider_TimerFired;
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
index 76a044c02..e4ab34770 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
@@ -9,7 +9,6 @@ using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Threading;
-using MediaBrowser.Model.System;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
@@ -20,14 +19,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public event EventHandler<GenericEventArgs<TimerInfo>> TimerFired;
private readonly ITimerFactory _timerFactory;
- private readonly IPowerManagement _powerManagement;
- public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1, ITimerFactory timerFactory, IPowerManagement powerManagement)
+ public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1, ITimerFactory timerFactory)
: base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase))
{
_logger = logger1;
_timerFactory = timerFactory;
- _powerManagement = powerManagement;
}
public void RestartTimers()
@@ -36,7 +33,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
foreach (var item in GetAll().ToList())
{
- AddOrUpdateSystemTimer(item, false);
+ AddOrUpdateSystemTimer(item);
}
}
@@ -59,7 +56,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public override void Update(TimerInfo item)
{
base.Update(item);
- AddOrUpdateSystemTimer(item, false);
+ AddOrUpdateSystemTimer(item);
}
public void AddOrUpdate(TimerInfo item, bool resetTimer)
@@ -90,7 +87,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
base.Add(item);
- AddOrUpdateSystemTimer(item, true);
+ AddOrUpdateSystemTimer(item);
}
private bool ShouldStartTimer(TimerInfo item)
@@ -104,7 +101,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return true;
}
- private void AddOrUpdateSystemTimer(TimerInfo item, bool scheduleSystemWakeTimer)
+ private void AddOrUpdateSystemTimer(TimerInfo item)
{
StopTimer(item);
@@ -124,23 +121,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var dueTime = startDate - now;
StartTimer(item, dueTime);
-
- if (scheduleSystemWakeTimer && dueTime >= TimeSpan.FromMinutes(15))
- {
- ScheduleSystemWakeTimer(startDate, item.Name);
- }
- }
-
- private void ScheduleSystemWakeTimer(DateTime startDate, string displayName)
- {
- try
- {
- _powerManagement.ScheduleWake(startDate.AddMinutes(-5), displayName);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error scheduling wake timer");
- }
}
private void StartTimer(TimerInfo item, TimeSpan dueTime)
diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs
index f5986f943..8a0f2671a 100644
--- a/Emby.Server.Implementations/ServerApplicationPaths.cs
+++ b/Emby.Server.Implementations/ServerApplicationPaths.cs
@@ -13,8 +13,13 @@ namespace Emby.Server.Implementations
/// <summary>
/// Initializes a new instance of the <see cref="BaseApplicationPaths" /> class.
/// </summary>
- public ServerApplicationPaths(string programDataPath, string appFolderPath, string applicationResourcesPath, string logDirectoryPath = null)
- : base(programDataPath, appFolderPath, logDirectoryPath)
+ public ServerApplicationPaths(
+ string programDataPath,
+ string appFolderPath,
+ string applicationResourcesPath,
+ string logDirectoryPath = null,
+ string configurationDirectoryPath = null)
+ : base(programDataPath, appFolderPath, logDirectoryPath, configurationDirectoryPath)
{
ApplicationResourcesPath = applicationResourcesPath;
}
diff --git a/Emby.Server.Implementations/Session/FirebaseSessionController.cs b/Emby.Server.Implementations/Session/FirebaseSessionController.cs
deleted file mode 100644
index cfe513305..000000000
--- a/Emby.Server.Implementations/Session/FirebaseSessionController.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Text;
-using MediaBrowser.Common;
-
-namespace Emby.Server.Implementations.Session
-{
- public class FirebaseSessionController : ISessionController
- {
- private readonly IHttpClient _httpClient;
- private readonly IJsonSerializer _json;
- private readonly ISessionManager _sessionManager;
-
- public SessionInfo Session { get; private set; }
-
- private readonly string _token;
-
- private IApplicationHost _appHost;
- private string _senderId;
- private string _applicationId;
-
- public FirebaseSessionController(IHttpClient httpClient,
- IApplicationHost appHost,
- IJsonSerializer json,
- SessionInfo session,
- string token, ISessionManager sessionManager)
- {
- _httpClient = httpClient;
- _json = json;
- _appHost = appHost;
- Session = session;
- _token = token;
- _sessionManager = sessionManager;
-
- _applicationId = _appHost.GetValue("firebase_applicationid");
- _senderId = _appHost.GetValue("firebase_senderid");
- }
-
- public static bool IsSupported(IApplicationHost appHost)
- {
- return !string.IsNullOrEmpty(appHost.GetValue("firebase_applicationid")) && !string.IsNullOrEmpty(appHost.GetValue("firebase_senderid"));
- }
-
- public bool IsSessionActive
- {
- get
- {
- return (DateTime.UtcNow - Session.LastActivityDate).TotalDays <= 3;
- }
- }
-
- public bool SupportsMediaControl
- {
- get { return true; }
- }
-
- public async Task SendMessage<T>(string name, string messageId, T data, ISessionController[] allControllers, CancellationToken cancellationToken)
- {
- if (!IsSessionActive)
- {
- return;
- }
-
- if (string.IsNullOrEmpty(_senderId) || string.IsNullOrEmpty(_applicationId))
- {
- return;
- }
-
- foreach (var controller in allControllers)
- {
- // Don't send if there's an active web socket connection
- if ((controller is WebSocketController) && controller.IsSessionActive)
- {
- return;
- }
- }
-
- var msg = new WebSocketMessage<T>
- {
- Data = data,
- MessageType = name,
- MessageId = messageId,
- ServerId = _appHost.SystemId
- };
-
- var req = new FirebaseBody<T>
- {
- to = _token,
- data = msg
- };
-
- var byteArray = Encoding.UTF8.GetBytes(_json.SerializeToString(req));
-
- var enableLogging = false;
-
-#if DEBUG
- enableLogging = true;
-#endif
-
- var options = new HttpRequestOptions
- {
- Url = "https://fcm.googleapis.com/fcm/send",
- RequestContentType = "application/json",
- RequestContentBytes = byteArray,
- CancellationToken = cancellationToken,
- LogRequest = enableLogging,
- LogResponse = enableLogging,
- LogErrors = enableLogging
- };
-
- options.RequestHeaders["Authorization"] = string.Format("key={0}", _applicationId);
- options.RequestHeaders["Sender"] = string.Format("id={0}", _senderId);
-
- using (var response = await _httpClient.Post(options).ConfigureAwait(false))
- {
-
- }
- }
- }
-
- internal class FirebaseBody<T>
- {
- public string to { get; set; }
- public WebSocketMessage<T> data { get; set; }
- }
-}
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 419c24f13..7321e9f86 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -1574,14 +1574,6 @@ namespace Emby.Server.Implementations.Session
{
session.Capabilities = capabilities;
- if (!string.IsNullOrEmpty(capabilities.PushToken))
- {
- if (string.Equals(capabilities.PushTokenType, "firebase", StringComparison.OrdinalIgnoreCase) && FirebaseSessionController.IsSupported(_appHost))
- {
- EnsureFirebaseController(session, capabilities.PushToken);
- }
- }
-
if (saveCapabilities)
{
CapabilitiesChanged?.Invoke(this, new SessionEventArgs
@@ -1600,11 +1592,6 @@ namespace Emby.Server.Implementations.Session
}
}
- private void EnsureFirebaseController(SessionInfo session, string token)
- {
- session.EnsureController<FirebaseSessionController>(s => new FirebaseSessionController(_httpClient, _appHost, _jsonSerializer, s, token, this));
- }
-
private ClientCapabilities GetSavedCapabilities(string deviceId)
{
return _deviceManager.GetCapabilities(deviceId);
diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs
index 8cacc1124..275bd83ea 100644
--- a/Emby.Server.Implementations/Udp/UdpServer.cs
+++ b/Emby.Server.Implementations/Udp/UdpServer.cs
@@ -40,6 +40,7 @@ namespace Emby.Server.Implementations.Udp
_json = json;
_socketFactory = socketFactory;
+ AddMessageResponder("who is JellyfinServer?", true, RespondToV2Message);
AddMessageResponder("who is EmbyServer?", true, RespondToV2Message);
AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message);
}
diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs
index b54634387..64e03f22e 100644
--- a/Jellyfin.Server/CoreAppHost.cs
+++ b/Jellyfin.Server/CoreAppHost.cs
@@ -11,8 +11,8 @@ namespace Jellyfin.Server
{
public class CoreAppHost : ApplicationHost
{
- public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager)
- : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, environmentInfo, imageEncoder, systemEvents, networkManager)
+ public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager)
+ : base(applicationPaths, loggerFactory, options, fileSystem, environmentInfo, imageEncoder, systemEvents, networkManager)
{
}
diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index 8ecae1b5b..98c578e83 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -25,6 +25,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.0.1" />
+ <PackageReference Include="Serilog.Sinks.Async" Version="1.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
<PackageReference Include="SkiaSharp" Version="1.68.0" />
diff --git a/Jellyfin.Server/PowerManagement.cs b/Jellyfin.Server/PowerManagement.cs
deleted file mode 100644
index c27c51893..000000000
--- a/Jellyfin.Server/PowerManagement.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using MediaBrowser.Model.System;
-
-namespace Jellyfin.Server.Native
-{
- public class PowerManagement : IPowerManagement
- {
- public void PreventSystemStandby()
- {
-
- }
-
- public void AllowSystemStandby()
- {
-
- }
-
- public void ScheduleWake(DateTime wakeTimeUtc, string displayName)
- {
-
- }
- }
-}
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index 2dd4d9af6..d74315755 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -13,7 +13,6 @@ using Emby.Server.Implementations;
using Emby.Server.Implementations.EnvironmentInfo;
using Emby.Server.Implementations.IO;
using Emby.Server.Implementations.Networking;
-using Jellyfin.Server.Native;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Drawing;
@@ -47,6 +46,8 @@ namespace Jellyfin.Server
}
ServerApplicationPaths appPaths = createApplicationPaths(options);
+ // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
+ Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
await createLogger(appPaths);
_loggerFactory = new SerilogLoggerFactory();
_logger = _loggerFactory.CreateLogger("Main");
@@ -71,7 +72,6 @@ namespace Jellyfin.Server
_loggerFactory,
options,
fileSystem,
- new PowerManagement(),
environmentInfo,
new NullImageEncoder(),
new SystemEvents(_loggerFactory.CreateLogger("SystemEvents")),
@@ -102,43 +102,66 @@ namespace Jellyfin.Server
private static ServerApplicationPaths createApplicationPaths(StartupOptions options)
{
- string programDataPath;
- if (options.ContainsOption("-programdata"))
+ string programDataPath = Environment.GetEnvironmentVariable("JELLYFIN_DATA_PATH");
+ if (string.IsNullOrEmpty(programDataPath))
{
- programDataPath = options.GetOption("-programdata");
- }
- else
- {
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (options.ContainsOption("-programdata"))
{
- programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ programDataPath = options.GetOption("-programdata");
}
else
{
- // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored.
- programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
- // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used.
- if (string.IsNullOrEmpty(programDataPath))
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ }
+ else
{
- programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share");
+ // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored.
+ programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
+ // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used.
+ if (string.IsNullOrEmpty(programDataPath))
+ {
+ programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share");
+ }
}
+ programDataPath = Path.Combine(programDataPath, "jellyfin");
+ // Ensure the dir exists
+ Directory.CreateDirectory(programDataPath);
+ }
+ }
+
+ string configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR");
+ if (string.IsNullOrEmpty(configDir))
+ {
+ if (options.ContainsOption("-configdir"))
+ {
+ configDir = options.GetOption("-configdir");
+ }
+ else
+ {
+ // Let BaseApplicationPaths set up the default value
+ configDir = null;
}
- programDataPath = Path.Combine(programDataPath, "jellyfin");
}
string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR");
if (string.IsNullOrEmpty(logDir))
{
- logDir = Path.Combine(programDataPath, "logs");
- // Ensure logDir exists
- Directory.CreateDirectory(logDir);
- // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
- Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir);
+ if (options.ContainsOption("-logdir"))
+ {
+ logDir = options.GetOption("-logdir");
+ }
+ else
+ {
+ // Let BaseApplicationPaths set up the default value
+ logDir = null;
+ }
}
string appPath = AppContext.BaseDirectory;
- return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir);
+ return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir, configDir);
}
private static async Task createLogger(IApplicationPaths appPaths)
@@ -173,10 +196,10 @@ namespace Jellyfin.Server
{
Serilog.Log.Logger = new LoggerConfiguration()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}")
- .WriteTo.File(
+ .WriteTo.Async(x => x.File(
Path.Combine(appPaths.LogDirectoryPath, "log_.log"),
rollingInterval: RollingInterval.Day,
- outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}")
+ outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}"))
.Enrich.FromLogContext()
.CreateLogger();
@@ -233,7 +256,7 @@ namespace Jellyfin.Server
}
}
- public static void Shutdown()
+ public static void Shutdown()
{
ApplicationTaskCompletionSource.SetResult(true);
}
diff --git a/Jellyfin.Server/Resources/Configuration/logging.json b/Jellyfin.Server/Resources/Configuration/logging.json
index 78f99b2ad..d16991277 100644
--- a/Jellyfin.Server/Resources/Configuration/logging.json
+++ b/Jellyfin.Server/Resources/Configuration/logging.json
@@ -2,16 +2,25 @@
"Serilog": {
"MinimumLevel": "Information",
"WriteTo": [
- { "Name": "Console",
+ {
+ "Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
},
- { "Name": "File",
+ {
+ "Name": "Async",
"Args": {
- "path": "%JELLYFIN_LOG_DIR%//log_.log",
- "rollingInterval": "Day",
- "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}"
+ "configure": [
+ {
+ "Name": "File",
+ "Args": {
+ "path": "%JELLYFIN_LOG_DIR%//log_.log",
+ "rollingInterval": "Day",
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}"
+ }
+ }
+ ]
}
}
]
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 28e75bf55..fa6502bda 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -590,6 +590,22 @@ namespace MediaBrowser.Api.Playback
}
/// <summary>
+ /// Parses query parameters as StreamOptions
+ /// <summary>
+ /// <param name="request">The stream request.</param>
+ private void ParseStreamOptions(StreamRequest request)
+ {
+ foreach (var param in Request.QueryString) {
+ if (Char.IsLower(param.Name[0])) {
+ // This was probably not parsed initially and should be a StreamOptions
+ // TODO: This should be incorporated either in the lower framework for parsing requests
+ // or the generated URL should correctly serialize it
+ request.StreamOptions[param.Name] = param.Value;
+ }
+ }
+ }
+
+ /// <summary>
/// Parses the dlna headers.
/// </summary>
/// <param name="request">The request.</param>
@@ -667,6 +683,8 @@ namespace MediaBrowser.Api.Playback
ParseParams(request);
}
+ ParseStreamOptions(request);
+
var url = Request.PathInfo;
if (string.IsNullOrEmpty(request.AudioCodec))
diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs
index 39d69ea15..c4f760b15 100644
--- a/MediaBrowser.Common/IApplicationHost.cs
+++ b/MediaBrowser.Common/IApplicationHost.cs
@@ -135,7 +135,5 @@ namespace MediaBrowser.Common
object CreateInstance(Type type);
PackageVersionClass SystemUpdateLevel { get; }
-
- string GetValue(string name);
}
}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 43f775392..a1dc9b7d4 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -37,7 +37,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles
private readonly IProcessFactory _processFactory;
private readonly ITextEncoding _textEncoding;
- public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IProcessFactory processFactory, ITextEncoding textEncoding)
+ public SubtitleEncoder(
+ ILibraryManager libraryManager,
+ ILogger logger,
+ IApplicationPaths appPaths,
+ IFileSystem fileSystem,
+ IMediaEncoder mediaEncoder,
+ IJsonSerializer json,
+ IHttpClient httpClient,
+ IMediaSourceManager mediaSourceManager,
+ IProcessFactory processFactory,
+ ITextEncoding textEncoding)
{
_libraryManager = libraryManager;
_logger = logger;
@@ -46,6 +56,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
_mediaEncoder = mediaEncoder;
_json = json;
_httpClient = httpClient;
+ _mediaSourceManager = mediaSourceManager;
_processFactory = processFactory;
_textEncoding = textEncoding;
}
diff --git a/MediaBrowser.Model/Session/ClientCapabilities.cs b/MediaBrowser.Model/Session/ClientCapabilities.cs
index ded4c0e84..0ba9988bb 100644
--- a/MediaBrowser.Model/Session/ClientCapabilities.cs
+++ b/MediaBrowser.Model/Session/ClientCapabilities.cs
@@ -12,8 +12,6 @@ namespace MediaBrowser.Model.Session
public bool SupportsMediaControl { get; set; }
public bool SupportsContentUploading { get; set; }
public string MessageCallbackUrl { get; set; }
- public string PushToken { get; set; }
- public string PushTokenType { get; set; }
public bool SupportsPersistentIdentifier { get; set; }
public bool SupportsSync { get; set; }
diff --git a/MediaBrowser.Model/System/IPowerManagement.cs b/MediaBrowser.Model/System/IPowerManagement.cs
deleted file mode 100644
index 03907568c..000000000
--- a/MediaBrowser.Model/System/IPowerManagement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-
-namespace MediaBrowser.Model.System
-{
- public interface IPowerManagement
- {
- void PreventSystemStandby();
- void AllowSystemStandby();
- void ScheduleWake(DateTime wakeTimeUtc, string displayName);
- }
-}
diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
index 0dbc43313..2c94d6a07 100644
--- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
@@ -720,82 +720,6 @@ namespace MediaBrowser.Providers.Music
return null;
}
- private long _lastMbzUrlQueryTicks = 0;
- private List<MbzUrl> _mbzUrls = null;
- private MbzUrl _chosenUrl;
-
- private async Task<MbzUrl> GetMbzUrl(bool forceMusicBrainzProper = false)
- {
- if (_chosenUrl == null || _mbzUrls == null || (DateTime.UtcNow.Ticks - _lastMbzUrlQueryTicks) > TimeSpan.FromHours(12).Ticks)
- {
- var urls = await RefreshMzbUrls(forceMusicBrainzProper).ConfigureAwait(false);
-
- if (urls.Count > 1)
- {
- _chosenUrl = urls[new Random().Next(0, urls.Count)];
- }
- else
- {
- _chosenUrl = urls[0];
- }
- }
-
- return _chosenUrl;
- }
-
- private async Task<List<MbzUrl>> RefreshMzbUrls(bool forceMusicBrainzProper = false)
- {
- List<MbzUrl> list = null;
-
- if (!forceMusicBrainzProper)
- {
- var musicbrainzadminurl = _appHost.GetValue("musicbrainzadminurl");
-
- if (!string.IsNullOrEmpty(musicbrainzadminurl))
- {
- try
- {
- var options = new HttpRequestOptions
- {
- Url = musicbrainzadminurl,
- UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion
- };
-
- using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
- {
- using (var stream = response.Content)
- {
- var results = await _json.DeserializeFromStreamAsync<List<MbzUrl>>(stream).ConfigureAwait(false);
-
- list = results;
- }
- }
- _lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error getting music brainz info");
- }
- }
- }
-
- if (list == null)
- {
- list = new List<MbzUrl>
- {
- new MbzUrl
- {
- url = MusicBrainzBaseUrl,
- throttleMs = 1000
- }
- };
- }
-
- _mbzUrls = list.ToList();
-
- return list;
- }
-
internal Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
{
return GetMusicBrainzResponse(url, isSearch, false, cancellationToken);
@@ -806,7 +730,7 @@ namespace MediaBrowser.Providers.Music
/// </summary>
internal async Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken)
{
- var urlInfo = await GetMbzUrl(forceMusicBrainzProper).ConfigureAwait(false);
+ var urlInfo = new MbzUrl(MusicBrainzBaseUrl, 1000);
var throttleMs = urlInfo.throttleMs;
if (throttleMs > 0)
@@ -841,6 +765,12 @@ namespace MediaBrowser.Providers.Music
internal class MbzUrl
{
+ internal MbzUrl(string url, int throttleMs)
+ {
+ this.url = url;
+ this.throttleMs = throttleMs;
+ }
+
public string url { get; set; }
public int throttleMs { get; set; }
}
diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
index 5c4eb62a8..bb4624b5c 100644
--- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
@@ -270,21 +270,13 @@ namespace MediaBrowser.Providers.Omdb
public static string GetOmdbUrl(string query, IApplicationHost appHost, CancellationToken cancellationToken)
{
- var baseUrl = appHost.GetValue("omdb_baseurl");
+ const string url = "https://www.omdbapi.com?apikey=fe53f97e";
- if (string.IsNullOrEmpty(baseUrl))
+ if (string.IsNullOrWhiteSpace(query))
{
- baseUrl = "https://www.omdbapi.com";
+ return url;
}
-
- var url = baseUrl + "?apikey=fe53f97e";
-
- if (!string.IsNullOrWhiteSpace(query))
- {
- url += "&" + query;
- }
-
- return url;
+ return url + "&" + query;
}
private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken)
diff --git a/README.md b/README.md
index c4133eb9d..dfa8457de 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,36 @@
<h1 align="center">Jellyfin</h1>
<h3 align="center">The Free Software Media System</h3>
-<p align="center">
-Jellyfin is a free software media system that puts you in control of managing and streaming your media.
-</p>
-
------
-
-<p align="center">
-<strong>Want to get started?</strong> Choose from <a href="https://github.com/jellyfin/jellyfin/wiki/Prebuilt-Packages">Prebuilt Packages</a>, or <a href="https://github.com/jellyfin/jellyfin/wiki/Building-from-Source">Build from Source</a>.
-</p>
-<p align="center">
-<strong>Want to contribute?</strong> Check out <a href="https://github.com/jellyfin/jellyfin/wiki/Contributing-to-Jellyfin">our wiki for guidelines</a>.
-</p>
-
---
<p align="center">
+<img alt="Logo banner" src="https://raw.githubusercontent.com/jellyfin/jellyfin-ux/master/branding/SVG/banner-logo-solid.svg?sanitize=true"/>
+<br/></br>
<a href="https://github.com/jellyfin/jellyfin"><img alt="GPL 2.0 License" src="https://img.shields.io/github/license/jellyfin/jellyfin.svg"></a>
<a href="https://cloud.drone.io/jellyfin/jellyfin"><img alt="Build Status" src="https://cloud.drone.io/api/badges/jellyfin/jellyfin/status.svg"></a>
<a href="https://hub.docker.com/r/jellyfin/jellyfin"><img alt="Docker Pull Count" src="https://img.shields.io/docker/pulls/jellyfin/jellyfin.svg"></a>
-<a href="https://matrix.to/#/#jellyfin:matrix.org"><img alt="Chat on Matrix" src="https://img.shields.io/matrix/jellyfin:matrix.org.svg?logo=matrix"></a>
+<a href="https://jellyfin.readthedocs.io"><img alt="Documentation" src="https://img.shields.io/readthedocs/jellyfin.svg"></a>
+<a href="https://matrix.to/#/+jellyfin:matrix.org"><img alt="Chat on Matrix" src="https://img.shields.io/matrix/jellyfin:matrix.org.svg?logo=matrix"></a>
<a href="https://www.reddit.com/r/jellyfin/"><img alt="Join our Subreddit" src="https://img.shields.io/badge/reddit-r%2Fjellyfin-%23FF5700.svg"></a>
</p>
-For further details, please see [our wiki](https://github.com/jellyfin/jellyfin/wiki).
-
-To receive the latest updates, please visit [our public chat on Matrix/Riot](https://matrix.to/#/#jellyfin:matrix.org), our [announce chat](https://matrix.to/#/#jellyfin-announce:matrix.org) for release info, and follow us on [Social Media](https://github.com/jellyfin/jellyfin/wiki/Social-Media).
-
-## About
-
-The Jellyfin project was started as a result of Emby's decision to take their code closed-source, as well as various philosophical differences with the core developers. Jellyfin seeks to be the free software alternative to Emby and Plex to provide media management and streaming from a dedicated server to end-user devices.
-
-Jellyfin is descended from Emby 3.5.2, ported to the .NET Core framework, and aims to contain build facilities for every platform.
+---
-## Issues and Feature Requests
+Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps. Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. There are no strings attached, no premium licenses or features, and no hidden agendas: just a team who want to build something better and work together to achieve it. We welcome anyone who is interested in joining us in our quest!
+For further details, please see [our documentation page](https://jellyfin.readthedocs.io). To receive the latest updates, get help with Jellyfin, and join the community, please visit [one of our communication channels on Matrix/Riot or social media](https://jellyfin.readthedocs.io/en/latest/user-docs/getting-help).
+For more information about the project, please see our [about page](https://jellyfin.readthedocs.io/en/latest/about/).
<p align="center">
- <strong>New idea or improvement?</strong>
-<em>Open a <a href="https://github.com/jellyfin/jellyfin/wiki/Feature-Requests">Feature Request</a>.</em>
+<strong>Want to get started?</strong>
+<em>Choose from <a href="https://jellyfin.readthedocs.io/en/latest/user-docs/installing/">Prebuilt Packages</a> or <a href="https://jellyfin.readthedocs.io/en/latest/user-docs/building/">Build from Source</a>, then see our <a href="https://jellyfin.readthedocs.io/en/latest/user-docs/quick-start/">Quickstart guide</a>.</em>
</p>
<p align="center">
- <Strong>Something not working right?</strong>
-<em>Open an <a href="https://github.com/jellyfin/jellyfin/wiki/Issue-Guidelines">Issue</a>.</em>
+<strong>Want to contribute?</strong>
+<em>Check out <a href="https://jellyfin.readthedocs.io/en/latest/developer-docs/contributing/">our documentation for guidelines</a>.</em>
+</p>
+<p align="center">
+<strong>New idea or improvement? Something not working right?</strong>
+<em>Open an <a href="https://jellyfin.readthedocs.io/en/latest/developer-docs/issues/">Issue</a>.</em>
</p>
-
-
-## Contributing to Jellyfin
-
-If you're interested in contributing, please see [our wiki for guidelines](https://github.com/jellyfin/jellyfin/wiki/Contributing-to-Jellyfin).
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 379b5b43c..791d6cac5 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.5.2.0")]
+[assembly: AssemblyVersion("10.0.0")]
diff --git a/debian/changelog b/debian/changelog
index 9dc21d467..61223e725 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+jellyfin (10.0.0-1) unstable; urgency=medium
+
+ * The first Jellyfin release under our new versioning scheme
+ * Numerous bugfixes and code readability improvements
+ * Updated logging configuration, including flag for it and configdir
+ * Updated theming including logo
+ * Dozens of other improvements as documented in GitHub pull request #419
+
+ -- Joshua Boniface <joshua@boniface.me> Sat, 05 Jan 2019 15:39:25 -0500
+
jellyfin (3.5.2-5) unstable; urgency=medium
* Fully GPL'd release - remove tainted code from MediaBrowser.Common
@@ -34,16 +44,3 @@ jellyfin (3.5.2) unstable; urgency=medium
* Rename from emby-server on version 3.5.2
-- Joshua Boniface <joshua@boniface.me> Sun, 9 Dec 2018 15:20:58 -0400
-
-emby-server (3.5.2-unlocked) unstable; urgency=medium
-
- * Taking changes from upstream 3.5.2, beautifying some JS files
-
- -- Vasily <just.one.man@yandex.ru> Mon, 22 Oct 2018 03:45:13 +0400
-
-emby-server (3.4.1.18-unlocked) unstable; urgency=medium
-
- * Hard fork of Emby 3.4.1.18 including premium unlock
-
- -- Joshua Boniface <joshua@boniface.me> Thu, 9 Aug 2018 00:33:19 -0400
-
diff --git a/debian/conf/jellyfin b/debian/conf/jellyfin
index fb00e7f65..861865aae 100644
--- a/debian/conf/jellyfin
+++ b/debian/conf/jellyfin
@@ -15,8 +15,10 @@
# General options
#
-# Data directory
-JELLYFIN_DATA="/var/lib/jellyfin"
+# Program directories
+JELLYFIN_DATA_DIRECTORY="/var/lib/jellyfin"
+JELLYFIN_CONFIG_DIRECTORY="/etc/jellyfin"
+JELLYFIN_LOG_DIRECTORY="/var/log/jellyfin"
# Restart script for in-app server control
JELLYFIN_RESTART_SCRIPT="/usr/lib/jellyfin/restart.sh"
# Additional options for the binary
@@ -29,4 +31,4 @@ JELLYFIN_ADD_OPTS=""
# Application username
JELLYFIN_USER="jellyfin"
# Full application command
-JELLYFIN_ARGS="-programdata $JELLYFIN_DATA -restartpath $JELLYFIN_RESTART_SCRIPT $JELLYFIN_ADD_OPTS"
+JELLYFIN_ARGS="-programdata $JELLYFIN_DATA_DIRECTORY -configdir $JELLYFIN_CONFIG_DIRECTORY -logdir $JELLYFIN_LOG_DIRECTORY -restartpath $JELLYFIN_RESTART_SCRIPT $JELLYFIN_ADD_OPTS"
diff --git a/debian/conf/logging.json b/debian/conf/logging.json
new file mode 100644
index 000000000..5d98484cd
--- /dev/null
+++ b/debian/conf/logging.json
@@ -0,0 +1,29 @@
+{
+ "Serilog": {
+ "MinimumLevel": "Information",
+ "WriteTo": [
+ { "Name": "Console",
+ "Args": {
+ "outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}"
+ }
+ },
+ {
+ "Name": "Async",
+ "Args": {
+ "configure": [
+ {
+ "Name": "File",
+ "Args": {
+ "path": "%JELLYFIN_LOG_DIR%//jellyfin.log",
+ "fileSizeLimitBytes": 10485700,
+ "rollOnFileSizeLimit": true,
+ "retainedFileCountLimit": 10,
+ "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}"
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/debian/control b/debian/control
index 13c62c806..74bebeaf1 100644
--- a/debian/control
+++ b/debian/control
@@ -9,6 +9,9 @@ Build-Depends: debhelper (>= 9),
libfontconfig1-dev,
libfreetype6-dev
Standards-Version: 3.9.4
+Homepage: https://jellyfin.media/
+Vcs-Git: https://github.org/jellyfin/jellyfin.git
+Vcs-Browser: https://github.org/jellyfin/jellyfin
Package: jellyfin
Replaces: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server
diff --git a/debian/install b/debian/install
index bc26f9f09..adaff7b26 100644
--- a/debian/install
+++ b/debian/install
@@ -1,5 +1,6 @@
usr/lib/jellyfin usr/lib/
debian/conf/jellyfin etc/default/
+debian/conf/logging.json etc/jellyfin/
debian/conf/jellyfin.service.conf etc/systemd/system/jellyfin.service.d/
debian/bin/jellyfin-sudoers etc/sudoers.d/
debian/bin/restart.sh usr/lib/jellyfin/
diff --git a/debian/jellyfin.service b/debian/jellyfin.service
index 4c3739909..c17422029 100644
--- a/debian/jellyfin.service
+++ b/debian/jellyfin.service
@@ -6,7 +6,7 @@ After = network.target
Type = simple
EnvironmentFile = /etc/default/jellyfin
User = jellyfin
-ExecStart = /usr/bin/jellyfin -programdata ${JELLYFIN_DATA} -restartpath ${JELLYFIN_RESTART_SCRIPT} ${JELLYFIN_ADD_OPTS}
+ExecStart = /usr/bin/jellyfin -programdata ${JELLYFIN_DATA_DIRECTORY} -configdir ${JELLYFIN_CONFIG_DIRECTORY} -logdir ${JELLYFIN_LOG_DIRECTORY} -restartpath ${JELLYFIN_RESTART_SCRIPT} ${JELLYFIN_ADD_OPTS}
Restart = on-failure
TimeoutSec = 15
diff --git a/debian/postinst b/debian/postinst
index 502bba342..3690d20ba 100644
--- a/debian/postinst
+++ b/debian/postinst
@@ -2,7 +2,6 @@
set -e
NAME=jellyfin
-CONF_FILE=/etc/${NAME}.conf
DEFAULT_FILE=/etc/default/${NAME}
# Source Jellyfin default configuration
@@ -10,13 +9,10 @@ if [[ -f $DEFAULT_FILE ]]; then
. $DEFAULT_FILE
fi
-# Source Jellyfin user configuration overrides
-if [[ -f $CONF_FILE ]]; then
- . $CONF_FILE
-fi
-
-# Data directory where Jellyfin database, cache and logs are stored
-PROGRAMDATA=${JELLYFIN_DATA-/var/lib/$NAME}
+# Data directories for program data (cache, db), configs, and logs
+PROGRAMDATA=${JELLYFIN_DATA_DIRECTORY-/var/lib/$NAME}
+CONFIGDATA=${JELLYFIN_CONFIG_DIRECTORY-/etc/$NAME}
+LOGDATA=${JELLYFIN_LOG_DIRECTORY-/var/log/$NAME}
case "$1" in
configure)
@@ -29,13 +25,24 @@ case "$1" in
adduser --system --ingroup jellyfin --shell /bin/false jellyfin --no-create-home --home ${PROGRAMDATA} \
--gecos "Jellyfin default user" > /dev/null 2>&1
fi
- # ensure $PROGRAMDATA has appropriate permissions
+ # ensure $PROGRAMDATA exists
if [[ ! -d $PROGRAMDATA ]]; then
mkdir $PROGRAMDATA
- chown -R jellyfin:jellyfin $PROGRAMDATA
fi
+ # ensure $CONFIGDATA exists
+ if [[ ! -d $CONFIGDATA ]]; then
+ mkdir $CONFIGDATA
+ fi
+ # ensure $LOGDATA exists
+ if [[ ! -d $LOGDATA ]]; then
+ mkdir $LOGDATA
+ fi
+ # Ensure permissions are correct on all config directories
+ chown -R jellyfin:jellyfin $PROGRAMDATA
+ chown -R jellyfin:jellyfin $CONFIGDATA
+ chown -R jellyfin:jellyfin $LOGDATA
- chmod +x ${JELLYFIN_DIR}/restart.sh > /dev/null 2>&1 || true
+ chmod +x /usr/lib/jellyfin/restart.sh > /dev/null 2>&1 || true
# Install jellyfin symlink into /usr/bin
ln -sf /usr/lib/jellyfin/bin/jellyfin /usr/bin/jellyfin
diff --git a/debian/postrm b/debian/postrm
index 852841b16..690f5d587 100644
--- a/debian/postrm
+++ b/debian/postrm
@@ -2,7 +2,6 @@
set -e
NAME=jellyfin
-CONF_FILE=/etc/${NAME}.conf
DEFAULT_FILE=/etc/default/${NAME}
# Source Jellyfin default configuration
@@ -10,13 +9,10 @@ if [[ -f $DEFAULT_FILE ]]; then
. $DEFAULT_FILE
fi
-# Source Jellyfin user configuration overrides
-if [[ -f $CONF_FILE ]]; then
- . $CONF_FILE
-fi
-
-# Data directory where Jellyfin database, cache and logs are stored
-PROGRAMDATA=${JELLYFIN_DATA-/var/lib/$NAME}
+# Data directories for program data (cache, db), configs, and logs
+PROGRAMDATA=${JELLYFIN_DATA_DIRECTORY-/var/lib/$NAME}
+CONFIGDATA=${JELLYFIN_CONFIG_DIRECTORY-/etc/$NAME}
+LOGDATA=${JELLYFIN_DATA_DIRECTORY-/var/log/$NAME}
# In case this system is running systemd, we make systemd reload the unit files
# to pick up changes.
@@ -37,14 +33,29 @@ case "$1" in
deb-systemd-helper unmask jellyfin.service >/dev/null
fi
+ # Remove user and group
userdel jellyfin > /dev/null 2>&1 || true
delgroup --quiet jellyfin > /dev/null 2>&1 || true
+ # Remove config dir
+ if [[ -d $CONFIGDATA ]]; then
+ rm -rf $CONFIGDATA
+ fi
+ # Remove log dir
+ if [[ -d $LOGDATA ]]; then
+ rm -rf $LOGDATA
+ fi
+ # Remove program data dir
if [[ -d $PROGRAMDATA ]]; then
rm -rf $PROGRAMDATA
fi
+ # Remove binary symlink
[[ -f /usr/bin/jellyfin ]] && rm /usr/bin/jellyfin
+ # Remove sudoers config
[[ -f /etc/sudoers.d/jellyfin-sudoers ]] && rm /etc/sudoers.d/jellyfin-sudoers
- [[ -d /var/lib/jellyfin ]] && rm -rf /var/lib/jellyfin
+ # Remove anything at the default locations; catches situations where the user moved the defaults
+ [[ -e /etc/jellyfin ]] && rm -rf /etc/jellyfin
+ [[ -e /var/log/jellyfin ]] && rm -rf /var/log/jellyfin
+ [[ -e /var/lib/jellyfin ]] && rm -rf /var/lib/jellyfin
;;
remove)
if [[ -x "/usr/bin/deb-systemd-helper" ]]; then
diff --git a/debian/preinst b/debian/preinst
index 2ce29a0cf..0063e0e63 100644
--- a/debian/preinst
+++ b/debian/preinst
@@ -2,7 +2,6 @@
set -e
NAME=jellyfin
-CONF_FILE=/etc/${NAME}.conf
DEFAULT_FILE=/etc/default/${NAME}
# Source Jellyfin default configuration
@@ -10,13 +9,10 @@ if [[ -f $DEFAULT_FILE ]]; then
. $DEFAULT_FILE
fi
-# Source Jellyfin user configuration overrides
-if [[ -f $CONF_FILE ]]; then
- . $CONF_FILE
-fi
-
-# Data directory where Jellyfin database, cache and logs are stored
-PROGRAMDATA=${JELLYFIN_DATA-/var/lib/$NAME}
+# Data directories for program data (cache, db), configs, and logs
+PROGRAMDATA=${JELLYFIN_DATA_DIRECTORY-/var/lib/$NAME}
+CONFIGDATA=${JELLYFIN_CONFIG_DIRECTORY-/etc/$NAME}
+LOGDATA=${JELLYFIN_DATA_DIRECTORY-/var/log/$NAME}
# In case this system is running systemd, we make systemd reload the unit files
# to pick up changes.
@@ -57,6 +53,14 @@ case "$1" in
# Clean up old Emby cruft that can break the user's system
[[ -f /etc/sudoers.d/emby ]] && rm -f /etc/sudoers.d/emby
+ # If we have existing config or log dirs in /var/lib/jellyfin, move them into the right place
+ if [[ -d $PROGRAMDATA/config ]]; then
+ mv $PROGRAMDATA/config $CONFIGDATA
+ fi
+ if [[ -d $PROGRAMDATA/logs ]]; then
+ mv $PROGRAMDATA/logs $LOGDATA
+ fi
+
;;
abort-upgrade)
;;
diff --git a/debian/prerm b/debian/prerm
index 3cdffed79..4770c03c4 100644
--- a/debian/prerm
+++ b/debian/prerm
@@ -2,7 +2,6 @@
set -e
NAME=jellyfin
-CONF_FILE=/etc/${NAME}.conf
DEFAULT_FILE=/etc/default/${NAME}
# Source Jellyfin default configuration
@@ -10,13 +9,10 @@ if [[ -f $DEFAULT_FILE ]]; then
. $DEFAULT_FILE
fi
-# Source Jellyfin user configuration overrides
-if [[ -f $CONF_FILE ]]; then
- . $CONF_FILE
-fi
-
-# Data directory where Jellyfin database, cache and logs are stored
-PROGRAMDATA=${JELLYFIN_DATA-/var/lib/$NAME}
+# Data directories for program data (cache, db), configs, and logs
+PROGRAMDATA=${JELLYFIN_DATA_DIRECTORY-/var/lib/$NAME}
+CONFIGDATA=${JELLYFIN_CONFIG_DIRECTORY-/etc/$NAME}
+LOGDATA=${JELLYFIN_DATA_DIRECTORY-/var/log/$NAME}
case "$1" in
remove|upgrade|deconfigure)
diff --git a/debian/source/options b/debian/source/options
new file mode 100644
index 000000000..45bef4764
--- /dev/null
+++ b/debian/source/options
@@ -0,0 +1 @@
+tar-ignore = ".git*"