diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index b5bc7692ec..ea3845f0c9 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4254,6 +4254,54 @@ namespace Emby.Server.Implementations.Data } } + if (!string.IsNullOrWhiteSpace(query.HasNoAudioTrackWithLanguage)) + { + whereClauses.Add("((select language from MediaStreams where MediaStreams.ItemId=A.Guid and MediaStreams.StreamType='Audio' and MediaStreams.Language=@HasNoAudioTrackWithLanguage limit 1) is null)"); + if (statement != null) + { + statement.TryBind("@HasNoAudioTrackWithLanguage", query.HasNoAudioTrackWithLanguage); + } + } + + if (!string.IsNullOrWhiteSpace(query.HasNoInternalSubtitleTrackWithLanguage)) + { + whereClauses.Add("((select language from MediaStreams where MediaStreams.ItemId=A.Guid and MediaStreams.StreamType='Subtitle' and MediaStreams.IsExternal=0 and MediaStreams.Language=@HasNoInternalSubtitleTrackWithLanguage limit 1) is null)"); + if (statement != null) + { + statement.TryBind("@HasNoInternalSubtitleTrackWithLanguage", query.HasNoInternalSubtitleTrackWithLanguage); + } + } + + if (!string.IsNullOrWhiteSpace(query.HasNoExternalSubtitleTrackWithLanguage)) + { + whereClauses.Add("((select language from MediaStreams where MediaStreams.ItemId=A.Guid and MediaStreams.StreamType='Subtitle' and MediaStreams.IsExternal=1 and MediaStreams.Language=@HasNoExternalSubtitleTrackWithLanguage limit 1) is null)"); + if (statement != null) + { + statement.TryBind("@HasNoExternalSubtitleTrackWithLanguage", query.HasNoExternalSubtitleTrackWithLanguage); + } + } + + if (!string.IsNullOrWhiteSpace(query.HasNoSubtitleTrackWithLanguage)) + { + whereClauses.Add("((select language from MediaStreams where MediaStreams.ItemId=A.Guid and MediaStreams.StreamType='Subtitle' and MediaStreams.Language=@HasNoSubtitleTrackWithLanguage limit 1) is null)"); + if (statement != null) + { + statement.TryBind("@HasNoSubtitleTrackWithLanguage", query.HasNoSubtitleTrackWithLanguage); + } + } + + if (query.HasChapterImages.HasValue) + { + if (query.HasChapterImages.Value) + { + whereClauses.Add("((select imagepath from Chapters2 where Chapters2.ItemId=A.Guid and imagepath not null limit 1) not null)"); + } + else + { + whereClauses.Add("((select imagepath from Chapters2 where Chapters2.ItemId=A.Guid and imagepath not null limit 1) is null)"); + } + } + if (query.HasDeadParentId.HasValue && query.HasDeadParentId.Value) { whereClauses.Add("ParentId NOT NULL AND ParentId NOT IN (select guid from TypedBaseItems)"); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 8c5ecf782e..510ecee76b 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -620,37 +620,12 @@ namespace Emby.Server.Implementations.Library return ResolveItem(args, resolvers); } - private readonly List _ignoredPaths = new List(); - - public void RegisterIgnoredPath(string path) - { - lock (_ignoredPaths) - { - _ignoredPaths.Add(path); - } - } - public void UnRegisterIgnoredPath(string path) - { - lock (_ignoredPaths) - { - _ignoredPaths.Remove(path); - } - } - public bool IgnoreFile(FileSystemMetadata file, BaseItem parent) { if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent))) { return true; } - - //lock (_ignoredPaths) - { - if (_ignoredPaths.Contains(file.FullName, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - } return false; } diff --git a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs index cad28c809c..225360159b 100644 --- a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv return new[] { // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(12).Ticks} + new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} }; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs index 84adf0cfc9..4dcbc4b54c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs @@ -26,10 +26,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); private readonly TaskCompletionSource _liveStreamTaskCompletionSource = new TaskCompletionSource(); - private readonly MulticastStream _multicastStream; - private readonly string _tempFilePath; - private bool _enableFileBuffer = false; public HdHomerunHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment) : base(mediaSource, environment, fileSystem) @@ -39,7 +36,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _appHost = appHost; OriginalStreamId = originalStreamId; - _multicastStream = new MulticastStream(_logger); _tempFilePath = Path.Combine(appPaths.TranscodingTempPath, UniqueId + ".ts"); } @@ -63,6 +59,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; OpenedMediaSource.Protocol = MediaProtocol.Http; + + //OpenedMediaSource.Path = _tempFilePath; + //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.SupportsDirectPlay = false; //OpenedMediaSource.SupportsDirectStream = true; //OpenedMediaSource.SupportsTranscoding = true; @@ -107,19 +106,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { _logger.Info("Beginning multicastStream.CopyUntilCancelled"); - if (_enableFileBuffer) + FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath)); + using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) { - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath)); - using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) - { - StreamHelper.CopyTo(response.Content, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken); - } - } - else - { - Resolve(openTaskCompletionSource); - - await _multicastStream.CopyUntilCancelled(response.Content, null, cancellationToken).ConfigureAwait(false); + StreamHelper.CopyTo(response.Content, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken); } } } @@ -158,7 +148,33 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) { - return _multicastStream.CopyToAsync(stream, cancellationToken); + return CopyFileTo(_tempFilePath, stream, cancellationToken); + } + + protected async Task CopyFileTo(string path, Stream outputStream, CancellationToken cancellationToken) + { + long startPosition = -20000; + + _logger.Info("Live stream starting position is {0} bytes", startPosition.ToString(CultureInfo.InvariantCulture)); + + var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows; + // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 + + using (var inputStream = (FileStream)GetInputStream(path, allowAsync)) + { + if (startPosition > 0) + { + inputStream.Seek(-20000, SeekOrigin.End); + } + + while (!cancellationToken.IsCancellationRequested) + { + StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken); + + //var position = fs.Position; + //_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path); + } + } } } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 69fe59b4a0..6c21066fb0 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -34,8 +34,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly INetworkManager _networkManager; private readonly string _tempFilePath; - private bool _enableFileBuffer = false; - private readonly MulticastStream _multicastStream; public HdHomerunUdpStream(MediaSourceInfo mediaSource, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment) : base(mediaSource, environment, fileSystem) @@ -48,7 +46,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _channelCommands = channelCommands; _numTuners = numTuners; _tempFilePath = Path.Combine(appPaths.TranscodingTempPath, UniqueId + ".ts"); - _multicastStream = new MulticastStream(_logger); } protected override async Task OpenInternal(CancellationToken openCancellationToken) @@ -126,17 +123,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (!cancellationToken.IsCancellationRequested) { - if (_enableFileBuffer) + FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath)); + using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) { - FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath)); - using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) - { - CopyTo(udpClient, fileStream, openTaskCompletionSource, cancellationToken); - } - } - else - { - await _multicastStream.CopyUntilCancelled(new UdpClientStream(udpClient), () => Resolve(openTaskCompletionSource), cancellationToken).ConfigureAwait(false); + CopyTo(udpClient, fileStream, openTaskCompletionSource, cancellationToken); } } } @@ -178,49 +168,33 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun }); } - public async Task CopyToAsync(Stream outputStream, CancellationToken cancellationToken) + public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) { - if (!_enableFileBuffer) - { - await _multicastStream.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false); - return; - } - - var path = _tempFilePath; + return CopyFileTo(_tempFilePath, stream, cancellationToken); + } + protected async Task CopyFileTo(string path, Stream outputStream, CancellationToken cancellationToken) + { long startPosition = -20000; - if (startPosition < 0) - { - var length = FileSystem.GetFileInfo(path).Length; - startPosition = Math.Max(length - startPosition, 0); - } _logger.Info("Live stream starting position is {0} bytes", startPosition.ToString(CultureInfo.InvariantCulture)); - var allowAsync = Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows; + var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows; // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 - using (var inputStream = GetInputStream(path, startPosition, allowAsync)) + using (var inputStream = (FileStream)GetInputStream(path, allowAsync)) { if (startPosition > 0) { - inputStream.Position = startPosition; + inputStream.Seek(-20000, SeekOrigin.End); } while (!cancellationToken.IsCancellationRequested) { - long bytesRead; - StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken); - bytesRead = 1; //var position = fs.Position; //_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path); - - if (bytesRead == 0) - { - await Task.Delay(100, cancellationToken).ConfigureAwait(false); - } } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index ec371c741f..bf7bf9ff8b 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -58,8 +58,8 @@ namespace Emby.Server.Implementations.ScheduledTasks /// public IEnumerable GetDefaultTriggers() { - return new[] { - + return new[] { + new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerDaily, @@ -88,6 +88,12 @@ namespace Emby.Server.Implementations.ScheduledTasks IsFolder = false, Recursive = true, DtoOptions = new DtoOptions(false) + { + EnableImages = false + }, + SourceTypes = new SourceType[] { SourceType.Library }, + HasChapterImages = false, + IsVirtualItem = false }) .OfType