Merge branch 'jellyfin:master' into whitelist-dlls

This commit is contained in:
AmbulantRex 2023-04-15 07:11:33 -06:00 committed by GitHub
commit 4a0b135b7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
87 changed files with 536 additions and 586 deletions

View File

@ -20,18 +20,18 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3 uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3
with: with:
dotnet-version: '7.0.x' dotnet-version: '7.0.x'
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9 uses: github/codeql-action/init@d186a2a36cc67bfa1b860e6170d37fb9634742c7 # v2.2.11
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
queries: +security-extended queries: +security-extended
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9 uses: github/codeql-action/autobuild@d186a2a36cc67bfa1b860e6170d37fb9634742c7 # v2.2.11
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9 uses: github/codeql-action/analyze@d186a2a36cc67bfa1b860e6170d37fb9634742c7 # v2.2.11

View File

@ -17,14 +17,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Notify as seen - name: Notify as seen
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}
comment-id: ${{ github.event.comment.id }} comment-id: ${{ github.event.comment.id }}
reactions: '+1' reactions: '+1'
- name: Checkout the latest code - name: Checkout the latest code
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}
fetch-depth: 0 fetch-depth: 0
@ -43,7 +43,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Notify as seen - name: Notify as seen
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
if: ${{ github.event.comment != null }} if: ${{ github.event.comment != null }}
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}
@ -51,14 +51,14 @@ jobs:
reactions: eyes reactions: eyes
- name: Checkout the latest code - name: Checkout the latest code
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}
fetch-depth: 0 fetch-depth: 0
- name: Notify as running - name: Notify as running
id: comment_running id: comment_running
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
if: ${{ github.event.comment != null }} if: ${{ github.event.comment != null }}
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}
@ -93,7 +93,7 @@ jobs:
exit ${retcode} exit ${retcode}
- name: Notify with result success - name: Notify with result success
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
if: ${{ github.event.comment != null && success() }} if: ${{ github.event.comment != null && success() }}
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}
@ -108,7 +108,7 @@ jobs:
reactions: hooray reactions: hooray
- name: Notify with result failure - name: Notify with result failure
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
if: ${{ github.event.comment != null && failure() }} if: ${{ github.event.comment != null && failure() }}
with: with:
token: ${{ secrets.JF_BOT_TOKEN }} token: ${{ secrets.JF_BOT_TOKEN }}

View File

@ -14,7 +14,7 @@ jobs:
permissions: read-all permissions: read-all
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
@ -39,7 +39,7 @@ jobs:
permissions: read-all permissions: read-all
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
@ -110,7 +110,7 @@ jobs:
direction: last direction: last
body-includes: openapi-diff-workflow-comment body-includes: openapi-diff-workflow-comment
- name: Reply or edit difference comment (changed) - name: Reply or edit difference comment (changed)
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
if: ${{ steps.read-diff.outputs.body != '' }} if: ${{ steps.read-diff.outputs.body != '' }}
with: with:
issue-number: ${{ github.event.pull_request.number }} issue-number: ${{ github.event.pull_request.number }}
@ -125,7 +125,7 @@ jobs:
</details> </details>
- name: Edit difference comment (unchanged) - name: Edit difference comment (unchanged)
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0
if: ${{ steps.read-diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }} if: ${{ steps.read-diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }}
with: with:
issue-number: ${{ github.event.pull_request.number }} issue-number: ${{ github.event.pull_request.number }}

View File

@ -23,13 +23,13 @@
<PackageVersion Include="libse" Version="3.6.11" /> <PackageVersion Include="libse" Version="3.6.11" />
<PackageVersion Include="LrcParser" Version="2023.308.0" /> <PackageVersion Include="LrcParser" Version="2023.308.0" />
<PackageVersion Include="MetaBrainz.MusicBrainz" Version="5.0.0" /> <PackageVersion Include="MetaBrainz.MusicBrainz" Version="5.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="7.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="7.0.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.5" />
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" /> <PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.4" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.4" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.4" /> <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
@ -38,8 +38,8 @@
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="7.0.4" /> <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="7.0.5" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="7.0.4" /> <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="7.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" /> <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />

View File

@ -7,7 +7,6 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Sockets; using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Dlna.PlayTo; using Emby.Dlna.PlayTo;
using Emby.Dlna.Ssdp; using Emby.Dlna.Ssdp;

View File

@ -116,7 +116,7 @@ namespace Emby.Dlna.PlayTo
return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString); return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString);
} }
public string BuildPost(ServiceAction action, string xmlNamesapce, object value, string commandParameter = "") public string BuildPost(ServiceAction action, string xmlNamespace, object value, string commandParameter = "")
{ {
var stateString = string.Empty; var stateString = string.Empty;
@ -137,10 +137,10 @@ namespace Emby.Dlna.PlayTo
} }
} }
return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString);
} }
public string BuildPost(ServiceAction action, string xmlNamesapce, object value, Dictionary<string, string> dictionary) public string BuildPost(ServiceAction action, string xmlNamespace, object value, Dictionary<string, string> dictionary)
{ {
var stateString = string.Empty; var stateString = string.Empty;
@ -150,9 +150,9 @@ namespace Emby.Dlna.PlayTo
{ {
stateString += BuildArgumentXml(arg, "0"); stateString += BuildArgumentXml(arg, "0");
} }
else if (dictionary.ContainsKey(arg.Name)) else if (dictionary.TryGetValue(arg.Name, out var argValue))
{ {
stateString += BuildArgumentXml(arg, dictionary[arg.Name]); stateString += BuildArgumentXml(arg, argValue);
} }
else else
{ {
@ -160,7 +160,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString);
} }
private string BuildArgumentXml(Argument argument, string? value, string commandParameter = "") private string BuildArgumentXml(Argument argument, string? value, string commandParameter = "")

View File

@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.Data
if (JournalSizeLimit.HasValue) if (JournalSizeLimit.HasValue)
{ {
WriteConnection.Execute("PRAGMA journal_size_limit=" + (int)JournalSizeLimit.Value); WriteConnection.Execute("PRAGMA journal_size_limit=" + JournalSizeLimit.Value);
} }
if (Synchronous.HasValue) if (Synchronous.HasValue)
@ -166,18 +166,6 @@ namespace Emby.Server.Implementations.Data
public IStatement PrepareStatement(IDatabaseConnection connection, string sql) public IStatement PrepareStatement(IDatabaseConnection connection, string sql)
=> connection.PrepareStatement(sql); => connection.PrepareStatement(sql);
public IStatement[] PrepareAll(IDatabaseConnection connection, IReadOnlyList<string> sql)
{
int len = sql.Count;
IStatement[] statements = new IStatement[len];
for (int i = 0; i < len; i++)
{
statements[i] = connection.PrepareStatement(sql[i]);
}
return statements;
}
protected bool TableExists(ManagedConnection connection, string name) protected bool TableExists(ManagedConnection connection, string name)
{ {
return connection.RunInTransaction( return connection.RunInTransaction(

View File

@ -624,14 +624,8 @@ namespace Emby.Server.Implementations.Data
private void SaveItemsInTransaction(IDatabaseConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples) private void SaveItemsInTransaction(IDatabaseConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples)
{ {
var statements = PrepareAll(db, new string[] using (var saveItemStatement = PrepareStatement(db, SaveItemCommandText))
{ using (var deleteAncestorsStatement = PrepareStatement(db, "delete from AncestorIds where ItemId=@ItemId"))
SaveItemCommandText,
"delete from AncestorIds where ItemId=@ItemId"
});
using (var saveItemStatement = statements[0])
using (var deleteAncestorsStatement = statements[1])
{ {
var requiresReset = false; var requiresReset = false;
foreach (var tuple in tuples) foreach (var tuple in tuples)
@ -1286,15 +1280,13 @@ namespace Emby.Server.Implementations.Data
CheckDisposed(); CheckDisposed();
using (var connection = GetConnection(true)) using (var connection = GetConnection(true))
using (var statement = PrepareStatement(connection, _retrieveItemColumnsSelectQuery))
{ {
using (var statement = PrepareStatement(connection, _retrieveItemColumnsSelectQuery)) statement.TryBind("@guid", id);
{
statement.TryBind("@guid", id);
foreach (var row in statement.ExecuteQuery()) foreach (var row in statement.ExecuteQuery())
{ {
return GetItem(row, new InternalItemsQuery()); return GetItem(row, new InternalItemsQuery());
}
} }
} }
@ -1309,7 +1301,8 @@ namespace Emby.Server.Implementations.Data
{ {
return false; return false;
} }
else if (type == typeof(UserRootFolder))
if (type == typeof(UserRootFolder))
{ {
return false; return false;
} }
@ -1319,55 +1312,68 @@ namespace Emby.Server.Implementations.Data
{ {
return false; return false;
} }
else if (type == typeof(MusicArtist))
if (type == typeof(MusicArtist))
{ {
return false; return false;
} }
else if (type == typeof(Person))
if (type == typeof(Person))
{ {
return false; return false;
} }
else if (type == typeof(MusicGenre))
if (type == typeof(MusicGenre))
{ {
return false; return false;
} }
else if (type == typeof(Genre))
if (type == typeof(Genre))
{ {
return false; return false;
} }
else if (type == typeof(Studio))
if (type == typeof(Studio))
{ {
return false; return false;
} }
else if (type == typeof(PlaylistsFolder))
if (type == typeof(PlaylistsFolder))
{ {
return false; return false;
} }
else if (type == typeof(PhotoAlbum))
if (type == typeof(PhotoAlbum))
{ {
return false; return false;
} }
else if (type == typeof(Year))
if (type == typeof(Year))
{ {
return false; return false;
} }
else if (type == typeof(Book))
if (type == typeof(Book))
{ {
return false; return false;
} }
else if (type == typeof(LiveTvProgram))
if (type == typeof(LiveTvProgram))
{ {
return false; return false;
} }
else if (type == typeof(AudioBook))
if (type == typeof(AudioBook))
{ {
return false; return false;
} }
else if (type == typeof(Audio))
if (type == typeof(Audio))
{ {
return false; return false;
} }
else if (type == typeof(MusicAlbum))
if (type == typeof(MusicAlbum))
{ {
return false; return false;
} }
@ -1958,22 +1964,19 @@ namespace Emby.Server.Implementations.Data
{ {
CheckDisposed(); CheckDisposed();
var chapters = new List<ChapterInfo>();
using (var connection = GetConnection(true)) using (var connection = GetConnection(true))
using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc"))
{ {
var chapters = new List<ChapterInfo>(); statement.TryBind("@ItemId", item.Id);
using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc")) foreach (var row in statement.ExecuteQuery())
{ {
statement.TryBind("@ItemId", item.Id); chapters.Add(GetChapter(row, item));
foreach (var row in statement.ExecuteQuery())
{
chapters.Add(GetChapter(row, item));
}
} }
return chapters;
} }
return chapters;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -1982,16 +1985,14 @@ namespace Emby.Server.Implementations.Data
CheckDisposed(); CheckDisposed();
using (var connection = GetConnection(true)) using (var connection = GetConnection(true))
using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex"))
{ {
using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex")) statement.TryBind("@ItemId", item.Id);
{ statement.TryBind("@ChapterIndex", index);
statement.TryBind("@ItemId", item.Id);
statement.TryBind("@ChapterIndex", index);
foreach (var row in statement.ExecuteQuery()) foreach (var row in statement.ExecuteQuery())
{ {
return GetChapter(row, item); return GetChapter(row, item);
}
} }
} }
@ -2392,6 +2393,7 @@ namespace Emby.Server.Implementations.Data
// genres, tags, studios, person, year? // genres, tags, studios, person, year?
builder.Append("+ (Select count(1) * 10 from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from ItemValues where ItemId=@SimilarItemId))"); builder.Append("+ (Select count(1) * 10 from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from ItemValues where ItemId=@SimilarItemId))");
builder.Append("+ (Select count(1) * 10 from People where ItemId=Guid and Name in (select Name from People where ItemId=@SimilarItemId))");
if (item is MusicArtist) if (item is MusicArtist)
{ {
@ -2843,13 +2845,10 @@ namespace Emby.Server.Implementations.Data
connection.RunInTransaction( connection.RunInTransaction(
db => db =>
{ {
var itemQueryStatement = PrepareStatement(db, itemQuery);
var totalRecordCountQueryStatement = PrepareStatement(db, totalRecordCountQuery);
if (!isReturningZeroItems) if (!isReturningZeroItems)
{ {
using (new QueryTimeLogger(Logger, itemQuery, "GetItems.ItemQuery")) using (new QueryTimeLogger(Logger, itemQuery, "GetItems.ItemQuery"))
using (var statement = itemQueryStatement) using (var statement = PrepareStatement(db, itemQuery))
{ {
if (EnableJoinUserData(query)) if (EnableJoinUserData(query))
{ {
@ -2884,7 +2883,7 @@ namespace Emby.Server.Implementations.Data
if (query.EnableTotalRecordCount) if (query.EnableTotalRecordCount)
{ {
using (new QueryTimeLogger(Logger, totalRecordCountQuery, "GetItems.TotalRecordCount")) using (new QueryTimeLogger(Logger, totalRecordCountQuery, "GetItems.TotalRecordCount"))
using (var statement = totalRecordCountQueryStatement) using (var statement = PrepareStatement(db, totalRecordCountQuery))
{ {
if (EnableJoinUserData(query)) if (EnableJoinUserData(query))
{ {
@ -4753,22 +4752,20 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
commandText.Append(" LIMIT ").Append(query.Limit); commandText.Append(" LIMIT ").Append(query.Limit);
} }
var list = new List<string>();
using (var connection = GetConnection(true)) using (var connection = GetConnection(true))
using (var statement = PrepareStatement(connection, commandText.ToString()))
{ {
var list = new List<string>(); // Run this again to bind the params
using (var statement = PrepareStatement(connection, commandText.ToString())) GetPeopleWhereClauses(query, statement);
foreach (var row in statement.ExecuteQuery())
{ {
// Run this again to bind the params list.Add(row.GetString(0));
GetPeopleWhereClauses(query, statement);
foreach (var row in statement.ExecuteQuery())
{
list.Add(row.GetString(0));
}
} }
return list;
} }
return list;
} }
public List<PersonInfo> GetPeople(InternalPeopleQuery query) public List<PersonInfo> GetPeople(InternalPeopleQuery query)
@ -4793,23 +4790,20 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
commandText += " LIMIT " + query.Limit; commandText += " LIMIT " + query.Limit;
} }
var list = new List<PersonInfo>();
using (var connection = GetConnection(true)) using (var connection = GetConnection(true))
using (var statement = PrepareStatement(connection, commandText))
{ {
var list = new List<PersonInfo>(); // Run this again to bind the params
GetPeopleWhereClauses(query, statement);
using (var statement = PrepareStatement(connection, commandText)) foreach (var row in statement.ExecuteQuery())
{ {
// Run this again to bind the params list.Add(GetPerson(row));
GetPeopleWhereClauses(query, statement);
foreach (var row in statement.ExecuteQuery())
{
list.Add(GetPerson(row));
}
} }
return list;
} }
return list;
} }
private List<string> GetPeopleWhereClauses(InternalPeopleQuery query, IStatement statement) private List<string> GetPeopleWhereClauses(InternalPeopleQuery query, IStatement statement)

View File

@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Jellyfin.Api.Helpers;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using Jellyfin.Extensions; using Jellyfin.Extensions;
@ -572,9 +571,7 @@ namespace Emby.Server.Implementations.Dto
return null; return null;
} }
}).Where(i => i is not null) }).Where(i => i is not null)
.Where(i => user is null ? .Where(i => user is null || i.IsVisible(user))
true :
i.IsVisible(user))
.DistinctBy(x => x.Name, StringComparer.OrdinalIgnoreCase) .DistinctBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);

View File

@ -1503,6 +1503,12 @@ namespace Emby.Server.Implementations.Library
}); });
query.TopParentIds = userViews.SelectMany(i => GetTopParentIdsForQuery(i, user)).ToArray(); query.TopParentIds = userViews.SelectMany(i => GetTopParentIdsForQuery(i, user)).ToArray();
// Prevent searching in all libraries due to empty filter
if (query.TopParentIds.Length == 0)
{
query.TopParentIds = new[] { Guid.NewGuid() };
}
} }
} }
@ -1879,7 +1885,7 @@ namespace Emby.Server.Implementations.Library
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path); _logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path);
size = new ImageDimensions(0, 0); size = default;
image.Width = 0; image.Width = 0;
image.Height = 0; image.Height = 0;
} }
@ -2743,9 +2749,7 @@ namespace Emby.Server.Implementations.Library
} }
}) })
.Where(i => i is not null) .Where(i => i is not null)
.Where(i => query.User is null ? .Where(i => query.User is null || i.IsVisible(query.User))
true :
i.IsVisible(query.User))
.ToList(); .ToList();
} }

