mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-12-16 14:03:03 +03:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b25d6d1e48 | ||
|
|
cf59140276 | ||
|
|
cc4563a477 | ||
|
|
0d984b5162 | ||
|
|
279cba008b | ||
|
|
0359035000 |
@@ -36,7 +36,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Naming</PackageId>
|
<PackageId>Jellyfin.Naming</PackageId>
|
||||||
<VersionPrefix>10.9.5</VersionPrefix>
|
<VersionPrefix>10.9.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using Jellyfin.Extensions;
|
using Jellyfin.Extensions;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -13,6 +14,8 @@ namespace Emby.Server.Implementations.Data
|
|||||||
public abstract class BaseSqliteRepository : IDisposable
|
public abstract class BaseSqliteRepository : IDisposable
|
||||||
{
|
{
|
||||||
private bool _disposed = false;
|
private bool _disposed = false;
|
||||||
|
private SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
|
||||||
|
private SqliteConnection _writeConnection;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
|
/// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
|
||||||
@@ -98,9 +101,55 @@ namespace Emby.Server.Implementations.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SqliteConnection GetConnection(bool readOnly = false)
|
protected ManagedConnection GetConnection(bool readOnly = false)
|
||||||
{
|
{
|
||||||
var connection = new SqliteConnection($"Filename={DbFilePath}" + (readOnly ? ";Mode=ReadOnly" : string.Empty));
|
if (!readOnly)
|
||||||
|
{
|
||||||
|
_writeLock.Wait();
|
||||||
|
if (_writeConnection is not null)
|
||||||
|
{
|
||||||
|
return new ManagedConnection(_writeConnection, _writeLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
var writeConnection = new SqliteConnection($"Filename={DbFilePath};Pooling=False");
|
||||||
|
writeConnection.Open();
|
||||||
|
|
||||||
|
if (CacheSize.HasValue)
|
||||||
|
{
|
||||||
|
writeConnection.Execute("PRAGMA cache_size=" + CacheSize.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(LockingMode))
|
||||||
|
{
|
||||||
|
writeConnection.Execute("PRAGMA locking_mode=" + LockingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(JournalMode))
|
||||||
|
{
|
||||||
|
writeConnection.Execute("PRAGMA journal_mode=" + JournalMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JournalSizeLimit.HasValue)
|
||||||
|
{
|
||||||
|
writeConnection.Execute("PRAGMA journal_size_limit=" + JournalSizeLimit.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Synchronous.HasValue)
|
||||||
|
{
|
||||||
|
writeConnection.Execute("PRAGMA synchronous=" + (int)Synchronous.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PageSize.HasValue)
|
||||||
|
{
|
||||||
|
writeConnection.Execute("PRAGMA page_size=" + PageSize.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeConnection.Execute("PRAGMA temp_store=" + (int)TempStore);
|
||||||
|
|
||||||
|
return new ManagedConnection(_writeConnection = writeConnection, _writeLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
var connection = new SqliteConnection($"Filename={DbFilePath};Mode=ReadOnly");
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
if (CacheSize.HasValue)
|
if (CacheSize.HasValue)
|
||||||
@@ -135,17 +184,17 @@ namespace Emby.Server.Implementations.Data
|
|||||||
|
|
||||||
connection.Execute("PRAGMA temp_store=" + (int)TempStore);
|
connection.Execute("PRAGMA temp_store=" + (int)TempStore);
|
||||||
|
|
||||||
return connection;
|
return new ManagedConnection(connection, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqliteCommand PrepareStatement(SqliteConnection connection, string sql)
|
public SqliteCommand PrepareStatement(ManagedConnection connection, string sql)
|
||||||
{
|
{
|
||||||
var command = connection.CreateCommand();
|
var command = connection.CreateCommand();
|
||||||
command.CommandText = sql;
|
command.CommandText = sql;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool TableExists(SqliteConnection connection, string name)
|
protected bool TableExists(ManagedConnection connection, string name)
|
||||||
{
|
{
|
||||||
using var statement = PrepareStatement(connection, "select DISTINCT tbl_name from sqlite_master");
|
using var statement = PrepareStatement(connection, "select DISTINCT tbl_name from sqlite_master");
|
||||||
foreach (var row in statement.ExecuteQuery())
|
foreach (var row in statement.ExecuteQuery())
|
||||||
@@ -159,7 +208,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<string> GetColumnNames(SqliteConnection connection, string table)
|
protected List<string> GetColumnNames(ManagedConnection connection, string table)
|
||||||
{
|
{
|
||||||
var columnNames = new List<string>();
|
var columnNames = new List<string>();
|
||||||
|
|
||||||
@@ -174,7 +223,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
return columnNames;
|
return columnNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void AddColumn(SqliteConnection connection, string table, string columnName, string type, List<string> existingColumnNames)
|
protected void AddColumn(ManagedConnection connection, string table, string columnName, string type, List<string> existingColumnNames)
|
||||||
{
|
{
|
||||||
if (existingColumnNames.Contains(columnName, StringComparison.OrdinalIgnoreCase))
|
if (existingColumnNames.Contains(columnName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@@ -207,6 +256,24 @@ namespace Emby.Server.Implementations.Data
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dispose)
|
||||||
|
{
|
||||||
|
_writeLock.Wait();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_writeConnection.Dispose();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_writeLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
_writeLock.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_writeConnection = null;
|
||||||
|
_writeLock = null;
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
62
Emby.Server.Implementations/Data/ManagedConnection.cs
Normal file
62
Emby.Server.Implementations/Data/ManagedConnection.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
|
||||||
|
namespace Emby.Server.Implementations.Data;
|
||||||
|
|
||||||
|
public sealed class ManagedConnection : IDisposable
|
||||||
|
{
|
||||||
|
private readonly SemaphoreSlim? _writeLock;
|
||||||
|
|
||||||
|
private SqliteConnection _db;
|
||||||
|
|
||||||
|
private bool _disposed = false;
|
||||||
|
|
||||||
|
public ManagedConnection(SqliteConnection db, SemaphoreSlim? writeLock)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_writeLock = writeLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqliteTransaction BeginTransaction()
|
||||||
|
=> _db.BeginTransaction();
|
||||||
|
|
||||||
|
public SqliteCommand CreateCommand()
|
||||||
|
=> _db.CreateCommand();
|
||||||
|
|
||||||
|
public void Execute(string commandText)
|
||||||
|
=> _db.Execute(commandText);
|
||||||
|
|
||||||
|
public SqliteCommand PrepareStatement(string sql)
|
||||||
|
=> _db.PrepareStatement(sql);
|
||||||
|
|
||||||
|
public IEnumerable<SqliteDataReader> Query(string commandText)
|
||||||
|
=> _db.Query(commandText);
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_writeLock is null)
|
||||||
|
{
|
||||||
|
// Read connections are managed with an internal pool
|
||||||
|
_db.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Write lock is managed by BaseSqliteRepository
|
||||||
|
// Don't dispose here
|
||||||
|
_writeLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
_db = null!;
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -601,7 +601,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveItemsInTransaction(SqliteConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples)
|
private void SaveItemsInTransaction(ManagedConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples)
|
||||||
{
|
{
|
||||||
using (var saveItemStatement = PrepareStatement(db, SaveItemCommandText))
|
using (var saveItemStatement = PrepareStatement(db, SaveItemCommandText))
|
||||||
using (var deleteAncestorsStatement = PrepareStatement(db, "delete from AncestorIds where ItemId=@ItemId"))
|
using (var deleteAncestorsStatement = PrepareStatement(db, "delete from AncestorIds where ItemId=@ItemId"))
|
||||||
@@ -1980,7 +1980,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertChapters(Guid idBlob, IReadOnlyList<ChapterInfo> chapters, SqliteConnection db)
|
private void InsertChapters(Guid idBlob, IReadOnlyList<ChapterInfo> chapters, ManagedConnection db)
|
||||||
{
|
{
|
||||||
var startIndex = 0;
|
var startIndex = 0;
|
||||||
var limit = 100;
|
var limit = 100;
|
||||||
@@ -4476,7 +4476,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteWithSingleParam(SqliteConnection db, string query, Guid value)
|
private void ExecuteWithSingleParam(ManagedConnection db, string query, Guid value)
|
||||||
{
|
{
|
||||||
using (var statement = PrepareStatement(db, query))
|
using (var statement = PrepareStatement(db, query))
|
||||||
{
|
{
|
||||||
@@ -4632,7 +4632,7 @@ AND Type = @InternalPersonType)");
|
|||||||
return whereClauses;
|
return whereClauses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, SqliteConnection db, SqliteCommand deleteAncestorsStatement)
|
private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, ManagedConnection db, SqliteCommand deleteAncestorsStatement)
|
||||||
{
|
{
|
||||||
if (itemId.IsEmpty())
|
if (itemId.IsEmpty())
|
||||||
{
|
{
|
||||||
@@ -5148,7 +5148,7 @@ AND Type = @InternalPersonType)");
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, SqliteConnection db)
|
private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, ManagedConnection db)
|
||||||
{
|
{
|
||||||
if (itemId.IsEmpty())
|
if (itemId.IsEmpty())
|
||||||
{
|
{
|
||||||
@@ -5167,7 +5167,7 @@ AND Type = @InternalPersonType)");
|
|||||||
InsertItemValues(itemId, values, db);
|
InsertItemValues(itemId, values, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertItemValues(Guid id, List<(int MagicNumber, string Value)> values, SqliteConnection db)
|
private void InsertItemValues(Guid id, List<(int MagicNumber, string Value)> values, ManagedConnection db)
|
||||||
{
|
{
|
||||||
const int Limit = 100;
|
const int Limit = 100;
|
||||||
var startIndex = 0;
|
var startIndex = 0;
|
||||||
@@ -5239,7 +5239,7 @@ AND Type = @InternalPersonType)");
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertPeople(Guid id, List<PersonInfo> people, SqliteConnection db)
|
private void InsertPeople(Guid id, List<PersonInfo> people, ManagedConnection db)
|
||||||
{
|
{
|
||||||
const int Limit = 100;
|
const int Limit = 100;
|
||||||
var startIndex = 0;
|
var startIndex = 0;
|
||||||
@@ -5388,7 +5388,7 @@ AND Type = @InternalPersonType)");
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, SqliteConnection db)
|
private void InsertMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, ManagedConnection db)
|
||||||
{
|
{
|
||||||
const int Limit = 10;
|
const int Limit = 10;
|
||||||
var startIndex = 0;
|
var startIndex = 0;
|
||||||
@@ -5772,7 +5772,7 @@ AND Type = @InternalPersonType)");
|
|||||||
private void InsertMediaAttachments(
|
private void InsertMediaAttachments(
|
||||||
Guid id,
|
Guid id,
|
||||||
IReadOnlyList<MediaAttachment> attachments,
|
IReadOnlyList<MediaAttachment> attachments,
|
||||||
SqliteConnection db,
|
ManagedConnection db,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
const int InsertAtOnce = 10;
|
const int InsertAtOnce = 10;
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImportUserIds(SqliteConnection db, IEnumerable<User> users)
|
private void ImportUserIds(ManagedConnection db, IEnumerable<User> users)
|
||||||
{
|
{
|
||||||
var userIdsWithUserData = GetAllUserIdsWithUserData(db);
|
var userIdsWithUserData = GetAllUserIdsWithUserData(db);
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Guid> GetAllUserIdsWithUserData(SqliteConnection db)
|
private List<Guid> GetAllUserIdsWithUserData(ManagedConnection db)
|
||||||
{
|
{
|
||||||
var list = new List<Guid>();
|
var list = new List<Guid>();
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SaveUserData(SqliteConnection db, long internalUserId, string key, UserItemData userData)
|
private static void SaveUserData(ManagedConnection db, long internalUserId, string key, UserItemData userData)
|
||||||
{
|
{
|
||||||
using (var statement = db.PrepareStatement("replace into UserDatas (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"))
|
using (var statement = db.PrepareStatement("replace into UserDatas (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Data</PackageId>
|
<PackageId>Jellyfin.Data</PackageId>
|
||||||
<VersionPrefix>10.9.5</VersionPrefix>
|
<VersionPrefix>10.9.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Common</PackageId>
|
<PackageId>Jellyfin.Common</PackageId>
|
||||||
<VersionPrefix>10.9.5</VersionPrefix>
|
<VersionPrefix>10.9.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (IsFileProtocol)
|
if (IsFileProtocol)
|
||||||
{
|
{
|
||||||
IEnumerable<BaseItem> nonCachedChildren;
|
IEnumerable<BaseItem> nonCachedChildren = [];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -373,7 +373,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError(ex, "Error retrieving children folder");
|
Logger.LogError(ex, "Error retrieving children folder");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Report(ProgressHelpers.RetrievedChildren);
|
progress.Report(ProgressHelpers.RetrievedChildren);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Controller</PackageId>
|
<PackageId>Jellyfin.Controller</PackageId>
|
||||||
<VersionPrefix>10.9.5</VersionPrefix>
|
<VersionPrefix>10.9.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Model</PackageId>
|
<PackageId>Jellyfin.Model</PackageId>
|
||||||
<VersionPrefix>10.9.5</VersionPrefix>
|
<VersionPrefix>10.9.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1057,7 +1057,7 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
target.Tags = target.ProductionLocations.Concat(source.ProductionLocations).Distinct().ToArray();
|
target.ProductionLocations = target.ProductionLocations.Concat(source.ProductionLocations).Distinct().ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -193,11 +193,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
tags ??= new TagLib.Id3v2.Tag();
|
tags ??= new TagLib.Id3v2.Tag();
|
||||||
tags.AlbumArtists ??= mediaInfo.AlbumArtists;
|
tags.AlbumArtists = tags.AlbumArtists.Length == 0 ? mediaInfo.AlbumArtists : tags.AlbumArtists;
|
||||||
tags.Album ??= mediaInfo.Album;
|
tags.Album ??= mediaInfo.Album;
|
||||||
tags.Title ??= mediaInfo.Name;
|
tags.Title ??= mediaInfo.Name;
|
||||||
tags.Year = tags.Year == 0U ? Convert.ToUInt32(mediaInfo.ProductionYear, CultureInfo.InvariantCulture) : tags.Year;
|
tags.Year = tags.Year == 0U ? Convert.ToUInt32(mediaInfo.ProductionYear, CultureInfo.InvariantCulture) : tags.Year;
|
||||||
tags.Performers ??= mediaInfo.Artists;
|
tags.Performers = tags.Performers.Length == 0 ? mediaInfo.Artists : tags.Performers;
|
||||||
tags.Genres ??= mediaInfo.Genres;
|
tags.Genres ??= mediaInfo.Genres;
|
||||||
tags.Track = tags.Track == 0U ? Convert.ToUInt32(mediaInfo.IndexNumber, CultureInfo.InvariantCulture) : tags.Track;
|
tags.Track = tags.Track == 0U ? Convert.ToUInt32(mediaInfo.IndexNumber, CultureInfo.InvariantCulture) : tags.Track;
|
||||||
tags.Disc = tags.Disc == 0U ? Convert.ToUInt32(mediaInfo.ParentIndexNumber, CultureInfo.InvariantCulture) : tags.Disc;
|
tags.Disc = tags.Disc == 0U ? Convert.ToUInt32(mediaInfo.ParentIndexNumber, CultureInfo.InvariantCulture) : tags.Disc;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.9.5")]
|
[assembly: AssemblyVersion("10.9.6")]
|
||||||
[assembly: AssemblyFileVersion("10.9.5")]
|
[assembly: AssemblyFileVersion("10.9.6")]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Extensions</PackageId>
|
<PackageId>Jellyfin.Extensions</PackageId>
|
||||||
<VersionPrefix>10.9.5</VersionPrefix>
|
<VersionPrefix>10.9.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user