From 47d7eaeedbb1675981a6c2f780e13fd44133cba3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Nov 2017 15:08:20 -0500 Subject: fixes #1225 - Emby creates bogus seasons from subfolderss --- .../Library/Resolvers/TV/SeasonResolver.cs | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index a0ff29482..3bad69b56 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Globalization; using Emby.Naming.Common; using Emby.Naming.TV; +using MediaBrowser.Model.Logging; namespace Emby.Server.Implementations.Library.Resolvers.TV { @@ -21,16 +22,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV private readonly ILibraryManager _libraryManager; private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private readonly ILocalizationManager _localization; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// /// The config. - public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization) + public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, ILogger logger) { _config = config; _libraryManager = libraryManager; _localization = localization; + _logger = logger; } /// @@ -45,20 +48,40 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); var series = ((Series)args.Parent); + var path = args.Path; + var season = new Season { - IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber, + IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(path, true, true).SeasonNumber, SeriesId = series.Id, SeriesName = series.Name }; if (season.IndexNumber.HasValue) { + var resolver = new Emby.Naming.TV.EpisodeResolver(namingOptions); + + var episodeInfo = resolver.Resolve(path, true); + + if (episodeInfo != null) + { + if (episodeInfo.EpisodeNumber.HasValue && episodeInfo.SeasonNumber.HasValue) + { + _logger.Info("Found folder underneath series with episode number: {0}. Season {1}. Episode {2}", + path, + episodeInfo.SeasonNumber.Value, + episodeInfo.EpisodeNumber.Value); + + return null; + } + } + var seasonNumber = season.IndexNumber.Value; season.Name = seasonNumber == 0 ? args.LibraryOptions.SeasonZeroDisplayName : string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage); + } return season; -- cgit v1.2.3 From 77695f8abed3156de04c6bb2496c14a2ab3d90a8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 21 Nov 2017 17:14:56 -0500 Subject: 3.2.40.1 --- Emby.Dlna/PlayTo/PlayToController.cs | 6 +++ Emby.Drawing.Skia/Emby.Drawing.Skia.csproj | 3 -- Emby.Drawing.Skia/PlayedIndicatorDrawer.cs | 48 +++++----------------- Emby.Drawing.Skia/UnplayedCountIndicator.cs | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 9 +++- .../Browser/BrowserLauncher.cs | 2 +- .../EntryPoints/StartupWizard.cs | 25 +++++------ Emby.Server.Implementations/Library/UserManager.cs | 9 ++-- .../LiveTv/TunerHosts/M3UTunerHost.cs | 5 ++- .../LiveTv/TunerHosts/SharedHttpStream.cs | 22 +++++++--- .../Session/HttpSessionController.cs | 4 ++ .../Session/SessionManager.cs | 2 +- MediaBrowser.Api/UserService.cs | 2 +- MediaBrowser.Controller/Library/IUserManager.cs | 2 +- MediaBrowser.Model/Session/PlayRequest.cs | 1 + SharedVersion.cs | 2 +- 16 files changed, 72 insertions(+), 72 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index bd0a9e1f4..9b2c70394 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -321,6 +321,12 @@ namespace Emby.Dlna.PlayTo AddItemFromId(Guid.Parse(id), items); } + var startIndex = command.StartIndex ?? 0; + if (startIndex > 0) + { + items = items.Skip(startIndex).ToList(); + } + var playlist = new List(); var isFirst = true; diff --git a/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj index f2b32d52c..2b61561cb 100644 --- a/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj +++ b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj @@ -59,9 +59,6 @@ - - - ..\packages\SkiaSharp.1.58.1\lib\portable-net45+win8+wpa81+wp8\SkiaSharp.dll diff --git a/Emby.Drawing.Skia/PlayedIndicatorDrawer.cs b/Emby.Drawing.Skia/PlayedIndicatorDrawer.cs index 48f2da62b..2417043d6 100644 --- a/Emby.Drawing.Skia/PlayedIndicatorDrawer.cs +++ b/Emby.Drawing.Skia/PlayedIndicatorDrawer.cs @@ -15,7 +15,6 @@ namespace Emby.Drawing.Skia { public class PlayedIndicatorDrawer { - private const int FontSize = 42; private const int OffsetFromTopRightCorner = 38; private readonly IApplicationPaths _appPaths; @@ -44,48 +43,23 @@ namespace Emby.Drawing.Skia { paint.Color = new SKColor(255, 255, 255, 255); paint.Style = SKPaintStyle.Fill; - paint.Typeface = SKTypeface.FromFile(await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf", - _appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false)); - paint.TextSize = FontSize; - paint.IsAntialias = true; - - canvas.DrawText("a", (float)x-20, OffsetFromTopRightCorner + 12, paint); - } - } - - internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem) - { - var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); - - if (fileSystem.FileExists(filePath)) - { - return filePath; - } - var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name; - var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf"); - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath)); + paint.TextSize = 30; + paint.IsAntialias = true; - using (var stream = typeof(PlayedIndicatorDrawer).GetTypeInfo().Assembly.GetManifestResourceStream(namespacePath)) - { - using (var fileStream = fileSystem.GetFileStream(tempPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) - { - stream.CopyTo(fileStream); - } - } + var text = "✔️"; + var emojiChar = StringUtilities.GetUnicodeCharacterCode(text, SKTextEncoding.Utf32); + // or: + //var emojiChar = 0x1F680; - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath)); + // ask the font manager for a font with that character + var fontManager = SKFontManager.Default; + var emojiTypeface = fontManager.MatchCharacter(emojiChar); - try - { - fileSystem.CopyFile(tempPath, filePath, false); - } - catch (IOException) - { + paint.Typeface = emojiTypeface; + canvas.DrawText(text, (float)x-20, OffsetFromTopRightCorner + 12, paint); } - - return tempPath; } internal static async Task DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem) diff --git a/Emby.Drawing.Skia/UnplayedCountIndicator.cs b/Emby.Drawing.Skia/UnplayedCountIndicator.cs index 56a2519a3..b59bc1026 100644 --- a/Emby.Drawing.Skia/UnplayedCountIndicator.cs +++ b/Emby.Drawing.Skia/UnplayedCountIndicator.cs @@ -40,7 +40,7 @@ namespace Emby.Drawing.Skia { paint.Color = new SKColor(255, 255, 255, 255); paint.Style = SKPaintStyle.Fill; - paint.Typeface = SKTypeface.FromFile(PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem)); + paint.TextSize = 24; paint.IsAntialias = true; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 745d83eb5..531e13123 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -2317,12 +2317,17 @@ namespace Emby.Server.Implementations } } - public void LaunchUrl(string url) + public virtual void LaunchUrl(string url) { if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows && EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX) { - throw new NotImplementedException(); + throw new NotSupportedException(); + } + + if (!Environment.UserInteractive) + { + throw new NotSupportedException(); } var process = ProcessFactory.Create(new ProcessOptions diff --git a/Emby.Server.Implementations/Browser/BrowserLauncher.cs b/Emby.Server.Implementations/Browser/BrowserLauncher.cs index 05cde91e2..71497f6bf 100644 --- a/Emby.Server.Implementations/Browser/BrowserLauncher.cs +++ b/Emby.Server.Implementations/Browser/BrowserLauncher.cs @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Browser { appHost.LaunchUrl(url); } - catch (NotImplementedException) + catch (NotSupportedException) { } diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 614c04fd2..8d1355795 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -3,6 +3,7 @@ using Emby.Server.Implementations.Browser; using MediaBrowser.Controller; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; +using MediaBrowser.Controller.Configuration; namespace Emby.Server.Implementations.EntryPoints { @@ -20,15 +21,13 @@ namespace Emby.Server.Implementations.EntryPoints /// private readonly ILogger _logger; - /// - /// Initializes a new instance of the class. - /// - /// The app host. - /// The logger. - public StartupWizard(IServerApplicationHost appHost, ILogger logger) + private IServerConfigurationManager _config; + + public StartupWizard(IServerApplicationHost appHost, ILogger logger, IServerConfigurationManager config) { _appHost = appHost; _logger = logger; + _config = config; } /// @@ -38,16 +37,12 @@ namespace Emby.Server.Implementations.EntryPoints { if (_appHost.IsFirstRun) { - LaunchStartupWizard(); + BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost); + } + else if (_config.Configuration.IsStartupWizardCompleted) + { + BrowserLauncher.OpenDashboardPage("index.html", _appHost); } - } - - /// - /// Launches the startup wizard. - /// - private void LaunchStartupWizard() - { - BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost); } /// diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 0f48ff46b..c4e75add8 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -218,7 +218,7 @@ namespace Emby.Server.Implementations.Library return builder.ToString(); } - public async Task AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint) + public async Task AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint, bool isUserSession) { if (string.IsNullOrWhiteSpace(username)) { @@ -288,8 +288,11 @@ namespace Emby.Server.Implementations.Library // Update LastActivityDate and LastLoginDate, then save if (success) { - user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow; - UpdateUser(user); + if (isUserSession) + { + user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow; + UpdateUser(user); + } UpdateInvalidLoginAttemptCount(user, 0); } else diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index c96d1f359..e6c9b184e 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -152,6 +152,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts isRemote = !_networkManager.IsInLocalNetwork(uri.Host); } + var supportsDirectPlay = !info.EnableStreamLooping && info.TunerCount == 0; + var mediaSource = new MediaSourceInfo { Path = path, @@ -183,7 +185,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts IsInfiniteStream = true, IsRemote = isRemote, - IgnoreDts = true + IgnoreDts = true, + SupportsDirectPlay = supportsDirectPlay }; mediaSource.InferTotalBitrate(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index cc2cb3e5e..b8c7c7b18 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -88,6 +88,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts SetTempFilePath(extension); var taskCompletionSource = new TaskCompletionSource(); + + var now = DateTime.UtcNow; + StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); //OpenedMediaSource.Protocol = MediaProtocol.File; @@ -97,11 +100,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; OpenedMediaSource.Protocol = MediaProtocol.Http; - if (OpenedMediaSource.SupportsProbing) - { - await Task.Delay(3000).ConfigureAwait(false); - } - //OpenedMediaSource.Path = TempFilePath; //OpenedMediaSource.Protocol = MediaProtocol.File; @@ -111,6 +109,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts //OpenedMediaSource.SupportsDirectStream = true; //OpenedMediaSource.SupportsTranscoding = true; await taskCompletionSource.Task.ConfigureAwait(false); + + if (OpenedMediaSource.SupportsProbing) + { + var elapsed = (DateTime.UtcNow - now).TotalMilliseconds; + + var delay = Convert.ToInt32(3000 - elapsed); + + if (delay > 0) + { + Logger.Info("Delaying shared stream by {0}ms to allow the buffer to build.", delay); + + await Task.Delay(delay).ConfigureAwait(false); + } + } } protected override void CloseInternal() diff --git a/Emby.Server.Implementations/Session/HttpSessionController.cs b/Emby.Server.Implementations/Session/HttpSessionController.cs index e1c1bbe2b..e85254420 100644 --- a/Emby.Server.Implementations/Session/HttpSessionController.cs +++ b/Emby.Server.Implementations/Session/HttpSessionController.cs @@ -117,6 +117,10 @@ namespace Emby.Server.Implementations.Session { dict["SubtitleStreamIndex"] = command.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture); } + if (command.StartIndex.HasValue) + { + dict["StartIndex"] = command.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + } if (!string.IsNullOrWhiteSpace(command.MediaSourceId)) { dict["MediaSourceId"] = command.MediaSourceId; diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 30f6e6521..411781b25 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1423,7 +1423,7 @@ namespace Emby.Server.Implementations.Session if (enforcePassword) { - var result = await _userManager.AuthenticateUser(request.Username, request.Password, request.PasswordSha1, request.PasswordMd5, request.RemoteEndPoint).ConfigureAwait(false); + var result = await _userManager.AuthenticateUser(request.Username, request.Password, request.PasswordSha1, request.PasswordMd5, request.RemoteEndPoint, true).ConfigureAwait(false); if (result == null) { diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index ddefb08df..66d6a024e 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -473,7 +473,7 @@ namespace MediaBrowser.Api } else { - var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp).ConfigureAwait(false); + var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp, false).ConfigureAwait(false); if (success == null) { diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index d4232c77e..03e1d352e 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -143,7 +143,7 @@ namespace MediaBrowser.Controller.Library /// /// Authenticates the user. /// - Task AuthenticateUser(string username, string password, string passwordSha1, string passwordMd5, string remoteEndPoint); + Task AuthenticateUser(string username, string password, string passwordSha1, string passwordMd5, string remoteEndPoint, bool isUserSession); /// /// Starts the forgot password process. diff --git a/MediaBrowser.Model/Session/PlayRequest.cs b/MediaBrowser.Model/Session/PlayRequest.cs index d50cb5953..3477f2e57 100644 --- a/MediaBrowser.Model/Session/PlayRequest.cs +++ b/MediaBrowser.Model/Session/PlayRequest.cs @@ -37,5 +37,6 @@ namespace MediaBrowser.Model.Session public int? SubtitleStreamIndex { get; set; } public int? AudioStreamIndex { get; set; } public string MediaSourceId { get; set; } + public int? StartIndex { get; set; } } } \ No newline at end of file diff --git a/SharedVersion.cs b/SharedVersion.cs index 580bc7001..99dc764df 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.40.0")] +[assembly: AssemblyVersion("3.2.40.1")] -- cgit v1.2.3 From 4f09c1e06dab7cc8b260129648f5a54c77b8a4f9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 23 Nov 2017 10:46:16 -0500 Subject: reduce dlna chatter --- Emby.Dlna/Main/DlnaEntryPoint.cs | 3 +- Emby.Dlna/PlayTo/Device.cs | 16 +- Emby.Dlna/PlayTo/PlayToManager.cs | 194 +++++++++++---------- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 7 +- Emby.Server.Implementations/ApplicationHost.cs | 22 ++- .../EntryPoints/ExternalPortForwarding.cs | 3 +- .../Library/SearchEngine.cs | 3 +- Emby.Server.Implementations/Library/UserManager.cs | 2 +- .../LiveTv/LiveTvMediaSourceProvider.cs | 2 +- .../Networking/NetworkManager.cs | 10 +- .../Session/SessionManager.cs | 2 +- .../Social/SharingManager.cs | 5 +- Emby.Server.Implementations/Udp/UdpServer.cs | 28 +-- .../ScheduledTasksWebSocketListener.cs | 5 +- MediaBrowser.Api/SearchService.cs | 13 +- .../Session/SessionInfoWebSocketListener.cs | 5 +- .../System/ActivityLogWebSocketListener.cs | 3 +- .../System/SystemInfoWebSocketListener.cs | 5 +- MediaBrowser.Api/System/SystemService.cs | 5 +- MediaBrowser.Controller/IServerApplicationHost.cs | 7 +- .../Net/BasePeriodicWebSocketListener.cs | 8 +- MediaBrowser.Controller/Sync/ISyncManager.cs | 2 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- MediaBrowser.Model/Search/SearchHint.cs | 1 + MediaBrowser.WebDashboard/Api/PackageCreator.cs | 11 +- SharedVersion.cs | 2 +- 26 files changed, 215 insertions(+), 151 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 3dd36a27b..5eeab3dec 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -24,6 +24,7 @@ using MediaBrowser.Model.System; using MediaBrowser.Model.Threading; using Rssdp; using Rssdp.Infrastructure; +using System.Threading; namespace Emby.Dlna.Main { @@ -252,7 +253,7 @@ namespace Emby.Dlna.Main var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds; _Publisher.SupportPnpRootDevice = false; - var addresses = (await _appHost.GetLocalIpAddresses().ConfigureAwait(false)).ToList(); + var addresses = (await _appHost.GetLocalIpAddresses(CancellationToken.None).ConfigureAwait(false)).ToList(); var udn = CreateUuid(_appHost.SystemId); diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 165f123f1..a617117f3 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -831,7 +831,7 @@ namespace Emby.Dlna.PlayTo #region From XML - private async Task GetAVProtocolAsync() + private async Task GetAVProtocolAsync(CancellationToken cancellationToken) { if (_disposed) { @@ -845,12 +845,12 @@ namespace Emby.Dlna.PlayTo string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); var httpClient = new SsdpHttpClient(_httpClient, _config); - var document = await httpClient.GetDataAsync(url).ConfigureAwait(false); + var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false); AvCommands = TransportCommands.Create(document); } - private async Task GetRenderingProtocolAsync() + private async Task GetRenderingProtocolAsync(CancellationToken cancellationToken) { if (_disposed) { @@ -864,7 +864,7 @@ namespace Emby.Dlna.PlayTo string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); var httpClient = new SsdpHttpClient(_httpClient, _config); - var document = await httpClient.GetDataAsync(url).ConfigureAwait(false); + var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false); RendererCommands = TransportCommands.Create(document); } @@ -897,11 +897,11 @@ namespace Emby.Dlna.PlayTo set; } - public static async Task CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, ITimerFactory timerFactory) + public static async Task CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, ITimerFactory timerFactory, CancellationToken cancellationToken) { var ssdpHttpClient = new SsdpHttpClient(httpClient, config); - var document = await ssdpHttpClient.GetDataAsync(url.ToString()).ConfigureAwait(false); + var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false); var deviceProperties = new DeviceInfo(); @@ -987,8 +987,8 @@ namespace Emby.Dlna.PlayTo if (device.GetAvTransportService() != null) { - await device.GetRenderingProtocolAsync().ConfigureAwait(false); - await device.GetAVProtocolAsync().ConfigureAwait(false); + await device.GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false); + await device.GetAVProtocolAsync(cancellationToken).ConfigureAwait(false); } return device; diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index dd30dfc3d..f1b7181dd 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -18,6 +18,7 @@ using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Net; using MediaBrowser.Model.Threading; +using System.Threading; namespace Emby.Dlna.PlayTo { @@ -44,6 +45,8 @@ namespace Emby.Dlna.PlayTo private readonly List _nonRendererUrls = new List(); private DateTime _lastRendererClear; private bool _disposed; + private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1); + private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory) { @@ -98,92 +101,104 @@ namespace Emby.Dlna.PlayTo return; } + var cancellationToken = _disposeCancellationTokenSource.Token; + + await _sessionLock.WaitAsync(cancellationToken).ConfigureAwait(false); + try { - lock (_nonRendererUrls) + if (_disposed) { - if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10) - { - _nonRendererUrls.Clear(); - _lastRendererClear = DateTime.UtcNow; - } - - if (_nonRendererUrls.Contains(location, StringComparer.OrdinalIgnoreCase)) - { - return; - } + return; } - var uri = info.Location; - _logger.Debug("Attempting to create PlayToController from location {0}", location); - var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory).ConfigureAwait(false); + await AddDevice(info, location, cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + + } + catch (Exception ex) + { + _logger.ErrorException("Error creating PlayTo device.", ex); + + _nonRendererUrls.Add(location); + } + finally + { + _sessionLock.Release(); + } + } + + private async Task AddDevice(UpnpDeviceInfo info, string location, CancellationToken cancellationToken) + { + if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10) + { + _nonRendererUrls.Clear(); + _lastRendererClear = DateTime.UtcNow; + } + + if (_nonRendererUrls.Contains(location, StringComparer.OrdinalIgnoreCase)) + { + return; + } + + var uri = info.Location; + _logger.Debug("Attempting to create PlayToController from location {0}", location); + var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory, cancellationToken).ConfigureAwait(false); + + if (device.RendererCommands == null) + { + _nonRendererUrls.Add(location); + return; + } + + _logger.Debug("Logging session activity from location {0}", location); + var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null).ConfigureAwait(false); + + var controller = sessionInfo.SessionController as PlayToController; - if (device.RendererCommands == null) + if (controller == null) + { + string serverAddress; + if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Loopback)) { - lock (_nonRendererUrls) - { - _nonRendererUrls.Add(location); - return; - } + serverAddress = await GetServerAddress(null, cancellationToken).ConfigureAwait(false); } - - if (_disposed) + else { - return; + serverAddress = await GetServerAddress(info.LocalIpAddress, cancellationToken).ConfigureAwait(false); } - _logger.Debug("Logging session activity from location {0}", location); - var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null) - .ConfigureAwait(false); - - var controller = sessionInfo.SessionController as PlayToController; - - if (controller == null) + string accessToken = null; + + sessionInfo.SessionController = controller = new PlayToController(sessionInfo, + _sessionManager, + _libraryManager, + _logger, + _dlnaManager, + _userManager, + _imageProcessor, + serverAddress, + accessToken, + _deviceDiscovery, + _userDataManager, + _localization, + _mediaSourceManager, + _config, + _mediaEncoder); + + controller.Init(device); + + var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ?? + _dlnaManager.GetDefaultProfile(); + + _sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities { - if (_disposed) - { - return; - } + PlayableMediaTypes = profile.GetSupportedMediaTypes(), - string serverAddress; - if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Loopback)) + SupportedCommands = new string[] { - serverAddress = await GetServerAddress(null).ConfigureAwait(false); - } - else - { - serverAddress = await GetServerAddress(info.LocalIpAddress).ConfigureAwait(false); - } - - string accessToken = null; - - sessionInfo.SessionController = controller = new PlayToController(sessionInfo, - _sessionManager, - _libraryManager, - _logger, - _dlnaManager, - _userManager, - _imageProcessor, - serverAddress, - accessToken, - _deviceDiscovery, - _userDataManager, - _localization, - _mediaSourceManager, - _config, - _mediaEncoder); - - controller.Init(device); - - var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ?? - _dlnaManager.GetDefaultProfile(); - - _sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities - { - PlayableMediaTypes = profile.GetSupportedMediaTypes(), - - SupportedCommands = new string[] - { GeneralCommandType.VolumeDown.ToString(), GeneralCommandType.VolumeUp.ToString(), GeneralCommandType.Mute.ToString(), @@ -192,33 +207,23 @@ namespace Emby.Dlna.PlayTo GeneralCommandType.SetVolume.ToString(), GeneralCommandType.SetAudioStreamIndex.ToString(), GeneralCommandType.SetSubtitleStreamIndex.ToString() - }, + }, - SupportsMediaControl = true, + SupportsMediaControl = true, - // xbox one creates a new uuid everytime it restarts - SupportsPersistentIdentifier = (device.Properties.ModelName ?? string.Empty).IndexOf("xbox", StringComparison.OrdinalIgnoreCase) == -1 - }); + // xbox one creates a new uuid everytime it restarts + SupportsPersistentIdentifier = (device.Properties.ModelName ?? string.Empty).IndexOf("xbox", StringComparison.OrdinalIgnoreCase) == -1 + }); - _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error creating PlayTo device.", ex); - - lock (_nonRendererUrls) - { - _nonRendererUrls.Add(location); - } + _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName); } } - private Task GetServerAddress(IpAddressInfo address) + private Task GetServerAddress(IpAddressInfo address, CancellationToken cancellationToken) { if (address == null) { - return _appHost.GetLocalApiUrl(); + return _appHost.GetLocalApiUrl(cancellationToken); } return Task.FromResult(_appHost.GetLocalApiUrl(address)); @@ -226,6 +231,15 @@ namespace Emby.Dlna.PlayTo public void Dispose() { + try + { + _disposeCancellationTokenSource.Cancel(); + } + catch + { + + } + _disposed = true; _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered; GC.SuppressFinalize(this); diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index 78b688d92..d4b594367 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -7,6 +7,7 @@ using System.IO; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; +using System.Threading; namespace Emby.Dlna.PlayTo { @@ -89,7 +90,7 @@ namespace Emby.Dlna.PlayTo } } - public async Task GetDataAsync(string url) + public async Task GetDataAsync(string url, CancellationToken cancellationToken) { var options = new HttpRequestOptions { @@ -99,7 +100,9 @@ namespace Emby.Dlna.PlayTo BufferContent = false, // The periodic requests may keep some devices awake - LogRequestAsDebug = true + LogRequestAsDebug = true, + + CancellationToken = cancellationToken }; options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 531e13123..2e5c4be90 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1901,9 +1901,9 @@ namespace Emby.Server.Implementations /// Gets the system status. /// /// SystemInfo. - public async Task GetSystemInfo() + public async Task GetSystemInfo(CancellationToken cancellationToken) { - var localAddress = await GetLocalApiUrl().ConfigureAwait(false); + var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false); return new SystemInfo { @@ -1955,12 +1955,12 @@ namespace Emby.Server.Implementations get { return Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; } } - public async Task GetLocalApiUrl() + public async Task GetLocalApiUrl(CancellationToken cancellationToken) { try { // Return the first matched address, if found, or the first known local address - var address = (await GetLocalIpAddresses().ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback)); + var address = (await GetLocalIpAddresses(cancellationToken).ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback)); if (address != null) { @@ -1994,7 +1994,7 @@ namespace Emby.Server.Implementations HttpPort.ToString(CultureInfo.InvariantCulture)); } - public async Task> GetLocalIpAddresses() + public async Task> GetLocalIpAddresses(CancellationToken cancellationToken) { var addresses = ServerConfigurationManager .Configuration @@ -2011,7 +2011,7 @@ namespace Emby.Server.Implementations foreach (var address in addresses) { - var valid = await IsIpAddressValidAsync(address).ConfigureAwait(false); + var valid = await IsIpAddressValidAsync(address, cancellationToken).ConfigureAwait(false); if (valid) { list.Add(address); @@ -2043,7 +2043,7 @@ namespace Emby.Server.Implementations private readonly ConcurrentDictionary _validAddressResults = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private DateTime _lastAddressCacheClear; - private async Task IsIpAddressValidAsync(IpAddressInfo address) + private async Task IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken) { if (address.Equals(IpAddressInfo.Loopback) || address.Equals(IpAddressInfo.IPv6Loopback)) @@ -2075,7 +2075,9 @@ namespace Emby.Server.Implementations LogErrors = false, LogRequest = false, TimeoutMs = 30000, - BufferContent = false + BufferContent = false, + + CancellationToken = cancellationToken }, "POST").ConfigureAwait(false)) { @@ -2090,6 +2092,10 @@ namespace Emby.Server.Implementations } } } + catch (OperationCanceledException) + { + throw; + } catch { //Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false); diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 2cef46839..903bb0ff4 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -13,6 +13,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Threading; using Mono.Nat; using MediaBrowser.Model.Extensions; +using System.Threading; namespace Emby.Server.Implementations.EntryPoints { @@ -158,7 +159,7 @@ namespace Emby.Server.Implementations.EntryPoints try { - var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false); + var localAddressString = await _appHost.GetLocalApiUrl(CancellationToken.None).ConfigureAwait(false); Uri uri; if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri)) diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index df21c1409..8021399bd 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -191,7 +191,8 @@ namespace Emby.Server.Implementations.Library { ItemFields.AirTime, ItemFields.DateCreated, - ItemFields.ChannelInfo + ItemFields.ChannelInfo, + ItemFields.ParentId } } }; diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index c4e75add8..71c953b2c 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -815,7 +815,7 @@ namespace Emby.Server.Implementations.Library var text = new StringBuilder(); - var localAddress = _appHost.GetLocalApiUrl().Result ?? string.Empty; + var localAddress = _appHost.GetLocalApiUrl(CancellationToken.None).Result ?? string.Empty; text.AppendLine("Use your web browser to visit:"); text.AppendLine(string.Empty); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index ed8b3074b..29b7c41ef 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv } var list = sources.ToList(); - var serverUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false); + var serverUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false); foreach (var source in list) { diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index fbdb5c128..d938359e9 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -11,6 +11,7 @@ using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; +using System.Threading; namespace Emby.Server.Implementations.Networking { @@ -37,7 +38,7 @@ namespace Emby.Server.Implementations.Networking if (_localIpAddresses == null || forceRefresh) { - var addresses = GetLocalIpAddressesInternal().Select(ToIpAddressInfo).ToList(); + var addresses = GetLocalIpAddressesInternal().Result.Select(ToIpAddressInfo).ToList(); _localIpAddresses = addresses; _lastRefresh = DateTime.UtcNow; @@ -49,14 +50,14 @@ namespace Emby.Server.Implementations.Networking return _localIpAddresses; } - private IEnumerable GetLocalIpAddressesInternal() + private async Task> GetLocalIpAddressesInternal() { var list = GetIPsDefault() .ToList(); if (list.Count == 0) { - list.AddRange(GetLocalIpAddressesFallback().Result); + list.AddRange(await GetLocalIpAddressesFallback().ConfigureAwait(false)); } var listClone = list.ToList(); @@ -65,7 +66,8 @@ namespace Emby.Server.Implementations.Networking .OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1) .ThenBy(i => listClone.IndexOf(i)) .Where(FilterIpAddress) - .DistinctBy(i => i.ToString()); + .DistinctBy(i => i.ToString()) + .ToList(); } private bool FilterIpAddress(IPAddress address) diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 411781b25..f49251da5 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1182,7 +1182,7 @@ namespace Emby.Server.Implementations.Session { var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); - var info = await _appHost.GetSystemInfo().ConfigureAwait(false); + var info = await _appHost.GetSystemInfo(cancellationToken).ConfigureAwait(false); var tasks = sessions.Select(session => Task.Run(async () => { diff --git a/Emby.Server.Implementations/Social/SharingManager.cs b/Emby.Server.Implementations/Social/SharingManager.cs index 57cf93948..e94b9100a 100644 --- a/Emby.Server.Implementations/Social/SharingManager.cs +++ b/Emby.Server.Implementations/Social/SharingManager.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Social; using System; +using System.Threading; using System.Threading.Tasks; namespace Emby.Server.Implementations.Social @@ -42,7 +43,7 @@ namespace Emby.Server.Implementations.Social throw new ResourceNotFoundException(); } - var externalUrl = (await _appHost.GetSystemInfo().ConfigureAwait(false)).WanAddress; + var externalUrl = (await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false)).WanAddress; if (string.IsNullOrWhiteSpace(externalUrl)) { @@ -73,7 +74,7 @@ namespace Emby.Server.Implementations.Social { var info = _repository.GetShareInfo(id); - AddShareInfo(info, _appHost.GetSystemInfo().Result.WanAddress); + AddShareInfo(info, _appHost.GetSystemInfo(CancellationToken.None).Result.WanAddress); return info; } diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index 8dc1fae4b..28de80da1 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Udp private bool _isDisposed; - private readonly List>> _responders = new List>>(); + private readonly List>> _responders = new List>>(); private readonly IServerApplicationHost _appHost; private readonly IJsonSerializer _json; @@ -44,9 +44,9 @@ namespace Emby.Server.Implementations.Udp AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message); } - private void AddMessageResponder(string message, bool isSubstring, Func responder) + private void AddMessageResponder(string message, bool isSubstring, Func responder) { - _responders.Add(new Tuple>(message, isSubstring, responder)); + _responders.Add(new Tuple>(message, isSubstring, responder)); } /// @@ -67,9 +67,15 @@ namespace Emby.Server.Implementations.Udp if (responder != null) { + var cancellationToken = CancellationToken.None; + try { - await responder.Item2.Item3(responder.Item1, message.RemoteEndPoint, encoding).ConfigureAwait(false); + await responder.Item2.Item3(responder.Item1, message.RemoteEndPoint, encoding, cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + } catch (Exception ex) { @@ -78,7 +84,7 @@ namespace Emby.Server.Implementations.Udp } } - private Tuple>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding) + private Tuple>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding) { var text = encoding.GetString(buffer, 0, bytesReceived); var responder = _responders.FirstOrDefault(i => @@ -94,14 +100,14 @@ namespace Emby.Server.Implementations.Udp { return null; } - return new Tuple>>(text, responder); + return new Tuple>>(text, responder); } - private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding) + private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding, CancellationToken cancellationToken) { var parts = messageText.Split('|'); - var localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false); + var localUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(localUrl)) { @@ -112,7 +118,7 @@ namespace Emby.Server.Implementations.Udp Name = _appHost.FriendlyName }; - await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint).ConfigureAwait(false); + await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint, cancellationToken).ConfigureAwait(false); if (parts.Length > 1) { @@ -248,7 +254,7 @@ namespace Emby.Server.Implementations.Udp } } - public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint) + public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint, CancellationToken cancellationToken) { if (_isDisposed) { @@ -267,7 +273,7 @@ namespace Emby.Server.Implementations.Udp try { - await _udpClient.SendToAsync(bytes, 0, bytes.Length, remoteEndPoint, CancellationToken.None).ConfigureAwait(false); + await _udpClient.SendToAsync(bytes, 0, bytes.Length, remoteEndPoint, cancellationToken).ConfigureAwait(false); _logger.Info("Udp message sent to {0}", remoteEndPoint); } diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs index 69ce6a385..2d30625a9 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs @@ -3,9 +3,10 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Tasks; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; +using System.Threading; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Api.ScheduledTasks { @@ -63,7 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks /// /// The state. /// Task{IEnumerable{TaskInfo}}. - protected override Task> GetDataToSend(WebSocketListenerState state) + protected override Task> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken) { return Task.FromResult(TaskManager.ScheduledTasks .OrderBy(i => i.Name) diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index ad79ea57b..50033eee8 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -248,9 +248,20 @@ namespace MediaBrowser.Api if (song != null) { - result.Album = song.Album; result.AlbumArtist = song.AlbumArtists.FirstOrDefault(); result.Artists = song.Artists; + + album = song.AlbumEntity; + + if (album != null) + { + result.Album = album.Name; + result.AlbumId = album.Id.ToString("N"); + } + else + { + result.Album = song.Album; + } } if (!string.IsNullOrWhiteSpace(item.ChannelId)) diff --git a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs index e133a88a1..65c69fc7d 100644 --- a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs +++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs @@ -5,8 +5,9 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Session; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; +using System.Threading; using MediaBrowser.Model.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Api.Session { @@ -86,7 +87,7 @@ namespace MediaBrowser.Api.Session /// /// The state. /// Task{SystemInfo}. - protected override Task> GetDataToSend(WebSocketListenerState state) + protected override Task> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken) { return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto)); } diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs index 793f74571..f9cac7389 100644 --- a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs +++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Threading; +using System.Threading; namespace MediaBrowser.Api.System { @@ -43,7 +44,7 @@ namespace MediaBrowser.Api.System /// /// The state. /// Task{SystemInfo}. - protected override Task> GetDataToSend(WebSocketListenerState state) + protected override Task> GetDataToSend(WebSocketListenerState state, CancellationToken CancellationToken) { return Task.FromResult(new List()); } diff --git a/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs index 8d74cc66c..63847f2b5 100644 --- a/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs +++ b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs @@ -4,6 +4,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.System; using System.Threading.Tasks; using MediaBrowser.Model.Threading; +using System.Threading; namespace MediaBrowser.Api.System { @@ -40,9 +41,9 @@ namespace MediaBrowser.Api.System /// /// The state. /// Task{SystemInfo}. - protected override Task GetDataToSend(WebSocketListenerState state) + protected override Task GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken) { - return _appHost.GetSystemInfo(); + return _appHost.GetSystemInfo(cancellationToken); } } } diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index d850b2ce7..6de7dd98b 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -14,6 +14,7 @@ using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using MediaBrowser.Model.Services; +using System.Threading; namespace MediaBrowser.Api.System { @@ -164,14 +165,14 @@ namespace MediaBrowser.Api.System /// System.Object. public async Task Get(GetSystemInfo request) { - var result = await _appHost.GetSystemInfo().ConfigureAwait(false); + var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false); return ToOptimizedResult(result); } public async Task Get(GetPublicSystemInfo request) { - var result = await _appHost.GetSystemInfo().ConfigureAwait(false); + var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false); var publicInfo = new PublicSystemInfo { diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index e9f7d5932..380be068e 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Net; using System.Threading.Tasks; using MediaBrowser.Model.Net; +using System.Threading; namespace MediaBrowser.Controller { @@ -19,7 +20,7 @@ namespace MediaBrowser.Controller /// Gets the system info. /// /// SystemInfo. - Task GetSystemInfo(); + Task GetSystemInfo(CancellationToken cancellationToken); /// /// Gets a value indicating whether [supports automatic run at startup]. @@ -61,13 +62,13 @@ namespace MediaBrowser.Controller /// Gets the local ip address. /// /// The local ip address. - Task> GetLocalIpAddresses(); + Task> GetLocalIpAddresses(CancellationToken cancellationToken); /// /// Gets the local API URL. /// /// The local API URL. - Task GetLocalApiUrl(); + Task GetLocalApiUrl(CancellationToken cancellationToken); /// /// Gets the local API URL. diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index 6be94e7e6..17b82b3ca 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.Net /// /// The state. /// Task{`1}. - protected abstract Task GetDataToSend(TStateType state); + protected abstract Task GetDataToSend(TStateType state, CancellationToken cancellationToken); /// /// The logger @@ -209,7 +209,9 @@ namespace MediaBrowser.Controller.Net { var state = tuple.Item4; - var data = await GetDataToSend(state).ConfigureAwait(false); + var cancellationToken = tuple.Item2.Token; + + var data = await GetDataToSend(state, cancellationToken).ConfigureAwait(false); if (data != null) { @@ -218,7 +220,7 @@ namespace MediaBrowser.Controller.Net MessageType = Name, Data = data - }, tuple.Item2.Token).ConfigureAwait(false); + }, cancellationToken).ConfigureAwait(false); state.DateLastSendUtc = DateTime.UtcNow; } diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs index 0bf4b914f..5e9085a40 100644 --- a/MediaBrowser.Controller/Sync/ISyncManager.cs +++ b/MediaBrowser.Controller/Sync/ISyncManager.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Controller.Sync /// Gets the jobs. /// /// QueryResult<SyncJob>. - Task> GetJobs(SyncJobQuery query); + QueryResult GetJobs(SyncJobQuery query); /// /// Gets the job items. diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 37d266ac0..2da6f1c81 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1343,7 +1343,7 @@ namespace MediaBrowser.Model.Dlna if (itemBitrate > requestedMaxBitrate) { - _logger.Info("Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}", item.Bitrate.Value.ToString(CultureInfo.InvariantCulture), requestedMaxBitrate.ToString(CultureInfo.InvariantCulture)); + _logger.Info("Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}", itemBitrate.ToString(CultureInfo.InvariantCulture), requestedMaxBitrate.ToString(CultureInfo.InvariantCulture)); return false; } diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs index 5c5637481..f2617c909 100644 --- a/MediaBrowser.Model/Search/SearchHint.cs +++ b/MediaBrowser.Model/Search/SearchHint.cs @@ -107,6 +107,7 @@ namespace MediaBrowser.Model.Search /// /// The album. public string Album { get; set; } + public string AlbumId { get; set; } /// /// Gets or sets the album artist. diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index f55d95a2e..5fd94e0d7 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -200,7 +200,16 @@ namespace MediaBrowser.WebDashboard.Api sb.Append(""); sb.Append(""); sb.Append(""); - sb.Append(""); + + if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase)) + { + sb.Append(""); + } + else + { + sb.Append(""); + } + sb.Append(""); sb.Append(""); sb.Append(""); diff --git a/SharedVersion.cs b/SharedVersion.cs index 99dc764df..463ec3ae3 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.40.1")] +[assembly: AssemblyVersion("3.2.40.2")] -- cgit v1.2.3 From 58a7829ecd773dbc3c875d3f0d4438b847fd54b5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 25 Nov 2017 23:48:12 -0500 Subject: update library changed notifier --- .../EntryPoints/LibraryChangedNotifier.cs | 36 ++++++++++++++++++++-- Emby.Server.Implementations/IO/LibraryMonitor.cs | 7 +++-- .../IO/ManagedFileSystem.cs | 15 +++++++++ .../Library/LibraryManager.cs | 21 +++++++++---- .../LiveTv/EmbyTV/EmbyTV.cs | 19 ++++++++++++ .../LiveTv/LiveTvManager.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 4 +-- MediaBrowser.Controller/Library/ILibraryManager.cs | 9 ++---- .../Library/ItemChangeEventArgs.cs | 2 ++ MediaBrowser.Model/Entities/LibraryUpdateInfo.cs | 3 ++ SharedVersion.cs | 2 +- 12 files changed, 98 insertions(+), 24 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 299da0744..0e771cbec 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -260,7 +260,7 @@ namespace Emby.Server.Implementations.EntryPoints LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); } - var parent = e.Item.GetParent() as Folder; + var parent = e.Parent as Folder; if (parent != null) { _foldersRemovedFrom.Add(parent); @@ -363,10 +363,16 @@ namespace Emby.Server.Implementations.EntryPoints /// The folders removed from. /// The user id. /// LibraryUpdateInfo. - private LibraryUpdateInfo GetLibraryUpdateInfo(IEnumerable itemsAdded, IEnumerable itemsUpdated, IEnumerable itemsRemoved, IEnumerable foldersAddedTo, IEnumerable foldersRemovedFrom, Guid userId) + private LibraryUpdateInfo GetLibraryUpdateInfo(List itemsAdded, List itemsUpdated, List itemsRemoved, List foldersAddedTo, List foldersRemovedFrom, Guid userId) { var user = _userManager.GetUserById(userId); + var newAndRemoved = new List(); + newAndRemoved.AddRange(foldersAddedTo); + newAndRemoved.AddRange(foldersRemovedFrom); + + var allUserRootChildren = _libraryManager.GetUserRootFolder().GetChildren(user, true).OfType().ToList(); + return new LibraryUpdateInfo { ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(), @@ -377,7 +383,9 @@ namespace Emby.Server.Implementations.EntryPoints FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(), - FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray() + FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(), + + CollectionFolders = GetTopParentIds(newAndRemoved, user, allUserRootChildren).ToArray() }; } @@ -396,6 +404,28 @@ namespace Emby.Server.Implementations.EntryPoints return item.SourceType == SourceType.Library; } + private IEnumerable GetTopParentIds(List items, User user, List allUserRootChildren) + { + var list = new List(); + + foreach (var item in items) + { + // If the physical root changed, return the user root + if (item is AggregateFolder) + { + continue; + } + + var collectionFolders = _libraryManager.GetCollectionFolders(item, allUserRootChildren); + foreach (var folder in allUserRootChildren) + { + list.Add(folder.Id.ToString("N")); + } + } + + return list.Distinct(StringComparer.Ordinal); + } + /// /// Translates the physical item to user library. /// diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index c99b601c9..a2abb2a5c 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.IO /// The instance containing the event data. void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) { - if (e.Item.GetParent() is AggregateFolder) + if (e.Parent is AggregateFolder) { StopWatchingPath(e.Item.Path); } @@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.IO /// The instance containing the event data. void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e) { - if (e.Item.GetParent() is AggregateFolder) + if (e.Parent is AggregateFolder) { StartWatching(e.Item); } @@ -320,7 +320,8 @@ namespace Emby.Server.Implementations.IO IncludeSubdirectories = true }; - if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) + if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows || + _environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX) { newWatcher.InternalBufferSize = 32767; } diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 125d9e980..c8e4031a9 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -473,6 +473,11 @@ namespace Emby.Server.Implementations.IO public void SetHidden(string path, bool isHidden) { + if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) + { + return; + } + if (_sharpCifsFileSystem.IsEnabledForPath(path)) { _sharpCifsFileSystem.SetHidden(path, isHidden); @@ -498,6 +503,11 @@ namespace Emby.Server.Implementations.IO public void SetReadOnly(string path, bool isReadOnly) { + if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) + { + return; + } + if (_sharpCifsFileSystem.IsEnabledForPath(path)) { _sharpCifsFileSystem.SetReadOnly(path, isReadOnly); @@ -523,6 +533,11 @@ namespace Emby.Server.Implementations.IO public void SetAttributes(string path, bool isHidden, bool isReadOnly) { + if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) + { + return; + } + if (_sharpCifsFileSystem.IsEnabledForPath(path)) { _sharpCifsFileSystem.SetAttributes(path, isHidden, isReadOnly); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index f71e2714a..2934a5147 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -443,7 +443,7 @@ namespace Emby.Server.Implementations.Library BaseItem removed; _libraryItemsCache.TryRemove(item.Id, out removed); - ReportItemRemoved(item); + ReportItemRemoved(item, parent); } private IEnumerable GetMetadataPaths(BaseItem item, IEnumerable children) @@ -1804,7 +1804,7 @@ namespace Emby.Server.Implementations.Library /// Task. public void CreateItem(BaseItem item, CancellationToken cancellationToken) { - CreateItems(new[] { item }, cancellationToken); + CreateItems(new[] { item }, item.GetParent(), cancellationToken); } /// @@ -1813,7 +1813,7 @@ namespace Emby.Server.Implementations.Library /// The items. /// The cancellation token. /// Task. - public void CreateItems(IEnumerable items, CancellationToken cancellationToken) + public void CreateItems(IEnumerable items, BaseItem parent, CancellationToken cancellationToken) { var list = items.ToList(); @@ -1830,7 +1830,11 @@ namespace Emby.Server.Implementations.Library { try { - ItemAdded(this, new ItemChangeEventArgs { Item = item }); + ItemAdded(this, new ItemChangeEventArgs + { + Item = item, + Parent = parent ?? item.GetParent() + }); } catch (Exception ex) { @@ -1878,6 +1882,7 @@ namespace Emby.Server.Implementations.Library ItemUpdated(this, new ItemChangeEventArgs { Item = item, + Parent = item.GetParent(), UpdateReason = updateReason }); } @@ -1892,13 +1897,17 @@ namespace Emby.Server.Implementations.Library /// Reports the item removed. /// /// The item. - public void ReportItemRemoved(BaseItem item) + public void ReportItemRemoved(BaseItem item, BaseItem parent) { if (ItemRemoved != null) { try { - ItemRemoved(this, new ItemChangeEventArgs { Item = item }); + ItemRemoved(this, new ItemChangeEventArgs + { + Item = item, + Parent = parent + }); } catch (Exception ex) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index a4c5645e7..35d2d3c0a 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1512,6 +1512,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } + DeleteFileIfEmpty(recordPath); + TriggerRefresh(recordPath); _libraryMonitor.ReportFileSystemChangeComplete(recordPath, false); @@ -1542,6 +1544,23 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } + private void DeleteFileIfEmpty(string path) + { + var file = _fileSystem.GetFileInfo(path); + + if (file.Exists && file.Length == 0) + { + try + { + _fileSystem.DeleteFile(path); + } + catch (Exception ex) + { + _logger.ErrorException("Error deleting 0-byte failed recording file {0}", ex, path); + } + } + } + private void TriggerRefresh(string path) { _logger.Info("Triggering refresh on {0}", path); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 7e72d1b1a..7e27877e7 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1421,7 +1421,7 @@ namespace Emby.Server.Implementations.LiveTv if (newPrograms.Count > 0) { - _libraryManager.CreateItems(newPrograms, cancellationToken); + _libraryManager.CreateItems(newPrograms, null, cancellationToken); } // TODO: Do this in bulk diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f6a8f1d5a..98899253e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2236,7 +2236,7 @@ namespace MediaBrowser.Controller.Entities } var filename = System.IO.Path.GetFileNameWithoutExtension(Path); - var extensions = new List { ".nfo", ".xml", ".srt" }; + var extensions = new List { ".nfo", ".xml", ".srt", ".vtt", ".sub", ".idx", ".txt", ".edl" }; extensions.AddRange(SupportedImageExtensions); return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(extensions.Count), false, false) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 504d03a27..08b6a123d 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -466,11 +466,11 @@ namespace MediaBrowser.Controller.Entities item.SetParent(null); await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false); - LibraryManager.ReportItemRemoved(item); + LibraryManager.ReportItemRemoved(item, this); } } - LibraryManager.CreateItems(newItems, cancellationToken); + LibraryManager.CreateItems(newItems, this, cancellationToken); } } else diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 37e0d5661..9ef372eb6 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -195,16 +195,12 @@ namespace MediaBrowser.Controller.Library /// /// Creates the item. /// - /// The item. - /// The cancellation token. void CreateItem(BaseItem item, CancellationToken cancellationToken); /// /// Creates the items. /// - /// The items. - /// The cancellation token. - void CreateItems(IEnumerable items, CancellationToken cancellationToken); + void CreateItems(IEnumerable items, BaseItem parent, CancellationToken cancellationToken); /// /// Updates the item. @@ -237,8 +233,7 @@ namespace MediaBrowser.Controller.Library /// /// Reports the item removed. /// - /// The item. - void ReportItemRemoved(BaseItem item); + void ReportItemRemoved(BaseItem item, BaseItem parent); /// /// Finds the type of the collection. diff --git a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs index a2951f548..e671490d3 100644 --- a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs +++ b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs @@ -13,6 +13,8 @@ namespace MediaBrowser.Controller.Library /// The item. public BaseItem Item { get; set; } + public BaseItem Parent { get; set; } + /// /// Gets or sets the item. /// diff --git a/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs b/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs index b3d3be70e..8995e0888 100644 --- a/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs +++ b/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs @@ -35,6 +35,8 @@ namespace MediaBrowser.Model.Entities /// The items updated. public string[] ItemsUpdated { get; set; } + public string[] CollectionFolders { get; set; } + /// /// Initializes a new instance of the class. /// @@ -45,6 +47,7 @@ namespace MediaBrowser.Model.Entities ItemsAdded = new string[] { }; ItemsRemoved = new string[] { }; ItemsUpdated = new string[] { }; + CollectionFolders = new string[] { }; } } } diff --git a/SharedVersion.cs b/SharedVersion.cs index 463ec3ae3..90e6929e2 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.40.2")] +[assembly: AssemblyVersion("3.2.40.3")] -- cgit v1.2.3 From d06532c6029592e8fe1c0564b9286f086f438a7b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 27 Nov 2017 14:09:51 -0500 Subject: update rules for samples --- .../Library/CoreResolutionIgnoreRule.cs | 11 ----------- .../Library/Resolvers/Movies/MovieResolver.cs | 20 -------------------- 2 files changed, 31 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index 961f9886c..5c3e1dab1 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -141,17 +141,6 @@ namespace Emby.Server.Implementations.Library return true; } } - - // Ignore samples - var sampleFilename = " " + filename.Replace(".", " ", StringComparison.OrdinalIgnoreCase) - .Replace("-", " ", StringComparison.OrdinalIgnoreCase) - .Replace("_", " ", StringComparison.OrdinalIgnoreCase) - .Replace("!", " ", StringComparison.OrdinalIgnoreCase); - - if (sampleFilename.IndexOf(" sample ", StringComparison.OrdinalIgnoreCase) != -1) - { - return true; - } } return false; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 667616414..d74235ec7 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -125,10 +125,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (child.IsDirectory) { leftOver.Add(child); - } - else if (IsIgnored(child.Name)) - { - } else { @@ -298,22 +294,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return item; } - private bool IsIgnored(string filename) - { - // Ignore samples - var sampleFilename = " " + filename.Replace(".", " ", StringComparison.OrdinalIgnoreCase) - .Replace("-", " ", StringComparison.OrdinalIgnoreCase) - .Replace("_", " ", StringComparison.OrdinalIgnoreCase) - .Replace("!", " ", StringComparison.OrdinalIgnoreCase); - - if (sampleFilename.IndexOf(" sample ", StringComparison.OrdinalIgnoreCase) != -1) - { - return true; - } - - return false; - } - /// /// Sets the initial item values. /// -- cgit v1.2.3