View File

@ -154,8 +154,8 @@ namespace Emby.Server.Implementations.Library
// If file is strm or main media stream is missing, force a metadata refresh with remote probing // If file is strm or main media stream is missing, force a metadata refresh with remote probing
if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder
&& (item.Path.EndsWith(".strm", StringComparison.OrdinalIgnoreCase) && (item.Path.EndsWith(".strm", StringComparison.OrdinalIgnoreCase)
|| (item.MediaType == MediaType.Video && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Video)) || (item.MediaType == MediaType.Video && mediaSources[0].MediaStreams.All(i => i.Type != MediaStreamType.Video))
|| (item.MediaType == MediaType.Audio && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio)))) || (item.MediaType == MediaType.Audio && mediaSources[0].MediaStreams.All(i => i.Type != MediaStreamType.Audio))))
{ {
await item.RefreshMetadata( await item.RefreshMetadata(
new MetadataRefreshOptions(_directoryService) new MetadataRefreshOptions(_directoryService)

View File

@ -78,7 +78,8 @@ namespace Emby.Server.Implementations.Library.Resolvers
Set3DFormat(videoTmp); Set3DFormat(videoTmp);
return videoTmp; return videoTmp;
} }
else if (IsBluRayDirectory(filename))
if (IsBluRayDirectory(filename))
{ {
var videoTmp = new TVideoType var videoTmp = new TVideoType
{ {

View File

@ -627,10 +627,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_timerProvider.Update(existingTimer); _timerProvider.Update(existingTimer);
return Task.FromResult(existingTimer.Id); return Task.FromResult(existingTimer.Id);
} }
else
{ throw new ArgumentException("A scheduled recording already exists for this program.");
throw new ArgumentException("A scheduled recording already exists for this program.");
}
} }
info.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); info.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
@ -1866,8 +1864,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{ {
await writer.WriteStartDocumentAsync(true).ConfigureAwait(false); await writer.WriteStartDocumentAsync(true).ConfigureAwait(false);
await writer.WriteStartElementAsync(null, "tvshow", null).ConfigureAwait(false); await writer.WriteStartElementAsync(null, "tvshow", null).ConfigureAwait(false);
string id; if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out var id))
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out id))
{ {
await writer.WriteElementStringAsync(null, "id", null, id).ConfigureAwait(false); await writer.WriteElementStringAsync(null, "id", null, id).ConfigureAwait(false);
} }

View File

@ -415,14 +415,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{ {
return null; return null;
} }
else if (uri.IndexOf("http", StringComparison.OrdinalIgnoreCase) != -1)
if (uri.IndexOf("http", StringComparison.OrdinalIgnoreCase) != -1)
{ {
return uri; return uri;
} }
else
{ return apiUrl + "/image/" + uri + "?token=" + token;
return apiUrl + "/image/" + uri + "?token=" + token;
}
} }
private static double GetAspectRatio(ImageDataDto i) private static double GetAspectRatio(ImageDataDto i)

View File

@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken) public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken)
{ {
using var client = new TcpClient(); using var client = new TcpClient();
await client.ConnectAsync(remoteIp, HdHomeRunPort).ConfigureAwait(false); await client.ConnectAsync(remoteIp, HdHomeRunPort, cancellationToken).ConfigureAwait(false);
using var stream = client.GetStream(); using var stream = client.GetStream();
return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false); return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false);

View File

