mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-22 10:04:44 +01:00
Merge remote-tracking branch 'jellyfinorigin/master' into feature/pgsql_provider
This commit is contained in:
@@ -82,17 +82,17 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
public WebSocketState State => _socket.State;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SendAsync(OutboundWebSocketMessage message, CancellationToken cancellationToken)
|
||||
public async Task SendAsync(OutboundWebSocketMessage message, CancellationToken cancellationToken)
|
||||
{
|
||||
var json = JsonSerializer.SerializeToUtf8Bytes(message, _jsonOptions);
|
||||
return _socket.SendAsync(json, WebSocketMessageType.Text, true, cancellationToken);
|
||||
await _socket.SendAsync(json, WebSocketMessageType.Text, true, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SendAsync<T>(OutboundWebSocketMessage<T> message, CancellationToken cancellationToken)
|
||||
public async Task SendAsync<T>(OutboundWebSocketMessage<T> message, CancellationToken cancellationToken)
|
||||
{
|
||||
var json = JsonSerializer.SerializeToUtf8Bytes(message, _jsonOptions);
|
||||
return _socket.SendAsync(json, WebSocketMessageType.Text, true, cancellationToken);
|
||||
await _socket.SendAsync(json, WebSocketMessageType.Text, true, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -224,12 +224,12 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Task SendKeepAliveResponse()
|
||||
private async Task SendKeepAliveResponse()
|
||||
{
|
||||
LastKeepAliveDate = DateTime.UtcNow;
|
||||
return SendAsync(
|
||||
await SendAsync(
|
||||
new OutboundKeepAliveMessage(),
|
||||
CancellationToken.None);
|
||||
CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// Processes the web socket message received.
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
private Task ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
|
||||
private async Task ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
|
||||
{
|
||||
var tasks = new Task[_webSocketListeners.Length];
|
||||
for (var i = 0; i < _webSocketListeners.Length; ++i)
|
||||
@@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
tasks[i] = _webSocketListeners[i].ProcessMessageAsync(result);
|
||||
}
|
||||
|
||||
return Task.WhenAll(tasks);
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,7 +561,7 @@ namespace Emby.Server.Implementations.IO
|
||||
{
|
||||
var enumerationOptions = GetEnumerationOptions(recursive);
|
||||
|
||||
// On linux and osx the search pattern is case sensitive
|
||||
// On linux and macOS the search pattern is case-sensitive
|
||||
// If we're OK with case-sensitivity, and we're only filtering for one extension, then use the native method
|
||||
if ((enableCaseSensitiveExtensions || _isEnvironmentCaseInsensitive) && extensions is not null && extensions.Count == 1)
|
||||
{
|
||||
@@ -618,7 +618,7 @@ namespace Emby.Server.Implementations.IO
|
||||
{
|
||||
var enumerationOptions = GetEnumerationOptions(recursive);
|
||||
|
||||
// On linux and osx the search pattern is case sensitive
|
||||
// On linux and macOS the search pattern is case-sensitive
|
||||
// If we're OK with case-sensitivity, and we're only filtering for one extension, then use the native method
|
||||
if ((enableCaseSensitiveExtensions || _isEnvironmentCaseInsensitive) && extensions is not null && extensions.Length == 1)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
@@ -116,9 +117,9 @@ namespace Emby.Server.Implementations.Images
|
||||
|
||||
var mimeType = MimeTypes.GetMimeType(outputPath);
|
||||
|
||||
if (string.Equals(mimeType, "application/octet-stream", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(mimeType, MediaTypeNames.Application.Octet, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mimeType = "image/png";
|
||||
mimeType = MediaTypeNames.Image.Png;
|
||||
}
|
||||
|
||||
await ProviderManager.SaveImage(item, outputPath, mimeType, imageType, null, false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -755,14 +755,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (folder.Id.IsEmpty())
|
||||
{
|
||||
if (string.IsNullOrEmpty(folder.Path))
|
||||
{
|
||||
folder.Id = GetNewItemId(folder.GetType().Name, folder.GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
folder.Id = GetNewItemId(folder.Path, folder.GetType());
|
||||
}
|
||||
folder.Id = GetNewItemId(folder.Path, folder.GetType());
|
||||
}
|
||||
|
||||
var dbItem = GetItemById(folder.Id) as BasePluginFolder;
|
||||
@@ -1057,9 +1050,17 @@ namespace Emby.Server.Implementations.Library
|
||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Quickly scan CollectionFolders for changes
|
||||
foreach (var folder in GetUserRootFolder().Children.OfType<Folder>())
|
||||
foreach (var child in GetUserRootFolder().Children.OfType<Folder>())
|
||||
{
|
||||
await folder.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
// If the user has somehow deleted the collection directory, remove the metadata from the database.
|
||||
if (child is CollectionFolder collectionFolder && !Directory.Exists(collectionFolder.Path))
|
||||
{
|
||||
_itemRepository.DeleteItem(collectionFolder.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
await child.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Library
|
||||
public class MediaSourceManager : IMediaSourceManager, IDisposable
|
||||
{
|
||||
// Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message.
|
||||
private const char LiveStreamIdDelimeter = '_';
|
||||
private const char LiveStreamIdDelimiter = '_';
|
||||
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly IItemRepository _itemRepo;
|
||||
@@ -314,7 +314,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
private static void SetKeyProperties(IMediaSourceProvider provider, MediaSourceInfo mediaSource)
|
||||
{
|
||||
var prefix = provider.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture) + LiveStreamIdDelimeter;
|
||||
var prefix = provider.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture) + LiveStreamIdDelimiter;
|
||||
|
||||
if (!string.IsNullOrEmpty(mediaSource.OpenToken) && !mediaSource.OpenToken.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -867,11 +867,11 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(key);
|
||||
|
||||
var keys = key.Split(LiveStreamIdDelimeter, 2);
|
||||
var keys = key.Split(LiveStreamIdDelimiter, 2);
|
||||
|
||||
var provider = _providers.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture), keys[0], StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
var splitIndex = key.IndexOf(LiveStreamIdDelimeter, StringComparison.Ordinal);
|
||||
var splitIndex = key.IndexOf(LiveStreamIdDelimiter, StringComparison.Ordinal);
|
||||
var keyId = key.Substring(splitIndex + 1);
|
||||
|
||||
return (provider, keyId);
|
||||
|
||||
@@ -309,39 +309,40 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
var mediaTypes = new List<MediaType>();
|
||||
MediaType[] mediaTypes = [];
|
||||
|
||||
if (includeItemTypes.Length == 0)
|
||||
{
|
||||
HashSet<MediaType> tmpMediaTypes = [];
|
||||
foreach (var parent in parents.OfType<ICollectionFolder>())
|
||||
{
|
||||
switch (parent.CollectionType)
|
||||
{
|
||||
case CollectionType.books:
|
||||
mediaTypes.Add(MediaType.Book);
|
||||
mediaTypes.Add(MediaType.Audio);
|
||||
tmpMediaTypes.Add(MediaType.Book);
|
||||
tmpMediaTypes.Add(MediaType.Audio);
|
||||
break;
|
||||
case CollectionType.music:
|
||||
mediaTypes.Add(MediaType.Audio);
|
||||
tmpMediaTypes.Add(MediaType.Audio);
|
||||
break;
|
||||
case CollectionType.photos:
|
||||
mediaTypes.Add(MediaType.Photo);
|
||||
mediaTypes.Add(MediaType.Video);
|
||||
tmpMediaTypes.Add(MediaType.Photo);
|
||||
tmpMediaTypes.Add(MediaType.Video);
|
||||
break;
|
||||
case CollectionType.homevideos:
|
||||
mediaTypes.Add(MediaType.Photo);
|
||||
mediaTypes.Add(MediaType.Video);
|
||||
tmpMediaTypes.Add(MediaType.Photo);
|
||||
tmpMediaTypes.Add(MediaType.Video);
|
||||
break;
|
||||
default:
|
||||
mediaTypes.Add(MediaType.Video);
|
||||
tmpMediaTypes.Add(MediaType.Video);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mediaTypes = mediaTypes.Distinct().ToList();
|
||||
mediaTypes = tmpMediaTypes.ToArray();
|
||||
}
|
||||
|
||||
var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0
|
||||
var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Length == 0
|
||||
? new[]
|
||||
{
|
||||
BaseItemKind.Person,
|
||||
@@ -367,14 +368,9 @@ namespace Emby.Server.Implementations.Library
|
||||
Limit = limit * 5,
|
||||
IsPlayed = isPlayed,
|
||||
DtoOptions = options,
|
||||
MediaTypes = mediaTypes.ToArray()
|
||||
MediaTypes = mediaTypes
|
||||
};
|
||||
|
||||
if (parents.Count == 0)
|
||||
{
|
||||
return _libraryManager.GetItemList(query, false);
|
||||
}
|
||||
|
||||
return _libraryManager.GetItemList(query, parents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,5 +135,6 @@
|
||||
"TaskDownloadMissingLyricsDescription": "Téléchargement des paroles des chansons",
|
||||
"TaskMoveTrickplayImagesDescription": "Déplace les fichiers trickplay existants en fonction des paramètres de la bibliothèque.",
|
||||
"TaskDownloadMissingLyrics": "Télécharger les paroles des chansons manquantes",
|
||||
"TaskMoveTrickplayImages": "Changer l'emplacement des images Trickplay"
|
||||
"TaskMoveTrickplayImages": "Changer l'emplacement des images Trickplay",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrait ou obtient des segments de média à partir des plugins compatibles avec MediaSegment."
|
||||
}
|
||||
|
||||
@@ -129,5 +129,11 @@
|
||||
"TaskAudioNormalization": "Audio normalizācija",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Noņem vairs neeksistējošus vienumus no kolekcijām un atskaņošanas sarakstiem.",
|
||||
"TaskAudioNormalizationDescription": "Skanē failus priekš audio normālizācijas informācijas.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Notīrīt kolekcijas un atskaņošanas sarakstus"
|
||||
"TaskCleanCollectionsAndPlaylists": "Notīrīt kolekcijas un atskaņošanas sarakstus",
|
||||
"TaskExtractMediaSegments": "Multivides segmenta skenēšana",
|
||||
"TaskExtractMediaSegmentsDescription": "Izvelk vai iegūst multivides segmentus no MediaSegment iespējotiem spraudņiem.",
|
||||
"TaskMoveTrickplayImages": "Trickplay attēlu pārvietošana",
|
||||
"TaskMoveTrickplayImagesDescription": "Pārvieto esošos trickplay failus atbilstoši bibliotēkas iestatījumiem.",
|
||||
"TaskDownloadMissingLyrics": "Lejupielādēt trūkstošos vārdus",
|
||||
"TaskDownloadMissingLyricsDescription": "Lejupielādēt vārdus dziesmām"
|
||||
}
|
||||
|
||||
@@ -134,5 +134,7 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "整理媒體與播放清單",
|
||||
"TaskAudioNormalization": "音訊同等化",
|
||||
"TaskAudioNormalizationDescription": "掃描檔案裏的音訊同等化資料。",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "從資料庫及播放清單中移除已不存在的項目。"
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "從資料庫及播放清單中移除已不存在的項目。",
|
||||
"TaskMoveTrickplayImagesDescription": "根據媒體庫設定移動現有的 Trickplay 檔案。",
|
||||
"TaskMoveTrickplayImages": "轉移 Trickplay 影像位置"
|
||||
}
|
||||
|
||||
@@ -231,13 +231,13 @@ namespace Emby.Server.Implementations.Localization
|
||||
ratings.Add(new ParentalRating("21", 21));
|
||||
}
|
||||
|
||||
// A lot of countries don't excplicitly have a seperate rating for adult content
|
||||
// A lot of countries don't explicitly have a separate rating for adult content
|
||||
if (ratings.All(x => x.Value != 1000))
|
||||
{
|
||||
ratings.Add(new ParentalRating("XXX", 1000));
|
||||
}
|
||||
|
||||
// A lot of countries don't excplicitly have a seperate rating for banned content
|
||||
// A lot of countries don't explicitly have a separate rating for banned content
|
||||
if (ratings.All(x => x.Value != 1001))
|
||||
{
|
||||
ratings.Add(new ParentalRating("Banned", 1001));
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Emby.Server.Implementations.Plugins
|
||||
// Now load the assemblies..
|
||||
foreach (var plugin in _plugins)
|
||||
{
|
||||
UpdatePluginSuperceedStatus(plugin);
|
||||
UpdatePluginSupersededStatus(plugin);
|
||||
|
||||
if (plugin.IsEnabledAndSupported == false)
|
||||
{
|
||||
@@ -214,7 +214,7 @@ namespace Emby.Server.Implementations.Plugins
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdatePluginSuperceedStatus(plugin);
|
||||
UpdatePluginSupersededStatus(plugin);
|
||||
if (!plugin.IsEnabledAndSupported)
|
||||
{
|
||||
continue;
|
||||
@@ -624,9 +624,9 @@ namespace Emby.Server.Implementations.Plugins
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePluginSuperceedStatus(LocalPlugin plugin)
|
||||
private void UpdatePluginSupersededStatus(LocalPlugin plugin)
|
||||
{
|
||||
if (plugin.Manifest.Status != PluginStatus.Superceded)
|
||||
if (plugin.Manifest.Status != PluginStatus.Superseded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -876,7 +876,7 @@ namespace Emby.Server.Implementations.Plugins
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the status of the other versions of the plugin to "Superceded".
|
||||
/// Changes the status of the other versions of the plugin to "Superseded".
|
||||
/// </summary>
|
||||
/// <param name="plugin">The <see cref="LocalPlugin"/> that's master.</param>
|
||||
private void ProcessAlternative(LocalPlugin plugin)
|
||||
@@ -896,11 +896,11 @@ namespace Emby.Server.Implementations.Plugins
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.Manifest.Status == PluginStatus.Active && !ChangePluginState(previousVersion, PluginStatus.Superceded))
|
||||
if (plugin.Manifest.Status == PluginStatus.Active && !ChangePluginState(previousVersion, PluginStatus.Superseded))
|
||||
{
|
||||
_logger.LogError("Unable to enable version {Version} of {Name}", previousVersion.Version, previousVersion.Name);
|
||||
}
|
||||
else if (plugin.Manifest.Status == PluginStatus.Superceded && !ChangePluginState(previousVersion, PluginStatus.Active))
|
||||
else if (plugin.Manifest.Status == PluginStatus.Superseded && !ChangePluginState(previousVersion, PluginStatus.Active))
|
||||
{
|
||||
_logger.LogError("Unable to supercede version {Version} of {Name}", previousVersion.Version, previousVersion.Name);
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
DisposeTriggers();
|
||||
|
||||
var wassRunning = State == TaskState.Running;
|
||||
var wasRunning = State == TaskState.Running;
|
||||
var startTime = CurrentExecutionStartTime;
|
||||
|
||||
var token = CurrentCancellationTokenSource;
|
||||
@@ -596,7 +596,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
}
|
||||
|
||||
if (wassRunning)
|
||||
if (wasRunning)
|
||||
{
|
||||
OnTaskCompleted(startTime, DateTime.UtcNow, TaskCompletionStatus.Aborted, null);
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// InstallPackage has it's own inner cancellation token, so only throw this if it's ours
|
||||
// InstallPackage has its own inner cancellation token, so only throw this if it's ours
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
throw;
|
||||
|
||||
@@ -1304,7 +1304,7 @@ namespace Emby.Server.Implementations.Session
|
||||
|
||||
if (item is null)
|
||||
{
|
||||
_logger.LogError("A non-existent item Id {0} was passed into TranslateItemForPlayback", id);
|
||||
_logger.LogError("A nonexistent item Id {0} was passed into TranslateItemForPlayback", id);
|
||||
return Array.Empty<BaseItem>();
|
||||
}
|
||||
|
||||
@@ -1357,7 +1357,7 @@ namespace Emby.Server.Implementations.Session
|
||||
|
||||
if (item is null)
|
||||
{
|
||||
_logger.LogError("A non-existent item Id {0} was passed into TranslateItemForInstantMix", id);
|
||||
_logger.LogError("A nonexistent item Id {0} was passed into TranslateItemForInstantMix", id);
|
||||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
|
||||
@@ -276,11 +276,11 @@ namespace Emby.Server.Implementations.Session
|
||||
/// </summary>
|
||||
/// <param name="webSocket">The WebSocket.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private Task SendForceKeepAlive(IWebSocketConnection webSocket)
|
||||
private async Task SendForceKeepAlive(IWebSocketConnection webSocket)
|
||||
{
|
||||
return webSocket.SendAsync(
|
||||
await webSocket.SendAsync(
|
||||
new ForceKeepAliveMessage(WebSocketLostTimeout),
|
||||
CancellationToken.None);
|
||||
CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace Emby.Server.Implementations.Updates
|
||||
await _pluginManager.PopulateManifest(package, version.VersionNumber, plugin.Path, plugin.Manifest.Status).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Remove versions with a target ABI greater then the current application version.
|
||||
// Remove versions with a target ABI greater than the current application version.
|
||||
if (Version.TryParse(version.TargetAbi, out var targetAbi) && _applicationHost.ApplicationVersion < targetAbi)
|
||||
{
|
||||
package.Versions.RemoveAt(i);
|
||||
|
||||
Reference in New Issue
Block a user