From 04b6f23473c4091ce7caf9fbe79d424ac002c0e0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 29 Mar 2017 02:26:48 -0400 Subject: 3.2.9.1 --- Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Emby.Server.Implementations/FileOrganization') diff --git a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index 2850c3a61..b035fdcfd 100644 --- a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -151,8 +151,7 @@ namespace Emby.Server.Implementations.FileOrganization /// The extensions. private void DeleteLeftOverFiles(string path, IEnumerable extensions) { - var eligibleFiles = _fileSystem.GetFiles(path, true) - .Where(i => extensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)) + var eligibleFiles = _fileSystem.GetFiles(path, extensions.ToArray(), false, true) .ToList(); foreach (var file in eligibleFiles) -- cgit v1.2.3 From f641c501a78d6270793ee9c9fa185517be6df008 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 29 Mar 2017 15:16:43 -0400 Subject: improve cancellation support of auto-organize --- .../Networking/NetworkManager.cs | 6 +----- .../FileOrganization/TvFolderOrganizer.cs | 7 +++++++ Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs | 5 +++++ Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 18 +++++++++--------- .../LiveTv/LiveTvMediaSourceProvider.cs | 6 +++--- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 10 ++++++++++ MediaBrowser.Model/Entities/MediaStream.cs | 7 +++++++ MediaBrowser.Model/Net/IpAddressInfo.cs | 10 +++++----- RSSDP/SsdpCommunicationsServer.cs | 5 +---- 10 files changed, 49 insertions(+), 27 deletions(-) (limited to 'Emby.Server.Implementations/FileOrganization') diff --git a/Emby.Common.Implementations/Networking/NetworkManager.cs b/Emby.Common.Implementations/Networking/NetworkManager.cs index 2b84b2aa1..2f218656c 100644 --- a/Emby.Common.Implementations/Networking/NetworkManager.cs +++ b/Emby.Common.Implementations/Networking/NetworkManager.cs @@ -500,11 +500,7 @@ namespace Emby.Common.Implementations.Networking { return IpAddressInfo.IPv6Loopback; } - return new IpAddressInfo - { - Address = address.ToString(), - AddressFamily = address.AddressFamily == AddressFamily.InterNetworkV6 ? IpAddressFamily.InterNetworkV6 : IpAddressFamily.InterNetwork - }; + return new IpAddressInfo(address.ToString(), address.AddressFamily == AddressFamily.InterNetworkV6 ? IpAddressFamily.InterNetworkV6 : IpAddressFamily.InterNetwork); } public async Task GetHostAddressesAsync(string host) diff --git a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index b035fdcfd..807f1694c 100644 --- a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -72,17 +72,24 @@ namespace Emby.Server.Implementations.FileOrganization foreach (var file in eligibleFiles) { + cancellationToken.ThrowIfCancellationRequested(); + var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); try { var result = await organizer.OrganizeEpisodeFile(file.FullName, options, options.TvOptions.OverwriteExistingEpisodes, cancellationToken).ConfigureAwait(false); + if (result.Status == FileSortingStatus.Success && !processedFolders.Contains(file.DirectoryName, StringComparer.OrdinalIgnoreCase)) { processedFolders.Add(file.DirectoryName); } } + catch (OperationCanceledException) + { + break; + } catch (Exception ex) { _logger.ErrorException("Error organizing episode {0}", ex, file.FullName); diff --git a/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs b/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs index 9a8a930bd..3906df000 100644 --- a/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; namespace Emby.Server.Implementations.LiveTv @@ -29,6 +30,8 @@ namespace Emby.Server.Implementations.LiveTv var now = DateTime.UtcNow; + var allowVideoStreamCopy = mediaSource.MediaStreams.Any(i => i.Type == MediaStreamType.Video && i.AllowStreamCopy); + var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest { InputPath = mediaSource.Path, @@ -73,6 +76,8 @@ namespace Emby.Server.Implementations.LiveTv var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Video); if (videoStream != null) { + videoStream.AllowStreamCopy = allowVideoStreamCopy; + if (!videoStream.BitRate.HasValue) { var width = videoStream.Width ?? 1920; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index b9e73b62e..1c43b4188 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -261,7 +261,7 @@ namespace Emby.Server.Implementations.LiveTv return info.Item1; } - public Task> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken) + public Task> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken) { return GetLiveStream(id, mediaSourceId, true, cancellationToken); } @@ -323,7 +323,7 @@ namespace Emby.Server.Implementations.LiveTv return _services.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)); } - private async Task> GetLiveStream(string id, string mediaSourceId, bool isChannel, CancellationToken cancellationToken) + private async Task> GetLiveStream(string id, string mediaSourceId, bool isChannel, CancellationToken cancellationToken) { if (string.Equals(id, mediaSourceId, StringComparison.OrdinalIgnoreCase)) { @@ -334,7 +334,6 @@ namespace Emby.Server.Implementations.LiveTv bool isVideo; ILiveTvService service; IDirectStreamProvider directStreamProvider = null; - var assumeInterlaced = false; if (isChannel) { @@ -383,12 +382,7 @@ namespace Emby.Server.Implementations.LiveTv Normalize(info, service, isVideo); - if (!(service is EmbyTV.EmbyTV)) - { - assumeInterlaced = true; - } - - return new Tuple(info, directStreamProvider, assumeInterlaced); + return new Tuple(info, directStreamProvider); } private void Normalize(MediaSourceInfo mediaSource, ILiveTvService service, bool isVideo) @@ -492,6 +486,12 @@ namespace Emby.Server.Implementations.LiveTv { stream.NalLengthSize = "0"; } + + if (stream.Type == MediaStreamType.Video) + { + stream.IsInterlaced = true; + stream.AllowStreamCopy = false; + } } } } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 747e0fdd3..a9c449f83 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.LiveTv openKeys.Add(item.Id.ToString("N")); openKeys.Add(source.Id ?? string.Empty); source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray()); - } + } // Dummy this up so that direct play checks can still run if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) @@ -142,7 +142,7 @@ namespace Emby.Server.Implementations.LiveTv { if (!stream.SupportsProbing || stream.MediaStreams.Any(i => i.Index != -1)) { - await AddMediaInfo(stream, isAudio, cancellationToken).ConfigureAwait(false); + AddMediaInfo(stream, isAudio, cancellationToken); } else { @@ -158,7 +158,7 @@ namespace Emby.Server.Implementations.LiveTv return new Tuple(stream, directStreamProvider); } - private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) + private void AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) { mediaSource.DefaultSubtitleStreamIndex = null; diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 5242c5b1f..c8fa6be8c 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Controller.LiveTv /// The media source identifier. /// The cancellation token. /// Task{StreamResponseInfo}. - Task> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken); + Task> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken); /// /// Gets the program. diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 530ff1343..dd31d39b1 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -743,6 +743,11 @@ namespace MediaBrowser.Controller.MediaEncoding public bool CanStreamCopyVideo(EncodingJobInfo state, MediaStream videoStream) { + if (!videoStream.AllowStreamCopy) + { + return false; + } + var request = state.BaseRequest; if (videoStream.IsInterlaced) @@ -883,6 +888,11 @@ namespace MediaBrowser.Controller.MediaEncoding public bool CanStreamCopyAudio(EncodingJobInfo state, MediaStream audioStream, List supportedAudioCodecs) { + if (!audioStream.AllowStreamCopy) + { + return false; + } + var request = state.BaseRequest; // Source and target codecs must match diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 3cd3e7dde..133b9e566 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -13,6 +13,11 @@ namespace MediaBrowser.Model.Entities [DebuggerDisplay("StreamType = {Type}")] public class MediaStream { + public MediaStream() + { + AllowStreamCopy = true; + } + /// /// Gets or sets the codec. /// @@ -153,6 +158,8 @@ namespace MediaBrowser.Model.Entities public bool? IsAVC { get; set; } + public bool AllowStreamCopy { get; set; } + /// /// Gets or sets the channel layout. /// diff --git a/MediaBrowser.Model/Net/IpAddressInfo.cs b/MediaBrowser.Model/Net/IpAddressInfo.cs index 00a16c03d..57a0039c4 100644 --- a/MediaBrowser.Model/Net/IpAddressInfo.cs +++ b/MediaBrowser.Model/Net/IpAddressInfo.cs @@ -12,13 +12,13 @@ namespace MediaBrowser.Model.Net public string Address { get; set; } public IpAddressFamily AddressFamily { get; set; } - public IpAddressInfo() - { - - } - public IpAddressInfo(string address, IpAddressFamily addressFamily) { + if (string.IsNullOrWhiteSpace(address)) + { + throw new ArgumentNullException("address"); + } + Address = address; AddressFamily = addressFamily; } diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index cc464e689..e9dc4c54f 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -247,10 +247,7 @@ namespace Rssdp.Infrastructure { await SendMessageIfSocketNotDisposed(messageData, new IpEndPointInfo { - IpAddress = new IpAddressInfo - { - Address = SsdpConstants.MulticastLocalAdminAddress - }, + IpAddress = new IpAddressInfo(SsdpConstants.MulticastLocalAdminAddress, IpAddressFamily.InterNetwork), Port = SsdpConstants.MulticastPort }, cancellationToken).ConfigureAwait(false); -- cgit v1.2.3 From 497e93aae86de2de615ca3656e7641be6a0f422a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 29 Mar 2017 15:23:22 -0400 Subject: update auto-organize error handling --- .../FileOrganization/TvFolderOrganizer.cs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/FileOrganization') diff --git a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index 807f1694c..c885f03ac 100644 --- a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -53,9 +53,29 @@ namespace Emby.Server.Implementations.FileOrganization return false; } + private bool IsValidWatchLocation(string path, List libraryFolderPaths) + { + if (IsPathAlreadyInMediaLibrary(path, libraryFolderPaths)) + { + _logger.Info("Folder {0} is not eligible for auto-organize because it is also part of an Emby library", path); + return false; + } + + return true; + } + + private bool IsPathAlreadyInMediaLibrary(string path, List libraryFolderPaths) + { + return libraryFolderPaths.Any(i => string.Equals(i, path, StringComparison.Ordinal) || _fileSystem.ContainsSubPath(i, path)); + } + public async Task Organize(AutoOrganizeOptions options, CancellationToken cancellationToken, IProgress progress) { - var watchLocations = options.TvOptions.WatchLocations.ToList(); + var libraryFolderPaths = _libraryManager.GetVirtualFolders().SelectMany(i => i.Locations).ToList(); + + var watchLocations = options.TvOptions.WatchLocations + .Where(i => IsValidWatchLocation(i, libraryFolderPaths)) + .ToList(); var eligibleFiles = watchLocations.SelectMany(GetFilesToOrganize) .OrderBy(_fileSystem.GetCreationTimeUtc) -- cgit v1.2.3 From 7987e64d3875ac0e175224d81d6815596b9dfba9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 30 Mar 2017 13:56:32 -0400 Subject: add new file method overloads --- BDInfo/BDROM.cs | 11 ++++++-- .../IO/ManagedFileSystem.cs | 32 ++++++++++++++++++++-- .../FileOrganization/TvFolderOrganizer.cs | 6 ++-- .../Library/LibraryManager.cs | 4 +-- MediaBrowser.Model/IO/IFileSystem.cs | 1 + 5 files changed, 44 insertions(+), 10 deletions(-) (limited to 'Emby.Server.Implementations/FileOrganization') diff --git a/BDInfo/BDROM.cs b/BDInfo/BDROM.cs index d42e381da..123d1afe5 100644 --- a/BDInfo/BDROM.cs +++ b/BDInfo/BDROM.cs @@ -137,19 +137,19 @@ namespace BDInfo } if (DirectoryBDJO != null && - _fileSystem.GetFiles(DirectoryBDJO.FullName).Any()) + _fileSystem.GetFilePaths(DirectoryBDJO.FullName).Any()) { IsBDJava = true; } if (DirectorySNP != null && - GetFiles(DirectorySNP.FullName, ".mnv").Any()) + GetFilePaths(DirectorySNP.FullName, ".mnv").Any()) { IsPSP = true; } if (DirectorySSIF != null && - _fileSystem.GetFiles(DirectorySSIF.FullName).Any()) + _fileSystem.GetFilePaths(DirectorySSIF.FullName).Any()) { Is3D = true; } @@ -209,6 +209,11 @@ namespace BDInfo return _fileSystem.GetFiles(path, new[] { extension }, false, false); } + private IEnumerable GetFilePaths(string path, string extension) + { + return _fileSystem.GetFilePaths(path, new[] { extension }, false, false); + } + public void Scan() { List errorStreamClipFiles = new List(); diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs index ed940eca5..4d7a86821 100644 --- a/Emby.Common.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Common.Implementations/IO/ManagedFileSystem.cs @@ -662,7 +662,7 @@ namespace Emby.Common.Implementations.IO public IEnumerable GetFiles(string path, bool recursive = false) { - return GetFiles(path, null, true, recursive); + return GetFiles(path, null, false, recursive); } public IEnumerable GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) @@ -790,9 +790,37 @@ namespace Emby.Common.Implementations.IO } public IEnumerable GetFilePaths(string path, bool recursive = false) + { + return GetFilePaths(path, null, false, recursive); + } + + public IEnumerable GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; - return Directory.EnumerateFiles(path, "*", searchOption); + + // On linux and osx the search pattern is case sensitive + // If we're OK with case-sensitivity, and we're only filtering for one extension, then use the native method + if (enableCaseSensitiveExtensions && extensions != null && extensions.Length == 1) + { + return Directory.EnumerateFiles(path, "*" + extensions[0], searchOption); + } + + var files = Directory.EnumerateFiles(path, "*", searchOption); + + if (extensions != null && extensions.Length > 0) + { + files = files.Where(i => + { + var ext = Path.GetExtension(i); + if (ext == null) + { + return false; + } + return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase); + }); + } + + return files; } public IEnumerable GetFileSystemEntryPaths(string path, bool recursive = false) diff --git a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index c885f03ac..2cbf2613e 100644 --- a/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/Emby.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -178,18 +178,18 @@ namespace Emby.Server.Implementations.FileOrganization /// The extensions. private void DeleteLeftOverFiles(string path, IEnumerable extensions) { - var eligibleFiles = _fileSystem.GetFiles(path, extensions.ToArray(), false, true) + var eligibleFiles = _fileSystem.GetFilePaths(path, extensions.ToArray(), false, true) .ToList(); foreach (var file in eligibleFiles) { try { - _fileSystem.DeleteFile(file.FullName); + _fileSystem.DeleteFile(file); } catch (Exception ex) { - _logger.ErrorException("Error deleting file {0}", ex, file.FullName); + _logger.ErrorException("Error deleting file {0}", ex, file); } } } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 17e678615..dbb0160a5 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1255,9 +1255,9 @@ namespace Emby.Server.Implementations.Library private string GetCollectionType(string path) { - return _fileSystem.GetFiles(path, new[] { ".collection" }, true, false) + return _fileSystem.GetFilePaths(path, new[] { ".collection" }, true, false) .Select(i => _fileSystem.GetFileNameWithoutExtension(i)) - .FirstOrDefault(); + .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } /// diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index 180d2f227..e791503ab 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -298,6 +298,7 @@ namespace MediaBrowser.Model.IO /// if set to true [recursive]. /// IEnumerable<System.String>. IEnumerable GetFilePaths(string path, bool recursive = false); + IEnumerable GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive); /// /// Gets the file system entry paths. -- cgit v1.2.3