@ -170,9 +170,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
var nameInExtInf = nameParts.Length > 1 ? nameParts[^1].AsSpan().Trim() : ReadOnlySpan<char>.Empty; var nameInExtInf = nameParts.Length > 1 ? nameParts[^1].AsSpan().Trim() : ReadOnlySpan<char>.Empty;
string numberString = null; string numberString = null;
string attributeValue;
if (attributes.TryGetValue("tvg-chno", out attributeValue) if (attributes.TryGetValue("tvg-chno", out var attributeValue)
&& double.TryParse(attributeValue, CultureInfo.InvariantCulture, out _)) && double.TryParse(attributeValue, CultureInfo.InvariantCulture, out _))
{ {
numberString = attributeValue; numberString = attributeValue;

View File

@ -1,27 +1,27 @@
{ {
"DeviceOnlineWithName": "{0}-এর সাথে সংযুক্ত হয়েছে", "DeviceOnlineWithName": "{0}-এর সাথে সংযুক্ত হয়েছে",
"DeviceOfflineWithName": "{0}-এর সাথে সংযোগ বিচ্ছিন্ন হয়েছে", "DeviceOfflineWithName": "{0}-এর সাথে সংযোগ বিচ্ছিন্ন হয়েছে",
"Collections": "সংগ্রহ", "Collections": "সংগ্রহশালা",
"ChapterNameValue": "অধ্যায় {0}", "ChapterNameValue": "অধ্যায় {0}",
"Channels": "চ্যানেল", "Channels": "চ্যানেলসমূহ",
"CameraImageUploadedFrom": "{0} থেকে একটি নতুন ক্যামেরার চিত্র আপলোড করা হয়েছে", "CameraImageUploadedFrom": "{0} থেকে একটি নতুন ক্যামেরার চিত্র আপলোড করা হয়েছে",
"Books": "বই", "Books": "পুস্তকসমূহ",
"AuthenticationSucceededWithUserName": "{0} অনুমোদন সফল", "AuthenticationSucceededWithUserName": "{0} অনুমোদন সফল",
"Artists": "শিল্পীরা", "Artists": "শিল্পীগণ",
"Application": "অ্যাপ্লিকেশন", "Application": "অ্যাপ্লিকেশন",
"Albums": "অ্যালবামগুলো", "Albums": "অ্যালবামসমূহ",
"HeaderFavoriteEpisodes": "প্রিব পর্বগুলো", "HeaderFavoriteEpisodes": "প্রিব পর্বগুলো",
"HeaderFavoriteArtists": "প্রিয় শিল্পীরা", "HeaderFavoriteArtists": "প্রিয় শিল্পীরা",
"HeaderFavoriteAlbums": "প্রিয় এলবামগুলো", "HeaderFavoriteAlbums": "প্রিয় এলবামগুলো",
"HeaderContinueWatching": "দেখতে থাকুন", "HeaderContinueWatching": "দেখতে থাকুন",
"HeaderAlbumArtists": "লবাম শিল্পীবৃন্দ", "HeaderAlbumArtists": "অ্যালবাম শিল্পীবৃন্দ",
"Genres": "শৈলী", "Genres": "শৈলীধারাসমূহ",
"Folders": "ফোল্ডারগুলো", "Folders": "ফোল্ডারসমূহ",
"Favorites": "পছন্দসমূহ", "Favorites": "পছন্দসমূহ",
"FailedLoginAttemptWithUserName": "{0} লগিন করতে ব্যর্থ হয়েছে", "FailedLoginAttemptWithUserName": "{0} লগিন করতে ব্যর্থ হয়েছে",
"AppDeviceValues": "অ্যাপ: {0}, ডিভাইস: {0}", "AppDeviceValues": "অ্যাপ: {0}, ডিভাইস: {0}",
"VersionNumber": "সংস্করণ {0}", "VersionNumber": "সংস্করণ {0}",
"ValueSpecialEpisodeName": "বিশেষ - {0}", "ValueSpecialEpisodeName": "বিশেষ পর্ব - {0}",
"ValueHasBeenAddedToLibrary": "আপনার লাইব্রেরিতে {0} যোগ করা হয়েছে", "ValueHasBeenAddedToLibrary": "আপনার লাইব্রেরিতে {0} যোগ করা হয়েছে",
"UserStoppedPlayingItemWithValues": "{2}তে {1} বাজানো শেষ করেছেন {0}", "UserStoppedPlayingItemWithValues": "{2}তে {1} বাজানো শেষ করেছেন {0}",
"UserStartedPlayingItemWithValues": "{2}তে {1} বাজাচ্ছেন {0}", "UserStartedPlayingItemWithValues": "{2}তে {1} বাজাচ্ছেন {0}",
@ -36,10 +36,10 @@
"User": "ব্যবহারকারী", "User": "ব্যবহারকারী",
"TvShows": "টিভি শোগুলো", "TvShows": "টিভি শোগুলো",
"System": "সিস্টেম", "System": "সিস্টেম",
"Sync": "সিংক", "Sync": "সমলয় স্থাপন",
"SubtitleDownloadFailureFromForItem": "{2} থেকে {1} এর জন্য সাবটাইটেল ডাউনলোড ব্যর্থ", "SubtitleDownloadFailureFromForItem": "{2} থেকে {1} এর জন্য সাবটাইটেল ডাউনলোড ব্যর্থ",
"StartupEmbyServerIsLoading": "জেলিফিন সার্ভার লোড হচ্ছে। দয়া করে একটু পরে আবার চেষ্টা করুন।", "StartupEmbyServerIsLoading": "জেলিফিন সার্ভার লোড হচ্ছে। দয়া করে একটু পরে আবার চেষ্টা করুন।",
"Songs": "গানগুলো", "Songs": "সঙ্গীতসমূহ",
"Shows": "টিভি পর্ব", "Shows": "টিভি পর্ব",
"ServerNameNeedsToBeRestarted": "{0} রিস্টার্ট করা প্রয়োজন", "ServerNameNeedsToBeRestarted": "{0} রিস্টার্ট করা প্রয়োজন",
"ScheduledTaskStartedWithName": "{0} শুরু হয়েছে", "ScheduledTaskStartedWithName": "{0} শুরু হয়েছে",
@ -49,8 +49,8 @@
"PluginUninstalledWithName": "{0} বাদ দেয়া হয়েছে", "PluginUninstalledWithName": "{0} বাদ দেয়া হয়েছে",
"PluginInstalledWithName": "{0} ইন্সটল করা হয়েছে", "PluginInstalledWithName": "{0} ইন্সটল করা হয়েছে",
"Plugin": "প্লাগিন", "Plugin": "প্লাগিন",
"Playlists": "প্লেলিস্ট", "Playlists": "প্লে লিস্ট সমূহ",
"Photos": "ছবিগুলো", "Photos": "চিত্রসমূহ",
"NotificationOptionVideoPlaybackStopped": "ভিডিও চলা বন্ধ", "NotificationOptionVideoPlaybackStopped": "ভিডিও চলা বন্ধ",
"NotificationOptionVideoPlayback": "ভিডিও চলা শুরু হয়েছে", "NotificationOptionVideoPlayback": "ভিডিও চলা শুরু হয়েছে",
"NotificationOptionUserLockedOut": "ব্যবহারকারী ঢুকতে পারছে না", "NotificationOptionUserLockedOut": "ব্যবহারকারী ঢুকতে পারছে না",
@ -71,9 +71,9 @@
"NameSeasonUnknown": "সিজন অজানা", "NameSeasonUnknown": "সিজন অজানা",
"NameSeasonNumber": "সিজন {0}", "NameSeasonNumber": "সিজন {0}",
"NameInstallFailed": "{0} ইন্সটল ব্যর্থ", "NameInstallFailed": "{0} ইন্সটল ব্যর্থ",
"MusicVideos": "গানের ভিডিও", "MusicVideos": "সঙ্গীত ভিডিয়ো সমূহ",
"Music": "গান", "Music": "গান",
"Movies": "চলচ্চিত্র", "Movies": "চলচ্চিত্রসমূহ",
"MixedContent": "মিশ্র কন্টেন্ট", "MixedContent": "মিশ্র কন্টেন্ট",
"MessageServerConfigurationUpdated": "সার্ভারের কনফিগারেশন আপডেট করা হয়েছে", "MessageServerConfigurationUpdated": "সার্ভারের কনফিগারেশন আপডেট করা হয়েছে",
"HeaderRecordingGroups": "রেকর্ডিং দল", "HeaderRecordingGroups": "রেকর্ডিং দল",
@ -117,5 +117,11 @@
"Forced": "জোরকরে", "Forced": "জোরকরে",
"TaskCleanActivityLogDescription": "নির্ধারিত সময়ের আগের কাজের হিসাব মুছে দিন খালি করুন.", "TaskCleanActivityLogDescription": "নির্ধারিত সময়ের আগের কাজের হিসাব মুছে দিন খালি করুন.",
"TaskCleanActivityLog": "কাজের ফাইল খালি করুন", "TaskCleanActivityLog": "কাজের ফাইল খালি করুন",
"Default": "প্রাথমিক" "Default": "প্রাথমিক",
"HearingImpaired": "দুর্বল শ্রবণক্ষমতাধরদের জন্য",
"TaskOptimizeDatabaseDescription": "তথ্যভাণ্ডার সুবিন্যস্ত করে ও অব্যবহৃত জায়গা ছেড়ে দেয়। লাইব্রেরী স্ক্যান অথবা যেকোনো তথ্যভাণ্ডার পরিবর্তনের পর এই প্রক্রিয়া চালালে তথ্যভাণ্ডারের তথ্য প্রদান দ্রুততর হতে পারে।",
"External": "বাহ্যিক",
"TaskOptimizeDatabase": "তথ্যভাণ্ডার সুবিন্যাস",
"TaskKeyframeExtractor": "কি-ফ্রেম নিষ্কাশক",
"TaskKeyframeExtractorDescription": "ভিডিয়ো থেকে কি-ফ্রেম নিষ্কাশনের মাধ্যমে অধিকতর সঠিক HLS প্লে লিস্ট তৈরী করে। এই প্রক্রিয়া দীর্ঘ সময় ধরে চলতে পারে।"
} }

View File

@ -1,9 +1,9 @@
{ {
"Albums": "Albummer", "Albums": "Album",
"AppDeviceValues": "App: {0}, Enhed: {1}", "AppDeviceValues": "App: {0}, Enhed: {1}",
"Application": "Applikation", "Application": "Applikation",
"Artists": "Kunstnere", "Artists": "Kunstnere",
"AuthenticationSucceededWithUserName": "{0} succesfuldt autentificeret", "AuthenticationSucceededWithUserName": "{0} er logget ind",
"Books": "Bøger", "Books": "Bøger",
"CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}", "CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}",
"Channels": "Kanaler", "Channels": "Kanaler",
@ -11,17 +11,17 @@
"Collections": "Samlinger", "Collections": "Samlinger",
"DeviceOfflineWithName": "{0} har afbrudt forbindelsen", "DeviceOfflineWithName": "{0} har afbrudt forbindelsen",
"DeviceOnlineWithName": "{0} er forbundet", "DeviceOnlineWithName": "{0} er forbundet",
"FailedLoginAttemptWithUserName": "Fejlet loginforsøg fra {0}", "FailedLoginAttemptWithUserName": "Mislykket loginforsøg fra {0}",
"Favorites": "Favoritter", "Favorites": "Favoritter",
"Folders": "Mapper", "Folders": "Mapper",
"Genres": "Genrer", "Genres": "Genrer",
"HeaderAlbumArtists": "Albumkunstner", "HeaderAlbumArtists": "Albums kunstnere",
"HeaderContinueWatching": "Fortsæt afspilning", "HeaderContinueWatching": "Fortsæt afspilning",
"HeaderFavoriteAlbums": "Favoritalbummer", "HeaderFavoriteAlbums": "Favorit albummer",
"HeaderFavoriteArtists": "Favoritkunstnere", "HeaderFavoriteArtists": "Favorit kunstnere",
"HeaderFavoriteEpisodes": "Favoritepisoder", "HeaderFavoriteEpisodes": "Favorit afsnit",
"HeaderFavoriteShows": "Favoritserier", "HeaderFavoriteShows": "Favorit serier",
"HeaderFavoriteSongs": "Favoritsange", "HeaderFavoriteSongs": "Favorit sange",
"HeaderLiveTV": "Live-TV", "HeaderLiveTV": "Live-TV",
"HeaderNextUp": "Næste", "HeaderNextUp": "Næste",
"HeaderRecordingGroups": "Optagelsesgrupper", "HeaderRecordingGroups": "Optagelsesgrupper",
@ -39,90 +39,90 @@
"MixedContent": "Blandet indhold", "MixedContent": "Blandet indhold",
"Movies": "Film", "Movies": "Film",
"Music": "Musik", "Music": "Musik",
"MusicVideos": "Musik videoer", "MusicVideos": "Musikvideoer",
"NameInstallFailed": "{0} installationen mislykkedes", "NameInstallFailed": "{0} installationen mislykkedes",
"NameSeasonNumber": "Sæson {0}", "NameSeasonNumber": "Sæson {0}",
"NameSeasonUnknown": "Ukendt sæson", "NameSeasonUnknown": "Ukendt sæson",
"NewVersionIsAvailable": "En ny version af Jellyfin Server er tilgængelig til download.", "NewVersionIsAvailable": "En ny version af Jellyfin Server er tilgængelig.",
"NotificationOptionApplicationUpdateAvailable": "Opdatering til applikation tilgængelig", "NotificationOptionApplicationUpdateAvailable": "Opdatering til applikationen er tilgængelig",
"NotificationOptionApplicationUpdateInstalled": "Opdatering til applikation installeret", "NotificationOptionApplicationUpdateInstalled": "Opdatering til applikationen blev installeret",
"NotificationOptionAudioPlayback": "Lydafspilning påbegyndt", "NotificationOptionAudioPlayback": "Lydafspilning påbegyndt",
"NotificationOptionAudioPlaybackStopped": "Lydafspilning stoppet", "NotificationOptionAudioPlaybackStopped": "Lydafspilning stoppet",
"NotificationOptionCameraImageUploaded": "Kamerabillede uploadet", "NotificationOptionCameraImageUploaded": "Kamerabillede uploadet",
"NotificationOptionInstallationFailed": "Installationen fejlede", "NotificationOptionInstallationFailed": "Installationen mislykkedes",
"NotificationOptionNewLibraryContent": "Nyt indhold tilføjet", "NotificationOptionNewLibraryContent": "Nyt indhold tilføjet",
"NotificationOptionPluginError": "Pluginfejl", "NotificationOptionPluginError": "Plugin fejl",
"NotificationOptionPluginInstalled": "Plugin installeret", "NotificationOptionPluginInstalled": "Plugin blev installeret",
"NotificationOptionPluginUninstalled": "Plugin afinstalleret", "NotificationOptionPluginUninstalled": "Plugin blev afinstalleret",
"NotificationOptionPluginUpdateInstalled": "Opdatering til plugin installeret", "NotificationOptionPluginUpdateInstalled": "Opdatering til plugin blev installeret",
"NotificationOptionServerRestartRequired": "Genstart af server påkrævet", "NotificationOptionServerRestartRequired": "Genstart af serveren er påkrævet",
"NotificationOptionTaskFailed": "Planlagt opgave fejlet", "NotificationOptionTaskFailed": "Planlagt opgave er fejlet",
"NotificationOptionUserLockedOut": "Bruger låst ude", "NotificationOptionUserLockedOut": "Bruger er låst ude",
"NotificationOptionVideoPlayback": "Videoafspilning påbegyndt", "NotificationOptionVideoPlayback": "Videoafspilning påbegyndt",
"NotificationOptionVideoPlaybackStopped": "Videoafspilning stoppet", "NotificationOptionVideoPlaybackStopped": "Videoafspilning blev stoppet",
"Photos": "Fotoer", "Photos": "Fotos",
"Playlists": "Afspilningslister", "Playlists": "Afspilningslister",
"Plugin": "Plugin", "Plugin": "Plugin",
"PluginInstalledWithName": "{0} blev installeret", "PluginInstalledWithName": "{0} blev installeret",
"PluginUninstalledWithName": "{0} blev afinstalleret", "PluginUninstalledWithName": "{0} blev afinstalleret",
"PluginUpdatedWithName": "{0} blev opdateret", "PluginUpdatedWithName": "{0} blev opdateret",
"ProviderValue": "Udbyder: {0}", "ProviderValue": "Udbyder: {0}",
"ScheduledTaskFailedWithName": "{0} fejlet", "ScheduledTaskFailedWithName": "{0} mislykkedes",
"ScheduledTaskStartedWithName": "{0} påbegyndt", "ScheduledTaskStartedWithName": "{0} påbegyndte",
"ServerNameNeedsToBeRestarted": "{0} skal genstartes", "ServerNameNeedsToBeRestarted": "{0} skal genstartes",
"Shows": "Serier", "Shows": "Serier",
"Songs": "Sange", "Songs": "Sange",
"StartupEmbyServerIsLoading": "Jellyfin Server er i gang med at starte op. Prøv venligst igen om lidt.", "StartupEmbyServerIsLoading": "Jellyfin Server er i gang med at starte. Forsøg igen om et øjeblik.",
"SubtitleDownloadFailureForItem": "Fejlet i download af undertekster for {0}", "SubtitleDownloadFailureForItem": "Fejlet i download af undertekster for {0}",
"SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke downloades fra {0} til {1}", "SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke hentes fra {0} til {1}",
"Sync": "Synk", "Sync": "Synkroniser",
"System": "System", "System": "System",
"TvShows": "Tv-serier", "TvShows": "TV-serier",
"User": "Bruger", "User": "Bruger",
"UserCreatedWithName": "Bruger {0} er blevet oprettet", "UserCreatedWithName": "Bruger {0} er blevet oprettet",
"UserDeletedWithName": "Brugeren {0} er blevet slettet", "UserDeletedWithName": "Brugeren {0} er nu slettet",
"UserDownloadingItemWithValues": "{0} downloader {1}", "UserDownloadingItemWithValues": "{0} henter {1}",
"UserLockedOutWithName": "Brugeren {0} er blevet låst ude", "UserLockedOutWithName": "Brugeren {0} er blevet låst ude",
"UserOfflineFromDevice": "{0} har afbrudt fra {1}", "UserOfflineFromDevice": "{0} har afbrudt fra {1}",
"UserOnlineFromDevice": "{0} er online fra {1}", "UserOnlineFromDevice": "{0} er online fra {1}",
"UserPasswordChangedWithName": "Adgangskode er ændret for bruger {0}", "UserPasswordChangedWithName": "Adgangskode er ændret for brugeren {0}",
"UserPolicyUpdatedWithName": "Brugerpolitik er blevet opdateret for {0}", "UserPolicyUpdatedWithName": "Brugerpolitikken er blevet opdateret for {0}",
"UserStartedPlayingItemWithValues": "{0} har påbegyndt afspilning af {1}", "UserStartedPlayingItemWithValues": "{0} har påbegyndt afspilning af {1}",
"UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1} på {2}", "UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1} på {2}",
"ValueHasBeenAddedToLibrary": "{0} er blevet tilføjet til dit mediebibliotek", "ValueHasBeenAddedToLibrary": "{0} er blevet tilføjet til dit mediebibliotek",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Special - {0}",
"VersionNumber": "Version {0}", "VersionNumber": "Version {0}",
"TaskDownloadMissingSubtitlesDescription": "Søger på internettet efter manglende undertekster baseret på metadata konfiguration.", "TaskDownloadMissingSubtitlesDescription": "Søger på internettet efter manglende undertekster baseret på metadata konfigurationen.",
"TaskDownloadMissingSubtitles": "Download manglende undertekster", "TaskDownloadMissingSubtitles": "Hent manglende undertekster",
"TaskUpdatePluginsDescription": "Downloader og installere opdateringer for plugins som er konfigureret til at opdatere automatisk.", "TaskUpdatePluginsDescription": "Henter og installerer opdateringer for plugins, som er indstillet til at blive opdateret automatisk.",
"TaskUpdatePlugins": "Opdater Plugins", "TaskUpdatePlugins": "Opdater Plugins",
"TaskCleanLogsDescription": "Sletter log filer som er mere end {0} dage gammle.", "TaskCleanLogsDescription": "Sletter log filer som er mere end {0} dage gamle.",
"TaskCleanLogs": "Ryd Log Mappe", "TaskCleanLogs": "Ryd Log mappe",
"TaskRefreshLibraryDescription": "Scanner dit medie bibliotek for nye filer og opdaterer metadata.", "TaskRefreshLibraryDescription": "Scanner dit medie bibliotek for nye filer og opdateret metadata.",
"TaskRefreshLibrary": "Scan Medie Bibliotek", "TaskRefreshLibrary": "Scan Medie Bibliotek",
"TaskCleanCacheDescription": "Sletter cache filer som systemet ikke har brug for længere.", "TaskCleanCacheDescription": "Sletter cache filer som systemet ikke længere bruger.",
"TaskCleanCache": "Ryd Cache Mappe", "TaskCleanCache": "Ryd Cache mappe",
"TasksChannelsCategory": "Internet Kanaler", "TasksChannelsCategory": "Internet Kanaler",
"TasksApplicationCategory": "Applikation", "TasksApplicationCategory": "Applikation",
"TasksLibraryCategory": "Bibliotek", "TasksLibraryCategory": "Bibliotek",
"TasksMaintenanceCategory": "Vedligeholdelse", "TasksMaintenanceCategory": "Vedligeholdelse",
"TaskRefreshChapterImages": "Udtræk Kapitel billeder", "TaskRefreshChapterImages": "Udtræk kapitel billeder",
"TaskRefreshChapterImagesDescription": "Lav miniaturebilleder for videoer der har kapitler.", "TaskRefreshChapterImagesDescription": "Lav miniaturebilleder for videoer der har kapitler.",
"TaskRefreshChannelsDescription": "Genopfrisker internet kanal information.", "TaskRefreshChannelsDescription": "Opdater internet kanal information.",
"TaskRefreshChannels": "Genopfrisk Kanaler", "TaskRefreshChannels": "Opdater Kanaler",
"TaskCleanTranscodeDescription": "Fjern transcode filer som er mere end en dag gammel.", "TaskCleanTranscodeDescription": "Fjern transcode filer som er mere end 1 dag gammel.",
"TaskCleanTranscode": "Rengør Transcode Mappen", "TaskCleanTranscode": "Tøm Transcode mappen",
"TaskRefreshPeople": "Genopfrisk Personer", "TaskRefreshPeople": "Opdater Personer",
"TaskRefreshPeopleDescription": "Opdatere metadata for skuespillere og instruktører i dit bibliotek.", "TaskRefreshPeopleDescription": "Opdaterer metadata for skuespillere og instruktører i dit mediebibliotek.",
"TaskCleanActivityLogDescription": "Sletter linjer i aktivitetsloggen ældre end den konfigureret alder.", "TaskCleanActivityLogDescription": "Sletter linjer i aktivitetsloggen ældre end den konfigurerede alder.",
"TaskCleanActivityLog": "Ryd Aktivitetslog", "TaskCleanActivityLog": "Ryd Aktivitetslog",
"Undefined": "Udefineret", "Undefined": "Udefineret",
"Forced": "Tvunget", "Forced": "Tvunget",
"Default": "Standard", "Default": "Standard",
"TaskOptimizeDatabaseDescription": "Kompakter database og forkorter fri plads. Ved at køre denne proces efter at scanne biblioteket eller efter at ændre noget som kunne have indflydelse på databasen, kan forbedre ydeevne.", "TaskOptimizeDatabaseDescription": "Komprimerer databasen og frigør plads. Denne handling køres efter at have scannet mediebiblioteket, eller efter at have lavet ændringer til databasen, for at højne ydeevnen.",
"TaskOptimizeDatabase": "Optimér database", "TaskOptimizeDatabase": "Optimér database",
"TaskKeyframeExtractorDescription": "Udtrækker billeder fra videofiler for at lave mere præcise HLS playlister. Denne opgave kan godt tage lang tid.", "TaskKeyframeExtractorDescription": "Udtrækker billeder fra videofiler for at lave mere præcise HLS playlister. Denne opgave kan tage lang tid.",
"TaskKeyframeExtractor": "Billedramme udtrækker", "TaskKeyframeExtractor": "Nøglebillede udtræk",
"External": "Ekstern", "External": "Ekstern",
"HearingImpaired": "Hørehæmmet" "HearingImpaired": "Hørehæmmet"
} }

View File

@ -73,5 +73,25 @@
"Songs": "गाने", "Songs": "गाने",
"UserStartedPlayingItemWithValues": "{0} {2} पर {1} खेल रहे हैं", "UserStartedPlayingItemWithValues": "{0} {2} पर {1} खेल रहे हैं",
"UserStoppedPlayingItemWithValues": "{0} ने {2} पर {1} खेलना खत्म किया", "UserStoppedPlayingItemWithValues": "{0} ने {2} पर {1} खेलना खत्म किया",
"StartupEmbyServerIsLoading": "जेलीफ़िन सर्वर लोड हो रहा है। कृपया शीघ्र ही पुन: प्रयास करें।" "StartupEmbyServerIsLoading": "जेलीफ़िन सर्वर लोड हो रहा है। कृपया शीघ्र ही पुन: प्रयास करें।",
"ServerNameNeedsToBeRestarted": "{0} रीस्टार्ट करने की आवश्यकता है",
"UserCreatedWithName": "उपयोगकर्ता {0} बनाया गया",
"UserDownloadingItemWithValues": "{0} डाउनलोड हो रहा है",
"UserOfflineFromDevice": "{0} {1} से डिस्कनेक्ट हो गया है",
"Undefined": "अनिर्धारित",
"UserOnlineFromDevice": "{0} {1} से ऑनलाइन है",
"Shows": "शो",
"UserPasswordChangedWithName": "उपयोगकर्ता {0} के लिए पासवर्ड बदल दिया गया है",
"UserDeletedWithName": "उपयोगकर्ता {0} हटा दिया गया",
"UserPolicyUpdatedWithName": "{0} के लिए उपयोगकर्ता नीति अपडेट कर दी गई है",
"User": "उपयोगकर्ता",
"SubtitleDownloadFailureFromForItem": "{1} के लिए {0} से उपशीर्षक डाउनलोड करने में विफल",
"ProviderValue": "प्रदाता: {0}",
"ScheduledTaskFailedWithName": "{0}असफल",
"UserLockedOutWithName": "उपयोगकर्ता {0} को लॉक आउट कर दिया गया है",
"System": "प्रणाली",
"TvShows": "टीवी शो",
"HearingImpaired": "मूक बधिर",
"ValueSpecialEpisodeName": "विशेष",
"TasksMaintenanceCategory": "रखरखाव"
} }

View File

