aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs4
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs26
-rw-r--r--Emby.Server.Implementations/Collections/CollectionManager.cs18
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs10
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs12
-rw-r--r--Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs18
-rw-r--r--Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs13
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs41
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs6
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs7
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs15
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs23
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs17
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs6
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs13
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs18
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs6
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs32
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs8
-rw-r--r--Emby.Server.Implementations/Localization/Core/is.json11
-rw-r--r--Emby.Server.Implementations/Localization/Core/nl.json6
-rw-r--r--Emby.Server.Implementations/Localization/Core/pt.json3
-rw-r--r--Emby.Server.Implementations/Localization/LocalizationManager.cs80
-rw-r--r--Emby.Server.Implementations/MediaEncoder/EncodingManager.cs24
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs9
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/TaskManager.cs7
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs1
28 files changed, 267 insertions, 173 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index d104058cc..080c44829 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -80,11 +80,13 @@ using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Controller.SyncPlay;
using MediaBrowser.Controller.TV;
using MediaBrowser.LocalMetadata.Savers;
+using MediaBrowser.MediaEncoding.BdInfo;
using MediaBrowser.MediaEncoding.Subtitles;
using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System;
@@ -529,6 +531,8 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<ILocalizationManager, LocalizationManager>();
+ serviceCollection.AddSingleton<IBlurayExaminer, BdInfoExaminer>();
+
serviceCollection.AddSingleton<IUserDataRepository, SqliteUserDataRepository>();
serviceCollection.AddSingleton<IUserDataManager, UserDataManager>();
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index 84ba19464..961e225e9 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -157,16 +157,16 @@ namespace Emby.Server.Implementations.Channels
}
/// <inheritdoc />
- public QueryResult<Channel> GetChannelsInternal(ChannelQuery query)
+ public async Task<QueryResult<Channel>> GetChannelsInternalAsync(ChannelQuery query)
{
var user = query.UserId.Equals(default)
? null
: _userManager.GetUserById(query.UserId);
- var channels = GetAllChannels()
- .Select(GetChannelEntity)
+ var channels = await GetAllChannelEntitiesAsync()
.OrderBy(i => i.SortName)
- .ToList();
+ .ToListAsync()
+ .ConfigureAwait(false);
if (query.IsRecordingsFolder.HasValue)
{
@@ -226,6 +226,7 @@ namespace Emby.Server.Implementations.Channels
if (user is not null)
{
+ var userId = user.Id.ToString("N", CultureInfo.InvariantCulture);
channels = channels.Where(i =>
{
if (!i.IsVisible(user))
@@ -235,7 +236,7 @@ namespace Emby.Server.Implementations.Channels
try
{
- return GetChannelProvider(i).IsEnabledFor(user.Id.ToString("N", CultureInfo.InvariantCulture));
+ return GetChannelProvider(i).IsEnabledFor(userId);
}
catch
{
@@ -258,7 +259,7 @@ namespace Emby.Server.Implementations.Channels
{
foreach (var item in all)
{
- RefreshLatestChannelItems(GetChannelProvider(item), CancellationToken.None).GetAwaiter().GetResult();
+ await RefreshLatestChannelItems(GetChannelProvider(item), CancellationToken.None).ConfigureAwait(false);
}
}
@@ -269,13 +270,13 @@ namespace Emby.Server.Implementations.Channels
}
/// <inheritdoc />
- public QueryResult<BaseItemDto> GetChannels(ChannelQuery query)
+ public async Task<QueryResult<BaseItemDto>> GetChannelsAsync(ChannelQuery query)
{
var user = query.UserId.Equals(default)
? null
: _userManager.GetUserById(query.UserId);
- var internalResult = GetChannelsInternal(query);
+ var internalResult = await GetChannelsInternalAsync(query).ConfigureAwait(false);
var dtoOptions = new DtoOptions();
@@ -327,9 +328,12 @@ namespace Emby.Server.Implementations.Channels
progress.Report(100);
}
- private Channel GetChannelEntity(IChannel channel)
+ private async IAsyncEnumerable<Channel> GetAllChannelEntitiesAsync()
{
- return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).GetAwaiter().GetResult();
+ foreach (IChannel channel in GetAllChannels())
+ {
+ yield return GetChannel(GetInternalChannelId(channel.Name)) ?? await GetChannel(channel, CancellationToken.None).ConfigureAwait(false);
+ }
}
private MediaSourceInfo[] GetSavedMediaSources(BaseItem item)
@@ -401,7 +405,7 @@ namespace Emby.Server.Implementations.Channels
}
else
{
- results = new List<MediaSourceInfo>();
+ results = Enumerable.Empty<MediaSourceInfo>();
}
return results
diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs
index b53c8ca51..179683055 100644
--- a/Emby.Server.Implementations/Collections/CollectionManager.cs
+++ b/Emby.Server.Implementations/Collections/CollectionManager.cs
@@ -206,8 +206,7 @@ namespace Emby.Server.Implementations.Collections
throw new ArgumentException("No collection exists with the supplied Id");
}
- var list = new List<LinkedChild>();
- var itemList = new List<BaseItem>();
+ List<BaseItem>? itemList = null;
var linkedChildrenList = collection.GetLinkedChildren();
var currentLinkedChildrenIds = linkedChildrenList.Select(i => i.Id).ToList();
@@ -223,18 +222,23 @@ namespace Emby.Server.Implementations.Collections
if (!currentLinkedChildrenIds.Contains(id))
{
- itemList.Add(item);
+ (itemList ??= new()).Add(item);
- list.Add(LinkedChild.Create(item));
linkedChildrenList.Add(item);
}
}
- if (list.Count > 0)
+ if (itemList is not null)
{
- LinkedChild[] newChildren = new LinkedChild[collection.LinkedChildren.Length + list.Count];
+ var originalLen = collection.LinkedChildren.Length;
+ var newItemCount = itemList.Count;
+ LinkedChild[] newChildren = new LinkedChild[originalLen + newItemCount];
collection.LinkedChildren.CopyTo(newChildren, 0);
- list.CopyTo(newChildren, collection.LinkedChildren.Length);
+ for (int i = 0; i < newItemCount; i++)
+ {
+ newChildren[originalLen + i] = LinkedChild.Create(itemList[i]);
+ }
+
collection.LinkedChildren = newChildren;
collection.UpdateRatingToItems(linkedChildrenList);
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 0aa943270..3bf4d07c5 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -586,7 +586,7 @@ namespace Emby.Server.Implementations.Data
/// <exception cref="ArgumentNullException">
/// <paramref name="items"/> or <paramref name="cancellationToken"/> is <c>null</c>.
/// </exception>
- public void SaveItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken)
+ public void SaveItems(IReadOnlyList<BaseItem> items, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(items);
@@ -594,9 +594,11 @@ namespace Emby.Server.Implementations.Data
CheckDisposed();
- var tuples = new List<(BaseItem, List<Guid>, BaseItem, string, List<string>)>();
- foreach (var item in items)
+ var itemsLen = items.Count;
+ var tuples = new ValueTuple<BaseItem, List<Guid>, BaseItem, string, List<string>>[itemsLen];
+ for (int i = 0; i < itemsLen; i++)
{
+ var item = items[i];
var ancestorIds = item.SupportsAncestors ?
item.GetAncestorIds().Distinct().ToList() :
null;
@@ -606,7 +608,7 @@ namespace Emby.Server.Implementations.Data
var userdataKey = item.GetUserDataKeys().FirstOrDefault();
var inheritedTags = item.GetInheritedTags();
- tuples.Add((item, ancestorIds, topParent, userdataKey, inheritedTags));
+ tuples[i] = (item, ancestorIds, topParent, userdataKey, inheritedTags);
}
using (var connection = GetConnection())
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index e928f1ff3..45270de89 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -85,8 +85,8 @@ namespace Emby.Server.Implementations.Dto
{
var accessibleItems = user is null ? items : items.Where(x => x.IsVisible(user)).ToList();
var returnItems = new BaseItemDto[accessibleItems.Count];
- var programTuples = new List<(BaseItem, BaseItemDto)>();
- var channelTuples = new List<(BaseItemDto, LiveTvChannel)>();
+ List<(BaseItem, BaseItemDto)> programTuples = null;
+ List<(BaseItemDto, LiveTvChannel)> channelTuples = null;
for (int index = 0; index < accessibleItems.Count; index++)
{
@@ -95,11 +95,11 @@ namespace Emby.Server.Implementations.Dto
if (item is LiveTvChannel tvChannel)
{
- channelTuples.Add((dto, tvChannel));
+ (channelTuples ??= new()).Add((dto, tvChannel));
}
else if (item is LiveTvProgram)
{
- programTuples.Add((item, dto));
+ (programTuples ??= new()).Add((item, dto));
}
if (item is IItemByName byName)
@@ -122,12 +122,12 @@ namespace Emby.Server.Implementations.Dto
returnItems[index] = dto;
}
- if (programTuples.Count > 0)
+ if (programTuples is not null)
{
LivetvManager.AddInfoToProgramDto(programTuples, options.Fields, user).GetAwaiter().GetResult();
}
- if (channelTuples.Count > 0)
+ if (channelTuples is not null)
{
LivetvManager.AddChannelInfo(channelTuples, options, user);
}
diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
index 05d0a9b79..2e3988f9e 100644
--- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
@@ -276,25 +276,31 @@ namespace Emby.Server.Implementations.EntryPoints
/// Libraries the update timer callback.
/// </summary>
/// <param name="state">The state.</param>
- private void LibraryUpdateTimerCallback(object state)
+ private async void LibraryUpdateTimerCallback(object state)
{
+ List<Folder> foldersAddedTo;
+ List<Folder> foldersRemovedFrom;
+ List<BaseItem> itemsUpdated;
+ List<BaseItem> itemsAdded;
+ List<BaseItem> itemsRemoved;
lock (_libraryChangedSyncLock)
{
// Remove dupes in case some were saved multiple times
- var foldersAddedTo = _foldersAddedTo
+ foldersAddedTo = _foldersAddedTo
.DistinctBy(x => x.Id)
.ToList();
- var foldersRemovedFrom = _foldersRemovedFrom
+ foldersRemovedFrom = _foldersRemovedFrom
.DistinctBy(x => x.Id)
.ToList();
- var itemsUpdated = _itemsUpdated
+ itemsUpdated = _itemsUpdated
.Where(i => !_itemsAdded.Contains(i))
.DistinctBy(x => x.Id)
.ToList();
- SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None).GetAwaiter().GetResult();
+ itemsAdded = _itemsAdded.ToList();
+ itemsRemoved = _itemsRemoved.ToList();
if (LibraryUpdateTimer is not null)
{
@@ -308,6 +314,8 @@ namespace Emby.Server.Implementations.EntryPoints
_foldersAddedTo.Clear();
_foldersRemovedFrom.Clear();
}
+
+ await SendChangeNotifications(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo, foldersRemovedFrom, CancellationToken.None).ConfigureAwait(false);
}
/// <summary>
diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
index e724618b3..d32759017 100644
--- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
@@ -87,29 +87,30 @@ namespace Emby.Server.Implementations.EntryPoints
}
}
- private void UpdateTimerCallback(object? state)
+ private async void UpdateTimerCallback(object? state)
{
+ List<KeyValuePair<Guid, List<BaseItem>>> changes;
lock (_syncLock)
{
// Remove dupes in case some were saved multiple times
- var changes = _changedItems.ToList();
+ changes = _changedItems.ToList();
_changedItems.Clear();
- SendNotifications(changes, CancellationToken.None).GetAwaiter().GetResult();
-
if (_updateTimer is not null)
{
_updateTimer.Dispose();
_updateTimer = null;
}
}
+
+ await SendNotifications(changes, CancellationToken.None).ConfigureAwait(false);
}
private async Task SendNotifications(List<KeyValuePair<Guid, List<BaseItem>>> changes, CancellationToken cancellationToken)
{
- foreach (var pair in changes)
+ foreach ((var key, var value) in changes)
{
- await SendNotifications(pair.Key, pair.Value, cancellationToken).ConfigureAwait(false);
+ await SendNotifications(key, value, cancellationToken).ConfigureAwait(false);
}
}
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index a3c66dc79..e5c520ca2 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -113,6 +113,7 @@ namespace Emby.Server.Implementations.Library
/// <param name="imageProcessor">The image processor.</param>
/// <param name="memoryCache">The memory cache.</param>
/// <param name="namingOptions">The naming options.</param>
+ /// <param name="directoryService">The directory service.</param>
public LibraryManager(
IServerApplicationHost appHost,
ILoggerFactory loggerFactory,
@@ -128,7 +129,8 @@ namespace Emby.Server.Implementations.Library
IItemRepository itemRepository,
IImageProcessor imageProcessor,
IMemoryCache memoryCache,
- NamingOptions namingOptions)
+ NamingOptions namingOptions,
+ IDirectoryService directoryService)
{
_appHost = appHost;
_logger = loggerFactory.CreateLogger<LibraryManager>();
@@ -146,7 +148,7 @@ namespace Emby.Server.Implementations.Library
_memoryCache = memoryCache;
_namingOptions = namingOptions;
- _extraResolver = new ExtraResolver(loggerFactory.CreateLogger<ExtraResolver>(), namingOptions);
+ _extraResolver = new ExtraResolver(loggerFactory.CreateLogger<ExtraResolver>(), namingOptions, directoryService);
_configurationManager.ConfigurationUpdated += ConfigurationUpdated;
@@ -356,8 +358,8 @@ namespace Emby.Server.Implementations.Library
}
var children = item.IsFolder
- ? ((Folder)item).GetRecursiveChildren(false).ToList()
- : new List<BaseItem>();
+ ? ((Folder)item).GetRecursiveChildren(false)
+ : Enumerable.Empty<BaseItem>();
foreach (var metadataPath in GetMetadataPaths(item, children))
{
@@ -537,7 +539,7 @@ namespace Emby.Server.Implementations.Library
collectionType = GetContentTypeOverride(fullPath, true);
}
- var args = new ItemResolveArgs(_configurationManager.ApplicationPaths, directoryService)
+ var args = new ItemResolveArgs(_configurationManager.ApplicationPaths, this)
{
Parent = parent,
FileInfo = fileInfo,
@@ -1253,7 +1255,7 @@ namespace Emby.Server.Implementations.Library
var parent = GetItemById(query.ParentId);
if (parent is not null)
{
- SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent });
+ SetTopParentIdsOrAncestors(query, new[] { parent });
}
}
@@ -1277,7 +1279,7 @@ namespace Emby.Server.Implementations.Library
var parent = GetItemById(query.ParentId);
if (parent is not null)
{
- SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent });
+ SetTopParentIdsOrAncestors(query, new[] { parent });
}
}
@@ -1435,7 +1437,7 @@ namespace Emby.Server.Implementations.Library
var parent = GetItemById(query.ParentId);
if (parent is not null)
{
- SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent });
+ SetTopParentIdsOrAncestors(query, new[] { parent });
}
}
@@ -1455,7 +1457,7 @@ namespace Emby.Server.Implementations.Library
_itemRepository.GetItemList(query));
}
- private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List<BaseItem> parents)
+ private void SetTopParentIdsOrAncestors(InternalItemsQuery query, IReadOnlyCollection<BaseItem> parents)
{
if (parents.All(i => i is ICollectionFolder || i is UserView))
{
@@ -1602,7 +1604,7 @@ namespace Emby.Server.Implementations.Library
{
_logger.LogError(ex, "Error getting intros");
- return new List<IntroInfo>();
+ return Enumerable.Empty<IntroInfo>();
}
}
@@ -2876,7 +2878,7 @@ namespace Emby.Server.Implementations.Library
private async Task SavePeopleMetadataAsync(IEnumerable<PersonInfo> people, CancellationToken cancellationToken)
{
- var personsToSave = new List<BaseItem>();
+ List<BaseItem> personsToSave = null;
foreach (var person in people)
{
@@ -2918,12 +2920,12 @@ namespace Emby.Server.Implementations.Library
if (saveEntity)
{
- personsToSave.Add(personEntity);
+ (personsToSave ??= new()).Add(personEntity);
await RunMetadataSavers(personEntity, itemUpdateType).ConfigureAwait(false);
}
}
- if (personsToSave.Count > 0)
+ if (personsToSave is not null)
{
CreateItems(personsToSave, null, CancellationToken.None);
}
@@ -3085,22 +3087,19 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(path));
}
- var removeList = new List<NameValuePair>();
+ List<NameValuePair> removeList = null;
foreach (var contentType in _configurationManager.Configuration.ContentTypes)
{
- if (string.IsNullOrWhiteSpace(contentType.Name))
- {
- removeList.Add(contentType);
- }
- else if (_fileSystem.AreEqual(path, contentType.Name)
+ if (string.IsNullOrWhiteSpace(contentType.Name)
+ || _fileSystem.AreEqual(path, contentType.Name)
|| _fileSystem.ContainsSubPath(path, contentType.Name))
{
- removeList.Add(contentType);
+ (removeList ??= new()).Add(contentType);
}
}
- if (removeList.Count > 0)
+ if (removeList is not null)
{
_configurationManager.Configuration.ContentTypes = _configurationManager.Configuration.ContentTypes
.Except(removeList)
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
index 06621700a..a74f82475 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
@@ -158,7 +158,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
private MultiItemResolverResult ResolveMultipleAudio(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, bool parseName)
{
var files = new List<FileSystemMetadata>();
- var items = new List<BaseItem>();
var leftOver = new List<FileSystemMetadata>();
// Loop through each child file/folder and see if we find a video
@@ -180,7 +179,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
var result = new MultiItemResolverResult
{
ExtraFiles = leftOver,
- Items = items
+ Items = new List<BaseItem>()
};
var isInMixedFolder = resolverResult.Count > 1 || (parent is not null && parent.IsTopParent);
@@ -193,7 +192,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
continue;
}
- if (resolvedItem.Files.Count == 0)
+ // Until multi-part books are handled letting files stack hides them from browsing in the client
+ if (resolvedItem.Files.Count == 0 || resolvedItem.Extras.Count > 0 || resolvedItem.AlternateVersions.Count > 0)
{
continue;
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index a922e3685..bbc70701c 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -25,16 +25,19 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
private readonly ILogger<MusicAlbumResolver> _logger;
private readonly NamingOptions _namingOptions;
+ private readonly IDirectoryService _directoryService;
/// <summary>
/// Initializes a new instance of the <see cref="MusicAlbumResolver"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="namingOptions">The naming options.</param>
- public MusicAlbumResolver(ILogger<MusicAlbumResolver> logger, NamingOptions namingOptions)
+ /// <param name="directoryService">The directory service.</param>
+ public MusicAlbumResolver(ILogger<MusicAlbumResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService)
{
_logger = logger;
_namingOptions = namingOptions;
+ _directoryService = directoryService;
}
/// <summary>
@@ -109,7 +112,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
}
// If args contains music it's a music album
- if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService))
+ if (ContainsMusic(args.FileSystemChildren, true, _directoryService))
{
return true;
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
index 2538c2b5b..c858dc53d 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Emby.Naming.Common;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging;
@@ -18,19 +19,23 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
public class MusicArtistResolver : ItemResolver<MusicArtist>
{
private readonly ILogger<MusicAlbumResolver> _logger;
- private NamingOptions _namingOptions;
+ private readonly NamingOptions _namingOptions;
+ private readonly IDirectoryService _directoryService;
/// <summary>
/// Initializes a new instance of the <see cref="MusicArtistResolver"/> class.
/// </summary>
/// <param name="logger">Instance of the <see cref="MusicAlbumResolver"/> interface.</param>
/// <param name="namingOptions">The <see cref="NamingOptions"/>.</param>
+ /// <param name="directoryService">The directory service.</param>
public MusicArtistResolver(
ILogger<MusicAlbumResolver> logger,
- NamingOptions namingOptions)
+ NamingOptions namingOptions,
+ IDirectoryService directoryService)
{
_logger = logger;
_namingOptions = namingOptions;
+ _directoryService = directoryService;
}
/// <summary>
@@ -78,9 +83,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return null;
}
- var directoryService = args.DirectoryService;
-
- var albumResolver = new MusicAlbumResolver(_logger, _namingOptions);
+ var albumResolver = new MusicAlbumResolver(_logger, _namingOptions, _directoryService);
var directories = args.FileSystemChildren.Where(i => i.IsDirectory);
@@ -97,7 +100,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
}
// If we contain a music album assume we are an artist folder
- if (albumResolver.IsMusicAlbum(fileSystemInfo.FullName, directoryService))
+ if (albumResolver.IsMusicAlbum(fileSystemInfo.FullName, _directoryService))
{
// Stop once we see a music album
state.Stop();
diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
index e8615e7db..4fac91bf1 100644
--- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
@@ -25,14 +25,17 @@ namespace Emby.Server.Implementations.Library.Resolvers
{
private readonly ILogger _logger;
- protected BaseVideoResolver(ILogger logger, NamingOptions namingOptions)
+ protected BaseVideoResolver(ILogger logger, NamingOptions namingOptions, IDirectoryService directoryService)
{
_logger = logger;
NamingOptions = namingOptions;
+ DirectoryService = directoryService;
}
protected NamingOptions NamingOptions { get; }
+ protected IDirectoryService DirectoryService { get; }
+
/// <summary>
/// Resolves the specified args.
/// </summary>
@@ -65,13 +68,25 @@ namespace Emby.Server.Implementations.Library.Resolvers
var filename = child.Name;
if (child.IsDirectory)
{
- if (IsDvdDirectory(child.FullName, filename, args.DirectoryService))
+ if (IsDvdDirectory(child.FullName, filename, DirectoryService))
{
- videoType = VideoType.Dvd;
+ var videoTmp = new TVideoType
+ {
+ Path = args.Path,
+ VideoType = VideoType.Dvd
+ };
+ Set3DFormat(videoTmp);
+ return videoTmp;
}
else if (IsBluRayDirectory(filename))
{
- videoType = VideoType.BluRay;
+ var videoTmp = new TVideoType
+ {
+ Path = args.Path,
+ VideoType = VideoType.BluRay
+ };
+ Set3DFormat(videoTmp);
+ return videoTmp;
}
}
else if (IsDvdFile(filename))
diff --git a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
index 30c52e19d..b4791b945 100644
--- a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
@@ -4,6 +4,8 @@ using System.IO;
using Emby.Naming.Common;
using Emby.Naming.Video;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging;
@@ -14,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
/// <summary>
/// Resolves a Path into a Video or Video subclass.
/// </summary>
- internal class ExtraResolver
+ internal class ExtraResolver : BaseVideoResolver<Video>
{
private readonly NamingOptions _namingOptions;
private readonly IItemResolver[] _trailerResolvers;
@@ -25,11 +27,18 @@ namespace Emby.Server.Implementations.Library.Resolvers
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="namingOptions">An instance of <see cref="NamingOptions"/>.</param>
- public ExtraResolver(ILogger<ExtraResolver> logger, NamingOptions namingOptions)
+ /// <param name="directoryService">The directory service.</param>
+ public ExtraResolver(ILogger<ExtraResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService)
+ : base(logger, namingOptions, directoryService)
{
_namingOptions = namingOptions;
- _trailerResolvers = new IItemResolver[] { new GenericVideoResolver<Trailer>(logger, namingOptions) };
- _videoResolvers = new IItemResolver[] { new GenericVideoResolver<Video>(logger, namingOptions) };
+ _trailerResolvers = new IItemResolver[] { new GenericVideoResolver<Trailer>(logger, namingOptions, directoryService) };
+ _videoResolvers = new IItemResolver[] { this };
+ }
+
+ protected override Video Resolve(ItemResolveArgs args)
+ {
+ return ResolveVideo<Video>(args, true);
}
/// <summary>
diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs
index 5e33b402d..ba320266a 100644
--- a/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs
@@ -2,6 +2,7 @@
using Emby.Naming.Common;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers
@@ -18,8 +19,9 @@ namespace Emby.Server.Implementations.Library.Resolvers
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="namingOptions">The naming options.</param>
- public GenericVideoResolver(ILogger logger, NamingOptions namingOptions)
- : base(logger, namingOptions)
+ /// <param name="directoryService">The directory service.</param>
+ public GenericVideoResolver(ILogger logger, NamingOptions namingOptions, IDirectoryService directoryService)
+ : base(logger, namingOptions, directoryService)
{
}
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index ef4fa1fd2..ea980b992 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -43,8 +43,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
/// <param name="imageProcessor">The image processor.</param>
/// <param name="logger">The logger.</param>
/// <param name="namingOptions">The naming options.</param>
- public MovieResolver(IImageProcessor imageProcessor, ILogger<MovieResolver> logger, NamingOptions namingOptions)
- : base(logger, namingOptions)
+ /// <param name="directoryService">The directory service.</param>
+ public MovieResolver(IImageProcessor imageProcessor, ILogger<MovieResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService)
+ : base(logger, namingOptions, directoryService)
{
_imageProcessor = imageProcessor;
}
@@ -97,12 +98,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
- movie = FindMovie<MusicVideo>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false);
+ movie = FindMovie<MusicVideo>(args, args.Path, args.Parent, files, DirectoryService, collectionType, false);
}
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
{
- movie = FindMovie<Video>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false);
+ movie = FindMovie<Video>(args, args.Path, args.Parent, files, DirectoryService, collectionType, false);
}
if (string.IsNullOrEmpty(collectionType))
@@ -118,12 +119,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return null;
}
- movie = FindMovie<Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true);
+ movie = FindMovie<Movie>(args, args.Path, args.Parent, files, DirectoryService, collectionType, true);
}
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
- movie = FindMovie<Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true);
+ movie = FindMovie<Movie>(args, args.Path, args.Parent, files, DirectoryService, collectionType, true);
}
// ignore extras
diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index e11fb262e..9026160ff 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -1,7 +1,5 @@
#nullable disable
-#pragma warning disable CS1591
-
using System;
using System.Collections.Generic;
using System.IO;
@@ -12,15 +10,20 @@ using Jellyfin.Extensions;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers
{
+ /// <summary>
+ /// Class PhotoResolver.
+ /// </summary>
public class PhotoResolver : ItemResolver<Photo>
{
private readonly IImageProcessor _imageProcessor;
private readonly NamingOptions _namingOptions;
+ private readonly IDirectoryService _directoryService;
private static readonly HashSet<string> _ignoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
@@ -35,10 +38,17 @@ namespace Emby.Server.Implementations.Library.Resolvers
"default"
};
- public PhotoResolver(IImageProcessor imageProcessor, NamingOptions namingOptions)
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PhotoResolver"/> class.
+ /// </summary>
+ /// <param name="imageProcessor">The image processor.</param>
+ /// <param name="namingOptions">The naming options.</param>
+ /// <param name="directoryService">The directory service.</param>
+ public PhotoResolver(IImageProcessor imageProcessor, NamingOptions namingOptions, IDirectoryService directoryService)
{
_imageProcessor = imageProcessor;
_namingOptions = namingOptions;
+ _directoryService = directoryService;
}
/// <summary>
@@ -61,7 +71,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
var filename = Path.GetFileNameWithoutExtension(args.Path);
// Make sure the image doesn't belong to a video file
- var files = args.DirectoryService.GetFiles(Path.GetDirectoryName(args.Path));
+ var files = _directoryService.GetFiles(Path.GetDirectoryName(args.Path));
foreach (var file in files)
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
index 0fcc5070b..392ee4c77 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
@@ -5,6 +5,7 @@ using System.Linq;
using Emby.Naming.Common;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging;
@@ -20,8 +21,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="namingOptions">The naming options.</param>
- public EpisodeResolver(ILogger<EpisodeResolver> logger, NamingOptions namingOptions)
- : base(logger, namingOptions)
+ /// <param name="directoryService">The directory service.</param>
+ public EpisodeResolver(ILogger<EpisodeResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService)
+ : base(logger, namingOptions, directoryService)
{
}
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index 1137625f4..17f1d1905 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -111,10 +111,10 @@ namespace Emby.Server.Implementations.Library
if (query.IncludeExternalContent)
{
- var channelResult = _channelManager.GetChannelsInternal(new ChannelQuery
+ var channelResult = _channelManager.GetChannelsInternalAsync(new ChannelQuery
{
UserId = query.UserId
- });
+ }).GetAwaiter().GetResult();
var channels = channelResult.Items;
@@ -286,7 +286,7 @@ namespace Emby.Server.Implementations.Library
if (parents.Count == 0)
{
- return new List<BaseItem>();
+ return Array.Empty<BaseItem>();
}
if (includeItemTypes.Length == 0)
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 4003468d0..ee039ff0f 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1312,20 +1312,19 @@ namespace Emby.Server.Implementations.LiveTv
return 7;
}
- private QueryResult<BaseItem> GetEmbyRecordings(RecordingQuery query, DtoOptions dtoOptions, User user)
+ private async Task<QueryResult<BaseItem>> GetEmbyRecordingsAsync(RecordingQuery query, DtoOptions dtoOptions, User user)
{
if (user is null)
{
return new QueryResult<BaseItem>();
}
- var folderIds = GetRecordingFolders(user, true)
- .Select(i => i.Id)
- .ToList();
+ var folders = await GetRecordingFoldersAsync(user, true).ConfigureAwait(false);
+ var folderIds = Array.ConvertAll(folders, x => x.Id);
var excludeItemTypes = new List<BaseItemKind>();
- if (folderIds.Count == 0)
+ if (folderIds.Length == 0)
{
return new QueryResult<BaseItem>();
}
@@ -1392,7 +1391,7 @@ namespace Emby.Server.Implementations.LiveTv
{
MediaTypes = new[] { MediaType.Video },
Recursive = true,
- AncestorIds = folderIds.ToArray(),
+ AncestorIds = folderIds,
IsFolder = false,
IsVirtualItem = false,
Limit = limit,
@@ -1528,7 +1527,7 @@ namespace Emby.Server.Implementations.LiveTv
}
}
- public QueryResult<BaseItemDto> GetRecordings(RecordingQuery query, DtoOptions options)
+ public async Task<QueryResult<BaseItemDto>> GetRecordingsAsync(RecordingQuery query, DtoOptions options)
{
var user = query.UserId.Equals(default)
? null
@@ -1536,7 +1535,7 @@ namespace Emby.Server.Implementations.LiveTv
RemoveFields(options);
- var internalResult = GetEmbyRecordings(query, options, user);
+ var internalResult = await GetEmbyRecordingsAsync(query, options, user).ConfigureAwait(false);
var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user);
@@ -2379,12 +2378,11 @@ namespace Emby.Server.Implementations.LiveTv
return _tvDtoService.GetInternalProgramId(externalId);
}
- public List<BaseItem> GetRecordingFolders(User user)
- {
- return GetRecordingFolders(user, false);
- }
+ /// <inheritdoc />
+ public Task<BaseItem[]> GetRecordingFoldersAsync(User user)
+ => GetRecordingFoldersAsync(user, false);
- private List<BaseItem> GetRecordingFolders(User user, bool refreshChannels)
+ private async Task<BaseItem[]> GetRecordingFoldersAsync(User user, bool refreshChannels)
{
var folders = EmbyTV.EmbyTV.Current.GetRecordingFolders()
.SelectMany(i => i.Locations)
@@ -2396,14 +2394,16 @@ namespace Emby.Server.Implementations.LiveTv
.OrderBy(i => i.SortName)
.ToList();
- folders.AddRange(_channelManager.GetChannelsInternal(new MediaBrowser.Model.Channels.ChannelQuery
+ var channels = await _channelManager.GetChannelsInternalAsync(new MediaBrowser.Model.Channels.ChannelQuery
{
UserId = user.Id,
IsRecordingsFolder = true,
RefreshLatestChannelItems = refreshChannels
- }).Items);
+ }).ConfigureAwait(false);
+
+ folders.AddRange(channels.Items);
- return folders.Cast<BaseItem>().ToList();
+ return folders.Cast<BaseItem>().ToArray();
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
index 046be7c5c..f2020e05f 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
@@ -122,9 +122,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
var attributes = ParseExtInf(extInf, out string remaining);
extInf = remaining;
- if (attributes.TryGetValue("tvg-logo", out string value))
+ if (attributes.TryGetValue("tvg-logo", out string tvgLogo))
{
- channel.ImageUrl = value;
+ channel.ImageUrl = tvgLogo;
+ }
+ else if (attributes.TryGetValue("logo", out string logo))
+ {
+ channel.ImageUrl = logo;
}
if (attributes.TryGetValue("group-title", out string groupTitle))
diff --git a/Emby.Server.Implementations/Localization/Core/is.json b/Emby.Server.Implementations/Localization/Core/is.json
index b262a8b42..a40f49506 100644
--- a/Emby.Server.Implementations/Localization/Core/is.json
+++ b/Emby.Server.Implementations/Localization/Core/is.json
@@ -107,5 +107,14 @@
"TasksApplicationCategory": "Forrit",
"TasksLibraryCategory": "Miðlasafn",
"TasksMaintenanceCategory": "Viðhald",
- "Default": "Sjálfgefið"
+ "Default": "Sjálfgefið",
+ "TaskCleanActivityLog": "Hreinsa athafnaskrá",
+ "TaskRefreshPeople": "Endurnýja fólk",
+ "TaskDownloadMissingSubtitles": "Sækja texta sem vantar",
+ "TaskOptimizeDatabase": "Fínstilla gagnagrunn",
+ "Undefined": "Óskilgreint",
+ "TaskCleanLogsDescription": "Eyðir færslu skrám sem eru meira en {0} gömul.",
+ "TaskCleanLogs": "Hreinsa færslu skrá",
+ "TaskDownloadMissingSubtitlesDescription": "Leitar á netinu að texta sem vantar miðað við uppsetningu lýsigagna.",
+ "HearingImpaired": "Heyrnarskertur"
}
diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json
index 081ba0cc7..01a2ab273 100644
--- a/Emby.Server.Implementations/Localization/Core/nl.json
+++ b/Emby.Server.Implementations/Localization/Core/nl.json
@@ -95,13 +95,13 @@
"TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar ontbrekende ondertiteling gebaseerd op metadataconfiguratie.",
"TaskDownloadMissingSubtitles": "Ontbrekende ondertiteling downloaden",
"TaskRefreshChannelsDescription": "Vernieuwt informatie van internet kanalen.",
- "TaskRefreshChannels": "Vernieuw kanalen",
+ "TaskRefreshChannels": "Kanalen vernieuwen",
"TaskCleanTranscodeDescription": "Verwijdert transcode bestanden ouder dan 1 dag.",
"TaskCleanLogs": "Logboekmap opschonen",
"TaskCleanTranscode": "Transcoderingsmap opschonen",
"TaskUpdatePluginsDescription": "Downloadt en installeert updates van plug-ins waarvoor automatisch bijwerken is ingeschakeld.",
"TaskUpdatePlugins": "Plug-ins bijwerken",
- "TaskRefreshPeopleDescription": "Update metadata voor acteurs en regisseurs in de media bibliotheek.",
+ "TaskRefreshPeopleDescription": "Updatet metadata voor acteurs en regisseurs in je mediabibliotheek.",
"TaskRefreshPeople": "Personen vernieuwen",
"TaskCleanLogsDescription": "Verwijdert log bestanden ouder dan {0} dagen.",
"TaskRefreshLibraryDescription": "Scant de mediabibliotheek op nieuwe bestanden en vernieuwt de metadata.",
@@ -114,7 +114,7 @@
"TasksApplicationCategory": "Toepassing",
"TasksLibraryCategory": "Bibliotheek",
"TasksMaintenanceCategory": "Onderhoud",
- "TaskCleanActivityLogDescription": "Verwijdert activiteiten logs ouder dan de ingestelde leeftijd.",
+ "TaskCleanActivityLogDescription": "Verwijdert activiteitenlogs ouder dan de ingestelde leeftijd.",
"TaskCleanActivityLog": "Activiteitenlogboek legen",
"Undefined": "Niet gedefinieerd",
"Forced": "Geforceerd",
diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json
index 39229f45f..92e0d34ae 100644
--- a/Emby.Server.Implementations/Localization/Core/pt.json
+++ b/Emby.Server.Implementations/Localization/Core/pt.json
@@ -121,5 +121,6 @@
"TaskOptimizeDatabase": "Otimizar base de dados",
"TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
"External": "Externo",
- "HearingImpaired": "Problemas auditivos"
+ "HearingImpaired": "Problemas auditivos",
+ "TaskKeyframeExtractor": "Extrator de quadro-chave"
}
diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs
index 6e2a33fd5..166b71b4a 100644
--- a/Emby.Server.Implementations/Localization/LocalizationManager.cs
+++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs
@@ -184,10 +184,19 @@ namespace Emby.Server.Implementations.Localization
/// <inheritdoc />
public IEnumerable<ParentalRating> GetParentalRatings()
{
- var ratings = GetParentalRatingsDictionary().Values.ToList();
+ // Use server default language for ratings
+ // Fall back to empty list if there are no parental ratings for that language
+ var ratings = GetParentalRatingsDictionary()?.Values.ToList()
+ ?? new List<ParentalRating>();
- // Add common ratings to ensure them being available for selection.
+ // Add common ratings to ensure them being available for selection
// Based on the US rating system due to it being the main source of rating in the metadata providers
+ // Unrated
+ if (!ratings.Any(x => x.Value is null))
+ {
+ ratings.Add(new ParentalRating("Unrated", null));
+ }
+
// Minimum rating possible
if (!ratings.Any(x => x.Value == 0))
{
@@ -237,36 +246,26 @@ namespace Emby.Server.Implementations.Localization
/// <summary>
/// Gets the parental ratings dictionary.
/// </summary>
+ /// <param name="countryCode">The optional two letter ISO language string.</param>
/// <returns><see cref="Dictionary{String, ParentalRating}" />.</returns>
- private Dictionary<string, ParentalRating> GetParentalRatingsDictionary()
+ private Dictionary<string, ParentalRating>? GetParentalRatingsDictionary(string? countryCode = null)
{
- var countryCode = _configurationManager.Configuration.MetadataCountryCode;
-
- // Fall back to US ratings if no country code is specified or country code does not exist.
+ // Fallback to server default if no country code is specified.
if (string.IsNullOrEmpty(countryCode))
{
- countryCode = "us";
+ countryCode = _configurationManager.Configuration.MetadataCountryCode;
}
- return GetRatings(countryCode)
- ?? GetRatings("us")
- ?? throw new InvalidOperationException($"Invalid resource path: '{CountriesPath}'");
- }
-
- /// <summary>
- /// Gets the ratings for a country.
- /// </summary>
- /// <param name="countryCode">The country code.</param>
- /// <returns>The ratings.</returns>
- private Dictionary<string, ParentalRating>? GetRatings(string countryCode)
- {
- _allParentalRatings.TryGetValue(countryCode, out var countryValue);
+ if (_allParentalRatings.TryGetValue(countryCode, out var countryValue))
+ {
+ return countryValue;
+ }
- return countryValue;
+ return null;
}
/// <inheritdoc />
- public int? GetRatingLevel(string rating)
+ public int? GetRatingLevel(string rating, string? countryCode = null)
{
ArgumentException.ThrowIfNullOrEmpty(rating);
@@ -280,32 +279,51 @@ namespace Emby.Server.Implementations.Localization
rating = rating.Replace("Rated :", string.Empty, StringComparison.OrdinalIgnoreCase);
rating = rating.Replace("Rated ", string.Empty, StringComparison.OrdinalIgnoreCase);
- var ratingsDictionary = GetParentalRatingsDictionary();
-
- if (ratingsDictionary.TryGetValue(rating, out ParentalRating? value))
+ // Use rating system matching the language
+ if (!string.IsNullOrEmpty(countryCode))
+ {
+ var ratingsDictionary = GetParentalRatingsDictionary(countryCode);
+ if (ratingsDictionary is not null && ratingsDictionary.TryGetValue(rating, out ParentalRating? value))
+ {
+ return value.Value;
+ }
+ }
+ else
{
- return value.Value;
+ // Fall back to server default language for ratings check
+ // If it has no ratings, use the US ratings
+ var ratingsDictionary = GetParentalRatingsDictionary() ?? GetParentalRatingsDictionary("us");
+ if (ratingsDictionary is not null && ratingsDictionary.TryGetValue(rating, out ParentalRating? value))
+ {
+ return value.Value;
+ }
}
- // If we don't find anything check all ratings systems
+ // If we don't find anything, check all ratings systems
foreach (var dictionary in _allParentalRatings.Values)
{
- if (dictionary.TryGetValue(rating, out value))
+ if (dictionary.TryGetValue(rating, out var value))
{
return value.Value;
}
}
- // Try splitting by : to handle "Germany: FSK 18"
+ // Try splitting by : to handle "Germany: FSK-18"
if (rating.Contains(':', StringComparison.OrdinalIgnoreCase))
{
return GetRatingLevel(rating.AsSpan().RightPart(':').ToString());
}
- // Remove prefix country code to handle "DE-18"
+ // Handle prefix country code to handle "DE-18"
if (rating.Contains('-', StringComparison.OrdinalIgnoreCase))
{
- return GetRatingLevel(rating.AsSpan().RightPart('-').ToString());
+ var ratingSpan = rating.AsSpan();
+
+ // Extract culture from country prefix
+ var culture = FindLanguageInfo(ratingSpan.LeftPart('-').ToString());
+
+ // Check rating system of culture
+ return GetRatingLevel(ratingSpan.RightPart('-').ToString(), culture?.TwoLetterISOLanguageName);
}
return null;
diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
index 9fe51f083..7732e32d0 100644
--- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -15,6 +15,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
@@ -62,23 +63,16 @@ namespace Emby.Server.Implementations.MediaEncoder
/// Determines whether [is eligible for chapter image extraction] [the specified video].
/// </summary>
/// <param name="video">The video.</param>
+ /// <param name="libraryOptions">The library options for the video.</param>
/// <returns><c>true</c> if [is eligible for chapter image extraction] [the specified video]; otherwise, <c>false</c>.</returns>
- private bool IsEligibleForChapterImageExtraction(Video video)
+ private bool IsEligibleForChapterImageExtraction(Video video, LibraryOptions libraryOptions)
{
if (video.IsPlaceHolder)
{
return false;
}
- var libraryOptions = _libraryManager.GetLibraryOptions(video);
- if (libraryOptions is not null)
- {
- if (!libraryOptions.EnableChapterImageExtraction)
- {
- return false;
- }
- }
- else
+ if (libraryOptions is null || !libraryOptions.EnableChapterImageExtraction)
{
return false;
}
@@ -99,7 +93,9 @@ namespace Emby.Server.Implementations.MediaEncoder
public async Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
{
- if (!IsEligibleForChapterImageExtraction(video))
+ var libraryOptions = _libraryManager.GetLibraryOptions(video);
+
+ if (!IsEligibleForChapterImageExtraction(video, libraryOptions))
{
extractImages = false;
}
@@ -179,6 +175,12 @@ namespace Emby.Server.Implementations.MediaEncoder
chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path);
changesMade = true;
}
+ else if (libraryOptions?.EnableChapterImageExtraction != true)
+ {
+ // We have an image for the current chapter but the user has disabled chapter image extraction -> delete this chapter's image
+ chapter.ImagePath = null;
+ changesMade = true;
+ }
}
if (saveChapters && changesMade)
diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index ee9aa8569..1af2c96d2 100644
--- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -93,11 +93,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, ILogger logger)
{
ArgumentNullException.ThrowIfNull(scheduledTask);
-
ArgumentNullException.ThrowIfNull(applicationPaths);
-
ArgumentNullException.ThrowIfNull(taskManager);
-
ArgumentNullException.ThrowIfNull(logger);
ScheduledTask = scheduledTask;
@@ -332,7 +329,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
return;
}
- _logger.LogInformation("{0} fired for task: {1}", trigger.GetType().Name, Name);
+ _logger.LogDebug("{0} fired for task: {1}", trigger.GetType().Name, Name);
trigger.Stop();
@@ -378,7 +375,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
CurrentCancellationTokenSource = new CancellationTokenSource();
- _logger.LogInformation("Executing {0}", Name);
+ _logger.LogDebug("Executing {0}", Name);
((TaskManager)_taskManager).OnTaskExecuting(this);
@@ -406,7 +403,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error");
+ _logger.LogError(ex, "Error executing Scheduled Task");
failureException = ex;
diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs
index 6dc20e66b..42c30c959 100644
--- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs
@@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
{
var type = scheduledTask.ScheduledTask.GetType();
- _logger.LogInformation("Queuing task {0}", type.Name);
+ _logger.LogDebug("Queuing task {0}", type.Name);
lock (_taskQueue)
{
@@ -172,7 +172,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
{
var type = task.ScheduledTask.GetType();
- _logger.LogInformation("Queuing task {0}", type.Name);
+ _logger.LogDebug("Queuing task {0}", type.Name);
lock (_taskQueue)
{
@@ -254,9 +254,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
/// </summary>
private void ExecuteQueuedTasks()
{
- _logger.LogInformation("ExecuteQueuedTasks");
-
- // Execute queued tasks
lock (_taskQueue)
{
var list = new List<Tuple<Type, TaskOptions>>();
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
index abc203618..6ad6c4cbd 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
@@ -100,7 +100,6 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
EnableImages = false
},
SourceTypes = new SourceType[] { SourceType.Library },
- HasChapterImages = false,
IsVirtualItem = false
})
.OfType<Video>()