From 9f3389ff07f270b9e85d737f8184578705f940e3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 22 Aug 2017 14:47:53 -0400 Subject: [PATCH 01/18] update mac project --- MediaBrowser.Server.Mac.sln | 68 ------------------- MediaBrowser.Server.Mac/MacAppHost.cs | 4 +- MediaBrowser.Server.Mac/Main.cs | 26 +++---- .../Native/MonoFileSystem.cs | 2 +- 4 files changed, 13 insertions(+), 87 deletions(-) diff --git a/MediaBrowser.Server.Mac.sln b/MediaBrowser.Server.Mac.sln index ba912566ac..051ea660bd 100644 --- a/MediaBrowser.Server.Mac.sln +++ b/MediaBrowser.Server.Mac.sln @@ -17,8 +17,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "Media EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Implementations", "MediaBrowser.Server.Implementations\MediaBrowser.Server.Implementations.csproj", "{2E781478-814D-4A48-9D80-BFF206441A65}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.WebDashboard", "MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj", "{5624B7B5-B5A7-41D8-9F10-CC5611109619}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}" @@ -41,8 +39,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RSSDP", "RSSDP\RSSDP.csproj EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Skia", "Emby.Drawing.Skia\Emby.Drawing.Skia.csproj", "{2312DA6D-FF86-4597-9777-BCEEC32D96DD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Common.Implementations", "Emby.Common.Implementations\Emby.Common.Implementations.csproj", "{1E37A338-9F57-4B70-BD6D-BB9C591E319B}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketHttpListener", "SocketHttpListener\SocketHttpListener.csproj", "{1D74413B-E7CF-455B-B021-F52BDF881542}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{CB7F2326-6497-4A3D-BA03-48513B17A7BE}" @@ -210,26 +206,6 @@ Global {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|Any CPU.Build.0 = Release Mono|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|x86.ActiveCfg = Release Mono|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|x86.Build.0 = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.Build.0 = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|x86.ActiveCfg = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|x86.Build.0 = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.Build.0 = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.Build.0 = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.ActiveCfg = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.Build.0 = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|Any CPU.Build.0 = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|x86.ActiveCfg = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|x86.Build.0 = Release Mono|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.ActiveCfg = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.Build.0 = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|x86.ActiveCfg = Release Mono|Any CPU @@ -470,50 +446,6 @@ Global {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x64.Build.0 = Release|Any CPU {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x86.ActiveCfg = Release|Any CPU {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x86.Build.0 = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|x86.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|x86.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x86.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x86.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Any CPU.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x86.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x86.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Any CPU.Build.0 = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x86.ActiveCfg = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x86.Build.0 = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Any CPU.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Any CPU.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x86.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x86.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Win32.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Win32.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x64.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x64.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Mixed Platforms.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Mixed Platforms.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Win32.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Win32.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x64.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x64.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Win32.ActiveCfg = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Win32.Build.0 = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x64.ActiveCfg = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x64.Build.0 = Release|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Mixed Platforms.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Mixed Platforms.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Win32.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Win32.Build.0 = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x64.ActiveCfg = Debug|Any CPU - {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x64.Build.0 = Debug|Any CPU {1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU {1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|Any CPU.Build.0 = Debug|Any CPU {1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|x86.ActiveCfg = Debug|Any CPU diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs index 2f8ee983ca..7ad96d2bf2 100644 --- a/MediaBrowser.Server.Mac/MacAppHost.cs +++ b/MediaBrowser.Server.Mac/MacAppHost.cs @@ -19,11 +19,11 @@ namespace MediaBrowser.Server.Mac { public class MacAppHost : ApplicationHost { - public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) + public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager) { } - public override bool CanSelfRestart + public override bool CanSelfRestart { get { diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index cedeeb22ec..e70ef01eb8 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations; using System; using System.Diagnostics; using System.Globalization; @@ -20,21 +19,18 @@ using MonoMac.ObjCRuntime; using Emby.Server.Core; using Emby.Server.Core.Cryptography; using Emby.Server.Implementations; -using Emby.Common.Implementations.Logging; using Emby.Server.Implementations.Logging; -using Emby.Common.Implementations.EnvironmentInfo; using Emby.Server.Mac.Native; using Emby.Server.Implementations.IO; -using Emby.Common.Implementations.Networking; -using Emby.Common.Implementations.Cryptography; using Mono.Unix.Native; using MediaBrowser.Model.System; using MediaBrowser.Model.IO; -using Emby.Server.Implementations.Logging; using Emby.Drawing; using Emby.Drawing.Skia; using MediaBrowser.Controller.Drawing; using MediaBrowser.Model.Drawing; +using Emby.Server.Implementations.EnvironmentInfo; +using Emby.Server.Implementations.Networking; namespace MediaBrowser.Server.Mac { @@ -60,7 +56,7 @@ namespace MediaBrowser.Server.Mac var appPaths = CreateApplicationPaths(appFolderPath, customProgramDataPath); - var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); + var logManager = new SimpleLogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Info); logManager.AddConsoleOutput(); @@ -90,9 +86,7 @@ namespace MediaBrowser.Server.Mac // Within the mac bundle, go uo two levels then down into Resources folder var resourcesPath = Path.Combine(Path.GetDirectoryName(appFolderPath), "Resources"); - Action createDirectoryFn = (string obj) => Directory.CreateDirectory(obj); - - return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath, createDirectoryFn); + return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath); } /// @@ -161,7 +155,7 @@ namespace MediaBrowser.Server.Mac { var info = new EnvironmentInfo() { - CustomOperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX + OperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX }; var uname = GetUnixName(); @@ -186,23 +180,23 @@ namespace MediaBrowser.Server.Mac if (archX86.IsMatch(uname.machine)) { - info.CustomArchitecture = Architecture.X86; + info.SystemArchitecture = Architecture.X86; } else if (string.Equals(uname.machine, "x86_64", StringComparison.OrdinalIgnoreCase)) { - info.CustomArchitecture = Architecture.X64; + info.SystemArchitecture = Architecture.X64; } else if (uname.machine.StartsWith("arm", StringComparison.OrdinalIgnoreCase)) { - info.CustomArchitecture = Architecture.Arm; + info.SystemArchitecture = Architecture.Arm; } else if (System.Environment.Is64BitOperatingSystem) { - info.CustomArchitecture = Architecture.X64; + info.SystemArchitecture = Architecture.X64; } else { - info.CustomArchitecture = Architecture.X86; + info.SystemArchitecture = Architecture.X86; } return info; diff --git a/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs b/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs index 7aeff5ac8c..1fd140fb9e 100644 --- a/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs +++ b/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs @@ -1,4 +1,4 @@ -using Emby.Common.Implementations.IO; +using Emby.Server.Implementations.IO; using MediaBrowser.Model.Logging; using Mono.Unix.Native; using MediaBrowser.Model.System; From a38567e787a9b7c2b2f729c95103ef6ddb9344d2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 22 Aug 2017 14:50:58 -0400 Subject: [PATCH 02/18] update mac project --- MediaBrowser.Server.Mac/Main.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index e70ef01eb8..3863937f8a 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -119,10 +119,7 @@ namespace MediaBrowser.Server.Mac environmentInfo, imageEncoder, new SystemEvents(logManager.GetLogger("SystemEvents")), - new MemoryStreamProvider(), - new NetworkManager(logManager.GetLogger("NetworkManager")), - GenerateCertificate, - () => Environment.UserName); + new NetworkManager(logManager.GetLogger("NetworkManager"))); if (options.ContainsOption("-v")) { Console.WriteLine (AppHost.ApplicationVersion.ToString()); @@ -146,11 +143,6 @@ namespace MediaBrowser.Server.Mac } } - private static void GenerateCertificate(string certPath, string certHost, string certPassword) - { - CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, certPassword, _logger); - } - private static EnvironmentInfo GetEnvironmentInfo() { var info = new EnvironmentInfo() From 5ced09d169fa323a1db0d332cfbfed27b3e72c8c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:43:52 -0400 Subject: [PATCH 03/18] removed dead code --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 18 ------------------ Emby.Dlna/Didl/DidlBuilder.cs | 14 -------------- 2 files changed, 32 deletions(-) diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 5ce1d1925f..205f4e8900 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -508,23 +508,6 @@ namespace Emby.Dlna.ContentDirectory if (stubType.HasValue) { - if (stubType.Value == StubType.People) - { - var items = _libraryManager.GetPeopleItems(new InternalPeopleQuery - { - ItemId = item.Id - - }); - - var result = new QueryResult - { - Items = items.Select(i => new ServerItem(i)).ToArray(items.Count), - TotalRecordCount = items.Count - }; - - return ApplyPaging(result, startIndex, limit); - } - var person = item as Person; if (person != null) { @@ -1356,7 +1339,6 @@ namespace Emby.Dlna.ContentDirectory public enum StubType { Folder = 0, - People = 1, Latest = 2, Playlists = 3, Albums = 4, diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 65410bd67d..45becd482a 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -391,14 +391,6 @@ namespace Emby.Dlna.Didl private string GetDisplayName(BaseItem item, StubType? itemStubType, BaseItem context) { - if (itemStubType.HasValue && itemStubType.Value == StubType.People) - { - if (item is Video) - { - return _localization.GetLocalizedString("HeaderCastCrew"); - } - return _localization.GetLocalizedString("HeaderPeople"); - } if (itemStubType.HasValue && itemStubType.Value == StubType.Latest) { return _localization.GetLocalizedString("ViewTypeMusicLatest"); @@ -961,12 +953,6 @@ namespace Emby.Dlna.Didl private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer) { - if (stubType.HasValue && stubType.Value == StubType.People) - { - AddEmbeddedImageAsCover("people", writer); - return; - } - ImageDownloadInfo imageInfo = null; if (context is UserView) From db4e0a38e90c3b90a6e46d055396233b92a5aa19 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:44:13 -0400 Subject: [PATCH 04/18] update mac project --- MediaBrowser.Server.Mac/Emby.Server.Mac.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index 161a4076a0..fe9ab13fad 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -92,10 +92,6 @@ False ..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll - - ..\packages\NLog.4.4.12\lib\net45\NLog.dll - True - ..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll True From 4f7695556346e3d980bba7f7de8fe306084436e2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:45:04 -0400 Subject: [PATCH 05/18] fix MissingEpisodeProvider repeatedly adding and removing unaired items --- MediaBrowser.Providers/TV/MissingEpisodeProvider.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 45e10a76e4..cfe20c741f 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -191,6 +191,8 @@ namespace MediaBrowser.Providers.TV }); } + private const double UnairedEpisodeThresholdDays = 2; + /// /// Adds the missing episodes. /// @@ -248,8 +250,7 @@ namespace MediaBrowser.Providers.TV var targetSeries = DetermineAppropriateSeries(series, tuple.Item1); - var unairedThresholdDays = 2; - now = now.AddDays(0 - unairedThresholdDays); + now = now.AddDays(0 - UnairedEpisodeThresholdDays); if (airDate.Value < now) { @@ -329,9 +330,13 @@ namespace MediaBrowser.Providers.TV return true; } - if (!allowMissingEpisodes && i.Episode.IsMissingEpisode && !i.Episode.IsUnaired) + if (!allowMissingEpisodes && i.Episode.IsMissingEpisode) { - return true; + // If it's missing, but not unaired, remove it + if (!i.Episode.PremiereDate.HasValue || i.Episode.PremiereDate.Value.ToLocalTime().Date.AddDays(UnairedEpisodeThresholdDays) < DateTime.Now.Date) + { + return true; + } } return false; From 12854950f29180f65ac44aad756379081dc1c555 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:45:58 -0400 Subject: [PATCH 06/18] add comment --- Emby.Server.Implementations/IO/LibraryMonitor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 1467d9426a..3994e2b007 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -85,6 +85,8 @@ namespace Emby.Server.Implementations.IO public bool IsPathLocked(string path) { + // This method is not used by the core but it used by auto-organize + var lockedPaths = _tempIgnoredPaths.Keys.ToList(); return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path)); } From b04e80b28babc5a336f6c217d0604cb23b88dc8e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:46:57 -0400 Subject: [PATCH 07/18] remove unused localization strings --- .../Emby.Server.Implementations.csproj | 1 - .../Localization/Core/core.json | 179 ------------------ .../Localization/Core/en-US.json | 14 -- .../Localization/LocalizationManager.cs | 2 +- 4 files changed, 1 insertion(+), 195 deletions(-) delete mode 100644 Emby.Server.Implementations/Localization/Core/core.json diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 2a45fb3151..1dbb10b488 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -698,7 +698,6 @@ - diff --git a/Emby.Server.Implementations/Localization/Core/core.json b/Emby.Server.Implementations/Localization/Core/core.json deleted file mode 100644 index 976faa8cbc..0000000000 --- a/Emby.Server.Implementations/Localization/Core/core.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.", - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete." -} diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index 133644ff7b..c7f8652334 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -1,5 +1,4 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", "AppDeviceValues": "App: {0}, Device: {1}", "UserDownloadingItemWithValues": "{0} is downloading {1}", "FolderTypeMixed": "Mixed content", @@ -13,15 +12,12 @@ "FolderTypeBooks": "Books", "FolderTypeTvShows": "TV", "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", "ValueSpecialEpisodeName": "Special - {0}", "LabelChapterName": "Chapter {0}", "NameSeasonUnknown": "Season Unknown", "NameSeasonNumber": "Season {0}", "LabelExit": "Exit", "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", "LabelApiDocumentation": "Api Documentation", "LabelDeveloperResources": "Developer Resources", "LabelBrowseLibrary": "Browse Library", @@ -164,15 +160,5 @@ "HeaderStatus": "Status", "HeaderTracks": "Tracks", "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index a8cd1dc04d..278a39cd1e 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -335,7 +335,7 @@ namespace Emby.Server.Implementations.Localization const string prefix = "Core"; var key = prefix + culture; - return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "core.json")); + return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "en-US.json")); } private Dictionary GetDictionary(string prefix, string culture, string baseFilename) From 8732a603458ed32cf9e5834edc012b0409538294 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:48:03 -0400 Subject: [PATCH 08/18] set season name in SeasonResolver --- .../Library/Resolvers/TV/SeasonResolver.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 84ceac65e6..830bd9d85c 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -1,6 +1,8 @@ -using MediaBrowser.Controller.Configuration; +using System.Globalization; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Globalization; using MediaBrowser.Naming.Common; using MediaBrowser.Naming.TV; @@ -17,15 +19,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV private readonly IServerConfigurationManager _config; private readonly ILibraryManager _libraryManager; + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + private readonly ILocalizationManager _localization; /// /// Initializes a new instance of the class. /// /// The config. - public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager) + public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization) { _config = config; _libraryManager = libraryManager; + _localization = localization; } /// @@ -47,9 +52,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV SeriesName = series.Name }; - if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0) + if (season.IndexNumber.HasValue) { - season.Name = _config.Configuration.SeasonZeroDisplayName; + var seasonNumber = season.IndexNumber.Value; + + season.Name = seasonNumber == 0 ? + _config.Configuration.SeasonZeroDisplayName : + string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture)); } return season; From 636943be4b1674a14d09bef22471fd977bc56e11 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:48:51 -0400 Subject: [PATCH 09/18] shorten package cache time --- .../Updates/InstallationManager.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 4d1e1eaac7..393fb76e2f 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -277,15 +277,7 @@ namespace Emby.Server.Implementations.Updates private TimeSpan GetCacheLength() { - switch (GetSystemUpdateLevel()) - { - case PackageVersionClass.Beta: - return TimeSpan.FromMinutes(30); - case PackageVersionClass.Dev: - return TimeSpan.FromMinutes(3); - default: - return TimeSpan.FromHours(24); - } + return TimeSpan.FromMinutes(3); } protected PackageInfo[] FilterPackages(List packages) From f694ae7e95d7b6e682831ea26e5b2aa5b08fae55 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 12:49:42 -0400 Subject: [PATCH 10/18] add null checks to ScheduleDirect --- .../LiveTv/Listings/SchedulesDirect.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index e12acf1408..6fe3615d38 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -247,7 +247,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings ProgramAudio audioType = ProgramAudio.Stereo; bool repeat = programInfo.@new == null; - string newID = programInfo.programID + "T" + startAt.Ticks + "C" + channelId; + + var programId = programInfo.programID ?? string.Empty; + + string newID = programId + "T" + startAt.Ticks + "C" + channelId; if (programInfo.audioProperties != null) { @@ -300,7 +303,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings Etag = programInfo.md5 }; - var showId = programInfo.programID ?? string.Empty; + var showId = programId; if (!info.IsSeries) { @@ -339,11 +342,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings if (details.descriptions != null) { - if (details.descriptions.description1000 != null) + if (details.descriptions.description1000 != null && details.descriptions.description1000.Count > 0) { info.Overview = details.descriptions.description1000[0].description; } - else if (details.descriptions.description100 != null) + else if (details.descriptions.description100 != null && details.descriptions.description100.Count > 0) { info.Overview = details.descriptions.description100[0].description; } @@ -351,16 +354,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings if (info.IsSeries) { - info.SeriesId = programInfo.programID.Substring(0, 10); + info.SeriesId = programId.Substring(0, 10); if (details.metadata != null) { var gracenote = details.metadata.Find(x => x.Gracenote != null).Gracenote; - info.SeasonNumber = gracenote.season; - - if (gracenote.episode > 0) + if (gracenote != null) { - info.EpisodeNumber = gracenote.episode; + info.SeasonNumber = gracenote.season; + + if (gracenote.episode > 0) + { + info.EpisodeNumber = gracenote.episode; + } } } } From 6736f79abe3da4cdb8747ef83a02ff512230a614 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 13:08:17 -0400 Subject: [PATCH 11/18] removed dead code --- Emby.Server.Implementations/Dto/DtoService.cs | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 9dbf299ab8..c6243a0a6f 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -115,14 +115,10 @@ namespace Emby.Server.Implementations.Dto var programTuples = new List>(); var channelTuples = new List>(); - var refreshQueue = options.Fields.Contains(ItemFields.RefreshState) - ? _providerManager.GetRefreshQueue() - : null; - var index = 0; foreach (var item in items) { - var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner); + var dto = GetBaseItemDtoInternal(item, options, user, owner); var tvChannel = item as LiveTvChannel; if (tvChannel != null) @@ -176,11 +172,7 @@ namespace Emby.Server.Implementations.Dto { var syncDictionary = GetSyncedItemProgress(options); - var refreshQueue = options.Fields.Contains(ItemFields.RefreshState) - ? _providerManager.GetRefreshQueue() - : null; - - var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner); + var dto = GetBaseItemDtoInternal(item, options, user, owner); var tvChannel = item as LiveTvChannel; if (tvChannel != null) { @@ -312,7 +304,7 @@ namespace Emby.Server.Implementations.Dto } } - private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, Dictionary currentRefreshQueue, User user = null, BaseItem owner = null) + private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) { var fields = options.Fields; @@ -412,14 +404,10 @@ namespace Emby.Server.Implementations.Dto dto.Etag = item.GetEtag(user); } - if (currentRefreshQueue != null) - { - //dto.RefreshState = item.GetRefreshState(currentRefreshQueue); - } - + var liveTvManager = _livetvManager(); if (item is ILiveTvRecording) { - _livetvManager().AddInfoToRecordingDto(item, dto, user); + liveTvManager.AddInfoToRecordingDto(item, dto, user); } return dto; @@ -427,10 +415,7 @@ namespace Emby.Server.Implementations.Dto public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List taggedItems, Dictionary syncProgress, User user = null) { - var refreshQueue = options.Fields.Contains(ItemFields.RefreshState) - ? _providerManager.GetRefreshQueue() - : null; - var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user); + var dto = GetBaseItemDtoInternal(item, options, user); if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts)) { From 2d0c98733aa7cfe3337034bca815e807b203ac24 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 13:27:53 -0400 Subject: [PATCH 12/18] normalize media source container --- Emby.Server.Implementations/Dto/DtoService.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index c6243a0a6f..2ea88b52a4 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -369,6 +369,8 @@ namespace Emby.Server.Implementations.Dto { dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user); } + + NormalizeMediaSourceContainers(dto); } } @@ -413,6 +415,45 @@ namespace Emby.Server.Implementations.Dto return dto; } + private void NormalizeMediaSourceContainers(BaseItemDto dto) + { + foreach (var mediaSource in dto.MediaSources) + { + var container = mediaSource.Container; + if (string.IsNullOrWhiteSpace(container)) + { + continue; + } + var containers = container.Split(new[] { ',' }); + if (containers.Length < 2) + { + continue; + } + + var path = mediaSource.Path; + string fileExtensionContainer = null; + + if (!string.IsNullOrWhiteSpace(path)) + { + path = Path.GetExtension(path); + if (!string.IsNullOrWhiteSpace(path)) + { + path = Path.GetExtension(path); + if (!string.IsNullOrWhiteSpace(path)) + { + path = path.TrimStart('.'); + } + if (!string.IsNullOrWhiteSpace(path) && containers.Contains(path, StringComparer.OrdinalIgnoreCase)) + { + fileExtensionContainer = path; + } + } + } + + mediaSource.Container = fileExtensionContainer ?? containers[0]; + } + } + public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List taggedItems, Dictionary syncProgress, User user = null) { var dto = GetBaseItemDtoInternal(item, options, user); From 26f6f594cee19f0af4e609659efdddb466dc8731 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 14:00:42 -0400 Subject: [PATCH 13/18] improve handling of disconnected drives --- MediaBrowser.Controller/Entities/Folder.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index b088347842..11c0a57473 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -648,15 +648,15 @@ namespace MediaBrowser.Controller.Entities public static bool IsPathOffline(string path, List allLibraryPaths) { - if (FileSystem.FileExists(path)) - { - return false; - } + //if (FileSystem.FileExists(path)) + //{ + // return false; + //} var originalPath = path; // Depending on whether the path is local or unc, it may return either null or '\' at the top - while (!string.IsNullOrEmpty(path) && path.Length > 1) + while (!string.IsNullOrWhiteSpace(path) && path.Length > 1) { if (FileSystem.DirectoryExists(path)) { From af02f9d692a74749921815ab356c1180fcae6f08 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 14:44:40 -0400 Subject: [PATCH 14/18] add mpdecimate option --- .../LiveTv/TunerHosts/M3UTunerHost.cs | 1 + .../MediaEncoding/EncodingHelper.cs | 10 ++++++++++ .../MediaEncoding/EncodingJobInfo.cs | 5 +++++ MediaBrowser.Model/Dto/MediaSourceInfo.cs | 1 + MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 1 + 5 files changed, 18 insertions(+) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 1bc334f062..eac8455791 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -165,6 +165,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts RequiresOpening = true, RequiresClosing = true, RequiresLooping = info.EnableStreamLooping, + EnableMpDecimate = info.EnableMpDecimate, ReadAtNativeFramerate = false, diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index d99103852a..736f1b32f5 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -778,6 +778,11 @@ namespace MediaBrowser.Controller.MediaEncoding return false; } + if (state.EnableMpDecimate) + { + return false; + } + if (videoStream.IsInterlaced) { if (request.DeInterlace) @@ -1449,6 +1454,11 @@ namespace MediaBrowser.Controller.MediaEncoding } } + if (state.EnableMpDecimate) + { + filters.Add("mpdecimate,setpts=N/FRAME_RATE/TB"); + } + if (filters.Count > 0) { output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray())); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index c2ce969792..e76217fda6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -127,6 +127,11 @@ namespace MediaBrowser.Controller.MediaEncoding } } + public bool EnableMpDecimate + { + get { return MediaSource.EnableMpDecimate; } + } + public string AlbumCoverPath { get; set; } public string InputAudioSync { get; set; } diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 488b1e7a86..8f3f0648d3 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -41,6 +41,7 @@ namespace MediaBrowser.Model.Dto public string OpenToken { get; set; } public bool RequiresClosing { get; set; } public bool SupportsProbing { get; set; } + public bool EnableMpDecimate { get; set; } public string LiveStreamId { get; set; } public int? BufferMs { get; set; } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 15f60d8317..2c2f22e867 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -47,6 +47,7 @@ namespace MediaBrowser.Model.LiveTv public bool ImportFavoritesOnly { get; set; } public bool AllowHWTranscoding { get; set; } public bool EnableStreamLooping { get; set; } + public bool EnableMpDecimate { get; set; } public bool EnableNewHdhrChannelIds { get; set; } public string Source { get; set; } From d39a704b420a3a5a3fa835ec2bb32baf840f495a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 15:21:20 -0400 Subject: [PATCH 15/18] update nuget --- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index e4eff48886..45a0529f9a 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.736 + 3.0.737 Emby.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index f153d3e6b7..e5a0d454f0 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.736 + 3.0.737 Emby.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + From 82ab91f20971f46b8da97c0557fb0db38fe856bb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 15:45:40 -0400 Subject: [PATCH 16/18] add property to indicate support for on the fly subtitle extraction --- Emby.Dlna/Didl/DidlBuilder.cs | 2 +- .../Configuration/EncodingOptions.cs | 3 +- MediaBrowser.Model/Dlna/ITranscoderSupport.cs | 5 ++++ MediaBrowser.Model/Dlna/StreamBuilder.cs | 19 +++++++++---- MediaBrowser.Model/Dlna/StreamInfo.cs | 28 +++++++++---------- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +-- 7 files changed, 38 insertions(+), 25 deletions(-) diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 45becd482a..844a6a5ce6 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -236,7 +236,7 @@ namespace Emby.Dlna.Didl AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo); } - var subtitleProfiles = streamInfo.GetSubtitleProfiles(false, _serverAddress, _accessToken) + var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken) .Where(subtitle => subtitle.DeliveryMethod == SubtitleDeliveryMethod.External) .ToList(); diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index d619e31409..b093d82e33 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -14,6 +14,7 @@ namespace MediaBrowser.Model.Configuration public int H264Crf { get; set; } public string H264Preset { get; set; } public bool EnableHardwareEncoding { get; set; } + public bool EnableSubtitleExtraction { get; set; } public string[] HardwareDecodingCodecs { get; set; } @@ -26,7 +27,7 @@ namespace MediaBrowser.Model.Configuration VaapiDevice = "/dev/dri/card0"; H264Crf = 23; EnableHardwareEncoding = true; - + EnableSubtitleExtraction = true; HardwareDecodingCodecs = new string[] { "h264", "vc1" }; } } diff --git a/MediaBrowser.Model/Dlna/ITranscoderSupport.cs b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs index fd615733d3..14723bd273 100644 --- a/MediaBrowser.Model/Dlna/ITranscoderSupport.cs +++ b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs @@ -4,6 +4,7 @@ { bool CanEncodeToAudioCodec(string codec); bool CanEncodeToSubtitleCodec(string codec); + bool CanExtractSubtitles(string codec); } public class FullTranscoderSupport : ITranscoderSupport @@ -16,5 +17,9 @@ { return true; } + public bool CanExtractSubtitles(string codec) + { + return true; + } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 1cb7836699..10c6a05c0f 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -686,7 +686,7 @@ namespace MediaBrowser.Model.Dlna if (subtitleStream != null) { - SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, null, null); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, _transcoderSupport, null, null); playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleFormat = subtitleProfile.Format; @@ -728,7 +728,7 @@ namespace MediaBrowser.Model.Dlna if (subtitleStream != null) { - SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, transcodingProfile.Protocol, transcodingProfile.Container); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Protocol, transcodingProfile.Container); playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleFormat = subtitleProfile.Format; @@ -1183,7 +1183,7 @@ namespace MediaBrowser.Model.Dlna { if (subtitleStream != null) { - SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, playMethod, null, null); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, playMethod, _transcoderSupport, null, null); if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed) { @@ -1202,7 +1202,7 @@ namespace MediaBrowser.Model.Dlna return new Tuple(result, TranscodeReason.ContainerBitrateExceedsLimit); } - public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, string transcodingSubProtocol, string transcodingContainer) + public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, string transcodingSubProtocol, string transcodingContainer) { if (!subtitleStream.IsExternal && (playMethod != PlayMethod.Transcode || !string.Equals(transcodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase))) { @@ -1256,7 +1256,9 @@ namespace MediaBrowser.Model.Dlna } // Look for an external or hls profile that matches the stream type (text/graphical) and doesn't require conversion - return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false) ?? GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, true) ?? new SubtitleProfile + return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, false) ?? + GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, true) ?? + new SubtitleProfile { Method = SubtitleDeliveryMethod.Encode, Format = subtitleStream.Codec @@ -1291,7 +1293,7 @@ namespace MediaBrowser.Model.Dlna return false; } - private static SubtitleProfile GetExternalSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, bool allowConversion) + private static SubtitleProfile GetExternalSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, bool allowConversion) { foreach (SubtitleProfile profile in subtitleProfiles) { @@ -1310,6 +1312,11 @@ namespace MediaBrowser.Model.Dlna continue; } + if (!subtitleStream.IsExternal && !transcoderSupport.CanExtractSubtitles(subtitleStream.Codec)) + { + continue; + } + if ((profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)) || (profile.Method == SubtitleDeliveryMethod.Hls && subtitleStream.IsTextSubtitleStream)) { diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index f863d8c954..c63e74eafa 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -309,14 +309,14 @@ namespace MediaBrowser.Model.Dlna return list; } - public List GetExternalSubtitles(bool includeSelectedTrackOnly, string baseUrl, string accessToken) + public List GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) { - return GetExternalSubtitles(includeSelectedTrackOnly, false, baseUrl, accessToken); + return GetExternalSubtitles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); } - public List GetExternalSubtitles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + public List GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) { - List list = GetSubtitleProfiles(includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken); + List list = GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken); List newList = new List(); // First add the selected track @@ -331,12 +331,12 @@ namespace MediaBrowser.Model.Dlna return newList; } - public List GetSubtitleProfiles(bool includeSelectedTrackOnly, string baseUrl, string accessToken) + public List GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) { - return GetSubtitleProfiles(includeSelectedTrackOnly, false, baseUrl, accessToken); + return GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); } - public List GetSubtitleProfiles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + public List GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) { List list = new List(); @@ -352,7 +352,7 @@ namespace MediaBrowser.Model.Dlna { if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) { - AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks); + AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); } } } @@ -363,7 +363,7 @@ namespace MediaBrowser.Model.Dlna { if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) { - AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks); + AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); } } } @@ -371,28 +371,28 @@ namespace MediaBrowser.Model.Dlna return list; } - private void AddSubtitleProfiles(List list, MediaStream stream, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks) + private void AddSubtitleProfiles(List list, MediaStream stream, ITranscoderSupport transcoderSupport, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks) { if (enableAllProfiles) { foreach (SubtitleProfile profile in DeviceProfile.SubtitleProfiles) { - SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }); + SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }, transcoderSupport); list.Add(info); } } else { - SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles); + SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles, transcoderSupport); list.Add(info); } } - private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles) + private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles, ITranscoderSupport transcoderSupport) { - SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, PlayMethod, SubProtocol, Container); + SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, PlayMethod, transcoderSupport, SubProtocol, Container); SubtitleStreamInfo info = new SubtitleStreamInfo { IsForced = stream.IsForced, diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 45a0529f9a..eb8a55b4c7 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.737 + 3.0.740 Emby.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index e5a0d454f0..5c16159c73 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.737 + 3.0.740 Emby.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + From afd94407f9bad2030344e93c1ce04008209a65af Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 15:45:52 -0400 Subject: [PATCH 17/18] rework active recordings --- Emby.Server.Implementations/Dto/DtoService.cs | 15 ++ .../LiveTv/EmbyTV/EmbyTV.cs | 108 ++++++++++++-- .../LiveTv/EmbyTV/RecordingHelper.cs | 4 + .../LiveTv/LiveTvManager.cs | 135 +++++++++++------- .../LiveTv/LiveTvMediaSourceProvider.cs | 22 ++- .../Entities/IHasMediaSources.cs | 2 +- MediaBrowser.Controller/Entities/Video.cs | 39 ++++- .../LiveTv/ILiveTvManager.cs | 4 + .../LiveTv/ILiveTvRecording.cs | 9 ++ MediaBrowser.Controller/LiveTv/TimerInfo.cs | 3 + 10 files changed, 273 insertions(+), 68 deletions(-) diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 2ea88b52a4..17e91bfa88 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -411,6 +411,21 @@ namespace Emby.Server.Implementations.Dto { liveTvManager.AddInfoToRecordingDto(item, dto, user); } + else + { + var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path); + if (activeRecording != null) + { + dto.Type = "Recording"; + dto.CanDownload = false; + if (!string.IsNullOrWhiteSpace(dto.SeriesName)) + { + dto.EpisodeTitle = dto.Name; + dto.Name = dto.SeriesName; + } + liveTvManager.AddInfoToRecordingDto(item, dto, activeRecording, user); + } + } return dto; } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index ecad5c0eb2..f3d40ae19e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -830,6 +830,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV existingTimer.IsKids = updatedTimer.IsKids; existingTimer.IsNews = updatedTimer.IsNews; existingTimer.IsMovie = updatedTimer.IsMovie; + existingTimer.IsSeries = updatedTimer.IsSeries; + existingTimer.IsLive = updatedTimer.IsLive; + existingTimer.IsPremiere = updatedTimer.IsPremiere; existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries; existingTimer.IsRepeat = updatedTimer.IsRepeat; existingTimer.IsSports = updatedTimer.IsSports; @@ -861,7 +864,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public async Task> GetRecordingsAsync(CancellationToken cancellationToken) { - return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList(); + return new List(); + //return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList(); } public string GetActiveRecordingPath(string id) @@ -875,6 +879,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return null; } + public IEnumerable GetAllActiveRecordings() + { + return _activeRecordings.Values; + } + + public ActiveRecordingInfo GetActiveRecordingInfo(string path) + { + if (string.IsNullOrWhiteSpace(path)) + { + return null; + } + + foreach (var recording in _activeRecordings.Values) + { + if (string.Equals(recording.Path, path, StringComparison.Ordinal)) + { + return recording; + } + } + return null; + } + private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info) { var timer = info.Timer; @@ -1245,6 +1271,33 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV throw new FileNotFoundException(); } + public async Task> GetRecordingStreamMediaSources(ActiveRecordingInfo info, CancellationToken cancellationToken) + { + var stream = new MediaSourceInfo + { + Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveRecordings/" + info.Id + "/stream", + Id = info.Id, + SupportsDirectPlay = false, + SupportsDirectStream = true, + SupportsTranscoding = true, + IsInfiniteStream = true, + RequiresOpening = false, + RequiresClosing = false, + Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http, + BufferMs = 0, + IgnoreDts = true, + IgnoreIndex = true + }; + + var isAudio = false; + await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false); + + return new List + { + stream + }; + } + public async Task CloseLiveStream(string id, CancellationToken cancellationToken) { // Ignore the consumer id @@ -1327,7 +1380,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var activeRecordingInfo = new ActiveRecordingInfo { CancellationTokenSource = new CancellationTokenSource(), - Timer = timer + Timer = timer, + Id = timer.Id }; if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo)) @@ -1493,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath); recordPath = EnsureFileUnique(recordPath, timer.Id); - _libraryManager.RegisterIgnoredPath(recordPath); _libraryMonitor.ReportFileSystemChangeBeginning(recordPath); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath)); activeRecordingInfo.Path = recordPath; @@ -1512,6 +1565,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _timerProvider.AddOrUpdate(timer, false); SaveRecordingMetadata(timer, recordPath, seriesPath); + TriggerRefresh(recordPath); EnforceKeepUpTo(timer, seriesPath); }; @@ -1543,7 +1597,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - _libraryManager.UnRegisterIgnoredPath(recordPath); + TriggerRefresh(recordPath); _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true); ActiveRecordingInfo removed; @@ -1574,6 +1628,44 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV OnRecordingStatusChanged(); } + private void TriggerRefresh(string path) + { + var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path)); + + if (item != null) + { + item.ChangedExternally(); + } + } + + private BaseItem GetAffectedBaseItem(string path) + { + BaseItem item = null; + + while (item == null && !string.IsNullOrEmpty(path)) + { + item = _libraryManager.FindByPath(path, null); + + path = _fileSystem.GetDirectoryName(path); + } + + if (item != null) + { + // If the item has been deleted find the first valid parent that still exists + while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path)) + { + item = item.GetParent(); + + if (item == null) + { + break; + } + } + } + + return item; + } + private void OnRecordingStatusChanged() { EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs @@ -2621,14 +2713,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return list; } - class ActiveRecordingInfo - { - public string Path { get; set; } - public TimerInfo Timer { get; set; } - public ProgramInfo Program { get; set; } - public CancellationTokenSource CancellationTokenSource { get; set; } - } - private const int TunerDiscoveryDurationMs = 3000; public async Task> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 94be4a02ef..b5de6ef01e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -58,6 +58,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV timerInfo.OriginalAirDate = programInfo.OriginalAirDate; timerInfo.IsProgramSeries = programInfo.IsSeries; + timerInfo.IsSeries = programInfo.IsSeries; + timerInfo.IsLive = programInfo.IsLive; + timerInfo.IsPremiere = programInfo.IsPremiere; + timerInfo.HomePageUrl = programInfo.HomePageUrl; timerInfo.CommunityRating = programInfo.CommunityRating; timerInfo.Overview = programInfo.Overview; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 2882af007f..bf30546aba 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.LiveTv private readonly LiveTvDtoService _tvDtoService; - private readonly List _services = new List(); + private ILiveTvService[] _services = new ILiveTvService[] { }; private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1); @@ -124,7 +124,7 @@ namespace Emby.Server.Implementations.LiveTv /// The listing providers. public void AddParts(IEnumerable services, IEnumerable tunerHosts, IEnumerable listingProviders) { - _services.AddRange(services); + _services = services.ToArray(); _tunerHosts.AddRange(tunerHosts); _listingProviders.AddRange(listingProviders); @@ -1221,9 +1221,9 @@ namespace Emby.Server.Implementations.LiveTv await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false); var numComplete = 0; - double progressPerService = _services.Count == 0 + double progressPerService = _services.Length == 0 ? 0 - : 1 / _services.Count; + : 1 / _services.Length; var newChannelIdList = new List(); var newProgramIdList = new List(); @@ -1255,7 +1255,7 @@ namespace Emby.Server.Implementations.LiveTv numComplete++; double percent = numComplete; - percent /= _services.Count; + percent /= _services.Length; progress.Report(100 * percent); } @@ -1561,11 +1561,6 @@ namespace Emby.Server.Implementations.LiveTv return new QueryResult(); } - if ((query.IsInProgress ?? false)) - { - return new QueryResult(); - } - var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders() .SelectMany(i => i.Locations) .Distinct(StringComparer.OrdinalIgnoreCase) @@ -1577,13 +1572,10 @@ namespace Emby.Server.Implementations.LiveTv var excludeItemTypes = new List(); - if (!query.IsInProgress.HasValue) - { - folderIds.Add(internalLiveTvFolderId); + folderIds.Add(internalLiveTvFolderId); - excludeItemTypes.Add(typeof(LiveTvChannel).Name); - excludeItemTypes.Add(typeof(LiveTvProgram).Name); - } + excludeItemTypes.Add(typeof(LiveTvChannel).Name); + excludeItemTypes.Add(typeof(LiveTvProgram).Name); if (folderIds.Count == 0) { @@ -1632,6 +1624,19 @@ namespace Emby.Server.Implementations.LiveTv } } + if ((query.IsInProgress ?? false)) + { + // TODO: filter + var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray(); + var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray(); + + return new QueryResult + { + Items = items, + TotalRecordCount = items.Length + }; + } + return _libraryManager.GetItemsResult(new InternalItemsQuery(user) { MediaTypes = new[] { MediaType.Video }, @@ -1659,11 +1664,6 @@ namespace Emby.Server.Implementations.LiveTv return new QueryResult(); } - if (_services.Count > 1) - { - return new QueryResult(); - } - if (user == null || (query.IsInProgress ?? false)) { return new QueryResult(); @@ -1722,13 +1722,9 @@ namespace Emby.Server.Implementations.LiveTv var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - if (_services.Count == 1 && (!query.IsInProgress.HasValue || !query.IsInProgress.Value) && (!query.IsLibraryItem.HasValue || query.IsLibraryItem.Value)) + // TODO: Figure out how to merge emby recordings + service recordings + if (_services.Length == 1) { - if (!query.IsInProgress.HasValue) - { - await RefreshRecordings(folder.Id, cancellationToken).ConfigureAwait(false); - } - return GetEmbyRecordings(query, options, folder.Id, user); } @@ -1920,6 +1916,11 @@ namespace Emby.Server.Implementations.LiveTv await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false); } + public ActiveRecordingInfo GetActiveRecordingInfo(string path) + { + return EmbyTV.EmbyTV.Current.GetActiveRecordingInfo(path); + } + public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null) { var recording = (ILiveTvRecording)item; @@ -1949,20 +1950,6 @@ namespace Emby.Server.Implementations.LiveTv dto.IsKids = info.IsKids; dto.IsPremiere = info.IsPremiere; - dto.CanDelete = user == null - ? recording.CanDelete() - : recording.CanDelete(user); - - if (dto.MediaSources == null) - { - dto.MediaSources = recording.GetMediaSources(true); - } - - if (dto.MediaStreams == null) - { - dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToArray(); - } - if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue) { var now = DateTime.UtcNow.Ticks; @@ -1986,6 +1973,65 @@ namespace Emby.Server.Implementations.LiveTv } } + public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null) + { + var service = EmbyTV.EmbyTV.Current; + + var info = activeRecordingInfo.Timer; + + var channel = string.IsNullOrWhiteSpace(info.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, info.ChannelId)); + + dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) + ? null + : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"); + + dto.TimerId = string.IsNullOrEmpty(info.Id) + ? null + : _tvDtoService.GetInternalTimerId(service.Name, info.Id).ToString("N"); + + var startDate = info.StartDate; + var endDate = info.EndDate; + + dto.StartDate = startDate; + dto.EndDate = endDate; + dto.Status = info.Status.ToString(); + dto.IsRepeat = info.IsRepeat; + dto.EpisodeTitle = info.EpisodeTitle; + dto.IsMovie = info.IsMovie; + dto.IsSeries = info.IsSeries; + dto.IsSports = info.IsSports; + dto.IsLive = info.IsLive; + dto.IsNews = info.IsNews; + dto.IsKids = info.IsKids; + dto.IsPremiere = info.IsPremiere; + + if (info.Status == RecordingStatus.InProgress) + { + startDate = info.StartDate.AddSeconds(0 - info.PrePaddingSeconds); + endDate = info.EndDate.AddSeconds(info.PostPaddingSeconds); + + var now = DateTime.UtcNow.Ticks; + var start = startDate.Ticks; + var end = endDate.Ticks; + + var pct = now - start; + + pct /= end; + pct *= 100; + dto.CompletionPercentage = pct; + } + + if (channel != null) + { + dto.ChannelName = channel.Name; + + if (channel.HasImage(ImageType.Primary)) + { + dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel); + } + } + } + public async Task> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken) { var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); @@ -2098,7 +2144,6 @@ namespace Emby.Server.Implementations.LiveTv if (service is EmbyTV.EmbyTV) { - // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None); } @@ -2348,7 +2393,6 @@ namespace Emby.Server.Implementations.LiveTv var currentChannelsDict = new Dictionary(); var addCurrentProgram = options.AddCurrentProgram; - var addMediaSources = options.Fields.Contains(ItemFields.MediaSources); var addServiceName = options.Fields.Contains(ItemFields.ServiceName); foreach (var tuple in tuples) @@ -2367,11 +2411,6 @@ namespace Emby.Server.Implementations.LiveTv currentChannelsDict[dto.Id] = dto; - if (addMediaSources) - { - dto.MediaSources = channel.GetMediaSources(true); - } - if (addCurrentProgram) { var channelIdString = channel.Id.ToString("N"); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 5436a12b8d..0e52f874d4 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -43,9 +43,11 @@ namespace Emby.Server.Implementations.LiveTv if (baseItem.SourceType == SourceType.LiveTV) { - if (string.IsNullOrWhiteSpace(baseItem.Path)) + var activeRecordingInfo = _liveTvManager.GetActiveRecordingInfo(item.Path); + + if (string.IsNullOrWhiteSpace(baseItem.Path) || activeRecordingInfo != null) { - return GetMediaSourcesInternal(item, cancellationToken); + return GetMediaSourcesInternal(item, activeRecordingInfo, cancellationToken); } } @@ -56,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv private const char StreamIdDelimeter = '_'; private const string StreamIdDelimeterString = "_"; - private async Task> GetMediaSourcesInternal(IHasMediaSources item, CancellationToken cancellationToken) + private async Task> GetMediaSourcesInternal(IHasMediaSources item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken) { IEnumerable sources; @@ -67,12 +69,20 @@ namespace Emby.Server.Implementations.LiveTv if (item is ILiveTvRecording) { sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken) - .ConfigureAwait(false); + .ConfigureAwait(false); } else { - sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken) - .ConfigureAwait(false); + if (activeRecordingInfo != null) + { + sources = await EmbyTV.EmbyTV.Current.GetRecordingStreamMediaSources(activeRecordingInfo, cancellationToken) + .ConfigureAwait(false); + } + else + { + sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken) + .ConfigureAwait(false); + } } } catch (NotImplementedException) diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs index bf4acdfbd6..54786134f3 100644 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -4,7 +4,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities { - public interface IHasMediaSources : IHasUserData + public interface IHasMediaSources : IHasMetadata { /// /// Gets the media sources. diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index fa11787f51..3918ac8fc1 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -160,7 +160,7 @@ namespace MediaBrowser.Controller.Entities public string[] GetPlayableStreamFileNames() { - return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToArray(); + return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToArray(); } /// @@ -234,6 +234,35 @@ namespace MediaBrowser.Controller.Entities return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video))); } + [IgnoreDataMember] + public override SourceType SourceType + { + get + { + if (IsActiveRecording()) + { + return SourceType.LiveTV; + } + + return base.SourceType; + } + } + + protected bool IsActiveRecording() + { + return LiveTvManager.GetActiveRecordingInfo(Path) != null; + } + + public override bool CanDelete() + { + if (IsActiveRecording()) + { + return false; + } + + return base.CanDelete(); + } + [IgnoreDataMember] protected virtual bool EnableDefaultVideoUserDataKeys { @@ -616,6 +645,14 @@ namespace MediaBrowser.Controller.Entities var list = GetAllVideosForMediaSources(); var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList(); + if (IsActiveRecording()) + { + foreach (var mediaSource in result) + { + mediaSource.Type = MediaSourceType.Placeholder; + } + } + return result.OrderBy(i => { if (i.VideoType == VideoType.VideoFile) diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 862894f613..6ff630590a 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -384,5 +384,9 @@ namespace MediaBrowser.Controller.LiveTv string GetEmbyTvActiveRecordingPath(string id); Task GetEmbyTvLiveStream(string id); + + ActiveRecordingInfo GetActiveRecordingInfo(string path); + + void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null); } } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs index 43fc307f48..4b757f0b9b 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs @@ -36,4 +36,13 @@ namespace MediaBrowser.Controller.LiveTv DateTime? EndDate { get; set; } DateTime DateCreated { get; set; } } + + public class ActiveRecordingInfo + { + public string Id { get; set; } + public string Path { get; set; } + public TimerInfo Timer { get; set; } + public ProgramInfo Program { get; set; } + public CancellationTokenSource CancellationTokenSource { get; set; } + } } diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs index 0b94c85fae..a0002241db 100644 --- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs +++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs @@ -109,6 +109,9 @@ namespace MediaBrowser.Controller.LiveTv public bool IsKids { get; set; } public bool IsSports { get; set; } public bool IsNews { get; set; } + public bool IsSeries { get; set; } + public bool IsLive { get; set; } + public bool IsPremiere { get; set; } public int? ProductionYear { get; set; } public string EpisodeTitle { get; set; } public DateTime? OriginalAirDate { get; set; } From 5e0f8fd8c486ac37e487786c10c2d3f9e1293ce8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 23 Aug 2017 16:12:27 -0400 Subject: [PATCH 18/18] add encoding option to dictate whether or not subtitles can be extracted on the fly --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index fba02a2b01..8a24a887f3 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.28.3")] +[assembly: AssemblyVersion("3.2.28.4")]