@ -28,22 +28,22 @@
"ValueHasBeenAddedToLibrary": "{0} ਤੁਹਾਡੀ ਮੀਡੀਆ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ", "ValueHasBeenAddedToLibrary": "{0} ਤੁਹਾਡੀ ਮੀਡੀਆ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ",
"UserStoppedPlayingItemWithValues": "{0} ਨੇ {2} 'ਤੇ {1} ਖੇਡਣਾ ਪੂਰਾ ਕਰ ਲਿਆ ਹੈ", "UserStoppedPlayingItemWithValues": "{0} ਨੇ {2} 'ਤੇ {1} ਖੇਡਣਾ ਪੂਰਾ ਕਰ ਲਿਆ ਹੈ",
"UserStartedPlayingItemWithValues": "{0} {2} 'ਤੇ {1} ਖੇਡ ਰਿਹਾ ਹੈ", "UserStartedPlayingItemWithValues": "{0} {2} 'ਤੇ {1} ਖੇਡ ਰਿਹਾ ਹੈ",
"UserPolicyUpdatedWithName": "ਉਪਭੋਗਤਾ ਨੀਤੀ ਨੂੰ {0} ਲਈ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ", "UserPolicyUpdatedWithName": "ਵਰਤੋਂਕਾਰ ਨੀਤੀ ਨੂੰ {0} ਲਈ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ",
"UserPasswordChangedWithName": "ਪਾਸਵਰਡ ਯੂਜ਼ਰ ਲਈ ਬਦਲਿਆ ਗਿਆ ਹੈ {0}", "UserPasswordChangedWithName": "{0} ਵਰਤੋਂਕਾਰ ਲਈ ਪਾਸਵਰਡ ਬਦਲਿਆ ਗਿਆ ਸੀ",
"UserOnlineFromDevice": "{0} ਤੋਂ isਨਲਾਈਨ ਹੈ {1}", "UserOnlineFromDevice": "{0} ਨੂੰ {1} ਤੋਂ ਆਨਲਾਈਨ ਹੈ",
"UserOfflineFromDevice": "{0} ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ {1}", "UserOfflineFromDevice": "{0} ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ {1}",
"UserLockedOutWithName": "ਯੂਜ਼ਰ {0} ਨੂੰ ਲਾਕ ਆਉਟ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ", "UserLockedOutWithName": "ਵਰਤੋਂਕਾਰ {0} ਨੂੰ ਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ",
"UserDownloadingItemWithValues": "{0} ਡਾ{ਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ {1}", "UserDownloadingItemWithValues": "{0} {1} ਨੂੰ ਡਾਊਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ",
"UserDeletedWithName": "ਯੂਜ਼ਰ {0} ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ", "UserDeletedWithName": "ਵਰਤੋਂਕਾਰ {0} ਨੂੰ ਹਟਾਇਆ ਗਿਆ",
"UserCreatedWithName": "ਯੂਜ਼ਰ {0} ਬਣਾਇਆ ਗਿਆ ਹੈ", "UserCreatedWithName": "ਵਰਤੋਂਕਾਰ {0} ਬਣਾਇਆ ਗਿਆ ਹੈ",
"User": "ਯੂਜ਼ਰ", "User": "ਵਰਤੋਂਕਾਰ",
"Undefined": "ਪਰਿਭਾਸ਼ਤ", "Undefined": "ਪਰਿਭਾਸ਼ਤ",
"TvShows": "ਟੀਵੀ ਸ਼ੋਅਜ਼", "TvShows": "ਟੀਵੀ ਸ਼ੋਅ",
"System": "ਸਿਸਟਮ", "System": "ਸਿਸਟਮ",
"Sync": "ਸਿੰਕ", "Sync": "ਸਿੰਕ",
"SubtitleDownloadFailureFromForItem": "ਉਪਸਿਰਲੇਖ {1} ਲਈ {0} ਤੋਂ ਡਾ toਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ ਰਹੇ", "SubtitleDownloadFailureFromForItem": "ਉਪਸਿਰਲੇਖ {1} ਲਈ {0} ਤੋਂ ਡਾਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ ਰਹੇ",
"StartupEmbyServerIsLoading": "ਜੈਲੀਫਿਨ ਸਰਵਰ ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ. ਕਿਰਪਾ ਕਰਕੇ ਜਲਦੀ ਹੀ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ.", "StartupEmbyServerIsLoading": "Jellyfin ਸਰਵਰ ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ। ਛੇਤੀ ਹੀ ਫ਼ੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ।",
"Songs": "ਗਾਣੇ", "Songs": "ਗਾਣੇ",
"Shows": "ਸ਼ੋਅ", "Shows": "ਸ਼ੋਅ",
"ServerNameNeedsToBeRestarted": "{0} ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ", "ServerNameNeedsToBeRestarted": "{0} ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ",
"ScheduledTaskStartedWithName": "{0} ਸ਼ੁਰੂ ਹੋਇਆ", "ScheduledTaskStartedWithName": "{0} ਸ਼ੁਰੂ ਹੋਇਆ",
@ -57,12 +57,12 @@
"Photos": "ਫੋਟੋਆਂ", "Photos": "ਫੋਟੋਆਂ",
"NotificationOptionVideoPlaybackStopped": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਰੋਕਿਆ ਗਿਆ", "NotificationOptionVideoPlaybackStopped": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਰੋਕਿਆ ਗਿਆ",
"NotificationOptionVideoPlayback": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਸ਼ੁਰੂ ਹੋਇਆ", "NotificationOptionVideoPlayback": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਸ਼ੁਰੂ ਹੋਇਆ",
"NotificationOptionUserLockedOut": "ਉਪਭੋਗਤਾ ਨੂੰ ਲਾਕ ਆਉਟ ਕੀਤਾ ਗਿਆ", "NotificationOptionUserLockedOut": "ਵਰਤੋਂਕਾਰ ਨੂੰ ਲਾਕ ਕੀਤਾ",
"NotificationOptionTaskFailed": "ਨਿਰਧਾਰਤ ਕਾਰਜ ਅਸਫਲਤਾ", "NotificationOptionTaskFailed": "ਨਿਰਧਾਰਤ ਕਾਰਜ ਅਸਫਲਤਾ",
"NotificationOptionServerRestartRequired": "ਸਰਵਰ ਨੂੰ ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ", "NotificationOptionServerRestartRequired": "ਸਰਵਰ ਨੂੰ ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ",
"NotificationOptionPluginUpdateInstalled": "ਪਲੱਗਇਨ ਅਪਡੇਟ ਇੰਸਟੌਲ ਕੀਤਾ ਗਿਆ", "NotificationOptionPluginUpdateInstalled": "ਪਲੱਗਇਨ ਅਪਡੇਟ ਇੰਸਟੌਲ ਕੀਤਾ ਗਿਆ",
"NotificationOptionPluginUninstalled": "ਪਲੱਗਇਨ ਅਣਇੰਸਟੌਲ ਕੀਤਾ", "NotificationOptionPluginUninstalled": "ਪਲੱਗਇਨ ਅਣਇੰਸਟੌਲ ਕੀਤਾ",
"NotificationOptionPluginInstalled": "ਪਲੱਗਇਨ ਸਥਾਪਿਤ ਕੀਤਾ", "NotificationOptionPluginInstalled": "ਪਲੱਗਇਨ ਇੰਸਟਾਲ ਕੀਤੀ",
"NotificationOptionPluginError": "ਪਲੱਗਇਨ ਅਸਫਲ", "NotificationOptionPluginError": "ਪਲੱਗਇਨ ਅਸਫਲ",
"NotificationOptionNewLibraryContent": "ਨਵੀਂ ਸਮੱਗਰੀ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ", "NotificationOptionNewLibraryContent": "ਨਵੀਂ ਸਮੱਗਰੀ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ",
"NotificationOptionInstallationFailed": "ਇੰਸਟਾਲੇਸ਼ਨ ਅਸਫਲ", "NotificationOptionInstallationFailed": "ਇੰਸਟਾਲੇਸ਼ਨ ਅਸਫਲ",
@ -92,7 +92,7 @@
"HomeVideos": "ਘਰੇਲੂ ਵੀਡੀਓ", "HomeVideos": "ਘਰੇਲੂ ਵੀਡੀਓ",
"HeaderRecordingGroups": "ਰਿਕਾਰਡਿੰਗ ਸਮੂਹ", "HeaderRecordingGroups": "ਰਿਕਾਰਡਿੰਗ ਸਮੂਹ",
"HeaderNextUp": "ਅੱਗੇ", "HeaderNextUp": "ਅੱਗੇ",
"HeaderLiveTV": "ਲਾਈਵ ਟੀ", "HeaderLiveTV": "ਲਾਈਵ ਟੀਵੀ",
"HeaderFavoriteSongs": "ਮਨਪਸੰਦ ਗਾਣੇ", "HeaderFavoriteSongs": "ਮਨਪਸੰਦ ਗਾਣੇ",
"HeaderFavoriteShows": "ਮਨਪਸੰਦ ਸ਼ੋਅ", "HeaderFavoriteShows": "ਮਨਪਸੰਦ ਸ਼ੋਅ",
"HeaderFavoriteEpisodes": "ਮਨਪਸੰਦ ਐਪੀਸੋਡ", "HeaderFavoriteEpisodes": "ਮਨਪਸੰਦ ਐਪੀਸੋਡ",
@ -102,20 +102,22 @@
"HeaderAlbumArtists": "ਐਲਬਮ ਕਲਾਕਾਰ", "HeaderAlbumArtists": "ਐਲਬਮ ਕਲਾਕਾਰ",
"Genres": "ਸ਼ੈਲੀਆਂ", "Genres": "ਸ਼ੈਲੀਆਂ",
"Forced": "ਮਜਬੂਰ", "Forced": "ਮਜਬੂਰ",
"Folders": "ਫੋਲਡਰ", "Folders": "ਫੋਲਡਰ",
"Favorites": "ਮਨਪਸੰਦ", "Favorites": "ਮਨਪਸੰਦ",
"FailedLoginAttemptWithUserName": "ਤੋਂ ਲਾਗਇਨ ਕੋਸ਼ਿਸ਼ ਫੇਲ ਹੋਈ {0}", "FailedLoginAttemptWithUserName": "{0} ਤੋਂ ਲਾਗਇਨ ਕੋਸ਼ਿਸ਼ ਫੇਲ ਹੋਈ",
"DeviceOnlineWithName": "{0} ਜੁੜਿਆ ਹੋਇਆ ਹੈ", "DeviceOnlineWithName": "{0} ਜੁੜਿਆ ਹੋਇਆ ਹੈ",
"DeviceOfflineWithName": "{0} ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ", "DeviceOfflineWithName": "{0} ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ",
"Default": "ਡਿਫੌਲਟ", "Default": "ਡਿਫੌਲਟ",
"Collections": "ਸੰਗ੍ਰਹਿਣ", "Collections": "ਸੰਗ੍ਰਹਿਣ",
"ChapterNameValue": "ਅਧਿਆਇ {0}", "ChapterNameValue": "ਚੈਪਟਰ {0}",
"Channels": "ਚੈਨਲ", "Channels": "ਚੈਨਲ",
"CameraImageUploadedFrom": "ਤੋਂ ਇੱਕ ਨਵਾਂ ਕੈਮਰਾ ਚਿੱਤਰ ਅਪਲੋਡ ਕੀਤਾ ਗਿਆ ਹੈ {0}", "CameraImageUploadedFrom": "{0} ਤੋਂ ਇੱਕ ਨਵਾਂ ਕੈਮਰਾ ਚਿੱਤਰ ਅਪਲੋਡ ਕੀਤਾ ਗਿਆ ਹੈ",
"Books": "ਕਿਤਾਬਾਂ", "Books": "ਕਿਤਾਬਾਂ",
"AuthenticationSucceededWithUserName": "{0} ਸਫਲਤਾਪੂਰਕ ਪ੍ਰਮਾਣਿਤ", "AuthenticationSucceededWithUserName": "{0} ਸਫਲਤਾਪੂਰਕ ਪ੍ਰਮਾਣਿਤ",
"Artists": "ਕਲਾਕਾਰ", "Artists": "ਕਲਾਕਾਰ",
"Application": "ਐਪਲੀਕੇਸ਼ਨ", "Application": "ਐਪਲੀਕੇਸ਼ਨ",
"AppDeviceValues": "ਐਪ: {0}, ਜੰਤਰ: {1}", "AppDeviceValues": "ਐਪ: {0}, ਜੰਤਰ: {1}",
"Albums": "ਐਲਬਮਾਂ" "Albums": "ਐਲਬਮਾਂ",
"TaskOptimizeDatabase": "ਡਾਟਾਬੇਸ ਅਨੁਕੂਲ ਬਣਾਓ",
"External": "ਬਾਹਰੀ"
} }

View File

@ -122,5 +122,6 @@
"TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.", "TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
"External": "Externo", "External": "Externo",
"HearingImpaired": "Problemas auditivos", "HearingImpaired": "Problemas auditivos",
"TaskKeyframeExtractor": "Extrator de quadro-chave" "TaskKeyframeExtractor": "Extrator de quadro-chave",
"TaskKeyframeExtractorDescription": "Retira frames chave do video para criar listas HLS precisas. Esta tarefa pode correr durante algum tempo."
} }

View File

@ -42,7 +42,7 @@
"MusicVideos": "Муз. видео", "MusicVideos": "Муз. видео",
"NameInstallFailed": "Установка {0} неудачна", "NameInstallFailed": "Установка {0} неудачна",
"NameSeasonNumber": "Сезон {0}", "NameSeasonNumber": "Сезон {0}",
"NameSeasonUnknown": "Сезон неопознан", "NameSeasonUnknown": "Сезон не опознан",
"NewVersionIsAvailable": "Новая версия Jellyfin Server доступна для загрузки.", "NewVersionIsAvailable": "Новая версия Jellyfin Server доступна для загрузки.",
"NotificationOptionApplicationUpdateAvailable": "Имеется обновление приложения", "NotificationOptionApplicationUpdateAvailable": "Имеется обновление приложения",
"NotificationOptionApplicationUpdateInstalled": "Обновление приложения установлено", "NotificationOptionApplicationUpdateInstalled": "Обновление приложения установлено",
@ -96,7 +96,7 @@
"TaskRefreshChannels": "Обновление каналов", "TaskRefreshChannels": "Обновление каналов",
"TaskCleanTranscode": "Очистка каталога перекодировки", "TaskCleanTranscode": "Очистка каталога перекодировки",
"TaskUpdatePlugins": "Обновление плагинов", "TaskUpdatePlugins": "Обновление плагинов",
"TaskRefreshPeople": "Подновление людей", "TaskRefreshPeople": "Обновление информации о персонах",
"TaskCleanLogs": "Очистка каталога журналов", "TaskCleanLogs": "Очистка каталога журналов",
"TaskRefreshLibrary": "Сканирование медиатеки", "TaskRefreshLibrary": "Сканирование медиатеки",
"TaskRefreshChapterImages": "Извлечение изображений сцен", "TaskRefreshChapterImages": "Извлечение изображений сцен",

View File

