mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-05-24 02:02:29 -04:00
Merge remote-tracking branch 'jellyfinorigin/master' into feature/pgsql_provider
This commit is contained in:
commit
17003f4d76
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
## configure the following for a manuall install of a specific version from the repo
|
||||
## configure the following for a manual install of a specific version from the repo
|
||||
|
||||
# wget https://repo.jellyfin.org/releases/server/ubuntu/versions/jellyfin-ffmpeg/6.0.1-1/jellyfin-ffmpeg6_6.0.1-1-jammy_amd64.deb -O ffmpeg.deb
|
||||
|
||||
|
2
.github/ISSUE_TEMPLATE/issue report.yml
vendored
2
.github/ISSUE_TEMPLATE/issue report.yml
vendored
@ -14,7 +14,7 @@ body:
|
||||
label: "This issue respects the following points:"
|
||||
description: All conditions are **required**. Failure to comply with any of these conditions may cause your issue to be closed without comment.
|
||||
options:
|
||||
- label: This is a **bug**, not a question or a configuration issue; Please visit our forum or chat rooms first to troubleshoot with volunteers, before creating a report. The links can be found [here](https://jellyfin.org/contact/).
|
||||
- label: This is a **bug**, not a question or a configuration issue; Please visit our [forum or chat rooms](https://jellyfin.org/contact/) first to troubleshoot with volunteers, before creating a report.
|
||||
required: true
|
||||
- label: This issue is **not** already reported on [GitHub](https://github.com/jellyfin/jellyfin/issues?q=is%3Aopen+is%3Aissue) _(I've searched it)_.
|
||||
required: true
|
||||
|
8
.github/workflows/ci-codeql-analysis.yml
vendored
8
.github/workflows/ci-codeql-analysis.yml
vendored
@ -22,16 +22,16 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
|
||||
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # v4.3.0
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5
|
||||
uses: github/codeql-action/init@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-extended
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5
|
||||
uses: github/codeql-action/autobuild@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5
|
||||
uses: github/codeql-action/analyze@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
|
||||
|
4
.github/workflows/ci-compat.yml
vendored
4
.github/workflows/ci-compat.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
|
||||
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # v4.3.0
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
|
||||
@ -47,7 +47,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
|
||||
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # v4.3.0
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
|
||||
|
4
.github/workflows/ci-openapi.yml
vendored
4
.github/workflows/ci-openapi.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
|
||||
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # v4.3.0
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
- name: Generate openapi.json
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF)
|
||||
git checkout --progress --force $ANCESTOR_REF
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
|
||||
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # v4.3.0
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
- name: Generate openapi.json
|
||||
|
3
.github/workflows/ci-tests.yml
vendored
3
.github/workflows/ci-tests.yml
vendored
@ -16,12 +16,13 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
|
||||
fail-fast: false
|
||||
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
|
||||
- uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # v4.3.0
|
||||
with:
|
||||
dotnet-version: ${{ env.SDK_VERSION }}
|
||||
|
||||
|
2
.github/workflows/commands.yml
vendored
2
.github/workflows/commands.yml
vendored
@ -132,7 +132,7 @@ jobs:
|
||||
with:
|
||||
repository: jellyfin/jellyfin-triage-script
|
||||
- name: install python
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
||||
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
|
2
.github/workflows/issue-template-check.yml
vendored
2
.github/workflows/issue-template-check.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
with:
|
||||
repository: jellyfin/jellyfin-triage-script
|
||||
- name: install python
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
||||
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
|
@ -80,7 +80,7 @@
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.1" />
|
||||
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
|
||||
<PackageVersion Include="z440.atl.core" Version="6.13.0" />
|
||||
<PackageVersion Include="z440.atl.core" Version="6.14.0" />
|
||||
<PackageVersion Include="TMDbLib" Version="2.2.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
|
||||
|
@ -12,7 +12,7 @@ namespace Emby.Naming.TV
|
||||
/// <summary>
|
||||
/// Regex that matches strings of at least 2 characters separated by a dot or underscore.
|
||||
/// Used for removing separators between words, i.e turns "The_show" into "The show" while
|
||||
/// preserving namings like "S.H.O.W".
|
||||
/// preserving names like "S.H.O.W".
|
||||
/// </summary>
|
||||
[GeneratedRegex(@"((?<a>[^\._]{2,})[\._]*)|([\._](?<b>[^\._]{2,}))")]
|
||||
private static partial Regex SeriesNameRegex();
|
||||
|
@ -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);
|
||||
|
@ -58,7 +58,7 @@ namespace Jellyfin.Api.Auth
|
||||
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(ClaimTypes.Name, authorizationInfo.User?.Username ?? string.Empty),
|
||||
new Claim(ClaimTypes.Name, authorizationInfo.User.Username),
|
||||
new Claim(ClaimTypes.Role, role),
|
||||
new Claim(InternalClaimTypes.UserId, authorizationInfo.UserId.ToString("N", CultureInfo.InvariantCulture)),
|
||||
new Claim(InternalClaimTypes.DeviceId, authorizationInfo.DeviceId),
|
||||
|
@ -238,7 +238,7 @@ public class AudioController : BaseJellyfinApiController
|
||||
/// <param name="maxVideoBitDepth">Optional. The maximum video bit depth.</param>
|
||||
/// <param name="requireAvc">Optional. Whether to require avc.</param>
|
||||
/// <param name="deInterlace">Optional. Whether to deinterlace the video.</param>
|
||||
/// <param name="requireNonAnamorphic">Optional. Whether to require a non anamporphic stream.</param>
|
||||
/// <param name="requireNonAnamorphic">Optional. Whether to require a non anamorphic stream.</param>
|
||||
/// <param name="transcodingMaxAudioChannels">Optional. The maximum number of audio channels to transcode.</param>
|
||||
/// <param name="cpuCoreLimit">Optional. The limit of how many cpu cores to use.</param>
|
||||
/// <param name="liveStreamId">The live stream id.</param>
|
||||
|
@ -459,7 +459,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] int? videoStreamIndex,
|
||||
[FromQuery] EncodingContext? context,
|
||||
[FromQuery] Dictionary<string, string> streamOptions,
|
||||
[FromQuery] bool enableAdaptiveBitrateStreaming = true,
|
||||
[FromQuery] bool enableAdaptiveBitrateStreaming = false,
|
||||
[FromQuery] bool enableTrickplay = true,
|
||||
[FromQuery] bool enableAudioVbrEncoding = true,
|
||||
[FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
|
||||
@ -634,7 +634,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] int? videoStreamIndex,
|
||||
[FromQuery] EncodingContext? context,
|
||||
[FromQuery] Dictionary<string, string> streamOptions,
|
||||
[FromQuery] bool enableAdaptiveBitrateStreaming = true,
|
||||
[FromQuery] bool enableAdaptiveBitrateStreaming = false,
|
||||
[FromQuery] bool enableAudioVbrEncoding = true)
|
||||
{
|
||||
var streamingRequest = new HlsAudioRequestDto
|
||||
@ -1778,7 +1778,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
}
|
||||
else if (state.AudioStream?.CodecTag is not null && state.AudioStream.CodecTag.Equals("ac-4", StringComparison.Ordinal))
|
||||
{
|
||||
// ac-4 audio tends to hava a super weird sample rate that will fail most encoders
|
||||
// ac-4 audio tends to have a super weird sample rate that will fail most encoders
|
||||
// force resample it to 48KHz
|
||||
args += " -ar 48000";
|
||||
}
|
||||
@ -2056,16 +2056,16 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
}
|
||||
}
|
||||
|
||||
private Task DeleteLastFile(string playlistPath, string segmentExtension, int retryCount)
|
||||
private async Task DeleteLastFile(string playlistPath, string segmentExtension, int retryCount)
|
||||
{
|
||||
var file = GetLastTranscodingFile(playlistPath, segmentExtension, _fileSystem);
|
||||
|
||||
if (file is null)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
return DeleteFile(file.FullName, retryCount);
|
||||
await DeleteFile(file.FullName, retryCount).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task DeleteFile(string path, int retryCount)
|
||||
|
@ -222,7 +222,7 @@ public class UniversalAudioController : BaseJellyfinApiController
|
||||
TranscodeReasons = mediaSource.TranscodeReasons == 0 ? null : mediaSource.TranscodeReasons.ToString(),
|
||||
Context = EncodingContext.Static,
|
||||
StreamOptions = new Dictionary<string, string>(),
|
||||
EnableAdaptiveBitrateStreaming = true,
|
||||
EnableAdaptiveBitrateStreaming = false,
|
||||
EnableAudioVbrEncoding = enableAudioVbrEncoding
|
||||
};
|
||||
|
||||
|
@ -634,10 +634,10 @@ public class UserLibraryController : BaseJellyfinApiController
|
||||
{
|
||||
if (item is Person)
|
||||
{
|
||||
var hasMetdata = !string.IsNullOrWhiteSpace(item.Overview) && item.HasImage(ImageType.Primary);
|
||||
var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 3;
|
||||
var hasMetadata = !string.IsNullOrWhiteSpace(item.Overview) && item.HasImage(ImageType.Primary);
|
||||
var performFullRefresh = !hasMetadata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 3;
|
||||
|
||||
if (!hasMetdata)
|
||||
if (!hasMetadata)
|
||||
{
|
||||
var options = new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||
{
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Net.Mime;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
|
||||
namespace Jellyfin.Api.Formatters;
|
||||
@ -8,28 +6,14 @@ namespace Jellyfin.Api.Formatters;
|
||||
/// <summary>
|
||||
/// Css output formatter.
|
||||
/// </summary>
|
||||
public class CssOutputFormatter : TextOutputFormatter
|
||||
public sealed class CssOutputFormatter : StringOutputFormatter
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CssOutputFormatter"/> class.
|
||||
/// </summary>
|
||||
public CssOutputFormatter()
|
||||
{
|
||||
SupportedMediaTypes.Add("text/css");
|
||||
|
||||
SupportedEncodings.Add(Encoding.UTF8);
|
||||
SupportedEncodings.Add(Encoding.Unicode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write context object to stream.
|
||||
/// </summary>
|
||||
/// <param name="context">Writer context.</param>
|
||||
/// <param name="selectedEncoding">Unused. Writer encoding.</param>
|
||||
/// <returns>Write stream task.</returns>
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
|
||||
{
|
||||
var stringResponse = context.Object?.ToString();
|
||||
return stringResponse is null ? Task.CompletedTask : context.HttpContext.Response.WriteAsync(stringResponse);
|
||||
SupportedMediaTypes.Clear();
|
||||
SupportedMediaTypes.Add(MediaTypeNames.Text.Css);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
|
||||
namespace Jellyfin.Api.Formatters;
|
||||
@ -9,7 +6,7 @@ namespace Jellyfin.Api.Formatters;
|
||||
/// <summary>
|
||||
/// Xml output formatter.
|
||||
/// </summary>
|
||||
public class XmlOutputFormatter : TextOutputFormatter
|
||||
public sealed class XmlOutputFormatter : StringOutputFormatter
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="XmlOutputFormatter"/> class.
|
||||
@ -18,15 +15,5 @@ public class XmlOutputFormatter : TextOutputFormatter
|
||||
{
|
||||
SupportedMediaTypes.Clear();
|
||||
SupportedMediaTypes.Add(MediaTypeNames.Text.Xml);
|
||||
|
||||
SupportedEncodings.Add(Encoding.UTF8);
|
||||
SupportedEncodings.Add(Encoding.Unicode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
|
||||
{
|
||||
var stringResponse = context.Object?.ToString();
|
||||
return stringResponse is null ? Task.CompletedTask : context.HttpContext.Response.WriteAsync(stringResponse);
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ public class DynamicHlsHelper
|
||||
|
||||
if (EnableAdaptiveBitrateStreaming(state, isLiveStream, enableAdaptiveBitrateStreaming, _httpContextAccessor.HttpContext.GetNormalizedRemoteIP()))
|
||||
{
|
||||
var requestedVideoBitrate = state.VideoRequest is null ? 0 : state.VideoRequest.VideoBitRate ?? 0;
|
||||
var requestedVideoBitrate = state.VideoRequest?.VideoBitRate ?? 0;
|
||||
|
||||
// By default, vary by just 200k
|
||||
var variation = GetBitrateVariation(totalBitrate);
|
||||
@ -526,9 +526,7 @@ public class DynamicHlsHelper
|
||||
return false;
|
||||
}
|
||||
|
||||
// Having problems in android
|
||||
return false;
|
||||
// return state.VideoRequest.VideoBitRate.HasValue;
|
||||
return state.VideoRequest?.VideoBitRate.HasValue ?? false;
|
||||
}
|
||||
|
||||
private void AddSubtitles(StreamState state, IEnumerable<MediaStream> subtitles, StringBuilder builder, ClaimsPrincipal user)
|
||||
@ -616,7 +614,7 @@ public class DynamicHlsHelper
|
||||
&& state.VideoStream is not null
|
||||
&& state.VideoStream.Level.HasValue)
|
||||
{
|
||||
levelString = state.VideoStream.Level.Value.ToString(CultureInfo.InvariantCulture) ?? string.Empty;
|
||||
levelString = state.VideoStream.Level.Value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -210,7 +210,7 @@ public static class StreamingHelpers
|
||||
&& state.VideoRequest.VideoBitRate.Value >= state.VideoStream.BitRate.Value)
|
||||
{
|
||||
// Don't downscale the resolution if the width/height/MaxWidth/MaxHeight is not requested,
|
||||
// and the requested video bitrate is higher than source video bitrate.
|
||||
// and the requested video bitrate is greater than source video bitrate.
|
||||
if (state.VideoStream.Width.HasValue || state.VideoStream.Height.HasValue)
|
||||
{
|
||||
state.VideoRequest.MaxWidth = state.VideoStream?.Width;
|
||||
|
@ -61,7 +61,7 @@ public class OpenLiveStreamDto
|
||||
public bool? EnableDirectPlay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to enale direct stream.
|
||||
/// Gets or sets a value indicating whether to enable direct stream.
|
||||
/// </summary>
|
||||
public bool? EnableDirectStream { get; set; }
|
||||
|
||||
|
@ -4,7 +4,7 @@ using MediaBrowser.Model.Dlna;
|
||||
namespace Jellyfin.Api.Models.MediaInfoDtos;
|
||||
|
||||
/// <summary>
|
||||
/// Plabyback info dto.
|
||||
/// Playback info dto.
|
||||
/// </summary>
|
||||
public class PlaybackInfoDto
|
||||
{
|
||||
|
@ -3,7 +3,7 @@ using System;
|
||||
namespace Jellyfin.Data.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the relational informations for an <see cref="BaseItemEntity"/>.
|
||||
/// Represents the relational information for an <see cref="BaseItemEntity"/>.
|
||||
/// </summary>
|
||||
public class AncestorId
|
||||
{
|
||||
|
@ -3,7 +3,7 @@ using System;
|
||||
namespace Jellyfin.Data.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Provides informations about an Attachment to an <see cref="BaseItemEntity"/>.
|
||||
/// Provides information about an Attachment to an <see cref="BaseItemEntity"/>.
|
||||
/// </summary>
|
||||
public class AttachmentStreamInfo
|
||||
{
|
||||
@ -18,7 +18,7 @@ public class AttachmentStreamInfo
|
||||
public required BaseItemEntity Item { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets The index within the source file.
|
||||
/// Gets or Sets the index within the source file.
|
||||
/// </summary>
|
||||
public required int Index { get; set; }
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Jellyfin.Data.Entities;
|
||||
public class BaseItemMetadataField
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or Sets Numerical ID of this enumeratable.
|
||||
/// Gets or Sets Numerical ID of this enumerable.
|
||||
/// </summary>
|
||||
public required int Id { get; set; }
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace Jellyfin.Data.Entities;
|
||||
public class BaseItemTrailerType
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or Sets Numerical ID of this enumeratable.
|
||||
/// Gets or Sets Numerical ID of this enumerable.
|
||||
/// </summary>
|
||||
public required int Id { get; set; }
|
||||
|
||||
|
@ -24,7 +24,7 @@ public class ItemValue
|
||||
public required string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the sanatised Value.
|
||||
/// Gets or Sets the sanitized Value.
|
||||
/// </summary>
|
||||
public required string CleanValue { get; set; }
|
||||
|
||||
|
@ -43,7 +43,7 @@ namespace Jellyfin.Data.Entities.Libraries
|
||||
/// Gets or sets the next item in the collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// TODO check if this properly updated Dependant and has the proper principal relationship.
|
||||
/// TODO check if this properly updated Dependent and has the proper principal relationship.
|
||||
/// </remarks>
|
||||
public virtual CollectionItem? Next { get; set; }
|
||||
|
||||
@ -51,7 +51,7 @@ namespace Jellyfin.Data.Entities.Libraries
|
||||
/// Gets or sets the previous item in the collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// TODO check if this properly updated Dependant and has the proper principal relationship.
|
||||
/// TODO check if this properly updated Dependent and has the proper principal relationship.
|
||||
/// </remarks>
|
||||
public virtual CollectionItem? Previous { get; set; }
|
||||
|
||||
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
namespace Jellyfin.Data.Entities.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// An entity representing a a series.
|
||||
/// An entity representing a series.
|
||||
/// </summary>
|
||||
public class Series : LibraryItem
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ public class PeopleBaseItemMap
|
||||
public int? ListOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the Role name the assosiated actor played in the <see cref="BaseItemEntity"/>.
|
||||
/// Gets or Sets the Role name the associated actor played in the <see cref="BaseItemEntity"/>.
|
||||
/// </summary>
|
||||
public string? Role { get; set; }
|
||||
|
||||
|
@ -11,7 +11,7 @@ public enum ProgramAudioEntity
|
||||
Mono = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Sterio.
|
||||
/// Stereo.
|
||||
/// </summary>
|
||||
Stereo = 1,
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class TrickplayInfo
|
||||
public int Interval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets peak bandwith usage in bits per second.
|
||||
/// Gets or sets peak bandwidth usage in bits per second.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Required.
|
||||
|
@ -269,7 +269,7 @@ public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILog
|
||||
jellyfinDatabaseProvider.OnModelCreating(modelBuilder);
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// Configuration for each entity is in it's own class inside 'ModelConfiguration'.
|
||||
// Configuration for each entity is in its own class inside 'ModelConfiguration'.
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(JellyfinDbContext).Assembly);
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ public sealed class BaseItemRepository
|
||||
}
|
||||
|
||||
dbQuery = ApplyGroupingFilter(dbQuery, filter);
|
||||
dbQuery = ApplyQueryPageing(dbQuery, filter);
|
||||
dbQuery = ApplyQueryPaging(dbQuery, filter);
|
||||
|
||||
result.Items = dbQuery.AsEnumerable().Where(e => e is not null).Select(w => DeserialiseBaseItem(w, filter.SkipDeserialization)).ToArray();
|
||||
result.StartIndex = filter.StartIndex ?? 0;
|
||||
@ -250,7 +250,7 @@ public sealed class BaseItemRepository
|
||||
dbQuery = TranslateQuery(dbQuery, context, filter);
|
||||
|
||||
dbQuery = ApplyGroupingFilter(dbQuery, filter);
|
||||
dbQuery = ApplyQueryPageing(dbQuery, filter);
|
||||
dbQuery = ApplyQueryPaging(dbQuery, filter);
|
||||
|
||||
return dbQuery.AsEnumerable().Where(e => e is not null).Select(w => DeserialiseBaseItem(w, filter.SkipDeserialization)).ToArray();
|
||||
}
|
||||
@ -258,7 +258,7 @@ public sealed class BaseItemRepository
|
||||
private IQueryable<BaseItemEntity> ApplyGroupingFilter(IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter)
|
||||
{
|
||||
// This whole block is needed to filter duplicate entries on request
|
||||
// for the time beeing it cannot be used because it would destroy the ordering
|
||||
// for the time being it cannot be used because it would destroy the ordering
|
||||
// this results in "duplicate" responses for queries that try to lookup individual series or multiple versions but
|
||||
// for that case the invoker has to run a DistinctBy(e => e.PresentationUniqueKey) on their own
|
||||
|
||||
@ -289,7 +289,7 @@ public sealed class BaseItemRepository
|
||||
return dbQuery;
|
||||
}
|
||||
|
||||
private IQueryable<BaseItemEntity> ApplyQueryPageing(IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter)
|
||||
private IQueryable<BaseItemEntity> ApplyQueryPaging(IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter)
|
||||
{
|
||||
if (filter.Limit.HasValue || filter.StartIndex.HasValue)
|
||||
{
|
||||
@ -314,7 +314,7 @@ public sealed class BaseItemRepository
|
||||
dbQuery = TranslateQuery(dbQuery, context, filter);
|
||||
dbQuery = ApplyOrder(dbQuery, filter);
|
||||
dbQuery = ApplyGroupingFilter(dbQuery, filter);
|
||||
dbQuery = ApplyQueryPageing(dbQuery, filter);
|
||||
dbQuery = ApplyQueryPaging(dbQuery, filter);
|
||||
return dbQuery;
|
||||
}
|
||||
|
||||
@ -357,7 +357,7 @@ public sealed class BaseItemRepository
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(typeName);
|
||||
|
||||
// TODO: this isn't great. Refactor later to be both globally handled by a dedicated service not just an static variable and be loaded eagar.
|
||||
// TODO: this isn't great. Refactor later to be both globally handled by a dedicated service not just an static variable and be loaded eagerly.
|
||||
// currently this is done so that plugins may introduce their own type of baseitems as we dont know when we are first called, before or after plugins are loaded
|
||||
return _typeMap.GetOrAdd(typeName, k => AppDomain.CurrentDomain.GetAssemblies()
|
||||
.Select(a => a.GetType(k))
|
||||
@ -889,7 +889,7 @@ public sealed class BaseItemRepository
|
||||
/// <exception cref="InvalidOperationException">Will be thrown if an invalid serialisation is requested.</exception>
|
||||
public static BaseItemDto DeserialiseBaseItem(BaseItemEntity baseItemEntity, ILogger logger, IServerApplicationHost? appHost, bool skipDeserialization = false)
|
||||
{
|
||||
var type = GetType(baseItemEntity.Type) ?? throw new InvalidOperationException("Cannot deserialise unkown type.");
|
||||
var type = GetType(baseItemEntity.Type) ?? throw new InvalidOperationException("Cannot deserialise unknown type.");
|
||||
BaseItemDto? dto = null;
|
||||
if (TypeRequiresDeserialization(type) && baseItemEntity.Data is not null && !skipDeserialization)
|
||||
{
|
||||
@ -905,7 +905,7 @@ public sealed class BaseItemRepository
|
||||
|
||||
if (dto is null)
|
||||
{
|
||||
dto = Activator.CreateInstance(type) as BaseItemDto ?? throw new InvalidOperationException("Cannot deserialise unkown type.");
|
||||
dto = Activator.CreateInstance(type) as BaseItemDto ?? throw new InvalidOperationException("Cannot deserialise unknown type.");
|
||||
}
|
||||
|
||||
return Map(baseItemEntity, dto, appHost);
|
||||
@ -2065,7 +2065,7 @@ public sealed class BaseItemRepository
|
||||
if (filter.IncludeInheritedTags.Length > 0)
|
||||
{
|
||||
// Episodes do not store inherit tags from their parents in the database, and the tag may be still required by the client.
|
||||
// In addtion to the tags for the episodes themselves, we need to manually query its parent (the season)'s tags as well.
|
||||
// In addition to the tags for the episodes themselves, we need to manually query its parent (the season)'s tags as well.
|
||||
if (includeTypes.Length == 1 && includeTypes.FirstOrDefault() is BaseItemKind.Episode)
|
||||
{
|
||||
baseQuery = baseQuery
|
||||
|
@ -22,7 +22,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Jellyfin.Server.Implementations.MediaSegments;
|
||||
|
||||
/// <summary>
|
||||
/// Manages media segments retrival and storage.
|
||||
/// Manages media segments retrieval and storage.
|
||||
/// </summary>
|
||||
public class MediaSegmentManager : IMediaSegmentManager
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ public class TrickplayManager : ITrickplayManager
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="mediaEncoder">The media encoder.</param>
|
||||
/// <param name="fileSystem">The file systen.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="encodingHelper">The encoding helper.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="config">The server configuration manager.</param>
|
||||
|
@ -67,38 +67,40 @@ namespace Jellyfin.Server.Infrastructure
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue? range, long rangeLength)
|
||||
protected override async Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue? range, long rangeLength)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
ArgumentNullException.ThrowIfNull(result);
|
||||
|
||||
if (range is not null && rangeLength == 0)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
// It's a bit of wasted IO to perform this check again, but non-symlinks shouldn't use this code
|
||||
if (!IsSymLink(result.FileName))
|
||||
{
|
||||
return base.WriteFileAsync(context, result, range, rangeLength);
|
||||
await base.WriteFileAsync(context, result, range, rangeLength).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var response = context.HttpContext.Response;
|
||||
|
||||
if (range is not null)
|
||||
{
|
||||
return SendFileAsync(
|
||||
await SendFileAsync(
|
||||
result.FileName,
|
||||
response,
|
||||
offset: range.From ?? 0L,
|
||||
count: rangeLength);
|
||||
count: rangeLength).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
return SendFileAsync(
|
||||
await SendFileAsync(
|
||||
result.FileName,
|
||||
response,
|
||||
offset: 0,
|
||||
count: null);
|
||||
count: null).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task SendFileAsync(string filePath, HttpResponse response, long offset, long? count, CancellationToken cancellationToken = default)
|
||||
|
@ -46,7 +46,7 @@ namespace Jellyfin.Server.Migrations.Routines
|
||||
public Guid Id => Guid.Parse("{EF103419-8451-40D8-9F34-D1A8E93A1679}");
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string Name => "CreateLoggingConfigHeirarchy";
|
||||
public string Name => "CreateLoggingConfigHierarchy";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool PerformOnNewInstall => false;
|
||||
|
@ -61,7 +61,7 @@ namespace MediaBrowser.Common.Configuration
|
||||
object GetConfiguration(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the array of coniguration stores.
|
||||
/// Gets the array of configuration stores.
|
||||
/// </summary>
|
||||
/// <returns>Array of ConfigurationStore.</returns>
|
||||
ConfigurationStore[] GetConfigurationStores();
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -102,7 +103,7 @@ public static partial class NetworkUtils
|
||||
Span<byte> bytes = stackalloc byte[mask.AddressFamily == AddressFamily.InterNetwork ? NetworkConstants.IPv4MaskBytes : NetworkConstants.IPv6MaskBytes];
|
||||
if (!mask.TryWriteBytes(bytes, out var bytesWritten))
|
||||
{
|
||||
Console.WriteLine("Unable to write address bytes, only ${bytesWritten} bytes written.");
|
||||
Console.WriteLine("Unable to write address bytes, only {0} bytes written.", bytesWritten.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
var zeroed = false;
|
||||
|
@ -58,7 +58,7 @@ public interface IDeviceManager
|
||||
QueryResult<Device> GetDevices(DeviceQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets device infromation based on the provided query.
|
||||
/// Gets device information based on the provided query.
|
||||
/// </summary>
|
||||
/// <param name="query">The device query.</param>
|
||||
/// <returns>A <see cref="Task{QueryResult}"/> representing the retrieval of the device information.</returns>
|
||||
@ -109,7 +109,7 @@ public interface IDeviceManager
|
||||
DeviceOptionsDto? GetDeviceOptions(string deviceId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dto for client capabilites.
|
||||
/// Gets the dto for client capabilities.
|
||||
/// </summary>
|
||||
/// <param name="capabilities">The client capabilities.</param>
|
||||
/// <returns><see cref="ClientCapabilitiesDto"/> of the device.</returns>
|
||||
|
@ -22,7 +22,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
IReadOnlyList<string> Artists { get; set; }
|
||||
}
|
||||
|
||||
public static class Extentions
|
||||
public static class Extensions
|
||||
{
|
||||
public static IEnumerable<string> GetAllArtists<T>(this T item)
|
||||
where T : IHasArtist, IHasAlbumArtist
|
||||
|
@ -112,15 +112,15 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
return base.IsSaveLocalMetadataEnabled();
|
||||
}
|
||||
|
||||
protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
|
||||
protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
|
||||
{
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
// Should never get in here anyway
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
return base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, false, refreshOptions, directoryService, cancellationToken);
|
||||
await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, false, refreshOptions, directoryService, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
|
@ -1800,7 +1800,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// Adds a genre to the item.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <exception cref="ArgumentNullException">Throwns if name is null.</exception>
|
||||
/// <exception cref="ArgumentNullException">Throws if name is null.</exception>
|
||||
public void AddGenre(string name)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(name);
|
||||
@ -1985,8 +1985,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
ImageInfos = [.. ImageInfos, image];
|
||||
}
|
||||
|
||||
public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
=> LibraryManager.UpdateItemAsync(this, GetParent(), updateReason, cancellationToken);
|
||||
public virtual async Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
=> await LibraryManager.UpdateItemAsync(this, GetParent(), updateReason, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Validates that images within the item are still on the filesystem.
|
||||
@ -2375,7 +2375,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
protected Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
||||
protected async Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
||||
{
|
||||
var newOptions = new MetadataRefreshOptions(options)
|
||||
{
|
||||
@ -2436,10 +2436,10 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
return ownedItem.RefreshMetadata(newOptions, cancellationToken);
|
||||
await ownedItem.RefreshMetadata(newOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken)
|
||||
protected async Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
var newOptions = new MetadataRefreshOptions(options)
|
||||
{
|
||||
@ -2449,9 +2449,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var id = LibraryManager.GetNewItemId(path, typeof(Video));
|
||||
|
||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||
var video = LibraryManager.GetItemById(id) as Video;
|
||||
|
||||
if (video is null)
|
||||
if (LibraryManager.GetItemById(id) is not Video video)
|
||||
{
|
||||
video = LibraryManager.ResolvePath(FileSystem.GetFileSystemInfo(path)) as Video;
|
||||
|
||||
@ -2460,15 +2458,15 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
if (video is null)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (video.OwnerId.IsEmpty())
|
||||
{
|
||||
video.OwnerId = this.Id;
|
||||
video.OwnerId = Id;
|
||||
}
|
||||
|
||||
return RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken);
|
||||
await RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public string GetEtag(User user)
|
||||
|
@ -531,13 +531,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
private Task RefreshMetadataRecursive(IList<BaseItem> children, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
private async Task RefreshMetadataRecursive(IList<BaseItem> children, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
return RunTasks(
|
||||
await RunTasks(
|
||||
(baseItem, innerProgress) => RefreshChildMetadata(baseItem, refreshOptions, recursive && baseItem.IsFolder, innerProgress, cancellationToken),
|
||||
children,
|
||||
progress,
|
||||
cancellationToken);
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task RefreshAllMetadataForContainer(IMetadataContainer container, MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
@ -578,13 +578,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <param name="progress">The progress.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private Task ValidateSubFolders(IList<Folder> children, IDirectoryService directoryService, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
private async Task ValidateSubFolders(IList<Folder> children, IDirectoryService directoryService, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
return RunTasks(
|
||||
await RunTasks(
|
||||
(folder, innerProgress) => folder.ValidateChildrenInternal(innerProgress, true, false, false, null, directoryService, cancellationToken),
|
||||
children,
|
||||
progress,
|
||||
cancellationToken);
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1243,11 +1243,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.GenreIds.Count > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.VideoTypes.Length > 0)
|
||||
{
|
||||
return false;
|
||||
|
@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
var series = Series;
|
||||
if (series is not null)
|
||||
{
|
||||
return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000", CultureInfo.InvariantCulture);
|
||||
return series.PresentationUniqueKey + "-" + IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ namespace MediaBrowser.Controller.Library
|
||||
IReadOnlyList<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playack media sources.
|
||||
/// Gets the playback media sources.
|
||||
/// </summary>
|
||||
/// <param name="item">Item to use.</param>
|
||||
/// <param name="user">User to use for operation.</param>
|
||||
|
@ -61,7 +61,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
private readonly Version _minFixedKernel60i915Hang = new Version(6, 0, 18);
|
||||
private readonly Version _minKernelVersionAmdVkFmtModifier = new Version(5, 15);
|
||||
|
||||
private readonly Version _minFFmpegImplictHwaccel = new Version(6, 0);
|
||||
private readonly Version _minFFmpegImplicitHwaccel = new Version(6, 0);
|
||||
private readonly Version _minFFmpegHwaUnsafeOutput = new Version(6, 0);
|
||||
private readonly Version _minFFmpegOclCuTonemapMode = new Version(5, 1, 3);
|
||||
private readonly Version _minFFmpegSvtAv1Params = new Version(5, 1);
|
||||
@ -632,7 +632,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(container))
|
||||
{
|
||||
// this may not work, but if the client is that broken we can not do anything better
|
||||
// this may not work, but if the client is that broken we cannot do anything better
|
||||
return "aac";
|
||||
}
|
||||
|
||||
@ -2198,7 +2198,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var videoFrameRate = videoStream.ReferenceFrameRate;
|
||||
|
||||
// Add a little tolerance to the framerate check because some videos might record a framerate
|
||||
// that is slightly higher than the intended framerate, but the device can still play it correctly.
|
||||
// that is slightly greater than the intended framerate, but the device can still play it correctly.
|
||||
// 0.05 fps tolerance should be safe enough.
|
||||
if (!videoFrameRate.HasValue || videoFrameRate.Value > requestedFramerate.Value + 0.05f)
|
||||
{
|
||||
@ -3609,7 +3609,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return GetSwVidFilterChain(state, options, vidEncoder);
|
||||
}
|
||||
|
||||
// prefered nvdec/cuvid + cuda filters + nvenc pipeline
|
||||
// preferred nvdec/cuvid + cuda filters + nvenc pipeline
|
||||
return GetNvidiaVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
|
||||
}
|
||||
|
||||
@ -3650,8 +3650,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var subH = state.SubtitleStream?.Height;
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doCuTranspose = !string.IsNullOrEmpty(tranposeDir) && _mediaEncoder.SupportsFilter("transpose_cuda");
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doCuTranspose = !string.IsNullOrEmpty(transposeDir) && _mediaEncoder.SupportsFilter("transpose_cuda");
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isNvDecoder && doCuTranspose));
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
var swpInH = swapWAndH ? inW : inH;
|
||||
@ -3697,7 +3697,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// hw transpose
|
||||
if (doCuTranspose)
|
||||
{
|
||||
mainFilters.Add($"transpose_cuda=dir={tranposeDir}");
|
||||
mainFilters.Add($"transpose_cuda=dir={transposeDir}");
|
||||
}
|
||||
|
||||
var isRext = IsVideoStreamHevcRext(state);
|
||||
@ -3817,7 +3817,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return GetSwVidFilterChain(state, options, vidEncoder);
|
||||
}
|
||||
|
||||
// prefered d3d11va + opencl filters + amf pipeline
|
||||
// preferred d3d11va + opencl filters + amf pipeline
|
||||
return GetAmdDx11VidFiltersPrefered(state, options, vidDecoder, vidEncoder);
|
||||
}
|
||||
|
||||
@ -3857,8 +3857,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var subH = state.SubtitleStream?.Height;
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doOclTranspose = !string.IsNullOrEmpty(tranposeDir)
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doOclTranspose = !string.IsNullOrEmpty(transposeDir)
|
||||
&& _mediaEncoder.SupportsFilterWithOption(FilterOptionType.TransposeOpenclReversal);
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isD3d11vaDecoder && doOclTranspose));
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
@ -3902,12 +3902,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// map from d3d11va to opencl via d3d11-opencl interop.
|
||||
mainFilters.Add("hwmap=derive_device=opencl:mode=read");
|
||||
|
||||
// hw deint <= TODO: finsh the 'yadif_opencl' filter
|
||||
// hw deint <= TODO: finish the 'yadif_opencl' filter
|
||||
|
||||
// hw transpose
|
||||
if (doOclTranspose)
|
||||
{
|
||||
mainFilters.Add($"transpose_opencl=dir={tranposeDir}");
|
||||
mainFilters.Add($"transpose_opencl=dir={transposeDir}");
|
||||
}
|
||||
|
||||
var outFormat = doOclTonemap ? string.Empty : "nv12";
|
||||
@ -4043,13 +4043,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return GetSwVidFilterChain(state, options, vidEncoder);
|
||||
}
|
||||
|
||||
// prefered qsv(vaapi) + opencl filters pipeline
|
||||
// preferred qsv(vaapi) + opencl filters pipeline
|
||||
if (isIntelVaapiOclSupported)
|
||||
{
|
||||
return GetIntelQsvVaapiVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
|
||||
}
|
||||
|
||||
// prefered qsv(d3d11) + opencl filters pipeline
|
||||
// preferred qsv(d3d11) + opencl filters pipeline
|
||||
if (isIntelDx11OclSupported)
|
||||
{
|
||||
return GetIntelQsvDx11VidFiltersPrefered(state, options, vidDecoder, vidEncoder);
|
||||
@ -4098,8 +4098,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var subH = state.SubtitleStream?.Height;
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVppTranspose = !string.IsNullOrEmpty(tranposeDir);
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVppTranspose = !string.IsNullOrEmpty(transposeDir);
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || ((isD3d11vaDecoder || isQsvDecoder) && doVppTranspose));
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
var swpInH = swapWAndH ? inW : inH;
|
||||
@ -4192,7 +4192,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (!string.IsNullOrEmpty(hwScaleFilter) && doVppTranspose)
|
||||
{
|
||||
hwScaleFilter += $":transpose={tranposeDir}";
|
||||
hwScaleFilter += $":transpose={transposeDir}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(hwScaleFilter) && isMjpegEncoder)
|
||||
@ -4385,8 +4385,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var subH = state.SubtitleStream?.Height;
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVppTranspose = !string.IsNullOrEmpty(tranposeDir);
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVppTranspose = !string.IsNullOrEmpty(transposeDir);
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || ((isVaapiDecoder || isQsvDecoder) && doVppTranspose));
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
var swpInH = swapWAndH ? inW : inH;
|
||||
@ -4446,7 +4446,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// hw transpose(vaapi vpp)
|
||||
if (isVaapiDecoder && doVppTranspose)
|
||||
{
|
||||
mainFilters.Add($"transpose_vaapi=dir={tranposeDir}");
|
||||
mainFilters.Add($"transpose_vaapi=dir={transposeDir}");
|
||||
}
|
||||
|
||||
var outFormat = doTonemap ? (((isQsvDecoder && doVppTranspose) || isRext) ? "p010" : string.Empty) : "nv12";
|
||||
@ -4456,7 +4456,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (!string.IsNullOrEmpty(hwScaleFilter) && isQsvDecoder && doVppTranspose)
|
||||
{
|
||||
hwScaleFilter += $":transpose={tranposeDir}";
|
||||
hwScaleFilter += $":transpose={transposeDir}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(hwScaleFilter) && isMjpegEncoder)
|
||||
@ -4657,14 +4657,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return swFilterChain;
|
||||
}
|
||||
|
||||
// prefered vaapi + opencl filters pipeline
|
||||
// preferred vaapi + opencl filters pipeline
|
||||
if (_mediaEncoder.IsVaapiDeviceInteliHD)
|
||||
{
|
||||
// Intel iHD path, with extra vpp tonemap and overlay support.
|
||||
return GetIntelVaapiFullVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
|
||||
}
|
||||
|
||||
// prefered vaapi + vulkan filters pipeline
|
||||
// preferred vaapi + vulkan filters pipeline
|
||||
if (_mediaEncoder.IsVaapiDeviceAmd
|
||||
&& isVaapiVkSupported
|
||||
&& _mediaEncoder.IsVaapiDeviceSupportVulkanDrmInterop
|
||||
@ -4716,8 +4716,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var subH = state.SubtitleStream?.Height;
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVaVppTranspose = !string.IsNullOrEmpty(tranposeDir);
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVaVppTranspose = !string.IsNullOrEmpty(transposeDir);
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isVaapiDecoder && doVaVppTranspose));
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
var swpInH = swapWAndH ? inW : inH;
|
||||
@ -4772,7 +4772,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// hw transpose
|
||||
if (doVaVppTranspose)
|
||||
{
|
||||
mainFilters.Add($"transpose_vaapi=dir={tranposeDir}");
|
||||
mainFilters.Add($"transpose_vaapi=dir={transposeDir}");
|
||||
}
|
||||
|
||||
var outFormat = doTonemap ? (isRext ? "p010" : string.Empty) : "nv12";
|
||||
@ -4949,8 +4949,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|| string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVkTranspose = isVaapiDecoder && !string.IsNullOrEmpty(tranposeDir);
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVkTranspose = isVaapiDecoder && !string.IsNullOrEmpty(transposeDir);
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isVaapiDecoder && doVkTranspose));
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
var swpInH = swapWAndH ? inW : inH;
|
||||
@ -5043,13 +5043,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// vk transpose
|
||||
if (doVkTranspose)
|
||||
{
|
||||
if (string.Equals(tranposeDir, "reversal", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(transposeDir, "reversal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mainFilters.Add("flip_vulkan");
|
||||
}
|
||||
else
|
||||
{
|
||||
mainFilters.Add($"transpose_vulkan=dir={tranposeDir}");
|
||||
mainFilters.Add($"transpose_vulkan=dir={transposeDir}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -5417,8 +5417,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var usingHwSurface = isVtDecoder && (_mediaEncoder.EncoderVersion >= _minFFmpegWorkingVtHwSurface);
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVtTranspose = !string.IsNullOrEmpty(tranposeDir) && _mediaEncoder.SupportsFilter("transpose_vt");
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doVtTranspose = !string.IsNullOrEmpty(transposeDir) && _mediaEncoder.SupportsFilter("transpose_vt");
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && doVtTranspose;
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
var swpInH = swapWAndH ? inW : inH;
|
||||
@ -5462,7 +5462,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// hw transpose
|
||||
if (doVtTranspose)
|
||||
{
|
||||
mainFilters.Add($"transpose_vt=dir={tranposeDir}");
|
||||
mainFilters.Add($"transpose_vt=dir={transposeDir}");
|
||||
}
|
||||
|
||||
if (doVtTonemap)
|
||||
@ -5577,7 +5577,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return GetSwVidFilterChain(state, options, vidEncoder);
|
||||
}
|
||||
|
||||
// prefered rkmpp + rkrga + opencl filters pipeline
|
||||
// preferred rkmpp + rkrga + opencl filters pipeline
|
||||
if (isRkmppOclSupported)
|
||||
{
|
||||
return GetRkmppVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
|
||||
@ -5625,8 +5625,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var subH = state.SubtitleStream?.Height;
|
||||
|
||||
var rotation = state.VideoStream?.Rotation ?? 0;
|
||||
var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doRkVppTranspose = !string.IsNullOrEmpty(tranposeDir);
|
||||
var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
|
||||
var doRkVppTranspose = !string.IsNullOrEmpty(transposeDir);
|
||||
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isRkmppDecoder && doRkVppTranspose));
|
||||
var swpInW = swapWAndH ? inH : inW;
|
||||
var swpInH = swapWAndH ? inW : inH;
|
||||
@ -5697,7 +5697,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (!string.IsNullOrEmpty(hwScaleFilter) && doRkVppTranspose)
|
||||
{
|
||||
hwScaleFilter += $":transpose={tranposeDir}";
|
||||
hwScaleFilter += $":transpose={transposeDir}";
|
||||
}
|
||||
|
||||
// try enabling AFBC to save DDR bandwidth
|
||||
@ -6171,7 +6171,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var ffmpegVersion = _mediaEncoder.EncoderVersion;
|
||||
|
||||
// Set the av1 codec explicitly to trigger hw accelerator, otherwise libdav1d will be used.
|
||||
var isAv1 = ffmpegVersion < _minFFmpegImplictHwaccel
|
||||
var isAv1 = ffmpegVersion < _minFFmpegImplicitHwaccel
|
||||
&& string.Equals(videoCodec, "av1", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// Allow profile mismatch if decoding H.264 baseline with d3d11va and vaapi hwaccels.
|
||||
|
@ -46,20 +46,20 @@ public interface IMediaSegmentManager
|
||||
Task DeleteSegmentAsync(Guid segmentId);
|
||||
|
||||
/// <summary>
|
||||
/// Obtains all segments accociated with the itemId.
|
||||
/// Obtains all segments associated with the itemId.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The id of the <see cref="BaseItem"/>.</param>
|
||||
/// <param name="typeFilter">filteres all media segments of the given type to be included. If null all types are included.</param>
|
||||
/// <param name="filterByProvider">When set filteres the segments to only return those that which providers are currently enabled on their library.</param>
|
||||
/// <param name="typeFilter">filters all media segments of the given type to be included. If null all types are included.</param>
|
||||
/// <param name="filterByProvider">When set filters the segments to only return those that which providers are currently enabled on their library.</param>
|
||||
/// <returns>An enumerator of <see cref="MediaSegmentDto"/>'s.</returns>
|
||||
Task<IEnumerable<MediaSegmentDto>> GetSegmentsAsync(Guid itemId, IEnumerable<MediaSegmentType>? typeFilter, bool filterByProvider = true);
|
||||
|
||||
/// <summary>
|
||||
/// Obtains all segments accociated with the itemId.
|
||||
/// Obtains all segments associated with the itemId.
|
||||
/// </summary>
|
||||
/// <param name="item">The <see cref="BaseItem"/>.</param>
|
||||
/// <param name="typeFilter">filteres all media segments of the given type to be included. If null all types are included.</param>
|
||||
/// <param name="filterByProvider">When set filteres the segments to only return those that which providers are currently enabled on their library.</param>
|
||||
/// <param name="typeFilter">filters all media segments of the given type to be included. If null all types are included.</param>
|
||||
/// <param name="filterByProvider">When set filters the segments to only return those that which providers are currently enabled on their library.</param>
|
||||
/// <returns>An enumerator of <see cref="MediaSegmentDto"/>'s.</returns>
|
||||
Task<IEnumerable<MediaSegmentDto>> GetSegmentsAsync(BaseItem item, IEnumerable<MediaSegmentType>? typeFilter, bool filterByProvider = true);
|
||||
|
@ -24,9 +24,9 @@ namespace MediaBrowser.Controller.Net
|
||||
DateTime LastActivityDate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date of last Keeplive received.
|
||||
/// Gets or sets the date of last Keepalive received.
|
||||
/// </summary>
|
||||
/// <value>The date of last Keeplive received.</value>
|
||||
/// <value>The date of last Keepalive received.</value>
|
||||
DateTime LastKeepAliveDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -324,7 +324,7 @@ namespace MediaBrowser.Controller.Session
|
||||
Task<SessionInfo> GetSessionByAuthenticationToken(Device info, string deviceId, string remoteEndpoint, string appVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Logouts the specified access token.
|
||||
/// Logs out the specified access token.
|
||||
/// </summary>
|
||||
/// <param name="accessToken">The access token.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the log out process.</returns>
|
||||
|
@ -286,7 +286,7 @@ namespace MediaBrowser.Controller.Session
|
||||
/// <summary>
|
||||
/// Gets or sets the playlist item id.
|
||||
/// </summary>
|
||||
/// <value>The splaylist item id.</value>
|
||||
/// <value>The playlist item id.</value>
|
||||
public string PlaylistItemId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -5,7 +5,7 @@ using MediaBrowser.Controller.Library;
|
||||
namespace MediaBrowser.Controller.Sorting
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a BaseItem comparer that requires a User to perform it's comparison.
|
||||
/// Represents a BaseItem comparer that requires a User to perform its comparison.
|
||||
/// </summary>
|
||||
public interface IUserBaseItemComparer : IBaseItemComparer
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ public class StreamState : EncodingJobInfo, IDisposable
|
||||
public VideoRequestDto? VideoRequest => Request as VideoRequestDto;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the direct stream provicer.
|
||||
/// Gets or sets the direct stream provider.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Deprecated.
|
||||
|
@ -320,7 +320,7 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||
{
|
||||
AddImage(files, images, name + "-fanart", ImageType.Backdrop, imagePrefix);
|
||||
|
||||
// Support without the prefix if it's in it's own folder
|
||||
// Support without the prefix if it's in its own folder
|
||||
if (!isInMixedFolder)
|
||||
{
|
||||
AddImage(files, images, name + "-fanart", ImageType.Backdrop);
|
||||
|
@ -15,7 +15,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BoxSetXmlParser"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlParset}"/> interface.</param>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlParser}"/> interface.</param>
|
||||
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
|
||||
public BoxSetXmlParser(ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
|
||||
: base(logger, providerManager)
|
||||
|
@ -96,7 +96,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||
var directory = Path.GetDirectoryName(path) ?? throw new InvalidDataException($"Provided path ({path}) is not valid.");
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
// On Windows, savint the file will fail if the file is hidden or readonly
|
||||
// On Windows, saving the file will fail if the file is hidden or readonly
|
||||
FileSystem.SetAttributes(path, false, false);
|
||||
|
||||
var fileStreamOptions = new FileStreamOptions()
|
||||
|
@ -45,16 +45,16 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task WriteCustomElementsAsync(BaseItem item, XmlWriter writer)
|
||||
protected override async Task WriteCustomElementsAsync(BaseItem item, XmlWriter writer)
|
||||
{
|
||||
var game = (Playlist)item;
|
||||
|
||||
if (game.PlaylistMediaType == MediaType.Unknown)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
return writer.WriteElementStringAsync(null, "PlaylistMediaType", null, game.PlaylistMediaType.ToString());
|
||||
await writer.WriteElementStringAsync(null, "PlaylistMediaType", null, game.PlaylistMediaType.ToString()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -84,7 +84,7 @@ public class BdInfoDirectoryInfo : IDirectoryInfo
|
||||
/// Gets the files matching a pattern.
|
||||
/// </summary>
|
||||
/// <param name="searchPattern">The search pattern.</param>
|
||||
/// <returns>All files of the directory matchign the search pattern.</returns>
|
||||
/// <returns>All files of the directory matching the search pattern.</returns>
|
||||
public IFileInfo[] GetFiles(string searchPattern)
|
||||
{
|
||||
return _fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false)
|
||||
@ -96,8 +96,8 @@ public class BdInfoDirectoryInfo : IDirectoryInfo
|
||||
/// Gets the files matching a pattern and search options.
|
||||
/// </summary>
|
||||
/// <param name="searchPattern">The search pattern.</param>
|
||||
/// <param name="searchOption">The search optin.</param>
|
||||
/// <returns>All files of the directory matchign the search pattern and options.</returns>
|
||||
/// <param name="searchOption">The search option.</param>
|
||||
/// <returns>All files of the directory matching the search pattern and options.</returns>
|
||||
public IFileInfo[] GetFiles(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
return _fileSystem.GetFiles(
|
||||
|
@ -1101,14 +1101,14 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||
|
||||
private void StopProcesses()
|
||||
{
|
||||
List<ProcessWrapper> proceses;
|
||||
List<ProcessWrapper> processes;
|
||||
lock (_runningProcessesLock)
|
||||
{
|
||||
proceses = _runningProcesses.ToList();
|
||||
processes = _runningProcesses.ToList();
|
||||
_runningProcesses.Clear();
|
||||
}
|
||||
|
||||
foreach (var process in proceses)
|
||||
foreach (var process in processes)
|
||||
{
|
||||
if (!process.HasExited)
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||
|
||||
if (result.Streams is not null)
|
||||
{
|
||||
// Convert all dictionaries to case insensitive
|
||||
// Convert all dictionaries to case-insensitive
|
||||
foreach (var stream in result.Streams)
|
||||
{
|
||||
if (stream.Tags is not null)
|
||||
@ -70,7 +70,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a dictionary to case insensitive.
|
||||
/// Converts a dictionary to case-insensitive.
|
||||
/// </summary>
|
||||
/// <param name="dict">The dict.</param>
|
||||
/// <returns>Dictionary{System.StringSystem.String}.</returns>
|
||||
|
@ -83,9 +83,9 @@ public class ServerConfiguration : BaseApplicationConfiguration
|
||||
public bool QuickConnectAvailable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [enable case sensitive item ids].
|
||||
/// Gets or sets a value indicating whether [enable case-sensitive item ids].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enable case sensitive item ids]; otherwise, <c>false</c>.</value>
|
||||
/// <value><c>true</c> if [enable case-sensitive item ids]; otherwise, <c>false</c>.</value>
|
||||
public bool EnableCaseSensitiveItemIds { get; set; } = true;
|
||||
|
||||
public bool DisableLiveTvChannelUserDataName { get; set; } = true;
|
||||
@ -249,7 +249,7 @@ public class ServerConfiguration : BaseApplicationConfiguration
|
||||
public bool AllowClientLogUpload { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the dummy chapter duration in seconds, use 0 (zero) or less to disable generation alltogether.
|
||||
/// Gets or sets the dummy chapter duration in seconds, use 0 (zero) or less to disable generation altogether.
|
||||
/// </summary>
|
||||
/// <value>The dummy chapters duration.</value>
|
||||
public int DummyChapterDuration { get; set; }
|
||||
|
@ -25,8 +25,8 @@ namespace MediaBrowser.Model.Dlna
|
||||
/// <param name="videoFramerate">The framerate.</param>
|
||||
/// <param name="packetLength">The packet length.</param>
|
||||
/// <param name="timestamp">The <see cref="TransportStreamTimestamp"/>.</param>
|
||||
/// <param name="isAnamorphic">A value indicating whether tthe video is anamorphic.</param>
|
||||
/// <param name="isInterlaced">A value indicating whether tthe video is interlaced.</param>
|
||||
/// <param name="isAnamorphic">A value indicating whether the video is anamorphic.</param>
|
||||
/// <param name="isInterlaced">A value indicating whether the video is interlaced.</param>
|
||||
/// <param name="refFrames">The reference frames.</param>
|
||||
/// <param name="numVideoStreams">The number of video streams.</param>
|
||||
/// <param name="numAudioStreams">The number of audio streams.</param>
|
||||
|
@ -59,7 +59,7 @@ public class DirectPlayProfile
|
||||
/// <returns>True if supported.</returns>
|
||||
public bool SupportsAudioCodec(string? codec)
|
||||
{
|
||||
// Video profiles can have audio codec restrictions too, therefore incude Video as valid type.
|
||||
// Video profiles can have audio codec restrictions too, therefore include Video as valid type.
|
||||
return (Type == DlnaProfileType.Audio || Type == DlnaProfileType.Video) && ContainerHelper.ContainsContainer(AudioCodec, codec);
|
||||
}
|
||||
}
|
||||
|
@ -1087,12 +1087,12 @@ namespace MediaBrowser.Model.Dlna
|
||||
|
||||
_logger.LogDebug(
|
||||
"Transcode Result for Profile: {Profile}, Path: {Path}, PlayMethod: {PlayMethod}, AudioStreamIndex: {AudioStreamIndex}, SubtitleStreamIndex: {SubtitleStreamIndex}, Reasons: {TranscodeReason}",
|
||||
options.Profile?.Name ?? "Anonymous Profile",
|
||||
options.Profile.Name ?? "Anonymous Profile",
|
||||
item.Path ?? "Unknown path",
|
||||
playlistItem?.PlayMethod,
|
||||
playlistItem.PlayMethod,
|
||||
audioStream?.Index,
|
||||
playlistItem?.SubtitleStreamIndex,
|
||||
playlistItem?.TranscodeReasons);
|
||||
playlistItem.SubtitleStreamIndex,
|
||||
playlistItem.TranscodeReasons);
|
||||
}
|
||||
|
||||
private static int GetDefaultAudioBitrate(string? audioCodec, int? audioChannels)
|
||||
|
@ -17,12 +17,12 @@ public static class ImageFormatExtensions
|
||||
public static string GetMimeType(this ImageFormat format)
|
||||
=> format switch
|
||||
{
|
||||
ImageFormat.Bmp => "image/bmp",
|
||||
ImageFormat.Bmp => MediaTypeNames.Image.Bmp,
|
||||
ImageFormat.Gif => MediaTypeNames.Image.Gif,
|
||||
ImageFormat.Jpg => MediaTypeNames.Image.Jpeg,
|
||||
ImageFormat.Png => "image/png",
|
||||
ImageFormat.Webp => "image/webp",
|
||||
ImageFormat.Svg => "image/svg+xml",
|
||||
ImageFormat.Png => MediaTypeNames.Image.Png,
|
||||
ImageFormat.Webp => MediaTypeNames.Image.Webp,
|
||||
ImageFormat.Svg => MediaTypeNames.Image.Svg,
|
||||
_ => throw new InvalidEnumArgumentException(nameof(format), (int)format, typeof(ImageFormat))
|
||||
};
|
||||
|
||||
|
@ -163,7 +163,7 @@ public class SessionInfoDto
|
||||
/// <summary>
|
||||
/// Gets or sets the playlist item id.
|
||||
/// </summary>
|
||||
/// <value>The splaylist item id.</value>
|
||||
/// <value>The playlist item id.</value>
|
||||
public string? PlaylistItemId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -8,7 +8,7 @@ namespace MediaBrowser.Model.Entities;
|
||||
public enum HardwareAccelerationType
|
||||
{
|
||||
/// <summary>
|
||||
/// Software accelleration.
|
||||
/// Software acceleration.
|
||||
/// </summary>
|
||||
none = 0,
|
||||
|
||||
|
@ -537,7 +537,7 @@ namespace MediaBrowser.Model.Entities
|
||||
get
|
||||
{
|
||||
// In some cases AverageFrameRate for videos will be read as 1000fps even if it is not.
|
||||
// This is probably due to a library compatability issue.
|
||||
// This is probably due to a library compatibility issue.
|
||||
// See https://github.com/jellyfin/jellyfin/pull/12603#discussion_r1748044018 for more info.
|
||||
return AverageFrameRate < 1000 ? AverageFrameRate : RealFrameRate;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace MediaBrowser.Model.Entities
|
||||
Tvdb = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The tvcom providerd.
|
||||
/// The tvcom provider.
|
||||
/// </summary>
|
||||
Tvcom = 5,
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace MediaBrowser.Model.Entities;
|
||||
public static class ProviderIdsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Case insensitive dictionary of <see cref="MetadataProvider"/> string representation.
|
||||
/// Case-insensitive dictionary of <see cref="MetadataProvider"/> string representation.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, string> _metadataProviderEnumDictionary =
|
||||
Enum.GetValues<MetadataProvider>()
|
||||
@ -107,7 +107,7 @@ public static class ProviderIdsExtensions
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="name">The name, this should not contain a '=' character.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <remarks>Due to how deserialization from the database works the name can not contain '='.</remarks>
|
||||
/// <remarks>Due to how deserialization from the database works the name cannot contain '='.</remarks>
|
||||
/// <returns><c>true</c> if the provider id got set successfully; otherwise, <c>false</c>.</returns>
|
||||
public static bool TrySetProviderId(this IHasProviderIds instance, string? name, string? value)
|
||||
{
|
||||
@ -153,7 +153,7 @@ public static class ProviderIdsExtensions
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="name">The name, this should not contain a '=' character.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <remarks>Due to how deserialization from the database works the name can not contain '='.</remarks>
|
||||
/// <remarks>Due to how deserialization from the database works the name cannot contain '='.</remarks>
|
||||
public static void SetProviderId(this IHasProviderIds instance, string name, string value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
|
@ -52,7 +52,7 @@ namespace MediaBrowser.Model.Globalization
|
||||
/// <summary>
|
||||
/// Gets the localization options.
|
||||
/// </summary>
|
||||
/// <returns><see cref="IEnumerable{LocalizatonOption}" />.</returns>
|
||||
/// <returns><see cref="IEnumerable{LocalizationOption}" />.</returns>
|
||||
IEnumerable<LocalizationOption> GetLocalizationOptions();
|
||||
|
||||
/// <summary>
|
||||
|
@ -145,7 +145,7 @@ namespace MediaBrowser.Model.IO
|
||||
/// Gets the directories.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="recursive">If set to <c>true</c> also searches in subdirectiories.</param>
|
||||
/// <param name="recursive">If set to <c>true</c> also searches in subdirectories.</param>
|
||||
/// <returns>All found directories.</returns>
|
||||
IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false);
|
||||
|
||||
@ -153,7 +153,7 @@ namespace MediaBrowser.Model.IO
|
||||
/// Gets the files.
|
||||
/// </summary>
|
||||
/// <param name="path">The path in which to search.</param>
|
||||
/// <param name="recursive">If set to <c>true</c> also searches in subdirectiories.</param>
|
||||
/// <param name="recursive">If set to <c>true</c> also searches in subdirectories.</param>
|
||||
/// <returns>All found files.</returns>
|
||||
IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false);
|
||||
|
||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using Jellyfin.Extensions;
|
||||
|
||||
namespace MediaBrowser.Model.Net
|
||||
@ -144,7 +145,7 @@ namespace MediaBrowser.Model.Net
|
||||
new("video/x-matroska", ".mkv"),
|
||||
}.ToFrozenDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static string GetMimeType(string path) => GetMimeType(path, "application/octet-stream");
|
||||
public static string GetMimeType(string path) => GetMimeType(path, MediaTypeNames.Application.Octet);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the MIME.
|
||||
|
@ -34,7 +34,12 @@ namespace MediaBrowser.Model.Plugins
|
||||
Malfunctioned = -3,
|
||||
|
||||
/// <summary>
|
||||
/// This plugin has been superceded by another version.
|
||||
/// This plugin has been superseded by another version.
|
||||
/// </summary>
|
||||
Superseded = -4,
|
||||
|
||||
/// <summary>
|
||||
/// [DEPRECATED] See Superseded.
|
||||
/// </summary>
|
||||
Superceded = -4,
|
||||
|
||||
|
@ -5,7 +5,7 @@ using MediaBrowser.Model.Entities;
|
||||
namespace MediaBrowser.Model.Session;
|
||||
|
||||
/// <summary>
|
||||
/// Class holding information on a runnning transcode.
|
||||
/// Class holding information on a running transcode.
|
||||
/// </summary>
|
||||
public class TranscodingInfo
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ namespace MediaBrowser.Model.System
|
||||
/// Gets or sets a value indicating whether the startup wizard is completed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Nullable for OpenAPI specification only to retain backwards compatibility in apiclients.
|
||||
/// Nullable for OpenAPI specification only to retain backwards compatibility in api clients.
|
||||
/// </remarks>
|
||||
/// <value>The startup completion status.</value>]
|
||||
public bool? StartupWizardCompleted { get; set; }
|
||||
|
@ -361,7 +361,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
blurayVideoStream.Codec = ffmpegVideoStream.Codec;
|
||||
blurayVideoStream.BitRate = blurayVideoStream.BitRate.GetValueOrDefault() == 0 ? ffmpegVideoStream.BitRate : blurayVideoStream.BitRate;
|
||||
blurayVideoStream.Width = blurayVideoStream.Width.GetValueOrDefault() == 0 ? ffmpegVideoStream.Width : blurayVideoStream.Width;
|
||||
blurayVideoStream.Height = blurayVideoStream.Height.GetValueOrDefault() == 0 ? ffmpegVideoStream.Width : blurayVideoStream.Height;
|
||||
blurayVideoStream.Height = blurayVideoStream.Height.GetValueOrDefault() == 0 ? ffmpegVideoStream.Height : blurayVideoStream.Height;
|
||||
blurayVideoStream.ColorRange = ffmpegVideoStream.ColorRange;
|
||||
blurayVideoStream.ColorSpace = ffmpegVideoStream.ColorSpace;
|
||||
blurayVideoStream.ColorTransfer = ffmpegVideoStream.ColorTransfer;
|
||||
@ -634,7 +634,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
var runtime = video.RunTimeTicks.GetValueOrDefault();
|
||||
|
||||
// Only process files with a runtime higher than 0 and lower than 12h. The latter are likely corrupted.
|
||||
// Only process files with a runtime greater than 0 and less than 12h. The latter are likely corrupted.
|
||||
if (runtime < 0 || runtime > TimeSpan.FromHours(12).Ticks)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
|
@ -148,21 +148,19 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
||||
item.Overview = (overview ?? string.Empty).StripHtml();
|
||||
}
|
||||
|
||||
internal Task EnsureInfo(string musicBrainzReleaseGroupId, CancellationToken cancellationToken)
|
||||
internal async Task EnsureInfo(string musicBrainzReleaseGroupId, CancellationToken cancellationToken)
|
||||
{
|
||||
var xmlPath = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
|
||||
|
||||
var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
|
||||
|
||||
if (fileInfo.Exists)
|
||||
if (fileInfo.Exists
|
||||
&& (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
|
||||
{
|
||||
if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return DownloadInfo(musicBrainzReleaseGroupId, cancellationToken);
|
||||
await DownloadInfo(musicBrainzReleaseGroupId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal async Task DownloadInfo(string musicBrainzReleaseGroupId, CancellationToken cancellationToken)
|
||||
|
@ -131,7 +131,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
||||
item.Overview = (overview ?? string.Empty).StripHtml();
|
||||
}
|
||||
|
||||
internal Task EnsureArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
|
||||
internal async Task EnsureArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
|
||||
{
|
||||
var xmlPath = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
|
||||
|
||||
@ -140,10 +140,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
||||
if (fileInfo.Exists
|
||||
&& (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
return DownloadArtistInfo(musicBrainzId, cancellationToken);
|
||||
await DownloadArtistInfo(musicBrainzId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal async Task DownloadArtistInfo(string musicBrainzId, CancellationToken cancellationToken)
|
||||
|
@ -101,11 +101,11 @@ namespace MediaBrowser.Providers.Plugins.StudioImages
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0}/images/{1}/{2}.jpg", GetRepositoryUrl(), image, filename);
|
||||
}
|
||||
|
||||
private Task EnsureThumbsList(string file, CancellationToken cancellationToken)
|
||||
private async Task EnsureThumbsList(string file, CancellationToken cancellationToken)
|
||||
{
|
||||
string url = string.Format(CultureInfo.InvariantCulture, "{0}/thumbs.txt", GetRepositoryUrl());
|
||||
|
||||
return EnsureList(url, file, _fileSystem, cancellationToken);
|
||||
await EnsureList(url, file, _fileSystem, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -73,7 +73,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
||||
protected IProviderManager ProviderManager { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether URLs after a closing XML tag are supporrted.
|
||||
/// Gets a value indicating whether URLs after a closing XML tag are supported.
|
||||
/// </summary>
|
||||
protected virtual bool SupportsUrlAfterClosingXmlTag => false;
|
||||
|
||||
@ -672,7 +672,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
||||
}
|
||||
|
||||
var fileSystemMetadata = _directoryService.GetFile(val);
|
||||
// non existing file returns null
|
||||
// nonexistent file returns null
|
||||
if (fileSystemMetadata is null || !fileSystemMetadata.Exists)
|
||||
{
|
||||
Logger.LogWarning("Artwork file {Path} specified in nfo file for {ItemName} does not exist.", uri, itemResult.Item.Name);
|
||||
|
@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging;
|
||||
namespace MediaBrowser.XbmcMetadata.Savers
|
||||
{
|
||||
/// <summary>
|
||||
/// Nfo saver for artsist.
|
||||
/// Nfo saver for artist.
|
||||
/// </summary>
|
||||
public class ArtistNfoSaver : BaseNfoSaver
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user