aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorCody Robibero <cody@robibe.ro>2023-11-09 22:03:55 -0700
committerGitHub <noreply@github.com>2023-11-09 22:03:55 -0700
commit892973a9e372000ad7babe2381e4e83b39591951 (patch)
treefc408136c09e6377309629ad6b2d4b2b26ff3c3f /MediaBrowser.Controller
parent35bd0c00c965176d6ddb167605ed3a3eba9a4524 (diff)
parent44b771bfb4b6412360b18c80621c90902c0a43a7 (diff)
Merge branch 'master' into media-type
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs1
-rw-r--r--MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs1
-rw-r--r--MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs9
-rw-r--r--MediaBrowser.Controller/Drawing/IImageEncoder.cs10
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs2
-rw-r--r--MediaBrowser.Controller/Entities/BaseItemExtensions.cs5
-rw-r--r--MediaBrowser.Controller/Entities/BasePluginFolder.cs3
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs2
-rw-r--r--MediaBrowser.Controller/Entities/ICollectionFolder.cs3
-rw-r--r--MediaBrowser.Controller/Entities/IHasDisplayOrder.cs2
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs8
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs37
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs78
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs24
-rw-r--r--MediaBrowser.Controller/Library/IUserViewManager.cs3
-rw-r--r--MediaBrowser.Controller/Library/ItemResolveArgs.cs7
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvProgram.cs2
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj6
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs76
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs32
-rw-r--r--MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs2
-rw-r--r--MediaBrowser.Controller/Providers/EpisodeInfo.cs1
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs1
-rw-r--r--MediaBrowser.Controller/Resolvers/IItemResolver.cs3
-rw-r--r--MediaBrowser.Controller/Session/SessionInfo.cs6
-rw-r--r--MediaBrowser.Controller/Sorting/IBaseItemComparer.cs6
-rw-r--r--MediaBrowser.Controller/Trickplay/ITrickplayManager.cs76
29 files changed, 297 insertions, 120 deletions
diff --git a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs
index b263c173e..6acab13fe 100644
--- a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs
+++ b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
diff --git a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs
index ac20120d9..975218ad7 100644
--- a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs
+++ b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs
@@ -1,4 +1,3 @@
-using System.Threading;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
diff --git a/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs b/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs
index dea1c2f32..2a7e6be0f 100644
--- a/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs
+++ b/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs
@@ -23,9 +23,12 @@ namespace MediaBrowser.Controller.ClientEvent
{
var fileName = $"upload_{clientName}_{clientVersion}_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid():N}.log";
var logFilePath = Path.Combine(_applicationPaths.LogDirectoryPath, fileName);
- await using var fileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None);
- await fileContents.CopyToAsync(fileStream).ConfigureAwait(false);
- return fileName;
+ var fileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None);
+ await using (fileStream.ConfigureAwait(false))
+ {
+ await fileContents.CopyToAsync(fileStream).ConfigureAwait(false);
+ return fileName;
+ }
}
}
}
diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
index e5c8ebfaf..c7bfbdb53 100644
--- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs
+++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
@@ -81,5 +81,15 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="posters">The list of poster paths.</param>
/// <param name="backdrops">The list of backdrop paths.</param>
void CreateSplashscreen(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops);
+
+ /// <summary>
+ /// Creates a new trickplay tile image.
+ /// </summary>
+ /// <param name="options">The options to use when creating the image. Width and Height are a quantity of thumbnails in this case, not pixels.</param>
+ /// <param name="quality">The image encode quality.</param>
+ /// <param name="imgWidth">The width of a single trickplay thumbnail.</param>
+ /// <param name="imgHeight">Optional height of a single trickplay thumbnail, if it is known.</param>
+ /// <returns>Height of single decoded trickplay thumbnail.</returns>
+ int CreateTrickplayTile(ImageCollageOptions options, int quality, int imgWidth, int? imgHeight);
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index f83065a01..98485f9a8 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -724,7 +724,7 @@ namespace MediaBrowser.Controller.Entities
if (this is IHasCollectionType view)
{
- if (string.Equals(view.CollectionType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
+ if (view.CollectionType == CollectionType.LiveTv)
{
return true;
}
diff --git a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs
index 615d236c7..dcd22a3b4 100644
--- a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs
+++ b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs
@@ -95,10 +95,7 @@ namespace MediaBrowser.Controller.Entities
}
var p = destProps.Find(x => x.Name == sourceProp.Name);
- if (p is not null)
- {
- p.SetValue(dest, v);
- }
+ p?.SetValue(dest, v);
}
}
diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
index afafaf1c2..4bf21061c 100644
--- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs
+++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
@@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System.Text.Json.Serialization;
+using Jellyfin.Data.Enums;
namespace MediaBrowser.Controller.Entities
{
@@ -11,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
public abstract class BasePluginFolder : Folder, ICollectionFolder
{
[JsonIgnore]
- public virtual string? CollectionType => null;
+ public virtual CollectionType? CollectionType => null;
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index f51162f9d..992bb19bb 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -11,6 +11,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
using Jellyfin.Extensions.Json;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
@@ -69,7 +70,7 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
- public string CollectionType { get; set; }
+ public CollectionType? CollectionType { get; set; }
/// <summary>
/// Gets the item's children.
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 44fe65103..e707eedbf 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -598,7 +598,7 @@ namespace MediaBrowser.Controller.Entities
for (var i = 0; i < childrenCount; i++)
{
- await actionBlock.SendAsync(i).ConfigureAwait(false);
+ await actionBlock.SendAsync(i, cancellationToken).ConfigureAwait(false);
}
actionBlock.Complete();
diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs
index 89e494ebc..742691b00 100644
--- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/ICollectionFolder.cs
@@ -3,6 +3,7 @@
#pragma warning disable CA1819, CS1591
using System;
+using Jellyfin.Data.Enums;
namespace MediaBrowser.Controller.Entities
{
@@ -27,6 +28,6 @@ namespace MediaBrowser.Controller.Entities
public interface IHasCollectionType
{
- string CollectionType { get; }
+ CollectionType? CollectionType { get; }
}
}
diff --git a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs b/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs
index 14459624e..7a73f3eaf 100644
--- a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs
+++ b/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs
@@ -1,5 +1,7 @@
#nullable disable
+using Jellyfin.Data.Enums;
+
namespace MediaBrowser.Controller.Entities
{
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 2de974349..555dd050c 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -39,10 +39,10 @@ namespace MediaBrowser.Controller.Entities
MediaTypes = Array.Empty<MediaType>();
MinSimilarityScore = 20;
OfficialRatings = Array.Empty<string>();
- OrderBy = Array.Empty<(string, SortOrder)>();
+ OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
PersonIds = Array.Empty<Guid>();
PersonTypes = Array.Empty<string>();
- PresetViews = Array.Empty<string>();
+ PresetViews = Array.Empty<CollectionType?>();
SeriesStatuses = Array.Empty<SeriesStatus>();
SourceTypes = Array.Empty<SourceType>();
StudioIds = Array.Empty<Guid>();
@@ -248,7 +248,7 @@ namespace MediaBrowser.Controller.Entities
public Guid[] TopParentIds { get; set; }
- public string[] PresetViews { get; set; }
+ public CollectionType?[] PresetViews { get; set; }
public TrailerType[] TrailerTypes { get; set; }
@@ -284,7 +284,7 @@ namespace MediaBrowser.Controller.Entities
public bool? HasChapterImages { get; set; }
- public IReadOnlyList<(string OrderBy, SortOrder SortOrder)> OrderBy { get; set; }
+ public IReadOnlyList<(ItemSortBy OrderBy, SortOrder SortOrder)> OrderBy { get; set; }
public DateTime? MinDateCreated { get; set; }
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 66210cb6c..d7ccfd8ae 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Entities.Movies
{
public BoxSet()
{
- DisplayOrder = ItemSortBy.PremiereDate;
+ DisplayOrder = "PremiereDate";
}
[JsonIgnore]
@@ -116,13 +116,13 @@ namespace MediaBrowser.Controller.Entities.Movies
{
var children = base.GetChildren(user, includeLinkedChildren, query);
- if (string.Equals(DisplayOrder, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(DisplayOrder, "SortName", StringComparison.OrdinalIgnoreCase))
{
// Sort by name
return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
}
- if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase))
{
// Sort by release date
return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList();
@@ -136,7 +136,7 @@ namespace MediaBrowser.Controller.Entities.Movies
{
var children = base.GetRecursiveChildren(user, query);
- if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase))
{
// Sort by release date
return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList();
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 47432ee93..1f94cf767 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Querying;
@@ -16,21 +17,21 @@ namespace MediaBrowser.Controller.Entities
{
public class UserView : Folder, IHasCollectionType
{
- private static readonly string[] _viewTypesEligibleForGrouping = new string[]
+ private static readonly CollectionType?[] _viewTypesEligibleForGrouping =
{
- Model.Entities.CollectionType.Movies,
- Model.Entities.CollectionType.TvShows,
- string.Empty
+ Jellyfin.Data.Enums.CollectionType.Movies,
+ Jellyfin.Data.Enums.CollectionType.TvShows,
+ null
};
- private static readonly string[] _originalFolderViewTypes = new string[]
+ private static readonly CollectionType?[] _originalFolderViewTypes =
{
- Model.Entities.CollectionType.Books,
- Model.Entities.CollectionType.MusicVideos,
- Model.Entities.CollectionType.HomeVideos,
- Model.Entities.CollectionType.Photos,
- Model.Entities.CollectionType.Music,
- Model.Entities.CollectionType.BoxSets
+ Jellyfin.Data.Enums.CollectionType.Books,
+ Jellyfin.Data.Enums.CollectionType.MusicVideos,
+ Jellyfin.Data.Enums.CollectionType.HomeVideos,
+ Jellyfin.Data.Enums.CollectionType.Photos,
+ Jellyfin.Data.Enums.CollectionType.Music,
+ Jellyfin.Data.Enums.CollectionType.BoxSets
};
public static ITVSeriesManager TVSeriesManager { get; set; }
@@ -38,7 +39,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Gets or sets the view type.
/// </summary>
- public string ViewType { get; set; }
+ public CollectionType? ViewType { get; set; }
/// <summary>
/// Gets or sets the display parent id.
@@ -52,7 +53,7 @@ namespace MediaBrowser.Controller.Entities
/// <inheritdoc />
[JsonIgnore]
- public string CollectionType => ViewType;
+ public CollectionType? CollectionType => ViewType;
/// <inheritdoc />
[JsonIgnore]
@@ -160,7 +161,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- return string.Equals(Model.Entities.CollectionType.Playlists, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase);
+ return collectionFolder.CollectionType == Jellyfin.Data.Enums.CollectionType.Playlists;
}
public static bool IsEligibleForGrouping(Folder folder)
@@ -169,14 +170,14 @@ namespace MediaBrowser.Controller.Entities
&& IsEligibleForGrouping(collectionFolder.CollectionType);
}
- public static bool IsEligibleForGrouping(string viewType)
+ public static bool IsEligibleForGrouping(CollectionType? viewType)
{
- return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
+ return _viewTypesEligibleForGrouping.Contains(viewType);
}
- public static bool EnableOriginalFolder(string viewType)
+ public static bool EnableOriginalFolder(CollectionType? viewType)
{
- return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
+ return _originalFolderViewTypes.Contains(viewType);
}
protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken)
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 5f187e64e..42431c832 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Controller.Entities
_tvSeriesManager = tvSeriesManager;
}
- public QueryResult<BaseItem> GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query)
+ public QueryResult<BaseItem> GetUserItems(Folder queryParent, Folder displayParent, CollectionType? viewType, InternalItemsQuery query)
{
var user = query.User;
@@ -67,49 +67,49 @@ namespace MediaBrowser.Controller.Entities
case CollectionType.Movies:
return GetMovieFolders(queryParent, user, query);
- case SpecialFolder.TvShowSeries:
+ case CollectionType.TvShowSeries:
return GetTvSeries(queryParent, user, query);
- case SpecialFolder.TvGenres:
+ case CollectionType.TvGenres:
return GetTvGenres(queryParent, user, query);
- case SpecialFolder.TvGenre:
+ case CollectionType.TvGenre:
return GetTvGenreItems(queryParent, displayParent, user, query);
- case SpecialFolder.TvResume:
+ case CollectionType.TvResume:
return GetTvResume(queryParent, user, query);
- case SpecialFolder.TvNextUp:
+ case CollectionType.TvNextUp:
return GetTvNextUp(queryParent, query);
- case SpecialFolder.TvLatest:
+ case CollectionType.TvLatest:
return GetTvLatest(queryParent, user, query);
- case SpecialFolder.MovieFavorites:
+ case CollectionType.MovieFavorites:
return GetFavoriteMovies(queryParent, user, query);
- case SpecialFolder.MovieLatest:
+ case CollectionType.MovieLatest:
return GetMovieLatest(queryParent, user, query);
- case SpecialFolder.MovieGenres:
+ case CollectionType.MovieGenres:
return GetMovieGenres(queryParent, user, query);
- case SpecialFolder.MovieGenre:
+ case CollectionType.MovieGenre:
return GetMovieGenreItems(queryParent, displayParent, user, query);
- case SpecialFolder.MovieResume:
+ case CollectionType.MovieResume:
return GetMovieResume(queryParent, user, query);
- case SpecialFolder.MovieMovies:
+ case CollectionType.MovieMovies:
return GetMovieMovies(queryParent, user, query);
- case SpecialFolder.MovieCollections:
+ case CollectionType.MovieCollections:
return GetMovieCollections(user, query);
- case SpecialFolder.TvFavoriteEpisodes:
+ case CollectionType.TvFavoriteEpisodes:
return GetFavoriteEpisodes(queryParent, user, query);
- case SpecialFolder.TvFavoriteSeries:
+ case CollectionType.TvFavoriteSeries:
return GetFavoriteSeries(queryParent, user, query);
default:
@@ -146,12 +146,12 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>
{
- GetUserView(SpecialFolder.MovieResume, "HeaderContinueWatching", "0", parent),
- GetUserView(SpecialFolder.MovieLatest, "Latest", "1", parent),
- GetUserView(SpecialFolder.MovieMovies, "Movies", "2", parent),
- GetUserView(SpecialFolder.MovieCollections, "Collections", "3", parent),
- GetUserView(SpecialFolder.MovieFavorites, "Favorites", "4", parent),
- GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent)
+ GetUserView(CollectionType.MovieResume, "HeaderContinueWatching", "0", parent),
+ GetUserView(CollectionType.MovieLatest, "Latest", "1", parent),
+ GetUserView(CollectionType.MovieMovies, "Movies", "2", parent),
+ GetUserView(CollectionType.MovieCollections, "Collections", "3", parent),
+ GetUserView(CollectionType.MovieFavorites, "Favorites", "4", parent),
+ GetUserView(CollectionType.MovieGenres, "Genres", "5", parent)
};
return GetResult(list, query);
@@ -264,7 +264,7 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i is not null)
- .Select(i => GetUserViewWithName(SpecialFolder.MovieGenre, i.SortName, parent));
+ .Select(i => GetUserViewWithName(CollectionType.MovieGenre, i.SortName, parent));
return GetResult(genres, query);
}
@@ -303,13 +303,13 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>
{
- GetUserView(SpecialFolder.TvResume, "HeaderContinueWatching", "0", parent),
- GetUserView(SpecialFolder.TvNextUp, "HeaderNextUp", "1", parent),
- GetUserView(SpecialFolder.TvLatest, "Latest", "2", parent),
- GetUserView(SpecialFolder.TvShowSeries, "Shows", "3", parent),
- GetUserView(SpecialFolder.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent),
- GetUserView(SpecialFolder.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent),
- GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent)
+ GetUserView(CollectionType.TvResume, "HeaderContinueWatching", "0", parent),
+ GetUserView(CollectionType.TvNextUp, "HeaderNextUp", "1", parent),
+ GetUserView(CollectionType.TvLatest, "Latest", "2", parent),
+ GetUserView(CollectionType.TvShowSeries, "Shows", "3", parent),
+ GetUserView(CollectionType.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent),
+ GetUserView(CollectionType.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent),
+ GetUserView(CollectionType.TvGenres, "Genres", "6", parent)
};
return GetResult(list, query);
@@ -330,7 +330,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query)
{
- var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows, string.Empty });
+ var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows });
var result = _tvSeriesManager.GetNextUp(
new NextUpQuery
@@ -392,7 +392,7 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i is not null)
- .Select(i => GetUserViewWithName(SpecialFolder.TvGenre, i.SortName, parent));
+ .Select(i => GetUserViewWithName(CollectionType.TvGenre, i.SortName, parent));
return GetResult(genres, query);
}
@@ -943,7 +943,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
}
- private BaseItem[] GetMediaFolders(User user, IEnumerable<string> viewTypes)
+ private BaseItem[] GetMediaFolders(User user, IEnumerable<CollectionType> viewTypes)
{
if (user is null)
{
@@ -952,7 +952,7 @@ namespace MediaBrowser.Controller.Entities
{
var folder = i as ICollectionFolder;
- return folder is not null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
+ return folder?.CollectionType is not null && viewTypes.Contains(folder.CollectionType.Value);
}).ToArray();
}
@@ -961,11 +961,11 @@ namespace MediaBrowser.Controller.Entities
{
var folder = i as ICollectionFolder;
- return folder is not null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
+ return folder?.CollectionType is not null && viewTypes.Contains(folder.CollectionType.Value);
}).ToArray();
}
- private BaseItem[] GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes)
+ private BaseItem[] GetMediaFolders(Folder parent, User user, IEnumerable<CollectionType> viewTypes)
{
if (parent is null || parent is UserView)
{
@@ -975,12 +975,12 @@ namespace MediaBrowser.Controller.Entities
return new BaseItem[] { parent };
}
- private UserView GetUserViewWithName(string type, string sortName, BaseItem parent)
+ private UserView GetUserViewWithName(CollectionType? type, string sortName, BaseItem parent)
{
- return _userViewManager.GetUserSubView(parent.Id, parent.Id.ToString("N", CultureInfo.InvariantCulture), type, sortName);
+ return _userViewManager.GetUserSubView(parent.Id, type, parent.Id.ToString("N", CultureInfo.InvariantCulture), sortName);
}
- private UserView GetUserView(string type, string localizationKey, string sortName, BaseItem parent)
+ private UserView GetUserView(CollectionType? type, string localizationKey, string sortName, BaseItem parent)
{
return _userViewManager.GetUserSubView(parent.Id, type, localizationKey, sortName);
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index f34e3d68d..9ec22324f 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -79,7 +79,7 @@ namespace MediaBrowser.Controller.Library
IDirectoryService directoryService,
Folder parent,
LibraryOptions libraryOptions,
- string collectionType = null);
+ CollectionType? collectionType = null);
/// <summary>
/// Gets a Person.
@@ -199,9 +199,9 @@ namespace MediaBrowser.Controller.Library
/// <param name="sortBy">The sort by.</param>
/// <param name="sortOrder">The sort order.</param>
/// <returns>IEnumerable{BaseItem}.</returns>
- IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, SortOrder sortOrder);
+ IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ItemSortBy> sortBy, SortOrder sortOrder);
- IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy);
+ IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy);
/// <summary>
/// Gets the user root folder.
@@ -256,28 +256,28 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
- string GetContentType(BaseItem item);
+ CollectionType? GetContentType(BaseItem item);
/// <summary>
/// Gets the type of the inherited content.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
- string GetInheritedContentType(BaseItem item);
+ CollectionType? GetInheritedContentType(BaseItem item);
/// <summary>
/// Gets the type of the configured content.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
- string GetConfiguredContentType(BaseItem item);
+ CollectionType? GetConfiguredContentType(BaseItem item);
/// <summary>
/// Gets the type of the configured content.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.String.</returns>
- string GetConfiguredContentType(string path);
+ CollectionType? GetConfiguredContentType(string path);
/// <summary>
/// Normalizes the root path list.
@@ -329,7 +329,7 @@ namespace MediaBrowser.Controller.Library
User user,
string name,
Guid parentId,
- string viewType,
+ CollectionType? viewType,
string sortName);
/// <summary>
@@ -343,7 +343,7 @@ namespace MediaBrowser.Controller.Library
UserView GetNamedView(
User user,
string name,
- string viewType,
+ CollectionType? viewType,
string sortName);
/// <summary>
@@ -355,7 +355,7 @@ namespace MediaBrowser.Controller.Library
/// <returns>The named view.</returns>
UserView GetNamedView(
string name,
- string viewType,
+ CollectionType viewType,
string sortName);
/// <summary>
@@ -370,7 +370,7 @@ namespace MediaBrowser.Controller.Library
UserView GetNamedView(
string name,
Guid parentId,
- string viewType,
+ CollectionType? viewType,
string sortName,
string uniqueId);
@@ -383,7 +383,7 @@ namespace MediaBrowser.Controller.Library
/// <returns>The shadow view.</returns>
UserView GetShadowView(
BaseItem parent,
- string viewType,
+ CollectionType? viewType,
string sortName);
/// <summary>
diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs
index 055627d3e..a565dc88b 100644
--- a/MediaBrowser.Controller/Library/IUserViewManager.cs
+++ b/MediaBrowser.Controller/Library/IUserViewManager.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Library;
@@ -28,7 +29,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="localizationKey">Localization key to use.</param>
/// <param name="sortName">Sort to use.</param>
/// <returns>User view.</returns>
- UserView GetUserSubView(Guid parentId, string type, string localizationKey, string sortName);
+ UserView GetUserSubView(Guid parentId, CollectionType? type, string localizationKey, string sortName);
/// <summary>
/// Gets latest items.
diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
index dcd0110fb..6202f92f5 100644
--- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs
+++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.IO;
@@ -120,7 +121,7 @@ namespace MediaBrowser.Controller.Library
}
}
- public string CollectionType { get; set; }
+ public CollectionType? CollectionType { get; set; }
public bool HasParent<T>()
where T : Folder
@@ -220,7 +221,7 @@ namespace MediaBrowser.Controller.Library
return GetFileSystemEntryByName(name) is not null;
}
- public string GetCollectionType()
+ public CollectionType? GetCollectionType()
{
return CollectionType;
}
@@ -229,7 +230,7 @@ namespace MediaBrowser.Controller.Library
/// Gets the configured content type for the path.
/// </summary>
/// <returns>The configured content type.</returns>
- public string GetConfiguredContentType()
+ public CollectionType? GetConfiguredContentType()
{
return _libraryManager.GetConfiguredContentType(Path);
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
index c721fb778..05540d490 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvProgram : BaseItem, IHasLookupInfo<ItemLookupInfo>, IHasStartDate, IHasProgramAttributes
{
- private static string EmbyServiceName = "Emby";
+ private const string EmbyServiceName = "Emby";
public LiveTvProgram()
{
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 69c0d26b6..f9468f6cd 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -49,8 +49,12 @@
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
- <!-- Code Analyzers-->
+ <!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="IDisposableAnalyzers">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index fba347bda..6621ae284 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -100,6 +100,13 @@ namespace MediaBrowser.Controller.MediaEncoding
{ "truehd", 6 },
};
+ private static readonly string _defaultMjpegEncoder = "mjpeg";
+ private static readonly Dictionary<string, string> _mjpegCodecMap = new(StringComparer.OrdinalIgnoreCase)
+ {
+ { "vaapi", _defaultMjpegEncoder + "_vaapi" },
+ { "qsv", _defaultMjpegEncoder + "_qsv" }
+ };
+
public static readonly string[] LosslessAudioCodecs = new string[]
{
"alac",
@@ -167,6 +174,24 @@ namespace MediaBrowser.Controller.MediaEncoding
return defaultEncoder;
}
+ private string GetMjpegEncoder(EncodingJobInfo state, EncodingOptions encodingOptions)
+ {
+ if (state.VideoType == VideoType.VideoFile)
+ {
+ var hwType = encodingOptions.HardwareAccelerationType;
+
+ if (!string.IsNullOrEmpty(hwType)
+ && encodingOptions.EnableHardwareEncoding
+ && _mjpegCodecMap.TryGetValue(hwType, out var preferredEncoder)
+ && _mediaEncoder.SupportsEncoder(preferredEncoder))
+ {
+ return preferredEncoder;
+ }
+ }
+
+ return _defaultMjpegEncoder;
+ }
+
private bool IsVaapiSupported(EncodingJobInfo state)
{
// vaapi will throw an error with this input
@@ -300,6 +325,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return GetH264Encoder(state, encodingOptions);
}
+ if (string.Equals(codec, "mjpeg", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetMjpegEncoder(state, encodingOptions);
+ }
+
if (string.Equals(codec, "vp8", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase))
{
@@ -745,12 +775,17 @@ namespace MediaBrowser.Controller.MediaEncoding
private string GetVaapiDeviceArgs(string renderNodePath, string driver, string kernelDriver, string srcDeviceAlias, string alias)
{
alias ??= VaapiAlias;
- renderNodePath = renderNodePath ?? "/dev/dri/renderD128";
- var driverOpts = string.IsNullOrEmpty(driver)
- ? ":" + renderNodePath
- : ":,driver=" + driver + (string.IsNullOrEmpty(kernelDriver) ? string.Empty : ",kernel_driver=" + kernelDriver);
+
+ // 'renderNodePath' has higher priority than 'kernelDriver'
+ var driverOpts = string.IsNullOrEmpty(renderNodePath)
+ ? (string.IsNullOrEmpty(kernelDriver) ? string.Empty : ",kernel_driver=" + kernelDriver)
+ : renderNodePath;
+
+ // 'driver' behaves similarly to env LIBVA_DRIVER_NAME
+ driverOpts += string.IsNullOrEmpty(driver) ? string.Empty : ",driver=" + driver;
+
var options = string.IsNullOrEmpty(srcDeviceAlias)
- ? driverOpts
+ ? (string.IsNullOrEmpty(driverOpts) ? string.Empty : ":" + driverOpts)
: "@" + srcDeviceAlias;
return string.Format(
@@ -872,14 +907,14 @@ namespace MediaBrowser.Controller.MediaEncoding
if (_mediaEncoder.IsVaapiDeviceInteliHD)
{
- args.Append(GetVaapiDeviceArgs(null, "iHD", null, null, VaapiAlias));
+ args.Append(GetVaapiDeviceArgs(options.VaapiDevice, "iHD", null, null, VaapiAlias));
}
else if (_mediaEncoder.IsVaapiDeviceInteli965)
{
// Only override i965 since it has lower priority than iHD in libva lookup.
Environment.SetEnvironmentVariable("LIBVA_DRIVER_NAME", "i965");
Environment.SetEnvironmentVariable("LIBVA_DRIVER_NAME_JELLYFIN", "i965");
- args.Append(GetVaapiDeviceArgs(null, "i965", null, null, VaapiAlias));
+ args.Append(GetVaapiDeviceArgs(options.VaapiDevice, "i965", null, null, VaapiAlias));
}
var filterDevArgs = string.Empty;
@@ -1745,11 +1780,9 @@ namespace MediaBrowser.Controller.MediaEncoding
// Values 0-3, 0 being highest quality but slower
var profileScore = 0;
- string crf;
var qmin = "0";
var qmax = "50";
-
- crf = "10";
+ var crf = "10";
if (isVc1)
{
@@ -2947,7 +2980,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
- "scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2",
+ @"scale=trunc(min(max(iw\,ih*a)\,min({0}\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\,ih)\,min({0}/a\,{1}))/2)*2",
maxWidthParam,
maxHeightParam,
scaleVal);
@@ -2989,7 +3022,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
- "scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2",
+ @"scale=trunc(min(max(iw\,ih*a)\,{0})/{1})*{1}:trunc(ow/a/2)*2",
maxWidthParam,
scaleVal);
}
@@ -3001,7 +3034,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(
CultureInfo.InvariantCulture,
- "scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})",
+ @"scale=trunc(oh*a/{1})*{1}:min(max(iw/a\,ih)\,{0})",
maxHeightParam,
scaleVal);
}
@@ -3021,19 +3054,19 @@ namespace MediaBrowser.Controller.MediaEncoding
switch (threedFormat.Value)
{
case Video3DFormat.HalfSideBySide:
- filter = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
+ filter = @"crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
// hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not.
break;
case Video3DFormat.FullSideBySide:
- filter = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
+ filter = @"crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
// fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to requestedWidth.
break;
case Video3DFormat.HalfTopAndBottom:
- filter = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
+ filter = @"crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
// htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth
break;
case Video3DFormat.FullTopAndBottom:
- filter = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
+ filter = @"crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
// ftab crop height in half, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth
break;
default:
@@ -4919,6 +4952,15 @@ namespace MediaBrowser.Controller.MediaEncoding
subFilters?.RemoveAll(filter => string.IsNullOrEmpty(filter));
overlayFilters?.RemoveAll(filter => string.IsNullOrEmpty(filter));
+ var framerate = GetFramerateParam(state);
+ if (framerate.HasValue)
+ {
+ mainFilters.Insert(0, string.Format(
+ CultureInfo.InvariantCulture,
+ "fps={0}",
+ framerate.Value));
+ }
+
var mainStr = string.Empty;
if (mainFilters?.Count > 0)
{
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 4114dea4f..c2cef4978 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -4,8 +4,10 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
@@ -138,6 +140,36 @@ namespace MediaBrowser.Controller.MediaEncoding
Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, ImageFormat? targetFormat, CancellationToken cancellationToken);
/// <summary>
+ /// Extracts the video images on interval.
+ /// </summary>
+ /// <param name="inputFile">Input file.</param>
+ /// <param name="container">Video container type.</param>
+ /// <param name="mediaSource">Media source information.</param>
+ /// <param name="imageStream">Media stream information.</param>
+ /// <param name="maxWidth">The maximum width.</param>
+ /// <param name="interval">The interval.</param>
+ /// <param name="allowHwAccel">Allow for hardware acceleration.</param>
+ /// <param name="threads">The input/output thread count for ffmpeg.</param>
+ /// <param name="qualityScale">The qscale value for ffmpeg.</param>
+ /// <param name="priority">The process priority for the ffmpeg process.</param>
+ /// <param name="encodingHelper">EncodingHelper instance.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Directory where images where extracted. A given image made before another will always be named with a lower number.</returns>
+ Task<string> ExtractVideoImagesOnIntervalAccelerated(
+ string inputFile,
+ string container,
+ MediaSourceInfo mediaSource,
+ MediaStream imageStream,
+ int maxWidth,
+ TimeSpan interval,
+ bool allowHwAccel,
+ int? threads,
+ int? qualityScale,
+ ProcessPriorityClass? priority,
+ EncodingHelper encodingHelper,
+ CancellationToken cancellationToken);
+
+ /// <summary>
/// Gets the media info.
/// </summary>
/// <param name="request">The request.</param>
diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
index e0942e490..0a706c307 100644
--- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
+++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Net
/// <summary>
/// The logger.
/// </summary>
- protected ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> Logger;
+ protected readonly ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> Logger;
protected BasePeriodicWebSocketListener(ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> logger)
{
diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs
index c4ad352a3..2f7ebb5cc 100644
--- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs
+++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using Jellyfin.Data.Enums;
namespace MediaBrowser.Controller.Providers
{
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 16943f6aa..eb5069b06 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Events;
diff --git a/MediaBrowser.Controller/Resolvers/IItemResolver.cs b/MediaBrowser.Controller/Resolvers/IItemResolver.cs
index 282aa721e..0699734c4 100644
--- a/MediaBrowser.Controller/Resolvers/IItemResolver.cs
+++ b/MediaBrowser.Controller/Resolvers/IItemResolver.cs
@@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System.Collections.Generic;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
@@ -32,7 +33,7 @@ namespace MediaBrowser.Controller.Resolvers
MultiItemResolverResult ResolveMultiple(
Folder parent,
List<FileSystemMetadata> files,
- string collectionType,
+ CollectionType? collectionType,
IDirectoryService directoryService);
}
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index 07ad529b4..3e30c8dc4 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -111,6 +111,12 @@ namespace MediaBrowser.Controller.Session
public DateTime LastPlaybackCheckIn { get; set; }
/// <summary>
+ /// Gets or sets the last paused date.
+ /// </summary>
+ /// <value>The last paused date.</value>
+ public DateTime? LastPausedDate { get; set; }
+
+ /// <summary>
/// Gets or sets the name of the device.
/// </summary>
/// <value>The name of the device.</value>
diff --git a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs
index 07fe1ea8a..96f8a2af5 100644
--- a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs
+++ b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Sorting
@@ -9,9 +10,8 @@ namespace MediaBrowser.Controller.Sorting
public interface IBaseItemComparer : IComparer<BaseItem?>
{
/// <summary>
- /// Gets the name.
+ /// Gets the comparer type.
/// </summary>
- /// <value>The name.</value>
- string Name { get; }
+ ItemSortBy Type { get; }
}
}
diff --git a/MediaBrowser.Controller/Trickplay/ITrickplayManager.cs b/MediaBrowser.Controller/Trickplay/ITrickplayManager.cs
new file mode 100644
index 000000000..0c41f3023
--- /dev/null
+++ b/MediaBrowser.Controller/Trickplay/ITrickplayManager.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Data.Entities;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Configuration;
+
+namespace MediaBrowser.Controller.Trickplay;
+
+/// <summary>
+/// Interface ITrickplayManager.
+/// </summary>
+public interface ITrickplayManager
+{
+ /// <summary>
+ /// Generates new trickplay images and metadata.
+ /// </summary>
+ /// <param name="video">The video.</param>
+ /// <param name="replace">Whether or not existing data should be replaced.</param>
+ /// <param name="cancellationToken">CancellationToken to use for operation.</param>
+ /// <returns>Task.</returns>
+ Task RefreshTrickplayDataAsync(Video video, bool replace, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Creates trickplay tiles out of individual thumbnails.
+ /// </summary>
+ /// <param name="images">Ordered file paths of the thumbnails to be used.</param>
+ /// <param name="width">The width of a single thumbnail.</param>
+ /// <param name="options">The trickplay options.</param>
+ /// <param name="outputDir">The output directory.</param>
+ /// <returns>The associated trickplay information.</returns>
+ /// <remarks>
+ /// The output directory will be DELETED and replaced if it already exists.
+ /// </remarks>
+ TrickplayInfo CreateTiles(List<string> images, int width, TrickplayOptions options, string outputDir);
+
+ /// <summary>
+ /// Get available trickplay resolutions and corresponding info.
+ /// </summary>
+ /// <param name="itemId">The item.</param>
+ /// <returns>Map of width resolutions to trickplay tiles info.</returns>
+ Task<Dictionary<int, TrickplayInfo>> GetTrickplayResolutions(Guid itemId);
+
+ /// <summary>
+ /// Saves trickplay info.
+ /// </summary>
+ /// <param name="info">The trickplay info.</param>
+ /// <returns>Task.</returns>
+ Task SaveTrickplayInfo(TrickplayInfo info);
+
+ /// <summary>
+ /// Gets all trickplay infos for all media streams of an item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>A map of media source id to a map of tile width to trickplay info.</returns>
+ Task<Dictionary<string, Dictionary<int, TrickplayInfo>>> GetTrickplayManifest(BaseItem item);
+
+ /// <summary>
+ /// Gets the path to a trickplay tile image.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="width">The width of a single thumbnail.</param>
+ /// <param name="index">The tile's index.</param>
+ /// <returns>The absolute path.</returns>
+ string GetTrickplayTilePath(BaseItem item, int width, int index);
+
+ /// <summary>
+ /// Gets the trickplay HLS playlist.
+ /// </summary>
+ /// <param name="itemId">The item.</param>
+ /// <param name="width">The width of a single thumbnail.</param>
+ /// <param name="apiKey">Optional api key of the requesting user.</param>
+ /// <returns>The text content of the .m3u8 playlist.</returns>
+ Task<string?> GetHlsPlaylist(Guid itemId, int width, string? apiKey);
+}