@ -5,12 +5,12 @@
"Artists": "藝人", "Artists": "藝人",
"AuthenticationSucceededWithUserName": "{0} 授權成功", "AuthenticationSucceededWithUserName": "{0} 授權成功",
"Books": "圖書", "Books": "圖書",
"CameraImageUploadedFrom": "{0} 成功上傳一張新片", "CameraImageUploadedFrom": "{0} 成功上傳一張新片",
"Channels": "頻道", "Channels": "頻道",
"ChapterNameValue": "章節 {0}", "ChapterNameValue": "第 {0} 章",
"Collections": "合輯", "Collections": "合輯",
"DeviceOfflineWithName": "{0} 已斷開連接", "DeviceOfflineWithName": "{0} 已斷開連接",
"DeviceOnlineWithName": "{0} 已連接", "DeviceOnlineWithName": "{0} 已連接",
"FailedLoginAttemptWithUserName": "{0} 登入失敗", "FailedLoginAttemptWithUserName": "{0} 登入失敗",
"Favorites": "我的最愛", "Favorites": "我的最愛",
"Folders": "資料夾", "Folders": "資料夾",
@ -23,43 +23,43 @@
"HeaderFavoriteShows": "最愛的節目", "HeaderFavoriteShows": "最愛的節目",
"HeaderFavoriteSongs": "最愛的歌曲", "HeaderFavoriteSongs": "最愛的歌曲",
"HeaderLiveTV": "電視直播", "HeaderLiveTV": "電視直播",
"HeaderNextUp": "接下來", "HeaderNextUp": "接著播放",
"HeaderRecordingGroups": "錄製組", "HeaderRecordingGroups": "錄製組",
"HomeVideos": "家庭影片", "HomeVideos": "家庭影片",
"Inherit": "繼承", "Inherit": "繼承",
"ItemAddedWithName": "{0} 已添加至媒體庫", "ItemAddedWithName": "{0} 已添加至媒體庫",
"ItemRemovedWithName": "{0} 已從媒體庫移除", "ItemRemovedWithName": "{0} 已從媒體庫移除",
"LabelIpAddressValue": "IP 地址: {0}", "LabelIpAddressValue": "IP 地址: {0}",
"LabelRunningTimeValue": "運行時間: {0}", "LabelRunningTimeValue": "運行時間: {0}",
"Latest": "最新", "Latest": "最新",
"MessageApplicationUpdated": "Jellyfin 伺服器已更新", "MessageApplicationUpdated": "Jellyfin 更新",
"MessageApplicationUpdatedTo": "Jellyfin 伺服器已更新至 {0}", "MessageApplicationUpdatedTo": "Jellyfin 更新至 {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定 {0} 已更新", "MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定 {0} 已更新",
"MessageServerConfigurationUpdated": "伺服器設定已經更新", "MessageServerConfigurationUpdated": "伺服器設定已經更新",
"MixedContent": "混合內容", "MixedContent": "混合內容",
"Movies": "電影", "Movies": "電影",
"Music": "音樂", "Music": "音樂",
"MusicVideos": "音樂影片", "MusicVideos": "MV",
"NameInstallFailed": "{0} 安裝失敗", "NameInstallFailed": "{0} 安裝失敗",
"NameSeasonNumber": "第 {0} 季", "NameSeasonNumber": "第 {0} 季",
"NameSeasonUnknown": "未知季數", "NameSeasonUnknown": "未知的季度",
"NewVersionIsAvailable": "新版本的 Jellyfin 伺服器可供下載。", "NewVersionIsAvailable": "有較新版本的 Jellyfin 可供下載。",
"NotificationOptionApplicationUpdateAvailable": "有可用的更新", "NotificationOptionApplicationUpdateAvailable": "有可用的更新",
"NotificationOptionApplicationUpdateInstalled": "應用程式已更新", "NotificationOptionApplicationUpdateInstalled": "應用程式已更新",
"NotificationOptionAudioPlayback": "開始播放音訊", "NotificationOptionAudioPlayback": "開始播放音訊",
"NotificationOptionAudioPlaybackStopped": "停止播放音訊", "NotificationOptionAudioPlaybackStopped": "停止播放音訊",
"NotificationOptionCameraImageUploaded": "相片已上傳", "NotificationOptionCameraImageUploaded": "相片已上傳",
"NotificationOptionInstallationFailed": "安裝失敗", "NotificationOptionInstallationFailed": "安裝失敗",
"NotificationOptionNewLibraryContent": "已添加新内容", "NotificationOptionNewLibraryContent": "已添加新内容",
"NotificationOptionPluginError": "擴充元件錯誤", "NotificationOptionPluginError": "插件出現錯誤",
"NotificationOptionPluginInstalled": "擴充元件已安裝", "NotificationOptionPluginInstalled": "插件已被安裝",
"NotificationOptionPluginUninstalled": "擴充元件已移除", "NotificationOptionPluginUninstalled": "插件已被移除",
"NotificationOptionPluginUpdateInstalled": "擴充元件更新已安裝", "NotificationOptionPluginUpdateInstalled": "插件已被更新",
"NotificationOptionServerRestartRequired": "伺服器需要重", "NotificationOptionServerRestartRequired": "伺服器需要重",
"NotificationOptionTaskFailed": "計劃任務失敗", "NotificationOptionTaskFailed": "排程任務執行失敗",
"NotificationOptionUserLockedOut": "用家已鎖定", "NotificationOptionUserLockedOut": "用戶已被鎖定",
"NotificationOptionVideoPlayback": "開始播放視頻", "NotificationOptionVideoPlayback": "開始播放影片",
"NotificationOptionVideoPlaybackStopped": "已停止播放視頻", "NotificationOptionVideoPlaybackStopped": "已停止播放影片",
"Photos": "相片", "Photos": "相片",
"Playlists": "播放清單", "Playlists": "播放清單",
"Plugin": "插件", "Plugin": "插件",
@ -69,51 +69,51 @@
"ProviderValue": "提供者: {0}", "ProviderValue": "提供者: {0}",
"ScheduledTaskFailedWithName": "{0} 任務失敗", "ScheduledTaskFailedWithName": "{0} 任務失敗",
"ScheduledTaskStartedWithName": "{0} 任務開始", "ScheduledTaskStartedWithName": "{0} 任務開始",
"ServerNameNeedsToBeRestarted": "{0} 需要重", "ServerNameNeedsToBeRestarted": "{0} 需要重",
"Shows": "節目", "Shows": "節目",
"Songs": "歌曲", "Songs": "歌曲",
"StartupEmbyServerIsLoading": "Jellyfin 伺服器載入中,請稍後再試。", "StartupEmbyServerIsLoading": "Jellyfin 載入中,請稍後再試。",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的字幕", "SubtitleDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的字幕",
"Sync": "同步", "Sync": "同步",
"System": "系統", "System": "系統",
"TvShows": "電視節目", "TvShows": "電視節目",
"User": "使用者", "User": "用戶",
"UserCreatedWithName": "使用者 {0} 已創建", "UserCreatedWithName": "用戶 {0} 已被建立",
"UserDeletedWithName": "使用者 {0} 已移除", "UserDeletedWithName": "用戶 {0} 已被移除",
"UserDownloadingItemWithValues": "{0} 正在下載 {1}", "UserDownloadingItemWithValues": "{0} 正在下載 {1}",
"UserLockedOutWithName": "使用者 {0} 已被鎖定", "UserLockedOutWithName": "使用者 {0} 已被鎖定",
"UserOfflineFromDevice": "{0} 從 {1} 斷開", "UserOfflineFromDevice": "{0} 從 {1} 斷開連接",
"UserOnlineFromDevice": "{0} 已連綫,來自 {1}", "UserOnlineFromDevice": "{0} 從 {1} 連線",
"UserPasswordChangedWithName": "使用者 {0} 的密碼已變更", "UserPasswordChangedWithName": "{0} 的密碼已被變改",
"UserPolicyUpdatedWithName": "使用者協議已更新為 {0}", "UserPolicyUpdatedWithName": "使用者協議已更新為 {0}",
"UserStartedPlayingItemWithValues": "{0} 正在 {2} 上播放 {1}", "UserStartedPlayingItemWithValues": "{0} 正在 {2} 上播放 {1}",
"UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}", "UserStoppedPlayingItemWithValues": "{0} 已停止在 {2} 上播放 {1}",
"ValueHasBeenAddedToLibrary": "{0} 已添加到你的媒體庫", "ValueHasBeenAddedToLibrary": "已添加 {0} 到你的媒體庫",
"ValueSpecialEpisodeName": "特典 - {0}", "ValueSpecialEpisodeName": "特典 - {0}",
"VersionNumber": "版本{0}", "VersionNumber": "版本 {0}",
"TaskDownloadMissingSubtitles": "下載遺失的字幕", "TaskDownloadMissingSubtitles": "下載缺少的字幕",
"TaskUpdatePlugins": "更新插件", "TaskUpdatePlugins": "更新插件",
"TasksApplicationCategory": "應用程式", "TasksApplicationCategory": "應用程式",
"TaskRefreshLibraryDescription": "掃描媒體庫以查找新文件並刷新metadata。", "TaskRefreshLibraryDescription": "掃描媒體庫以加入新增檔案及重新載入 metadata。",
"TasksMaintenanceCategory": "維護", "TasksMaintenanceCategory": "維護",
"TaskDownloadMissingSubtitlesDescription": "根據metadata配置在互聯網上搜索缺少的字幕。", "TaskDownloadMissingSubtitlesDescription": "根據元數據中的設定,在互聯網上搜索缺少的字幕。",
"TaskRefreshChannelsDescription": "刷新互聯網頻道信息。", "TaskRefreshChannelsDescription": "重新載入網絡頻道的資訊。",
"TaskRefreshChannels": "刷新頻道", "TaskRefreshChannels": "重新載入頻道",
"TaskCleanTranscodeDescription": "刪除超過一天的轉碼文件。", "TaskCleanTranscodeDescription": "刪除超過一天的轉碼文件。",
"TaskCleanTranscode": "清理轉碼目錄", "TaskCleanTranscode": "清理轉碼目錄",
"TaskUpdatePluginsDescription": "下載並安裝配置為自動更新的插件的更新。", "TaskUpdatePluginsDescription": "下載並更新能夠被自動更新的插件。",
"TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的元數據。", "TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的元數據。",
"TaskCleanLogsDescription": "刪除超過{0}天的日誌文件。", "TaskCleanLogsDescription": "刪除超過{0}天的日誌文件。",
"TaskCleanLogs": "清理日誌目錄", "TaskCleanLogs": "清理日誌目錄",
"TaskRefreshLibrary": "掃描媒體庫", "TaskRefreshLibrary": "掃描媒體庫",
"TaskRefreshChapterImagesDescription": "為帶有章節的視頻創建縮略圖。", "TaskRefreshChapterImagesDescription": "為帶有章節的影片建立縮圖。",
"TaskRefreshChapterImages": "提取章節圖像", "TaskRefreshChapterImages": "提取章節圖像",
"TaskCleanCacheDescription": "刪除系統不再需要的緩存文件。", "TaskCleanCacheDescription": "刪除系統不再需要的緩存文件。",
"TaskCleanCache": "清理緩存目錄", "TaskCleanCache": "清理緩存目錄",
"TasksChannelsCategory": "互聯網頻道", "TasksChannelsCategory": "頻道",
"TasksLibraryCategory": "庫", "TasksLibraryCategory": "庫",
"TaskRefreshPeople": "刷新人物", "TaskRefreshPeople": "重新載入人物",
"TaskCleanActivityLog": "清理活動記錄", "TaskCleanActivityLog": "清理活動記錄",
"Undefined": "未定義", "Undefined": "未定義",
"Forced": "強制", "Forced": "強制",
@ -121,7 +121,7 @@
"TaskOptimizeDatabaseDescription": "壓縮數據庫並截斷可用空間。在掃描媒體庫或執行其他數據庫的修改後運行此任務可能會提高性能。", "TaskOptimizeDatabaseDescription": "壓縮數據庫並截斷可用空間。在掃描媒體庫或執行其他數據庫的修改後運行此任務可能會提高性能。",
"TaskOptimizeDatabase": "最佳化數據庫", "TaskOptimizeDatabase": "最佳化數據庫",
"TaskCleanActivityLogDescription": "刪除早於設定時間的日誌記錄。", "TaskCleanActivityLogDescription": "刪除早於設定時間的日誌記錄。",
"TaskKeyframeExtractorDescription": "提取關鍵格以創建更準確的HLS播放列表。次指示可能用時很長。", "TaskKeyframeExtractorDescription": "提取關鍵幀以建立更準確的 HLS 播放列表。此工作或需要使用較長時間來完成。",
"TaskKeyframeExtractor": "關鍵幀提取器", "TaskKeyframeExtractor": "關鍵幀提取器",
"External": "外部", "External": "外部",
"HearingImpaired": "聽力障礙" "HearingImpaired": "聽力障礙"

View File

@ -91,14 +91,14 @@
"HeaderRecordingGroups": "錄製組", "HeaderRecordingGroups": "錄製組",
"Inherit": "繼承", "Inherit": "繼承",
"SubtitleDownloadFailureFromForItem": "無法為 {1} 從 {0} 下載字幕", "SubtitleDownloadFailureFromForItem": "無法為 {1} 從 {0} 下載字幕",
"TaskDownloadMissingSubtitlesDescription": "透過中繼資料從網路上搜尋遺失的字幕。", "TaskDownloadMissingSubtitlesDescription": "透過媒體資訊從網路上搜尋遺失的字幕。",
"TaskDownloadMissingSubtitles": "下載遺失的字幕", "TaskDownloadMissingSubtitles": "下載遺失的字幕",
"TaskRefreshChannels": "重新整理頻道", "TaskRefreshChannels": "重新整理頻道",
"TaskUpdatePlugins": "更新附加元件", "TaskUpdatePlugins": "更新附加元件",
"TaskRefreshPeople": "更新人物", "TaskRefreshPeople": "更新人物",
"TaskCleanLogsDescription": "刪除超過 {0} 天的日誌文件。", "TaskCleanLogsDescription": "刪除超過 {0} 天的日誌文件。",
"TaskCleanLogs": "清空日誌資料夾", "TaskCleanLogs": "清空日誌資料夾",
"TaskRefreshLibraryDescription": "重新掃描媒體庫的新檔案並更新中繼資料。", "TaskRefreshLibraryDescription": "重新掃描媒體庫的新檔案並更新媒體資訊。",
"TaskRefreshLibrary": "重新掃描媒體庫", "TaskRefreshLibrary": "重新掃描媒體庫",
"TaskRefreshChapterImages": "擷取章節圖片", "TaskRefreshChapterImages": "擷取章節圖片",
"TaskCleanCacheDescription": "刪除系統已不需要的快取。", "TaskCleanCacheDescription": "刪除系統已不需要的快取。",
@ -108,7 +108,7 @@
"TaskCleanTranscodeDescription": "刪除超過一天的轉碼檔案。", "TaskCleanTranscodeDescription": "刪除超過一天的轉碼檔案。",
"TaskCleanTranscode": "清除轉碼資料夾", "TaskCleanTranscode": "清除轉碼資料夾",
"TaskUpdatePluginsDescription": "為已設置為自動更新的附加元件下載並安裝更新。", "TaskUpdatePluginsDescription": "為已設置為自動更新的附加元件下載並安裝更新。",
"TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的中繼資料。", "TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的資訊。",
"TaskRefreshChapterImagesDescription": "為有章節的影片建立縮圖。", "TaskRefreshChapterImagesDescription": "為有章節的影片建立縮圖。",
"TasksChannelsCategory": "網路頻道", "TasksChannelsCategory": "網路頻道",
"TasksApplicationCategory": "應用程式", "TasksApplicationCategory": "應用程式",

View File

@ -198,25 +198,25 @@ namespace Emby.Server.Implementations.Localization
} }
// Minimum rating possible // Minimum rating possible
if (!ratings.Any(x => x.Value == 0)) if (ratings.All(x => x.Value != 0))
{ {
ratings.Add(new ParentalRating("Approved", 0)); ratings.Add(new ParentalRating("Approved", 0));
} }
// Matches PG (this has different age restrictions depending on country) // Matches PG (this has different age restrictions depending on country)
if (!ratings.Any(x => x.Value == 10)) if (ratings.All(x => x.Value != 10))
{ {
ratings.Add(new ParentalRating("10", 10)); ratings.Add(new ParentalRating("10", 10));
} }
// Matches PG-13 // Matches PG-13
if (!ratings.Any(x => x.Value == 13)) if (ratings.All(x => x.Value != 13))
{ {
ratings.Add(new ParentalRating("13", 13)); ratings.Add(new ParentalRating("13", 13));
} }
// Matches TV-14 // Matches TV-14
if (!ratings.Any(x => x.Value == 14)) if (ratings.All(x => x.Value != 14))
{ {
ratings.Add(new ParentalRating("14", 14)); ratings.Add(new ParentalRating("14", 14));
} }
@ -229,13 +229,13 @@ namespace Emby.Server.Implementations.Localization
} }
// A lot of countries don't excplicitly have a seperate rating for adult content // A lot of countries don't excplicitly have a seperate rating for adult content
if (!ratings.Any(x => x.Value == 1000)) if (ratings.All(x => x.Value != 1000))
{ {
ratings.Add(new ParentalRating("XXX", 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 excplicitly have a seperate rating for banned content
if (!ratings.Any(x => x.Value == 1001)) if (ratings.All(x => x.Value != 1001))
{ {
ratings.Add(new ParentalRating("Banned", 1001)); ratings.Add(new ParentalRating("Banned", 1001));
} }

View File

@ -309,7 +309,7 @@ namespace Emby.Server.Implementations.Plugins
// If no version is given, return the current instance. // If no version is given, return the current instance.
var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList(); var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList();
plugin = plugins.FirstOrDefault(p => p.Instance is not null) ?? plugins.OrderByDescending(p => p.Version).FirstOrDefault(); plugin = plugins.FirstOrDefault(p => p.Instance is not null) ?? plugins.MaxBy(p => p.Version);
} }
else else
{ {

View File

@ -606,7 +606,7 @@ namespace Emby.Server.Implementations.Session
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogDebug("Error calling OnPlaybackStopped", ex); _logger.LogDebug(ex, "Error calling OnPlaybackStopped");
} }
} }
@ -953,7 +953,7 @@ namespace Emby.Server.Implementations.Session
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError("Error closing live stream", ex); _logger.LogError(ex, "Error closing live stream");
} }
} }

