diff options
| author | Luke <luke.pulverenti@gmail.com> | 2017-05-06 16:20:25 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-06 16:20:25 -0400 |
| commit | 21edff3ac2175190e0bca98c9a2f967c79ee57c2 (patch) | |
| tree | 6beddce4dffa97eb199da99867f6b493ce197e64 /Emby.Server.Implementations | |
| parent | 3e29d73d0c77c682e161c413703d5e36a8466885 (diff) | |
| parent | 90452d2faf5e0f34698873707e9e505df3c52f9c (diff) | |
Merge pull request #2618 from MediaBrowser/beta
Beta
Diffstat (limited to 'Emby.Server.Implementations')
36 files changed, 251 insertions, 394 deletions
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 8f03fa7a4..0cdd934b7 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -268,24 +268,14 @@ namespace Emby.Server.Implementations.Channels return; } - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(mediaSources, path); } public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken) { - IEnumerable<ChannelMediaInfo> results = new List<ChannelMediaInfo>(); - var video = item as Video; - if (video != null) - { - results = video.ChannelMediaSources; - } - var audio = item as Audio; - if (audio != null) - { - results = audio.ChannelMediaSources ?? GetSavedMediaSources(audio); - } + IEnumerable<ChannelMediaInfo> results = GetSavedMediaSources(item); return SortMediaInfoResults(results) .Select(i => GetMediaSource(item, i)) @@ -1115,7 +1105,7 @@ namespace Emby.Server.Implementations.Channels { try { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(result, path); } @@ -1378,7 +1368,6 @@ namespace Emby.Server.Implementations.Channels if (channelVideoItem != null) { channelVideoItem.ExtraType = info.ExtraType; - channelVideoItem.ChannelMediaSources = info.MediaSources; var mediaSource = info.MediaSources.FirstOrDefault(); item.Path = mediaSource == null ? null : mediaSource.Path; @@ -1427,7 +1416,7 @@ namespace Emby.Server.Implementations.Channels if (!_refreshedItems.ContainsKey(program.Id)) { _refreshedItems.TryAdd(program.Id, true); - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); + _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low); } } diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index d0bd76c35..9c26655fc 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Collections } else { - _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem)); + _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High); } EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs @@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Collections await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - _providerManager.QueueRefresh(collection.Id, refreshOptions); + _providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High); if (fireEvent) { @@ -244,7 +244,7 @@ namespace Emby.Server.Implementations.Collections collection.UpdateRatingToContent(); await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem)); + _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High); EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs { diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs index 0096f2284..e25955782 100644 --- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs +++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs @@ -71,10 +71,9 @@ namespace Emby.Server.Implementations.Data double newPercentCommplete = 45 + .55 * p; progress.Report(newPercentCommplete); }); - await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false); - progress.Report(100); await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false); + progress.Report(100); } private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress) @@ -115,115 +114,6 @@ namespace Emby.Server.Implementations.Data progress.Report(100); } - private async Task CleanDeletedItems(CancellationToken cancellationToken, IProgress<double> progress) - { - var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery - { - LocationTypes = new[] { LocationType.FileSystem }, - //Limit = limit, - - // These have their own cleanup routines - ExcludeItemTypes = new[] - { - typeof(Person).Name, - typeof(Genre).Name, - typeof(MusicGenre).Name, - typeof(GameGenre).Name, - typeof(Studio).Name, - typeof(Year).Name, - typeof(Channel).Name, - typeof(AggregateFolder).Name, - typeof(CollectionFolder).Name - } - }); - - var numComplete = 0; - var numItems = result.Count; - - var allLibraryPaths = _libraryManager - .GetVirtualFolders() - .SelectMany(i => i.Locations) - .ToList(); - - foreach (var item in result) - { - cancellationToken.ThrowIfCancellationRequested(); - - var path = item.Item2; - - try - { - var isPathInLibrary = false; - - if (allLibraryPaths.Any(i => path.StartsWith(i, StringComparison.Ordinal)) || - allLibraryPaths.Contains(path, StringComparer.Ordinal) || - path.StartsWith(_appPaths.ProgramDataPath, StringComparison.Ordinal)) - { - isPathInLibrary = true; - - if (_fileSystem.FileExists(path) || _fileSystem.DirectoryExists(path)) - { - continue; - } - } - - var libraryItem = _libraryManager.GetItemById(item.Item1); - - if (libraryItem == null) - { - continue; - } - - if (libraryItem.IsTopParent) - { - continue; - } - - var hasDualAccess = libraryItem as IHasDualAccess; - if (hasDualAccess != null && hasDualAccess.IsAccessedByName) - { - continue; - } - - var libraryItemPath = libraryItem.Path; - if (!string.Equals(libraryItemPath, path, StringComparison.OrdinalIgnoreCase)) - { - _logger.Error("CleanDeletedItems aborting delete for item {0}-{1} because paths don't match. {2}---{3}", libraryItem.Id, libraryItem.Name, libraryItem.Path ?? string.Empty, path ?? string.Empty); - continue; - } - - if (Folder.IsPathOffline(path, allLibraryPaths)) - { - continue; - } - - if (isPathInLibrary) - { - _logger.Info("Deleting item from database {0} because path no longer exists. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty); - } - else - { - _logger.Info("Deleting item from database {0} because path is no longer in the server library. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty); - } - - await libraryItem.OnFileDeleted().ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error in CleanDeletedItems. File {0}", ex, path); - } - - numComplete++; - double percent = numComplete; - percent /= numItems; - progress.Report(percent * 100); - } - } - /// <summary> /// Creates the triggers that define when the task will run /// </summary> diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 51f91acf3..61dce9bba 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -201,7 +201,6 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "OfficialRatingDescription", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames); AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames); @@ -209,7 +208,6 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames); AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "LocationType", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames); AddColumn(db, "TypedBaseItems", "IsLive", "BIT", existingColumnNames); @@ -240,7 +238,6 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CriticRatingSummary", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames); @@ -255,7 +252,6 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames); AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeriesSortName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "Keywords", "Text", existingColumnNames); @@ -429,7 +425,6 @@ namespace Emby.Server.Implementations.Data "ParentIndexNumber", "ProductionYear", "OfficialRating", - "OfficialRatingDescription", "HomePageUrl", "DisplayMediaType", "ForcedSortName", @@ -454,13 +449,11 @@ namespace Emby.Server.Implementations.Data "DateLastMediaAdded", "Album", "CriticRating", - "CriticRatingSummary", "IsVirtualItem", "SeriesName", "SeasonName", "SeasonId", "SeriesId", - "SeriesSortName", "PresentationUniqueKey", "InheritedParentalRatingValue", "InheritedTags", @@ -552,14 +545,12 @@ namespace Emby.Server.Implementations.Data "InheritedParentalRatingValue", "SortName", "RunTimeTicks", - "OfficialRatingDescription", "HomePageUrl", "VoteCount", "DisplayMediaType", "DateCreated", "DateModified", "ForcedSortName", - "LocationType", "PreferredMetadataLanguage", "PreferredMetadataCountryCode", "IsHD", @@ -579,7 +570,6 @@ namespace Emby.Server.Implementations.Data "SourceType", "TrailerTypes", "CriticRating", - "CriticRatingSummary", "InheritedTags", "CleanName", "PresentationUniqueKey", @@ -594,7 +584,6 @@ namespace Emby.Server.Implementations.Data "SeasonName", "SeasonId", "SeriesId", - "SeriesSortName", "ExternalSeriesId", "Tagline", "Keywords", @@ -833,7 +822,6 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@SortName", item.SortName); saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks); - saveItemStatement.TryBind("@OfficialRatingDescription", item.OfficialRatingDescription); saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl); saveItemStatement.TryBind("@VoteCount", item.VoteCount); saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType); @@ -841,7 +829,6 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@DateModified", item.DateModified); saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName); - saveItemStatement.TryBind("@LocationType", item.LocationType.ToString()); saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage); saveItemStatement.TryBind("@PreferredMetadataCountryCode", item.PreferredMetadataCountryCode); @@ -942,7 +929,6 @@ namespace Emby.Server.Implementations.Data } saveItemStatement.TryBind("@CriticRating", item.CriticRating); - saveItemStatement.TryBind("@CriticRatingSummary", item.CriticRatingSummary); var inheritedTags = item.InheritedTags; if (inheritedTags.Count > 0) @@ -1024,13 +1010,11 @@ namespace Emby.Server.Implementations.Data if (hasSeries != null) { saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId); - saveItemStatement.TryBind("@SeriesSortName", hasSeries.SeriesSortName); saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey); } else { saveItemStatement.TryBindNull("@SeriesId"); - saveItemStatement.TryBindNull("@SeriesSortName"); saveItemStatement.TryBindNull("@SeriesPresentationUniqueKey"); } @@ -1290,22 +1274,10 @@ namespace Emby.Server.Implementations.Data { return false; } - if (type == typeof(Year)) - { - return false; - } - if (type == typeof(Book)) - { - return false; - } if (type == typeof(Person)) { return false; } - if (type == typeof(RecordingGroup)) - { - return false; - } if (type == typeof(Channel)) { return false; @@ -1339,31 +1311,42 @@ namespace Emby.Server.Implementations.Data return false; } } - if (_config.Configuration.SkipDeserializationForPrograms) + + if (type == typeof(Year)) + { + return false; + } + if (type == typeof(Book)) { - if (type == typeof(LiveTvProgram)) - { - return false; - } + return false; + } + if (type == typeof(RecordingGroup)) + { + return false; } + if (type == typeof(LiveTvProgram)) + { + return false; + } + if (type == typeof(LiveTvAudioRecording)) + { + return false; + } + if (type == typeof(AudioPodcast)) + { + return false; + } + if (type == typeof(AudioBook)) + { + return false; + } + if (_config.Configuration.SkipDeserializationForAudio) { if (type == typeof(Audio)) { return false; } - if (type == typeof(LiveTvAudioRecording)) - { - return false; - } - if (type == typeof(AudioPodcast)) - { - return false; - } - if (type == typeof(AudioBook)) - { - return false; - } if (type == typeof(MusicAlbum)) { return false; @@ -1609,15 +1592,6 @@ namespace Emby.Server.Implementations.Data } index++; - if (query.HasField(ItemFields.OfficialRatingDescription)) - { - if (!reader.IsDBNull(index)) - { - item.OfficialRatingDescription = reader.GetString(index); - } - index++; - } - if (query.HasField(ItemFields.HomePageUrl)) { if (!reader.IsDBNull(index)) @@ -1803,15 +1777,6 @@ namespace Emby.Server.Implementations.Data } index++; - if (query.HasField(ItemFields.CriticRatingSummary)) - { - if (!reader.IsDBNull(index)) - { - item.CriticRatingSummary = reader.GetString(index); - } - index++; - } - if (!reader.IsDBNull(index)) { item.IsVirtualItem = reader.GetBoolean(index); @@ -1856,15 +1821,6 @@ namespace Emby.Server.Implementations.Data } index++; - if (hasSeries != null) - { - if (!reader.IsDBNull(index)) - { - hasSeries.SeriesSortName = reader.GetString(index); - } - } - index++; - if (!reader.IsDBNull(index)) { item.PresentationUniqueKey = reader.GetString(index); @@ -2893,6 +2849,10 @@ namespace Emby.Server.Implementations.Data { return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); } + if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) + { + return new Tuple<string, bool>("(Select SortName from TypedBaseItems where B.Guid=A.SeriesId)", false); + } return new Tuple<string, bool>(name, false); } @@ -4100,27 +4060,6 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("ProductionYear in (" + val + ")"); } - if (query.LocationTypes.Length == 1) - { - if (query.LocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90) - { - query.IsVirtualItem = true; - } - else - { - whereClauses.Add("LocationType=@LocationType"); - if (statement != null) - { - statement.TryBind("@LocationType", query.LocationTypes[0].ToString()); - } - } - } - else if (query.LocationTypes.Length > 1) - { - var val = string.Join(",", query.LocationTypes.Select(i => "'" + i + "'").ToArray()); - - whereClauses.Add("LocationType in (" + val + ")"); - } if (query.IsVirtualItem.HasValue) { whereClauses.Add("IsVirtualItem=@IsVirtualItem"); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 7c0baf9c2..78d76fd76 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.Dto if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo)) { - var userCanSync = user != null && user.Policy.EnableSync; + var userCanSync = user != null && user.Policy.EnableContentDownloading; if (userCanSync && _syncManager.SupportsSync(item)) { dto.SupportsSync = true; @@ -967,11 +967,6 @@ namespace Emby.Server.Implementations.Dto dto.CriticRating = item.CriticRating; - if (fields.Contains(ItemFields.CriticRatingSummary)) - { - dto.CriticRatingSummary = item.CriticRatingSummary; - } - var hasTrailers = item as IHasTrailers; if (hasTrailers != null) { diff --git a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 0a9c67285..86c8c5f68 100644 --- a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -352,7 +352,7 @@ namespace Emby.Server.Implementations.FileOrganization _libraryMonitor.ReportFileSystemChangeBeginning(path); var renameRelatedFiles = !hasRenamedFiles && - string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase); + string.Equals(_fileSystem.GetDirectoryName(path), _fileSystem.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase); if (renameRelatedFiles) { @@ -432,7 +432,7 @@ namespace Emby.Server.Implementations.FileOrganization // Now find other files var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path); - var directory = Path.GetDirectoryName(path); + var directory = _fileSystem.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory)) { @@ -445,7 +445,7 @@ namespace Emby.Server.Implementations.FileOrganization foreach (var file in files) { - directory = Path.GetDirectoryName(file); + directory = _fileSystem.GetDirectoryName(file); var filename = Path.GetFileName(file); filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension, @@ -470,7 +470,7 @@ namespace Emby.Server.Implementations.FileOrganization return new List<string>(); } - var episodePaths = series.GetRecursiveChildren() + var episodePaths = series.GetRecursiveChildren(i => i is Episode) .OfType<Episode>() .Where(i => { @@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.FileOrganization .Select(i => i.Path) .ToList(); - var folder = Path.GetDirectoryName(targetPath); + var folder = _fileSystem.GetDirectoryName(targetPath); var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath); try @@ -529,7 +529,7 @@ namespace Emby.Server.Implementations.FileOrganization _libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath); - _fileSystem.CreateDirectory(Path.GetDirectoryName(result.TargetPath)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(result.TargetPath)); var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath); diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs index dbaf97b1e..8cb7b5dbf 100644 --- a/Emby.Server.Implementations/HttpServer/FileWriter.cs +++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs @@ -58,6 +58,7 @@ namespace Emby.Server.Implementations.HttpServer Headers["Content-Type"] = contentType; TotalContentLength = fileSystem.GetFileInfo(path).Length; + Headers["Accept-Ranges"] = "bytes"; if (string.IsNullOrWhiteSpace(rangeHeader)) { @@ -66,7 +67,6 @@ namespace Emby.Server.Implementations.HttpServer } else { - Headers["Accept-Ranges"] = "bytes"; StatusCode = HttpStatusCode.PartialContent; SetRangeValues(); } @@ -96,8 +96,12 @@ namespace Emby.Server.Implementations.HttpServer RangeLength = 1 + RangeEnd - RangeStart; // Content-Length is the length of what we're serving, not the original content - Headers["Content-Length"] = RangeLength.ToString(UsCulture); - Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength); + var lengthString = RangeLength.ToString(UsCulture); + Headers["Content-Length"] = lengthString; + var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength); + Headers["Content-Range"] = rangeString; + + Logger.Info("Setting range response values for {0}. RangeRequest: {1} Content-Length: {2}, Content-Range: {3}", Path, RangeHeader, lengthString, rangeString); } /// <summary> diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 310161d41..687bd62b0 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -501,7 +501,7 @@ namespace Emby.Server.Implementations.HttpServer private bool ShouldCompressResponse(IRequest requestContext, string contentType) { // It will take some work to support compression with byte range requests - if (!string.IsNullOrEmpty(requestContext.Headers.Get("Range"))) + if (!string.IsNullOrWhiteSpace(requestContext.Headers.Get("Range"))) { return false; } @@ -566,7 +566,7 @@ namespace Emby.Server.Implementations.HttpServer }; } - if (!string.IsNullOrEmpty(rangeHeader)) + if (!string.IsNullOrWhiteSpace(rangeHeader)) { var stream = await factoryFn().ConfigureAwait(false); @@ -621,6 +621,7 @@ namespace Emby.Server.Implementations.HttpServer responseHeaders["Content-Encoding"] = requestedCompressionType; } + responseHeaders["Vary"] = "Accept-Encoding"; responseHeaders["Content-Length"] = content.Length.ToString(UsCulture); if (isHeadRequest) diff --git a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs index e88994bec..7c967949b 100644 --- a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -189,10 +189,15 @@ namespace Emby.Server.Implementations.HttpServer private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength) { var array = new byte[BufferSize]; - int count; - while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0) + int bytesRead; + while ((bytesRead = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0) { - var bytesToCopy = Math.Min(count, copyLength); + if (bytesRead == 0) + { + break; + } + + var bytesToCopy = Math.Min(bytesRead, copyLength); await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs index 6d9d7d921..57eef5db0 100644 --- a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs +++ b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs @@ -26,8 +26,8 @@ namespace Emby.Server.Implementations.HttpServer public void FilterResponse(IRequest req, IResponse res, object dto) { // Try to prevent compatibility view - res.AddHeader("X-UA-Compatible", "IE=Edge"); - res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"); + //res.AddHeader("X-UA-Compatible", "IE=Edge"); + res.AddHeader("Access-Control-Allow-Headers", "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Authorization"); res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"); res.AddHeader("Access-Control-Allow-Origin", "*"); @@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.HttpServer } } - var vary = "Accept-Encoding"; - var hasHeaders = dto as IHasHeaders; var sharpResponse = res as WebSocketSharpResponse; @@ -86,23 +84,9 @@ namespace Emby.Server.Implementations.HttpServer } } } - - string hasHeadersVary; - if (hasHeaders.Headers.TryGetValue("Vary", out hasHeadersVary)) - { - vary = hasHeadersVary; - } - - hasHeaders.Headers["Vary"] = vary; } //res.KeepAlive = false; - - // Per Google PageSpeed - // This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed. - // The correct version of the resource is delivered based on the client request header. - // This is a good choice for applications that are singly homed and depend on public proxies for user locality. - res.AddHeader("Vary", vary); } /// <summary> diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index c64672685..033cbd8b0 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.IO { item = LibraryManager.FindByPath(path, null); - path = System.IO.Path.GetDirectoryName(path); + path = _fileSystem.GetDirectoryName(path); } if (item != null) diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index 38908c2bd..2677f7b2a 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.Images CancellationToken cancellationToken) { var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N")); - FileSystem.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension)); + FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPathWithoutExtension)); string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(outputPath)) @@ -205,7 +205,7 @@ namespace Emby.Server.Implementations.Images private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) { - FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); + FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath)); var options = new ImageCollageOptions { diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index d782f5b88..64f025d93 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Library { if (parent == null) { - var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path)); + var parentFolderName = Path.GetFileName(_fileSystem.GetDirectoryName(path)); if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 16a73f392..685c794b7 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1962,8 +1962,34 @@ namespace Emby.Server.Implementations.Library return new List<Folder>(); } - return GetUserRootFolder().Children - .OfType<Folder>() + return GetCollectionFoldersInternal(item, GetUserRootFolder().Children.OfType<Folder>().ToList()); + } + + public List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren) + { + while (item != null) + { + var parent = item.GetParent(); + + if (parent == null || parent is AggregateFolder) + { + break; + } + + item = parent; + } + + if (item == null) + { + return new List<Folder>(); + } + + return GetCollectionFoldersInternal(item, allUserRootChildren); + } + + private List<Folder> GetCollectionFoldersInternal(BaseItem item, List<Folder> allUserRootChildren) + { + return allUserRootChildren .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase)) .ToList(); } @@ -2126,7 +2152,8 @@ namespace Emby.Server.Implementations.Library // Not sure why this is necessary but need to figure it out // View images are not getting utilized without this ForceSave = true - }); + + }, RefreshPriority.Normal); } return item; @@ -2188,7 +2215,8 @@ namespace Emby.Server.Implementations.Library { // Need to force save to increment DateLastSaved ForceSave = true - }); + + }, RefreshPriority.Normal); } return item; @@ -2252,7 +2280,8 @@ namespace Emby.Server.Implementations.Library { // Need to force save to increment DateLastSaved ForceSave = true - }); + + }, RefreshPriority.Normal); } return item; @@ -2328,7 +2357,7 @@ namespace Emby.Server.Implementations.Library { // Need to force save to increment DateLastSaved ForceSave = true - }); + }, RefreshPriority.Normal); } return item; diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs index 9d07837c6..b15c01125 100644 --- a/Emby.Server.Implementations/Library/MusicManager.cs +++ b/Emby.Server.Implementations/Library/MusicManager.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Playlists; using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Library { @@ -27,35 +28,14 @@ namespace Emby.Server.Implementations.Library return list.Concat(GetInstantMixFromGenres(item.Genres, user)); } - public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user) + public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist item, User user) { - var genres = user.RootFolder - .GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Audio).Name } - }) - .Cast<Audio>() - .Where(i => i.HasAnyArtist(artist.Name)) - .SelectMany(i => i.Genres) - .Concat(artist.Genres) - .Distinct(StringComparer.OrdinalIgnoreCase); - - return GetInstantMixFromGenres(genres, user); + return GetInstantMixFromGenres(item.Genres, user); } public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user) { - var genres = item - .GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Audio).Name } - }) - .Cast<Audio>() - .SelectMany(i => i.Genres) - .Concat(item.Genres) - .DistinctNames(); - - return GetInstantMixFromGenres(genres, user); + return GetInstantMixFromGenres(item.Genres, user); } public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user) @@ -63,7 +43,7 @@ namespace Emby.Server.Implementations.Library var genres = item .GetRecursiveChildren(user, new InternalItemsQuery(user) { - IncludeItemTypes = new[] {typeof(Audio).Name} + IncludeItemTypes = new[] { typeof(Audio).Name } }) .Cast<Audio>() .SelectMany(i => i.Genres) @@ -75,41 +55,40 @@ namespace Emby.Server.Implementations.Library public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user) { - var genres = item - .GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Audio).Name } - }) - .Cast<Audio>() - .SelectMany(i => i.Genres) - .Concat(item.Genres) - .DistinctNames(); - - return GetInstantMixFromGenres(genres, user); + return GetInstantMixFromGenres(item.Genres, user); } public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user) { - var genreList = genres.ToList(); + var genreIds = genres.DistinctNames().Select(i => + { + try + { + return _libraryManager.GetMusicGenre(i).Id.ToString("N"); + } + catch + { + return null; + } + + }).Where(i => i != null); - var inputItems = _libraryManager.GetItemList(new InternalItemsQuery(user) + return GetInstantMixFromGenreIds(genreIds, user); + } + + public IEnumerable<Audio> GetInstantMixFromGenreIds(IEnumerable<string> genreIds, User user) + { + return _libraryManager.GetItemList(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(Audio).Name }, - Genres = genreList.ToArray() + GenreIds = genreIds.ToArray(), - }); + Limit = 200, - var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + SortBy = new[] { ItemSortBy.Random } - return inputItems - .Cast<Audio>() - .Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey))) - .OrderByDescending(i => i.Item2) - .ThenBy(i => Guid.NewGuid()) - .Select(i => i.Item1) - .Take(200) - .OrderBy(i => Guid.NewGuid()); + }).Cast<Audio>(); } public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user) @@ -117,7 +96,7 @@ namespace Emby.Server.Implementations.Library var genre = item as MusicGenre; if (genre != null) { - return GetInstantMixFromGenres(new[] { item.Name }, user); + return GetInstantMixFromGenreIds(new[] { item.Id.ToString("N") }, user); } var playlist = item as Playlist; diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index 0968e8ea2..8bbda3b62 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -6,6 +6,7 @@ using System; using System.IO; using System.Linq; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { @@ -13,11 +14,13 @@ namespace Emby.Server.Implementations.Library.Resolvers { private readonly IImageProcessor _imageProcessor; private readonly ILibraryManager _libraryManager; + private readonly IFileSystem _fileSystem; - public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager) + public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager, IFileSystem fileSystem) { _imageProcessor = imageProcessor; _libraryManager = libraryManager; + _fileSystem = fileSystem; } /// <summary> @@ -41,7 +44,7 @@ namespace Emby.Server.Implementations.Library.Resolvers var filename = Path.GetFileNameWithoutExtension(args.Path); // Make sure the image doesn't belong to a video file - if (args.DirectoryService.GetFilePaths(Path.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename))) + if (args.DirectoryService.GetFilePaths(_fileSystem.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename))) { return null; } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index cf37366fb..bdab8552a 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -57,7 +57,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV { episode.SeriesId = series.Id; episode.SeriesName = series.Name; - episode.SeriesSortName = series.SortName; } if (season != null) { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index c065feda1..84ceac65e 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -44,7 +44,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV { IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber, SeriesId = series.Id, - SeriesSortName = series.SortName, SeriesName = series.Name }; diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index a47a3322e..f640ae2b1 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -165,7 +165,16 @@ namespace Emby.Server.Implementations.Library ExcludeItemTypes = excludeItemTypes.ToArray(), IncludeItemTypes = includeItemTypes.ToArray(), Limit = query.Limit, - IncludeItemsByName = true + IncludeItemsByName = string.IsNullOrWhiteSpace(query.ParentId), + ParentId = string.IsNullOrWhiteSpace(query.ParentId) ? (Guid?)null : new Guid(query.ParentId), + SortBy = new[] { ItemSortBy.SortName }, + Recursive = true, + + IsKids = query.IsKids, + IsMovie = query.IsMovie, + IsNews = query.IsNews, + IsSeries = query.IsSeries, + IsSports = query.IsSports }); // Add search hints based on item name diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 89b7198ca..0b9027291 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -942,7 +942,8 @@ namespace Emby.Server.Implementations.Library { return new UserPolicy { - EnableSync = true + EnableContentDownloading = true, + EnableSyncTranscoding = true }; } @@ -964,7 +965,7 @@ namespace Emby.Server.Implementations.Library var path = GetPolifyFilePath(user); - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); lock (_policySyncLock) { @@ -1051,7 +1052,7 @@ namespace Emby.Server.Implementations.Library config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json); } - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); lock (_configSyncLock) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 666c1fdcd..f1b3f41b4 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (!string.IsNullOrWhiteSpace(epgChannel.Name)) { - tunerChannel.Name = epgChannel.Name; + //tunerChannel.Name = epgChannel.Name; } if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl)) { @@ -1231,7 +1231,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV RequiresOpening = false, RequiresClosing = false, Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http, - BufferMs = 0 + BufferMs = 0, + IgnoreDts = true }; var isAudio = false; @@ -1496,7 +1497,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _libraryManager.RegisterIgnoredPath(recordPath); _libraryMonitor.ReportFileSystemChangeBeginning(recordPath); - _fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath)); activeRecordingInfo.Path = recordPath; var duration = recordingEndDate - DateTime.UtcNow; @@ -1516,8 +1517,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV EnforceKeepUpTo(timer, seriesPath); }; - await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken) - .ConfigureAwait(false); + await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false); recordingStatus = RecordingStatus.Completed; _logger.Info("Recording completed: {0}", recordPath); @@ -1725,7 +1725,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV while (FileExists(path, timerId)) { - var parent = Path.GetDirectoryName(originalPath); + var parent = _fileSystem.GetDirectoryName(originalPath); var name = Path.GetFileNameWithoutExtension(originalPath); name += "-" + index.ToString(CultureInfo.InvariantCulture); @@ -1765,7 +1765,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (regInfo.IsValid) { - return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory); + return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory, _config); } } @@ -1892,7 +1892,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - var imageSavePath = Path.Combine(Path.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension); + var imageSavePath = Path.Combine(_fileSystem.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension); // preserve original image extension imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path)); @@ -2155,11 +2155,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV writer.WriteElementString("mpaa", item.OfficialRating); } - if (!string.IsNullOrEmpty(item.OfficialRatingDescription)) - { - writer.WriteElementString("mpaadescription", item.OfficialRatingDescription); - } - var overview = (item.Overview ?? string.Empty) .StripHtml() .Replace(""", "'"); @@ -2251,11 +2246,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture)); } - if (!string.IsNullOrEmpty(item.CriticRatingSummary)) - { - writer.WriteElementString("criticratingsummary", item.CriticRatingSummary); - } - if (!string.IsNullOrWhiteSpace(item.Tagline)) { writer.WriteElementString("tagline", item.Tagline); @@ -2550,7 +2540,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData) { var path = GetChannelEpgCachePath(channelId); - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); lock (_epgLock) { _jsonSerializer.SerializeToFile(epgData, path); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 6cc5b6920..790e6c27d 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -11,14 +11,16 @@ using MediaBrowser.Model.IO; using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller; -using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; +using MediaBrowser.Common.Configuration; namespace Emby.Server.Implementations.LiveTv.EmbyTV { @@ -37,8 +39,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IProcessFactory _processFactory; private readonly IJsonSerializer _json; private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>(); + private readonly IServerConfigurationManager _config; - public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory) + public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory, IServerConfigurationManager config) { _logger = logger; _fileSystem = fileSystem; @@ -48,6 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _liveTvOptions = liveTvOptions; _httpClient = httpClient; _processFactory = processFactory; + _config = config; } private string OutputFormat @@ -76,23 +80,35 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile) { - return Path.ChangeExtension(targetFile, "." + OutputFormat); + var extension = OutputFormat; + + if (string.Equals(extension, "mpegts", StringComparison.OrdinalIgnoreCase)) + { + extension = "ts"; + } + + return Path.ChangeExtension(targetFile, "." + extension); } public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { - var durationToken = new CancellationTokenSource(duration); - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + //var durationToken = new CancellationTokenSource(duration); + //cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false); _logger.Info("Recording completed to file {0}", targetFile); } + private EncodingOptions GetEncodingOptions() + { + return _config.GetConfiguration<EncodingOptions>("encoding"); + } + private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { _targetPath = targetFile; - _fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile)); var process = _processFactory.Create(new ProcessOptions { @@ -118,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _logger.Info(commandLineLogMessage); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. _logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); @@ -162,28 +178,32 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks); - var inputModifiers = "-fflags +genpts -async 1 -vsync -1"; - var commandLineArgs = "-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\""; - - long startTimeTicks = 0; - //if (mediaSource.DateLiveStreamOpened.HasValue) - //{ - // var elapsed = DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value; - // elapsed -= TimeSpan.FromSeconds(10); - // if (elapsed.TotalSeconds >= 0) - // { - // startTimeTicks = elapsed.Ticks + startTimeTicks; - // } - //} - if (mediaSource.ReadAtNativeFramerate) + var flags = new List<string>(); + if (mediaSource.IgnoreDts) { - inputModifiers += " -re"; + flags.Add("+igndts"); + } + if (mediaSource.IgnoreIndex) + { + flags.Add("+ignidx"); } - if (startTimeTicks > 0) + var inputModifiers = "-async 1 -vsync -1"; + + if (flags.Count > 0) + { + inputModifiers += " -fflags " + string.Join("", flags.ToArray()); + } + + if (!string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareAccelerationType)) + { + inputModifiers += " -hwaccel auto"; + } + + if (mediaSource.ReadAtNativeFramerate) { - inputModifiers = "-ss " + _mediaEncoder.GetTimeParameter(startTimeTicks) + " " + inputModifiers; + inputModifiers += " -re"; } var analyzeDurationSeconds = 5; @@ -193,11 +213,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn"; - var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ? - " -f mp4 -movflags frag_keyframe+empty_moov" : - string.Empty; + //var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ? + // " -f mp4 -movflags frag_keyframe+empty_moov" : + // string.Empty; + + var outputParam = string.Empty; - commandLineArgs = string.Format(commandLineArgs, inputTempFile, targetFile, videoArgs, GetAudioArgs(mediaSource), subtitleArgs, durationParam, outputParam); + var commandLineArgs = string.Format("-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"", + inputTempFile, + targetFile, + videoArgs, + GetAudioArgs(mediaSource), + subtitleArgs, + durationParam, + outputParam); return inputModifiers + " " + commandLineArgs; } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 16ae26d45..953cb8e41 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } var file = _dataPath + ".json"; - _fileSystem.CreateDirectory(Path.GetDirectoryName(file)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(file)); lock (_fileDataLock) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index fc0a826b4..b50f5ac92 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings }).ConfigureAwait(false); - _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFile)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile)); using (var stream = _fileSystem.OpenRead(tempFile)) { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index a898d3084..fa86ac36d 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -857,7 +857,8 @@ namespace Emby.Server.Implementations.LiveTv _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) { MetadataRefreshMode = metadataRefreshMode - }); + + }, RefreshPriority.Normal); } return item.Id; @@ -1395,11 +1396,11 @@ namespace Emby.Server.Implementations.LiveTv foreach (var program in newPrograms) { - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); + _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low); } foreach (var program in updatedPrograms) { - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); + _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low); } currentChannel.IsMovie = isMovie; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 0a21603ee..d724a9fbc 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -420,7 +420,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun SupportsDirectPlay = false, SupportsDirectStream = true, SupportsTranscoding = true, - IsInfiniteStream = true + IsInfiniteStream = true, + IgnoreDts = true }; mediaSource.InferTotalBitrate(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs index abd7a00a9..02ebbcf16 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs @@ -29,6 +29,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts byte[] buffer = new byte[BufferSize]; + if (source == null) + { + throw new ArgumentNullException("source"); + } + while (!cancellationToken.IsCancellationRequested) { var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs b/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs index 5183f3a0b..7104935e1 100644 --- a/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs +++ b/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs @@ -29,15 +29,17 @@ namespace Emby.Server.Implementations.Logging _logManager.Flush(); var path = Path.Combine(_appPaths.LogDirectoryPath, "unhandled_" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); var builder = LogHelper.GetLogMessage(ex); // Write to console just in case file logging fails _console.WriteLine("UnhandledException"); - _console.WriteLine(builder.ToString()); - _fileSystem.WriteAllText(path, builder.ToString()); + var logMessage = builder.ToString(); + _console.WriteLine(logMessage); + + _fileSystem.WriteAllText(path, logMessage); } } } diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 204e04061..884a001f0 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.MediaEncoder var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames); - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); var container = video.Container; diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 386da73c6..18042b587 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -201,7 +201,8 @@ namespace Emby.Server.Implementations.Playlists _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem) { ForceSave = true - }); + + }, RefreshPriority.High); } public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds) @@ -228,7 +229,8 @@ namespace Emby.Server.Implementations.Playlists _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem) { ForceSave = true - }); + + }, RefreshPriority.High); } public async Task MoveItem(string playlistId, string entryId, int newIndex) diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index 5f37025e2..d1c70ba1d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { previouslyFailedImages.Add(key); - var parentPath = Path.GetDirectoryName(failHistoryPath); + var parentPath = _fileSystem.GetDirectoryName(failHistoryPath); _fileSystem.CreateDirectory(parentPath); diff --git a/Emby.Server.Implementations/Security/MBLicenseFile.cs b/Emby.Server.Implementations/Security/MBLicenseFile.cs index c791d6a52..dc0e8b161 100644 --- a/Emby.Server.Implementations/Security/MBLicenseFile.cs +++ b/Emby.Server.Implementations/Security/MBLicenseFile.cs @@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.Security } var licenseFile = Filename; - _fileSystem.CreateDirectory(Path.GetDirectoryName(licenseFile)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(licenseFile)); lock (_fileLock) { _fileSystem.WriteAllLines(licenseFile, lines); diff --git a/Emby.Server.Implementations/Session/HttpSessionController.cs b/Emby.Server.Implementations/Session/HttpSessionController.cs index cea5d9b40..2acc3902f 100644 --- a/Emby.Server.Implementations/Session/HttpSessionController.cs +++ b/Emby.Server.Implementations/Session/HttpSessionController.cs @@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.Session public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken) { - return Task.FromResult(true); + return SendMessage("LibraryChanged", info, cancellationToken); } public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 0a2312735..de00cf239 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -715,7 +715,8 @@ namespace Emby.Server.Implementations.Session ClientName = session.Client, DeviceId = session.DeviceId, IsPaused = info.IsPaused, - PlaySessionId = info.PlaySessionId + PlaySessionId = info.PlaySessionId, + IsAutomated = isAutomated }, _logger); diff --git a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs index b315d33c3..b441a29c1 100644 --- a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs @@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting { var hasSeries = item as IHasSeries; - return hasSeries != null ? hasSeries.SeriesSortName : null; + return hasSeries != null ? hasSeries.FindSeriesSortName() : null; } /// <summary> diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 840c7ce0d..57019cc4e 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.Updates }).ConfigureAwait(false); - _fileSystem.CreateDirectory(Path.GetDirectoryName(PackageCachePath)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(PackageCachePath)); _fileSystem.CopyFile(tempFile, PackageCachePath, true); _lastPackageUpdateTime = DateTime.UtcNow; @@ -627,7 +627,7 @@ namespace Emby.Server.Implementations.Updates // Success - move it to the real target try { - _fileSystem.CreateDirectory(Path.GetDirectoryName(target)); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(target)); _fileSystem.CopyFile(tempFile, target, true); //If it is an archive - write out a version file so we know what it is if (isArchive) |