View File

@ -69,9 +69,7 @@ namespace Emby.Server.Implementations.Session
T data, T data,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var socket = GetActiveSockets() var socket = GetActiveSockets().MaxBy(i => i.LastActivityDate);
.OrderByDescending(i => i.LastActivityDate)
.FirstOrDefault();
if (socket is null) if (socket is null)
{ {

View File

@ -620,10 +620,8 @@ namespace Emby.Server.Implementations.SyncPlay
RestartCurrentItem(); RestartCurrentItem();
return true; return true;
} }
else
{ return false;
return false;
}
} }
/// <inheritdoc /> /// <inheritdoc />
@ -637,10 +635,8 @@ namespace Emby.Server.Implementations.SyncPlay
RestartCurrentItem(); RestartCurrentItem();
return true; return true;
} }
else
{ return false;
return false;
}
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -339,10 +339,8 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
return sessionsCounter > 0; return sessionsCounter > 0;
} }
else
{ return false;
return false;
}
} }
/// <summary> /// <summary>

View File

@ -20,7 +20,6 @@ using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.MediaEncoding.Encoder; using MediaBrowser.MediaEncoding.Encoder;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
@ -2030,8 +2029,7 @@ public class DynamicHlsController : BaseJellyfinApiController
{ {
return fileSystem.GetFiles(folder, new[] { segmentExtension }, true, false) return fileSystem.GetFiles(folder, new[] { segmentExtension }, true, false)
.Where(i => Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase)) .Where(i => Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(fileSystem.GetLastWriteTimeUtc) .MaxBy(fileSystem.GetLastWriteTimeUtc);
.FirstOrDefault();
} }
catch (IOException) catch (IOException)
{ {

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Linq; using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;

View File

@ -146,7 +146,7 @@ public class PluginsController : BaseJellyfinApiController
var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId)).ToList(); var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId)).ToList();
// Select the un-instanced one first. // Select the un-instanced one first.
var plugin = plugins.FirstOrDefault(p => p.Instance is null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); var plugin = plugins.FirstOrDefault(p => p.Instance is null) ?? plugins.MinBy(p => p.Manifest.Status);
if (plugin is not null) if (plugin is not null)
{ {

View File

@ -1,8 +1,6 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Authentication;

View File

@ -3,7 +3,6 @@ using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;

View File

@ -533,10 +533,8 @@ public class SubtitleController : BaseJellyfinApiController
_logger.LogDebug("Fallback font size is {FileSize} Bytes", fileSize); _logger.LogDebug("Fallback font size is {FileSize} Bytes", fileSize);
return PhysicalFile(fontFile.FullName, MimeTypes.GetMimeType(fontFile.FullName)); return PhysicalFile(fontFile.FullName, MimeTypes.GetMimeType(fontFile.FullName));
} }
else
{ _logger.LogWarning("The selected font is null or empty");
_logger.LogWarning("The selected font is null or empty");
}
} }
else else
{ {

View File

@ -5,7 +5,6 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;

View File

@ -500,10 +500,8 @@ namespace Jellyfin.Networking.Manager
{ {
return true; return true;
} }
else
{ return address.IsPrivateAddressRange();
return address.IsPrivateAddressRange();
}
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -1171,13 +1169,15 @@ namespace Jellyfin.Networking.Manager
bindPreference = addr.Value; bindPreference = addr.Value;
break; break;
} }
else if ((addr.Key.Address.Equals(IPAddress.Any) || addr.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet)
if ((addr.Key.Address.Equals(IPAddress.Any) || addr.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet)
{ {
// External. // External.
bindPreference = addr.Value; bindPreference = addr.Value;
break; break;
} }
else if (addr.Key.Contains(source))
if (addr.Key.Contains(source))
{ {
// Match ip address. // Match ip address.
bindPreference = addr.Value; bindPreference = addr.Value;
@ -1256,8 +1256,7 @@ namespace Jellyfin.Networking.Manager
// Look for the best internal address. // Look for the best internal address.
bindAddress = addresses bindAddress = addresses
.Where(p => IsInLocalNetwork(p) && (p.Contains(source) || p.Equals(IPAddress.None))) .Where(p => IsInLocalNetwork(p) && (p.Contains(source) || p.Equals(IPAddress.None)))
.OrderBy(p => p.Tag) .MinBy(p => p.Tag)?.Address;
.FirstOrDefault()?.Address;
} }
if (bindAddress is not null) if (bindAddress is not null)

View File

@ -4,7 +4,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using EFCoreSecondLevelCacheInterceptor;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;

View File

@ -22,7 +22,6 @@ using MediaBrowser.Controller.Lyrics;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Activity; using MediaBrowser.Model.Activity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@ -133,9 +133,7 @@ namespace Jellyfin.Server.Migrations.Routines
SkipBackwardLength = dto.CustomPrefs.TryGetValue("skipBackLength", out length) && int.TryParse(length, out var skipBackwardLength) SkipBackwardLength = dto.CustomPrefs.TryGetValue("skipBackLength", out length) && int.TryParse(length, out var skipBackwardLength)
? skipBackwardLength ? skipBackwardLength
: 10000, : 10000,
EnableNextVideoInfoOverlay = dto.CustomPrefs.TryGetValue("enableNextVideoInfoOverlay", out var enabled) && !string.IsNullOrEmpty(enabled) EnableNextVideoInfoOverlay = !dto.CustomPrefs.TryGetValue("enableNextVideoInfoOverlay", out var enabled) || string.IsNullOrEmpty(enabled) || bool.Parse(enabled),
? bool.Parse(enabled)
: true,
DashboardTheme = dto.CustomPrefs.TryGetValue("dashboardtheme", out var theme) ? theme : string.Empty, DashboardTheme = dto.CustomPrefs.TryGetValue("dashboardtheme", out var theme) ? theme : string.Empty,
TvHome = dto.CustomPrefs.TryGetValue("tvhome", out var home) ? home : string.Empty TvHome = dto.CustomPrefs.TryGetValue("tvhome", out var home) ? home : string.Empty
}; };

View File

@ -4,7 +4,6 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Net.Mime; using System.Net.Mime;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Jellyfin.Api.Middleware; using Jellyfin.Api.Middleware;
using Jellyfin.MediaEncoding.Hls.Extensions; using Jellyfin.MediaEncoding.Hls.Extensions;

View File

@ -1,3 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Emby/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jellyfin/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Jellyfin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Playstate/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/UserDictionary/Words/=Playstate/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -50,7 +50,7 @@ namespace MediaBrowser.Common.Plugins
if (Version is not null && !Directory.Exists(dataFolderPath)) if (Version is not null && !Directory.Exists(dataFolderPath))
{ {
// Try again with the version number appended to the folder name. // Try again with the version number appended to the folder name.
dataFolderPath += "_" + Version.ToString(); dataFolderPath += "_" + Version;
} }
SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version);

View File

@ -801,16 +801,14 @@ namespace MediaBrowser.Controller.Entities
{ {
return allowed.Contains(ChannelId); return allowed.Contains(ChannelId);
} }
else
{
var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders);
foreach (var folder in collectionFolders) var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders);
foreach (var folder in collectionFolders)
{
if (allowed.Contains(folder.Id))
{ {
if (allowed.Contains(folder.Id)) return true;
{
return true;
}
} }
} }

View File

@ -197,10 +197,8 @@ namespace MediaBrowser.Controller.LiveTv
{ {
return 2.0 / 3; return 2.0 / 3;
} }
else
{ return 16.0 / 9;
return 16.0 / 9;
}
} }
public override string GetClientTypeName() public override string GetClientTypeName()

View File

@ -1,5 +1,3 @@
using System;
namespace MediaBrowser.Controller.Lyrics; namespace MediaBrowser.Controller.Lyrics;
/// <summary> /// <summary>

View File

@ -138,14 +138,10 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(hwType) if (!string.IsNullOrEmpty(hwType)
&& encodingOptions.EnableHardwareEncoding && encodingOptions.EnableHardwareEncoding
&& codecMap.ContainsKey(hwType)) && codecMap.TryGetValue(hwType, out var preferredEncoder)
&& _mediaEncoder.SupportsEncoder(preferredEncoder))
{ {
var preferredEncoder = codecMap[hwType]; return preferredEncoder;
if (_mediaEncoder.SupportsEncoder(preferredEncoder))
{
return preferredEncoder;
}
} }
} }
@ -561,7 +557,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
return Array.FindIndex(_videoProfilesH264, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase)); return Array.FindIndex(_videoProfilesH264, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase));
} }
else if (string.Equals("hevc", videoCodec, StringComparison.OrdinalIgnoreCase))
if (string.Equals("hevc", videoCodec, StringComparison.OrdinalIgnoreCase))
{ {
return Array.FindIndex(_videoProfilesH265, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase)); return Array.FindIndex(_videoProfilesH265, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase));
} }
@ -842,39 +839,38 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
var filterDevArgs = GetFilterHwDeviceArgs(VaapiAlias); var filterDevArgs = GetFilterHwDeviceArgs(VaapiAlias);
var doOclTonemap = isHwTonemapAvailable && IsOpenclFullSupported();
if (isHwTonemapAvailable && IsOpenclFullSupported()) if (_mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965)
{ {
if (_mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965) if (doOclTonemap && !isVaapiDecoder)
{ {
if (!isVaapiDecoder) args.Append(GetOpenclDeviceArgs(0, null, VaapiAlias, OpenclAlias));
{
args.Append(GetOpenclDeviceArgs(0, null, VaapiAlias, OpenclAlias));
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
}
}
else if (_mediaEncoder.IsVaapiDeviceAmd)
{
if (!IsVulkanFullSupported()
|| !_mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier
|| Environment.OSVersion.Version < _minKernelVersionAmdVkFmtModifier)
{
args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias));
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
}
else
{
// libplacebo wants an explicitly set vulkan filter device.
args.Append(GetVulkanDeviceArgs(0, null, VaapiAlias, VulkanAlias));
filterDevArgs = GetFilterHwDeviceArgs(VulkanAlias);
}
}
else
{
args.Append(GetOpenclDeviceArgs(0, null, null, OpenclAlias));
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
} }
} }
else if (_mediaEncoder.IsVaapiDeviceAmd)
{
if (IsVulkanFullSupported()
&& _mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier
&& Environment.OSVersion.Version >= _minKernelVersionAmdVkFmtModifier)
{
// libplacebo wants an explicitly set vulkan filter device.
args.Append(GetVulkanDeviceArgs(0, null, VaapiAlias, VulkanAlias));
filterDevArgs = GetFilterHwDeviceArgs(VulkanAlias);
}
else if (doOclTonemap)
{
// ROCm/ROCr OpenCL runtime
args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias));
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
}
}
else if (doOclTonemap)
{
args.Append(GetOpenclDeviceArgs(0, null, null, OpenclAlias));
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
}
args.Append(filterDevArgs); args.Append(filterDevArgs);
} }
@ -1114,19 +1110,19 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
return "-bsf:v h264_mp4toannexb"; return "-bsf:v h264_mp4toannexb";
} }
else if (IsH265(stream))
if (IsH265(stream))
{ {
return "-bsf:v hevc_mp4toannexb"; return "-bsf:v hevc_mp4toannexb";
} }
else if (IsAAC(stream))
if (IsAAC(stream))
{ {
// Convert adts header(mpegts) to asc header(mp4). // Convert adts header(mpegts) to asc header(mp4).
return "-bsf:a aac_adtstoasc"; return "-bsf:a aac_adtstoasc";
} }
else
{ return null;
return null;
}
} }
public static string GetAudioBitStreamArguments(EncodingJobInfo state, string segmentContainer, string mediaSourceContainer) public static string GetAudioBitStreamArguments(EncodingJobInfo state, string segmentContainer, string mediaSourceContainer)
@ -1204,10 +1200,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
return FormattableString.Invariant($" -rc_mode CBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); return FormattableString.Invariant($" -rc_mode CBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
} }
else
{ return FormattableString.Invariant($" -rc_mode VBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
return FormattableString.Invariant($" -rc_mode VBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
}
} }
return FormattableString.Invariant($" -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); return FormattableString.Invariant($" -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
@ -2619,8 +2613,8 @@ namespace MediaBrowser.Controller.MediaEncoding
if (outputWidth > maximumWidth || outputHeight > maximumHeight) if (outputWidth > maximumWidth || outputHeight > maximumHeight)
{ {
var scaleW = (double)maximumWidth / (double)outputWidth; var scaleW = (double)maximumWidth / outputWidth;
var scaleH = (double)maximumHeight / (double)outputHeight; var scaleH = (double)maximumHeight / outputHeight;
var scale = Math.Min(scaleW, scaleH); var scale = Math.Min(scaleW, scaleH);
outputWidth = Math.Min(maximumWidth, (int)(outputWidth * scale)); outputWidth = Math.Min(maximumWidth, (int)(outputWidth * scale));
outputHeight = Math.Min(maximumHeight, (int)(outputHeight * scale)); outputHeight = Math.Min(maximumHeight, (int)(outputHeight * scale));
@ -2767,79 +2761,76 @@ namespace MediaBrowser.Controller.MediaEncoding
widthParam, widthParam,
heightParam); heightParam);
} }
else
{ return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, requestedHeight.Value);
return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, requestedHeight.Value);
}
} }
// If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
else if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue)
if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue)
{ {
var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture);
var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture);
return string.Format( return string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
"scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2", "scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2",
maxWidthParam, maxWidthParam,
maxHeightParam, maxHeightParam,
scaleVal); scaleVal);
} }
// If a fixed width was requested // If a fixed width was requested
else if (requestedWidth.HasValue) if (requestedWidth.HasValue)
{ {
if (threedFormat.HasValue) if (threedFormat.HasValue)
{ {
// This method can handle 0 being passed in for the requested height // This method can handle 0 being passed in for the requested height
return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, 0); return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, 0);
} }
else
{
var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture);
return string.Format( var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture);
CultureInfo.InvariantCulture,
"scale={0}:trunc(ow/a/2)*2", return string.Format(
widthParam); CultureInfo.InvariantCulture,
} "scale={0}:trunc(ow/a/2)*2",
widthParam);
} }
// If a fixed height was requested // If a fixed height was requested
else if (requestedHeight.HasValue) if (requestedHeight.HasValue)
{ {
var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture); var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture);
return string.Format( return string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
"scale=trunc(oh*a/{1})*{1}:{0}", "scale=trunc(oh*a/{1})*{1}:{0}",
heightParam, heightParam,
scaleVal); scaleVal);
} }
// If a max width was requested // If a max width was requested
else if (requestedMaxWidth.HasValue) if (requestedMaxWidth.HasValue)
{ {
var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture);
return string.Format( return string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
"scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2", "scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2",
maxWidthParam, maxWidthParam,
scaleVal); scaleVal);
} }
// If a max height was requested // If a max height was requested
else if (requestedMaxHeight.HasValue) if (requestedMaxHeight.HasValue)
{ {
var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture);
return string.Format( return string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
"scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})", "scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})",
maxHeightParam, maxHeightParam,
scaleVal); scaleVal);
} }
return string.Empty; return string.Empty;
@ -2913,18 +2904,21 @@ namespace MediaBrowser.Controller.MediaEncoding
"yadif_cuda={0}:-1:0", "yadif_cuda={0}:-1:0",
doubleRateDeint ? "1" : "0"); doubleRateDeint ? "1" : "0");
} }
else if (hwDeintSuffix.Contains("vaapi", StringComparison.OrdinalIgnoreCase))
if (hwDeintSuffix.Contains("vaapi", StringComparison.OrdinalIgnoreCase))
{ {
return string.Format( return string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
"deinterlace_vaapi=rate={0}", "deinterlace_vaapi=rate={0}",
doubleRateDeint ? "field" : "frame"); doubleRateDeint ? "field" : "frame");
} }
else if (hwDeintSuffix.Contains("qsv", StringComparison.OrdinalIgnoreCase))
if (hwDeintSuffix.Contains("qsv", StringComparison.OrdinalIgnoreCase))
{ {
return "deinterlace_qsv=mode=2"; return "deinterlace_qsv=mode=2";
} }
else if (hwDeintSuffix.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase))
if (hwDeintSuffix.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase))
{ {
return string.Format( return string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -2955,7 +2949,8 @@ namespace MediaBrowser.Controller.MediaEncoding
options.VppTonemappingBrightness, options.VppTonemappingBrightness,
options.VppTonemappingContrast); options.VppTonemappingContrast);
} }
else if (string.Equals(hwTonemapSuffix, "vulkan", StringComparison.OrdinalIgnoreCase))
if (string.Equals(hwTonemapSuffix, "vulkan", StringComparison.OrdinalIgnoreCase))
{ {
args = "libplacebo=format={1}:tonemapping={2}:color_primaries=bt709:color_trc=bt709:colorspace=bt709:peak_detect=0:upscaler=none:downscaler=none"; args = "libplacebo=format={1}:tonemapping={2}:color_primaries=bt709:color_trc=bt709:colorspace=bt709:peak_detect=0:upscaler=none:downscaler=none";
@ -4269,7 +4264,8 @@ namespace MediaBrowser.Controller.MediaEncoding
// sw => hw // sw => hw
if (doVkTonemap) if (doVkTonemap)
{ {
mainFilters.Add("hwupload_vaapi"); mainFilters.Add("hwupload=derive_device=vaapi");
mainFilters.Add("format=vaapi");
mainFilters.Add("hwmap=derive_device=vulkan"); mainFilters.Add("hwmap=derive_device=vulkan");
mainFilters.Add("format=vulkan"); mainFilters.Add("format=vulkan");
} }
@ -4380,12 +4376,15 @@ namespace MediaBrowser.Controller.MediaEncoding
// prefer vaapi hwupload to vulkan hwupload, // prefer vaapi hwupload to vulkan hwupload,
// Mesa RADV does not support a dedicated transfer queue. // Mesa RADV does not support a dedicated transfer queue.
subFilters.Add("hwupload_vaapi"); subFilters.Add("hwupload=derive_device=vaapi");
subFilters.Add("format=vaapi");
subFilters.Add("hwmap=derive_device=vulkan"); subFilters.Add("hwmap=derive_device=vulkan");
subFilters.Add("format=vulkan"); subFilters.Add("format=vulkan");
overlayFilters.Add("overlay_vulkan=eof_action=endall:shortest=1:repeatlast=0"); overlayFilters.Add("overlay_vulkan=eof_action=endall:shortest=1:repeatlast=0");
overlayFilters.Add("scale_vulkan=format=nv12");
// TODO: figure out why libplacebo can sync without vaSyncSurface VPP support in radeonsi.
overlayFilters.Add("libplacebo=format=nv12:apply_filmgrain=0:apply_dolbyvision=0:upscaler=none:downscaler=none:dithering=none");
// OUTPUT vaapi(nv12/bgra) surface(vram) // OUTPUT vaapi(nv12/bgra) surface(vram)
// reverse-mapping via vaapi-vulkan interop. // reverse-mapping via vaapi-vulkan interop.
@ -4827,26 +4826,27 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
return videoStream.BitDepth.Value; return videoStream.BitDepth.Value;
} }
else if (string.Equals(videoStream.PixelFormat, "yuv420p", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.PixelFormat, "yuvj420p", StringComparison.OrdinalIgnoreCase) if (string.Equals(videoStream.PixelFormat, "yuv420p", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.PixelFormat, "yuv444p", StringComparison.OrdinalIgnoreCase)) || string.Equals(videoStream.PixelFormat, "yuvj420p", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.PixelFormat, "yuv444p", StringComparison.OrdinalIgnoreCase))
{ {
return 8; return 8;
} }
else if (string.Equals(videoStream.PixelFormat, "yuv420p10le", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.PixelFormat, "yuv444p10le", StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoStream.PixelFormat, "yuv420p10le", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.PixelFormat, "yuv444p10le", StringComparison.OrdinalIgnoreCase))
{ {
return 10; return 10;
} }
else if (string.Equals(videoStream.PixelFormat, "yuv420p12le", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.PixelFormat, "yuv444p12le", StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoStream.PixelFormat, "yuv420p12le", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.PixelFormat, "yuv444p12le", StringComparison.OrdinalIgnoreCase))
{ {
return 12; return 12;
} }
else
{ return 8;
return 8;
}
} }
return 0; return 0;
@ -5078,11 +5078,9 @@ namespace MediaBrowser.Controller.MediaEncoding
return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty) return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty)
+ (nvdecNoInternalCopy ? " -hwaccel_flags +unsafe_output" : string.Empty) + " -threads 1" + (isAv1 ? " -c:v av1" : string.Empty); + (nvdecNoInternalCopy ? " -hwaccel_flags +unsafe_output" : string.Empty) + " -threads 1" + (isAv1 ? " -c:v av1" : string.Empty);
} }
else
{ // cuvid decoder doesn't have threading issue.
// cuvid decoder doesn't have threading issue. return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty);
return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty);
}
} }
} }
@ -5440,7 +5438,8 @@ namespace MediaBrowser.Controller.MediaEncoding
// Automatically set thread count // Automatically set thread count
return mustSetThreadCount ? Math.Max(Environment.ProcessorCount - 1, 1) : 0; return mustSetThreadCount ? Math.Max(Environment.ProcessorCount - 1, 1) : 0;
} }
else if (threads >= Environment.ProcessorCount)
if (threads >= Environment.ProcessorCount)
{ {
return Environment.ProcessorCount; return Environment.ProcessorCount;
} }

View File

@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities.Security; using Jellyfin.Data.Entities.Security;
using Jellyfin.Data.Events;
using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;

View File

@ -1,7 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;

View File

@ -533,11 +533,9 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
_logger.LogWarning("Session {SessionId} is seeking to wrong position, correcting.", session.Id); _logger.LogWarning("Session {SessionId} is seeking to wrong position, correcting.", session.Id);
return; return;
} }
else
{ // Session is ready.
// Session is ready. context.SetBuffering(session, false);
context.SetBuffering(session, false);
}
if (!context.IsBuffering()) if (!context.IsBuffering())
{ {

View File

@ -313,17 +313,13 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
return true; return true;
} }
else
{ // Restoring playing item.
// Restoring playing item. SetPlayingItemByPlaylistId(playingItem.PlaylistItemId);
SetPlayingItemByPlaylistId(playingItem.PlaylistItemId);
return false;
}
}
else
{
return false; return false;
} }
return false;
} }
/// <summary> /// <summary>
@ -528,10 +524,8 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
{ {
return _shuffledPlaylist; return _shuffledPlaylist;
} }
else
{ return _sortedPlaylist;
return _sortedPlaylist;
}
} }
/// <summary> /// <summary>
@ -544,14 +538,13 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
{ {
return null; return null;
} }
else if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
{ {
return _shuffledPlaylist[PlayingItemIndex]; return _shuffledPlaylist[PlayingItemIndex];
} }
else
{ return _sortedPlaylist[PlayingItemIndex];
return _sortedPlaylist[PlayingItemIndex];
}
} }
} }
} }

View File

@ -73,10 +73,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
foreach (var info in idInfos) foreach (var info in idInfos)
{ {
var id = info.Key + "Id"; var id = info.Key + "Id";
if (!_validProviderIds.ContainsKey(id)) _validProviderIds.TryAdd(id, info.Key);
{
_validProviderIds.Add(id, info.Key);
}
} }
// Additional Mappings // Additional Mappings

View File

@ -375,7 +375,7 @@ namespace MediaBrowser.LocalMetadata.Savers
await writer.WriteStartElementAsync(null, "Person", null).ConfigureAwait(false); await writer.WriteStartElementAsync(null, "Person", null).ConfigureAwait(false);
await writer.WriteElementStringAsync(null, "Name", null, person.Name).ConfigureAwait(false); await writer.WriteElementStringAsync(null, "Name", null, person.Name).ConfigureAwait(false);
await writer.WriteElementStringAsync(null, "Type", null, person.Type.ToString()).ConfigureAwait(false); await writer.WriteElementStringAsync(null, "Type", null, person.Type.ToString()).ConfigureAwait(false);
await writer.WriteElementStringAsync(null, "Role", null, person.Role.ToString()).ConfigureAwait(false); await writer.WriteElementStringAsync(null, "Role", null, person.Role).ConfigureAwait(false);
if (person.SortOrder.HasValue) if (person.SortOrder.HasValue)
{ {

View File

@ -231,10 +231,8 @@ namespace MediaBrowser.MediaEncoding.Attachments
throw new InvalidOperationException( throw new InvalidOperationException(
string.Format(CultureInfo.InvariantCulture, "ffmpeg attachment extraction failed for {0} to {1}", inputPath, outputPath)); string.Format(CultureInfo.InvariantCulture, "ffmpeg attachment extraction failed for {0} to {1}", inputPath, outputPath));
} }
else
{ _logger.LogInformation("ffmpeg attachment extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath);
_logger.LogInformation("ffmpeg attachment extraction completed for {Path} to {Path}", inputPath, outputPath);
}
} }
private async Task<Stream> GetAttachmentStream( private async Task<Stream> GetAttachmentStream(
@ -376,10 +374,8 @@ namespace MediaBrowser.MediaEncoding.Attachments
throw new InvalidOperationException( throw new InvalidOperationException(
string.Format(CultureInfo.InvariantCulture, "ffmpeg attachment extraction failed for {0} to {1}", inputPath, outputPath)); string.Format(CultureInfo.InvariantCulture, "ffmpeg attachment extraction failed for {0} to {1}", inputPath, outputPath));
} }
else
{ _logger.LogInformation("ffmpeg attachment extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath);
_logger.LogInformation("ffmpeg attachment extraction completed for {Path} to {Path}", inputPath, outputPath);
}
} }
private string GetAttachmentCachePath(string mediaPath, MediaSourceInfo mediaSource, int attachmentStreamIndex) private string GetAttachmentCachePath(string mediaPath, MediaSourceInfo mediaSource, int attachmentStreamIndex)

View File

@ -1,4 +1,3 @@
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using BDInfo.IO; using BDInfo.IO;
@ -105,7 +104,7 @@ public class BdInfoDirectoryInfo : IDirectoryInfo
_impl.FullName, _impl.FullName,
new[] { searchPattern }, new[] { searchPattern },
false, false,
(searchOption & SearchOption.AllDirectories) == SearchOption.AllDirectories) searchOption == SearchOption.AllDirectories)
.Select(x => new BdInfoFileInfo(x)) .Select(x => new BdInfoFileInfo(x))
.ToArray(); .ToArray();
} }

View File

@ -217,12 +217,14 @@ namespace MediaBrowser.MediaEncoding.Encoder
return false; return false;
} }
else if (version < MinVersion) // Version is below what we recommend
if (version < MinVersion) // Version is below what we recommend
{ {
_logger.LogWarning("FFmpeg validation: The minimum recommended version is {MinVersion}", MinVersion); _logger.LogWarning("FFmpeg validation: The minimum recommended version is {MinVersion}", MinVersion);
return false; return false;
} }
else if (MaxVersion is not null && version > MaxVersion) // Version is above what we recommend
if (MaxVersion is not null && version > MaxVersion) // Version is above what we recommend
{ {
_logger.LogWarning("FFmpeg validation: The maximum recommended version is {MaxVersion}", MaxVersion); _logger.LogWarning("FFmpeg validation: The maximum recommended version is {MaxVersion}", MaxVersion);
return false; return false;
@ -491,7 +493,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
var found = Regex var found = Regex
.Matches(output, @"^\s\S{6}\s(?<codec>[\w|-]+)\s+.+$", RegexOptions.Multiline) .Matches(output, @"^\s\S{6}\s(?<codec>[\w|-]+)\s+.+$", RegexOptions.Multiline)
.Cast<Match>()
.Select(x => x.Groups["codec"].Value) .Select(x => x.Groups["codec"].Value)
.Where(x => required.Contains(x)); .Where(x => required.Contains(x));
@ -520,7 +521,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
var found = Regex var found = Regex
.Matches(output, @"^\s\S{3}\s(?<filter>[\w|-]+)\s+.+$", RegexOptions.Multiline) .Matches(output, @"^\s\S{3}\s(?<filter>[\w|-]+)\s+.+$", RegexOptions.Multiline)
.Cast<Match>()
.Select(x => x.Groups["filter"].Value) .Select(x => x.Groups["filter"].Value)
.Where(x => _requiredFilters.Contains(x)); .Where(x => _requiredFilters.Contains(x));

View File

@ -449,7 +449,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{ {
try try
{ {
_logger.LogInformation("Deleting converted subtitle due to failure: ", outputPath); _logger.LogInformation("Deleting converted subtitle due to failure: {Path}", outputPath);
_fileSystem.DeleteFile(outputPath); _fileSystem.DeleteFile(outputPath);
} }
catch (IOException ex) catch (IOException ex)
@ -624,10 +624,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
throw new FfmpegException( throw new FfmpegException(
string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle extraction failed for {0} to {1}", inputPath, outputPath)); string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle extraction failed for {0} to {1}", inputPath, outputPath));
} }
else
{ _logger.LogInformation("ffmpeg subtitle extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath);
_logger.LogInformation("ffmpeg subtitle extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath);
}
if (string.Equals(outputCodec, "ass", StringComparison.OrdinalIgnoreCase)) if (string.Equals(outputCodec, "ass", StringComparison.OrdinalIgnoreCase))
{ {

View File

@ -2,7 +2,6 @@
#pragma warning disable CA1819 #pragma warning disable CA1819
using System; using System;
using System.Collections.Generic;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Updates; using MediaBrowser.Model.Updates;

View File

@ -80,7 +80,8 @@ namespace MediaBrowser.Model.Cryptography
{ {
throw new FormatException("Hash string must contain a valid id"); throw new FormatException("Hash string must contain a valid id");
} }
else if (nextSegment == -1)
if (nextSegment == -1)
{ {
return new PasswordHash(hashString.ToString(), Array.Empty<byte>()); return new PasswordHash(hashString.ToString(), Array.Empty<byte>());
} }

View File

@ -1075,31 +1075,38 @@ namespace MediaBrowser.Model.Dlna
{ {
return 128000; return 128000;
} }
else if (totalBitrate <= 2000000)
if (totalBitrate <= 2000000)
{ {
return 384000; return 384000;
} }
else if (totalBitrate <= 3000000)
if (totalBitrate <= 3000000)
{ {
return 448000; return 448000;
} }
else if (totalBitrate <= 4000000)
if (totalBitrate <= 4000000)
{ {
return 640000; return 640000;
} }
else if (totalBitrate <= 5000000)
if (totalBitrate <= 5000000)
{ {
return 768000; return 768000;
} }
else if (totalBitrate <= 10000000)
if (totalBitrate <= 10000000)
{ {
return 1536000; return 1536000;
} }
else if (totalBitrate <= 15000000)
if (totalBitrate <= 15000000)
{ {
return 2304000; return 2304000;
} }
else if (totalBitrate <= 20000000)
if (totalBitrate <= 20000000)
{ {
return 3584000; return 3584000;
} }
@ -1443,7 +1450,8 @@ namespace MediaBrowser.Model.Dlna
{ {
return false; return false;
} }
else if (ContainerProfile.ContainsContainer(normalizedContainers, "mkv")
if (ContainerProfile.ContainsContainer(normalizedContainers, "mkv")
|| ContainerProfile.ContainsContainer(normalizedContainers, "matroska")) || ContainerProfile.ContainsContainer(normalizedContainers, "matroska"))
{ {
return true; return true;

View File

@ -430,7 +430,7 @@ namespace MediaBrowser.Model.Dlna
return totalBitrate.HasValue ? return totalBitrate.HasValue ?
Convert.ToInt64(totalBitrate.Value * totalSeconds) : Convert.ToInt64(totalBitrate.Value * totalSeconds) :
(long?)null; null;
} }
return null; return null;

View File

@ -17,11 +17,13 @@ namespace MediaBrowser.Model.MediaInfo
{ {
return "Dolby Digital"; return "Dolby Digital";
} }
else if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase))
if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase))
{ {
return "Dolby Digital+"; return "Dolby Digital+";
} }
else if (string.Equals(codec, "dca", StringComparison.OrdinalIgnoreCase))
if (string.Equals(codec, "dca", StringComparison.OrdinalIgnoreCase))
{ {
return "DTS"; return "DTS";
} }

View File

@ -1,6 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Lyrics;

View File

@ -882,10 +882,7 @@ namespace MediaBrowser.Providers.Manager
var key = providerId.Key; var key = providerId.Key;
// Don't replace existing Id's. // Don't replace existing Id's.
if (!lookupInfo.ProviderIds.ContainsKey(key)) lookupInfo.ProviderIds.TryAdd(key, providerId.Value);
{
lookupInfo.ProviderIds[key] = providerId.Value;
}
} }
} }

View File

@ -780,10 +780,7 @@ namespace MediaBrowser.Providers.Manager
{ {
foreach (var providerId in result.ProviderIds) foreach (var providerId in result.ProviderIds)
{ {
if (!existingMatch.ProviderIds.ContainsKey(providerId.Key)) existingMatch.ProviderIds.TryAdd(providerId.Key, providerId.Value);
{
existingMatch.ProviderIds.Add(providerId.Key, providerId.Value);
}
} }
if (string.IsNullOrWhiteSpace(existingMatch.ImageUrl)) if (string.IsNullOrWhiteSpace(existingMatch.ImageUrl))

View File

@ -100,10 +100,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
foreach (var info in idInfos) foreach (var info in idInfos)
{ {
var id = info.Key + "Id"; var id = info.Key + "Id";
if (!_validProviderIds.ContainsKey(id)) _validProviderIds.TryAdd(id, info.Key);
{
_validProviderIds.Add(id, info.Key);
}
} }
// Additional Mappings // Additional Mappings

View File

@ -221,10 +221,8 @@ namespace Rssdp.Infrastructure
{ {
return trimmedSegment.Substring(1, trimmedSegment.Length - 2); return trimmedSegment.Substring(1, trimmedSegment.Length - 2);
} }
else
{ return trimmedSegment;
return trimmedSegment;
}
} }
} }
} }

View File

@ -64,8 +64,7 @@ namespace Rssdp.Infrastructure
} }
message.Method = new HttpMethod(parts[0].Trim()); message.Method = new HttpMethod(parts[0].Trim());
Uri requestUri; if (Uri.TryCreate(parts[1].Trim(), UriKind.RelativeOrAbsolute, out var requestUri))
if (Uri.TryCreate(parts[1].Trim(), UriKind.RelativeOrAbsolute, out requestUri))
{ {
message.RequestUri = requestUri; message.RequestUri = requestUri;
} }

View File

@ -77,8 +77,7 @@ namespace Rssdp.Infrastructure
message.Version = ParseHttpVersion(parts[0].Trim()); message.Version = ParseHttpVersion(parts[0].Trim());
int statusCode = -1; if (!Int32.TryParse(parts[1].Trim(), out var statusCode))
if (!Int32.TryParse(parts[1].Trim(), out statusCode))
{ {
throw new ArgumentException("data status line is invalid. Status code is not a valid integer.", nameof(data)); throw new ArgumentException("data status line is invalid. Status code is not a valid integer.", nameof(data));
} }

View File

@ -171,10 +171,8 @@ namespace Rssdp
{ {
return "uuid:" + this.Uuid; return "uuid:" + this.Uuid;
} }
else
{ return _Udn;
return _Udn;
}
} }
set set

View File

@ -483,8 +483,7 @@ namespace Rssdp.Infrastructure
} }
} }
Uri retVal; Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out var retVal);
Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out retVal);
return retVal; return retVal;
} }
@ -501,8 +500,7 @@ namespace Rssdp.Infrastructure
} }
} }
Uri retVal; Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out var retVal);
Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out retVal);
return retVal; return retVal;
} }
@ -587,10 +585,8 @@ namespace Rssdp.Infrastructure
{ {
return OneSecond; return OneSecond;
} }
else
{ return searchWaitTime.Subtract(OneSecond);
return searchWaitTime.Subtract(OneSecond);
}
} }
private DiscoveredSsdpDevice FindExistingDeviceNotification(IEnumerable<DiscoveredSsdpDevice> devices, string notificationType, string usn) private DiscoveredSsdpDevice FindExistingDeviceNotification(IEnumerable<DiscoveredSsdpDevice> devices, string notificationType, string usn)

View File

@ -244,7 +244,6 @@ namespace Rssdp.Infrastructure
// Wait on random interval up to MX, as per SSDP spec. // Wait on random interval up to MX, as per SSDP spec.
// Also, as per UPnP 1.1/SSDP spec ignore missing/bank MX header. If over 120, assume random value between 0 and 120. // Also, as per UPnP 1.1/SSDP spec ignore missing/bank MX header. If over 120, assume random value between 0 and 120.
// Using 16 as minimum as that's often the minimum system clock frequency anyway. // Using 16 as minimum as that's often the minimum system clock frequency anyway.
int maxWaitInterval = 0;
if (String.IsNullOrEmpty(mx)) if (String.IsNullOrEmpty(mx))
{ {
// Windows Explorer is poorly behaved and doesn't supply an MX header value. // Windows Explorer is poorly behaved and doesn't supply an MX header value.
@ -254,7 +253,7 @@ namespace Rssdp.Infrastructure
// return; // return;
} }
if (!Int32.TryParse(mx, out maxWaitInterval) || maxWaitInterval <= 0) if (!Int32.TryParse(mx, out var maxWaitInterval) || maxWaitInterval <= 0)
{ {
return; return;
} }
@ -572,17 +571,14 @@ namespace Rssdp.Infrastructure
{ {
return nonzeroCacheLifetimesQuery.Min(); return nonzeroCacheLifetimesQuery.Min();
} }
else
{ return TimeSpan.Zero;
return TimeSpan.Zero;
}
} }
private string GetFirstHeaderValue(System.Net.Http.Headers.HttpRequestHeaders httpRequestHeaders, string headerName) private string GetFirstHeaderValue(System.Net.Http.Headers.HttpRequestHeaders httpRequestHeaders, string headerName)
{ {
string retVal = null; string retVal = null;
IEnumerable<String> values = null; if (httpRequestHeaders.TryGetValues(headerName, out var values) && values != null)
if (httpRequestHeaders.TryGetValues(headerName, out values) && values != null)
{ {
retVal = values.FirstOrDefault(); retVal = values.FirstOrDefault();
} }
@ -644,7 +640,7 @@ namespace Rssdp.Infrastructure
public string Key public string Key
{ {
get { return this.SearchTarget + ":" + this.EndPoint.ToString(); } get { return this.SearchTarget + ":" + this.EndPoint; }
} }
public bool IsOld() public bool IsOld()

View File

@ -13,7 +13,7 @@ RUN yum update -yq \
&& yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget
# Install DotNET SDK # Install DotNET SDK
RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
&& mkdir -p dotnet-sdk \ && mkdir -p dotnet-sdk \
&& tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \
&& ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet

View File

@ -12,7 +12,7 @@ RUN dnf update -yq \
&& dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget make && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget make
# Install DotNET SDK # Install DotNET SDK
RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
&& mkdir -p dotnet-sdk \ && mkdir -p dotnet-sdk \
&& tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \
&& ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet

View File

@ -17,7 +17,7 @@ RUN apt-get update -yqq \
libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0
# Install dotnet repository # Install dotnet repository
RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
&& mkdir -p dotnet-sdk \ && mkdir -p dotnet-sdk \
&& tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \
&& ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet

View File

@ -16,7 +16,7 @@ RUN apt-get update -yqq \
mmv build-essential lsb-release mmv build-essential lsb-release
# Install dotnet repository # Install dotnet repository
RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
&& mkdir -p dotnet-sdk \ && mkdir -p dotnet-sdk \
&& tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \
&& ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet

View File

@ -16,7 +16,7 @@ RUN apt-get update -yqq \
mmv build-essential lsb-release mmv build-essential lsb-release
# Install dotnet repository # Install dotnet repository
RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \
&& mkdir -p dotnet-sdk \ && mkdir -p dotnet-sdk \
&& tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \
&& ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet

View File

@ -120,8 +120,18 @@ public class SkiaEncoder : IImageEncoder
if (extension.Equals(".svg", StringComparison.OrdinalIgnoreCase)) if (extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
{ {
var svg = new SKSvg(); var svg = new SKSvg();
svg.Load(path); try
return new ImageDimensions(Convert.ToInt32(svg.Picture.CullRect.Width), Convert.ToInt32(svg.Picture.CullRect.Height)); {
svg.Load(path);
return new ImageDimensions(Convert.ToInt32(svg.Picture.CullRect.Width), Convert.ToInt32(svg.Picture.CullRect.Height));
}
catch (FormatException skiaColorException)
{
// This exception is known to be thrown on vector images that define custom styles
// Skia SVG is not able to handle that and as the repository is quite stale and has not received updates we just catch them
_logger.LogDebug(skiaColorException, "There was a issue loading the requested svg file");
return default;
}
} }
using var codec = SKCodec.Create(path, out SKCodecResult result); using var codec = SKCodec.Create(path, out SKCodecResult result);
@ -132,10 +142,10 @@ public class SkiaEncoder : IImageEncoder
return new ImageDimensions(info.Width, info.Height); return new ImageDimensions(info.Width, info.Height);
case SKCodecResult.Unimplemented: case SKCodecResult.Unimplemented:
_logger.LogDebug("Image format not supported: {FilePath}", path); _logger.LogDebug("Image format not supported: {FilePath}", path);
return new ImageDimensions(0, 0); return default;
default: default:
_logger.LogError("Unable to determine image dimensions for {FilePath}: {SkCodecResult}", path, result); _logger.LogError("Unable to determine image dimensions for {FilePath}: {SkCodecResult}", path, result);
return new ImageDimensions(0, 0); return default;
} }
} }

View File

@ -20,11 +20,13 @@ namespace Jellyfin.Extensions
{ {
return 0; return 0;
} }
else if (s1 is null)
if (s1 is null)
{ {
return -1; return -1;
} }
else if (s2 is null)
if (s2 is null)
{ {
return 1; return 1;
} }
@ -37,11 +39,13 @@ namespace Jellyfin.Extensions
{ {
return 0; return 0;
} }
else if (len1 == 0)
if (len1 == 0)
{ {
return -1; return -1;
} }
else if (len2 == 0)
if (len2 == 0)
{ {
return 1; return 1;
} }
@ -82,7 +86,8 @@ namespace Jellyfin.Extensions
{ {
return -1; return -1;
} }
else if (span1Len > span2Len)
if (span1Len > span2Len)
{ {
return 1; return 1;
} }

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Buffers.Text; using System.Buffers.Text;
using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;

View File

@ -1,6 +1,4 @@
using System; using System;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace Jellyfin.Extensions namespace Jellyfin.Extensions

View File

@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using AutoFixture; using AutoFixture;
using AutoFixture.AutoMoq; using AutoFixture.AutoMoq;
using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
using Jellyfin.Api.Auth.FirstTimeSetupPolicy; using Jellyfin.Api.Auth.FirstTimeSetupPolicy;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;

View File

@ -1,4 +1,3 @@
using System;
using Jellyfin.Api.Controllers; using Jellyfin.Api.Controllers;
using Xunit; using Xunit;

View File

@ -162,7 +162,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
[InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
[InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
public async Task BuildVideoItemSimple(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "") public async Task BuildVideoItemSimple(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "")
{ {
var options = await GetMediaOptions(deviceName, mediaSource); var options = await GetMediaOptions(deviceName, mediaSource);
BuildVideoItemSimpleTest(options, playMethod, why, transcodeMode, transcodeProtocol); BuildVideoItemSimpleTest(options, playMethod, why, transcodeMode, transcodeProtocol);
@ -260,7 +260,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
[InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
[InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
public async Task BuildVideoItemWithFirstExplicitStream(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "") public async Task BuildVideoItemWithFirstExplicitStream(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "")
{ {
var options = await GetMediaOptions(deviceName, mediaSource); var options = await GetMediaOptions(deviceName, mediaSource);
options.AudioStreamIndex = 1; options.AudioStreamIndex = 1;
@ -296,7 +296,7 @@ namespace Jellyfin.Model.Tests
// Tizen 4 4K 5.1 // Tizen 4 4K 5.1
[InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
[InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "") public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "")
{ {
var options = await GetMediaOptions(deviceName, mediaSource); var options = await GetMediaOptions(deviceName, mediaSource);
var streamCount = options.MediaSources[0].MediaStreams.Count; var streamCount = options.MediaSources[0].MediaStreams.Count;

View File

@ -238,9 +238,6 @@ namespace Jellyfin.Providers.Tests.Manager
} }
}; };
object? result;
List<PersonInfo> actual;
// overwrite provider id // overwrite provider id
var overwriteNewValue = new List<PersonInfo> var overwriteNewValue = new List<PersonInfo>
{ {
@ -249,9 +246,9 @@ namespace Jellyfin.Providers.Tests.Manager
Name = "Name 2" Name = "Name 2"
} }
}; };
Assert.False(TestMergeBaseItemDataPerson(GetOldValue(), overwriteNewValue, null, false, out result)); Assert.False(TestMergeBaseItemDataPerson(GetOldValue(), overwriteNewValue, null, false, out var result));
// People not already in target are not merged into it from source // People not already in target are not merged into it from source
actual = (List<PersonInfo>)result!; List<PersonInfo> actual = (List<PersonInfo>)result!;
Assert.Single(actual); Assert.Single(actual);
Assert.Equal("Name 1", actual[0].Name); Assert.Equal("Name 1", actual[0].Name);

View File

@ -90,7 +90,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers
}; };
_parser.Fetch(result, path, CancellationToken.None); _parser.Fetch(result, path, CancellationToken.None);
var item = (Series)result.Item; var item = result.Item;
Assert.Equal(id, item.ProviderIds[provider]); Assert.Equal(id, item.ProviderIds[provider]);
} }