Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1136a36eed | |||
| e8514de33b | |||
| 722cdcce5e | |||
| bfe0fdbcdc | |||
| 0b2a59e963 | |||
| 6329de4fc3 | |||
| 644df3585b | |||
| 3766a88bea | |||
| f333ef74b3 | |||
| 0394965753 | |||
| 53a45c6033 | |||
| adfe52f55a | |||
| c693da94ce | |||
| 1a7c2299c6 | |||
| 9c7d735a96 | |||
| 5df03b9010 | |||
| ef13a18450 |
@@ -9,8 +9,8 @@
|
|||||||
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
|
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
|
||||||
<PackageVersion Include="AutoFixture" Version="4.18.1" />
|
<PackageVersion Include="AutoFixture" Version="4.18.1" />
|
||||||
<PackageVersion Include="BDInfo" Version="0.8.0" />
|
<PackageVersion Include="BDInfo" Version="0.8.0" />
|
||||||
<PackageVersion Include="BlurHashSharp.SkiaSharp" Version="1.3.3" />
|
<PackageVersion Include="BlurHashSharp.SkiaSharp" Version="1.3.4" />
|
||||||
<PackageVersion Include="BlurHashSharp" Version="1.3.3" />
|
<PackageVersion Include="BlurHashSharp" Version="1.3.4" />
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
|
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
|
||||||
<PackageVersion Include="Diacritics" Version="3.3.29" />
|
<PackageVersion Include="Diacritics" Version="3.3.29" />
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Naming</PackageId>
|
<PackageId>Jellyfin.Naming</PackageId>
|
||||||
<VersionPrefix>10.10.4</VersionPrefix>
|
<VersionPrefix>10.10.5</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>
|
||||||
|
|||||||
@@ -276,6 +276,13 @@ namespace Emby.Server.Implementations.IO
|
|||||||
{
|
{
|
||||||
_logger.LogError(ex, "Reading the file at {Path} failed due to a permissions exception.", fileInfo.FullName);
|
_logger.LogError(ex, "Reading the file at {Path} failed due to a permissions exception.", fileInfo.FullName);
|
||||||
}
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
// IOException generally means the file is not accessible due to filesystem issues
|
||||||
|
// Catch this exception and mark the file as not exist to ignore it
|
||||||
|
_logger.LogError(ex, "Reading the file at {Path} failed due to an IO Exception. Marking the file as not existing", fileInfo.FullName);
|
||||||
|
result.Exists = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,6 +597,9 @@ namespace Emby.Server.Implementations.IO
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
|
public virtual IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
|
||||||
{
|
{
|
||||||
|
// Note: any of unhandled exceptions thrown by this method may cause the caller to believe the whole path is not accessible.
|
||||||
|
// But what causing the exception may be a single file under that path. This could lead to unexpected behavior.
|
||||||
|
// For example, the scanner will remove everything in that path due to unhandled errors.
|
||||||
var directoryInfo = new DirectoryInfo(path);
|
var directoryInfo = new DirectoryInfo(path);
|
||||||
var enumerationOptions = GetEnumerationOptions(recursive);
|
var enumerationOptions = GetEnumerationOptions(recursive);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
Livre,0
|
Livre,0
|
||||||
L,0
|
L,0
|
||||||
ER,9
|
AL,0
|
||||||
|
ER,10
|
||||||
10,10
|
10,10
|
||||||
|
A10,10
|
||||||
12,12
|
12,12
|
||||||
|
A12,12
|
||||||
14,14
|
14,14
|
||||||
|
A14,14
|
||||||
16,16
|
16,16
|
||||||
|
A16,16
|
||||||
18,18
|
18,18
|
||||||
|
A18,18
|
||||||
|
|||||||
|
@@ -6,8 +6,6 @@ TV-Y7,7
|
|||||||
TV-Y7-FV,7
|
TV-Y7-FV,7
|
||||||
PG,9
|
PG,9
|
||||||
TV-PG,9
|
TV-PG,9
|
||||||
PG-13,13
|
|
||||||
13+,13
|
|
||||||
TV-14,14
|
TV-14,14
|
||||||
14A,14
|
14A,14
|
||||||
16+,16
|
16+,16
|
||||||
|
|||||||
|
@@ -1,7 +1,7 @@
|
|||||||
A,0
|
A,0
|
||||||
A/fig,0
|
A/fig,0
|
||||||
A/i,0
|
A/i,0
|
||||||
A/fig/i,0
|
A/i/fig,0
|
||||||
APTA,0
|
APTA,0
|
||||||
ERI,0
|
ERI,0
|
||||||
TP,0
|
TP,0
|
||||||
|
|||||||
|
@@ -6,10 +6,11 @@ U,0
|
|||||||
6+,6
|
6+,6
|
||||||
7+,7
|
7+,7
|
||||||
PG,8
|
PG,8
|
||||||
9+,9
|
9,9
|
||||||
12,12
|
12,12
|
||||||
12+,12
|
12+,12
|
||||||
12A,12
|
12A,12
|
||||||
|
12PG,12
|
||||||
Teen,13
|
Teen,13
|
||||||
13+,13
|
13+,13
|
||||||
14+,14
|
14+,14
|
||||||
|
|||||||
|
@@ -4,6 +4,7 @@ PG,12
|
|||||||
12A,12
|
12A,12
|
||||||
12PG,12
|
12PG,12
|
||||||
15,15
|
15,15
|
||||||
|
15PG,15
|
||||||
15A,15
|
15A,15
|
||||||
16,16
|
16,16
|
||||||
18,18
|
18,18
|
||||||
|
|||||||
|
@@ -6,4 +6,5 @@ A,0
|
|||||||
12,12
|
12,12
|
||||||
15,15
|
15,15
|
||||||
18,18
|
18,18
|
||||||
|
C,18
|
||||||
Not approved,1001
|
Not approved,1001
|
||||||
|
|||||||
|
@@ -10,6 +10,7 @@ R16,16
|
|||||||
RP16,16
|
RP16,16
|
||||||
GA,18
|
GA,18
|
||||||
R18,18
|
R18,18
|
||||||
|
RP18,18
|
||||||
MA,1000
|
MA,1000
|
||||||
R,1001
|
R,1001
|
||||||
Objectionable,1001
|
Objectionable,1001
|
||||||
|
|||||||
|
@@ -5,23 +5,23 @@ TV-Y,0
|
|||||||
TV-Y7,7
|
TV-Y7,7
|
||||||
TV-Y7-FV,7
|
TV-Y7-FV,7
|
||||||
PG,10
|
PG,10
|
||||||
|
TV-PG,10
|
||||||
|
TV-PG-D,10
|
||||||
|
TV-PG-L,10
|
||||||
|
TV-PG-S,10
|
||||||
|
TV-PG-V,10
|
||||||
|
TV-PG-DL,10
|
||||||
|
TV-PG-DS,10
|
||||||
|
TV-PG-DV,10
|
||||||
|
TV-PG-LS,10
|
||||||
|
TV-PG-LV,10
|
||||||
|
TV-PG-SV,1
|
||||||
|
TV-PG-DLS,10
|
||||||
|
TV-PG-DLV,10
|
||||||
|
TV-PG-DSV,10
|
||||||
|
TV-PG-LSV,10
|
||||||
|
TV-PG-DLSV,10
|
||||||
PG-13,13
|
PG-13,13
|
||||||
TV-PG,13
|
|
||||||
TV-PG-D,13
|
|
||||||
TV-PG-L,13
|
|
||||||
TV-PG-S,13
|
|
||||||
TV-PG-V,13
|
|
||||||
TV-PG-DL,13
|
|
||||||
TV-PG-DS,13
|
|
||||||
TV-PG-DV,13
|
|
||||||
TV-PG-LS,13
|
|
||||||
TV-PG-LV,13
|
|
||||||
TV-PG-SV,13
|
|
||||||
TV-PG-DLS,13
|
|
||||||
TV-PG-DLV,13
|
|
||||||
TV-PG-DSV,13
|
|
||||||
TV-PG-LSV,13
|
|
||||||
TV-PG-DLSV,13
|
|
||||||
TV-14,14
|
TV-14,14
|
||||||
TV-14-D,14
|
TV-14-D,14
|
||||||
TV-14-L,14
|
TV-14-L,14
|
||||||
@@ -48,3 +48,5 @@ TV-MA-LS,17
|
|||||||
TV-MA-LV,17
|
TV-MA-LV,17
|
||||||
TV-MA-SV,17
|
TV-MA-SV,17
|
||||||
TV-MA-LSV,17
|
TV-MA-LSV,17
|
||||||
|
TV-X,18
|
||||||
|
TV-AO,18
|
||||||
|
|||||||
|
@@ -18,7 +18,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Data</PackageId>
|
<PackageId>Jellyfin.Data</PackageId>
|
||||||
<VersionPrefix>10.10.4</VersionPrefix>
|
<VersionPrefix>10.10.5</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>
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ namespace Jellyfin.Server.Migrations
|
|||||||
typeof(Routines.RemoveDuplicatePlaylistChildren)
|
typeof(Routines.RemoveDuplicatePlaylistChildren)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static readonly Guid _downgradeCheckMigration = Guid.Parse("36445464-849f-429f-9ad0-bb130efa0664");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run all needed migrations.
|
/// Run all needed migrations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -88,6 +90,12 @@ namespace Jellyfin.Server.Migrations
|
|||||||
? (MigrationOptions)xmlSerializer.DeserializeFromFile(typeof(MigrationOptions), migrationConfigPath)!
|
? (MigrationOptions)xmlSerializer.DeserializeFromFile(typeof(MigrationOptions), migrationConfigPath)!
|
||||||
: new MigrationOptions();
|
: new MigrationOptions();
|
||||||
|
|
||||||
|
// 10.10 specific EFCore migration check.
|
||||||
|
if (migrationOptions.Applied.Any(f => f.Id.Equals(_downgradeCheckMigration)))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("You cannot downgrade your jellyfin install from the library.db migration.");
|
||||||
|
}
|
||||||
|
|
||||||
// We have to deserialize it manually since the configuration manager may overwrite it
|
// We have to deserialize it manually since the configuration manager may overwrite it
|
||||||
var serverConfig = File.Exists(appPaths.SystemConfigurationFilePath)
|
var serverConfig = File.Exists(appPaths.SystemConfigurationFilePath)
|
||||||
? (ServerConfiguration)xmlSerializer.DeserializeFromFile(typeof(ServerConfiguration), appPaths.SystemConfigurationFilePath)!
|
? (ServerConfiguration)xmlSerializer.DeserializeFromFile(typeof(ServerConfiguration), appPaths.SystemConfigurationFilePath)!
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Jellyfin.Server.Migrations.Routines
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Guid Id => Guid.Parse("{67445D54-B895-4B24-9F4C-35CE0690EA07}");
|
public Guid Id => Guid.Parse("{D34BFC33-5D2E-4790-8085-069EF6EECB4E}");
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string Name => "MigrateRatingLevels";
|
public string Name => "MigrateRatingLevels";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Common</PackageId>
|
<PackageId>Jellyfin.Common</PackageId>
|
||||||
<VersionPrefix>10.10.4</VersionPrefix>
|
<VersionPrefix>10.10.5</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.Controller</PackageId>
|
<PackageId>Jellyfin.Controller</PackageId>
|
||||||
<VersionPrefix>10.10.4</VersionPrefix>
|
<VersionPrefix>10.10.5</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>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
public class SubtitleEditParser : ISubtitleParser
|
public class SubtitleEditParser : ISubtitleParser
|
||||||
{
|
{
|
||||||
private readonly ILogger<SubtitleEditParser> _logger;
|
private readonly ILogger<SubtitleEditParser> _logger;
|
||||||
private readonly Dictionary<string, SubtitleFormat[]> _subtitleFormats;
|
private readonly Dictionary<string, List<Type>> _subtitleFormatTypes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SubtitleEditParser"/> class.
|
/// Initializes a new instance of the <see cref="SubtitleEditParser"/> class.
|
||||||
@@ -26,10 +26,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
public SubtitleEditParser(ILogger<SubtitleEditParser> logger)
|
public SubtitleEditParser(ILogger<SubtitleEditParser> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_subtitleFormats = GetSubtitleFormats()
|
_subtitleFormatTypes = GetSubtitleFormatTypes();
|
||||||
.Where(subtitleFormat => !string.IsNullOrEmpty(subtitleFormat.Extension))
|
|
||||||
.GroupBy(subtitleFormat => subtitleFormat.Extension.TrimStart('.'), StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToDictionary(g => g.Key, g => g.ToArray(), StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -38,13 +35,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
var subtitle = new Subtitle();
|
var subtitle = new Subtitle();
|
||||||
var lines = stream.ReadAllLines().ToList();
|
var lines = stream.ReadAllLines().ToList();
|
||||||
|
|
||||||
if (!_subtitleFormats.TryGetValue(fileExtension, out var subtitleFormats))
|
if (!_subtitleFormatTypes.TryGetValue(fileExtension, out var subtitleFormatTypesForExtension))
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Unsupported file extension: {fileExtension}", nameof(fileExtension));
|
throw new ArgumentException($"Unsupported file extension: {fileExtension}", nameof(fileExtension));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var subtitleFormat in subtitleFormats)
|
foreach (var subtitleFormatType in subtitleFormatTypesForExtension)
|
||||||
{
|
{
|
||||||
|
var subtitleFormat = (SubtitleFormat)Activator.CreateInstance(subtitleFormatType, true)!;
|
||||||
_logger.LogDebug(
|
_logger.LogDebug(
|
||||||
"Trying to parse '{FileExtension}' subtitle using the {SubtitleFormatParser} format parser",
|
"Trying to parse '{FileExtension}' subtitle using the {SubtitleFormatParser} format parser",
|
||||||
fileExtension,
|
fileExtension,
|
||||||
@@ -97,11 +95,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool SupportsFileExtension(string fileExtension)
|
public bool SupportsFileExtension(string fileExtension)
|
||||||
=> _subtitleFormats.ContainsKey(fileExtension);
|
=> _subtitleFormatTypes.ContainsKey(fileExtension);
|
||||||
|
|
||||||
private List<SubtitleFormat> GetSubtitleFormats()
|
private Dictionary<string, List<Type>> GetSubtitleFormatTypes()
|
||||||
{
|
{
|
||||||
var subtitleFormats = new List<SubtitleFormat>();
|
var subtitleFormatTypes = new Dictionary<string, List<Type>>(StringComparer.OrdinalIgnoreCase);
|
||||||
var assembly = typeof(SubtitleFormat).Assembly;
|
var assembly = typeof(SubtitleFormat).Assembly;
|
||||||
|
|
||||||
foreach (var type in assembly.GetTypes())
|
foreach (var type in assembly.GetTypes())
|
||||||
@@ -113,9 +111,20 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// It shouldn't be null, but the exception is caught if it is
|
var tempInstance = (SubtitleFormat)Activator.CreateInstance(type, true)!;
|
||||||
var subtitleFormat = (SubtitleFormat)Activator.CreateInstance(type, true)!;
|
var extension = tempInstance.Extension.TrimStart('.');
|
||||||
subtitleFormats.Add(subtitleFormat);
|
if (!string.IsNullOrEmpty(extension))
|
||||||
|
{
|
||||||
|
// Store only the type, we will instantiate from it later
|
||||||
|
if (!subtitleFormatTypes.TryGetValue(extension, out var subtitleFormatTypesForExtension))
|
||||||
|
{
|
||||||
|
subtitleFormatTypes[extension] = [type];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subtitleFormatTypesForExtension.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -123,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return subtitleFormats;
|
return subtitleFormatTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1001,6 +1001,8 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
}))
|
}))
|
||||||
.All(satisfied => satisfied);
|
.All(satisfied => satisfied);
|
||||||
|
|
||||||
|
directAudioStreamSatisfied = directAudioStreamSatisfied && !playlistItem.TranscodeReasons.HasFlag(TranscodeReason.ContainerBitrateExceedsLimit);
|
||||||
|
|
||||||
var directAudioStream = directAudioStreamSatisfied ? audioStreamWithSupportedCodec : null;
|
var directAudioStream = directAudioStreamSatisfied ? audioStreamWithSupportedCodec : null;
|
||||||
|
|
||||||
if (channelsExceedsLimit && playlistItem.TargetAudioStream is not null)
|
if (channelsExceedsLimit && playlistItem.TargetAudioStream is not null)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Model</PackageId>
|
<PackageId>Jellyfin.Model</PackageId>
|
||||||
<VersionPrefix>10.10.4</VersionPrefix>
|
<VersionPrefix>10.10.5</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>
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
|
|
||||||
var fileStreamOptions = AsyncFile.WriteOptions;
|
var fileStreamOptions = AsyncFile.WriteOptions;
|
||||||
fileStreamOptions.Mode = FileMode.Create;
|
fileStreamOptions.Mode = FileMode.Create;
|
||||||
|
fileStreamOptions.Options = FileOptions.WriteThrough;
|
||||||
if (source.CanSeek)
|
if (source.CanSeek)
|
||||||
{
|
{
|
||||||
fileStreamOptions.PreallocationSize = source.Length;
|
fileStreamOptions.PreallocationSize = source.Length;
|
||||||
|
|||||||
@@ -79,21 +79,13 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(val) && movie is not null)
|
if (!string.IsNullOrWhiteSpace(val) && movie is not null)
|
||||||
{
|
{
|
||||||
// TODO Handle this better later
|
try
|
||||||
if (!val.Contains('<', StringComparison.Ordinal))
|
|
||||||
{
|
{
|
||||||
movie.CollectionName = val;
|
ParseSetXml(val, movie);
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
try
|
Logger.LogError(ex, "Error parsing set node");
|
||||||
{
|
|
||||||
ParseSetXml(val, movie);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError(ex, "Error parsing set node");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +128,12 @@ namespace MediaBrowser.XbmcMetadata.Parsers
|
|||||||
// Loop through each element
|
// Loop through each element
|
||||||
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
|
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
|
||||||
{
|
{
|
||||||
if (reader.NodeType == XmlNodeType.Element)
|
if (reader.NodeType == XmlNodeType.Text && reader.Depth == 1)
|
||||||
|
{
|
||||||
|
movie.CollectionName = reader.Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
switch (reader.Name)
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,7 +115,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(movie.CollectionName))
|
if (!string.IsNullOrEmpty(movie.CollectionName))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("set", movie.CollectionName);
|
writer.WriteStartElement("set");
|
||||||
|
writer.WriteElementString("name", movie.CollectionName);
|
||||||
|
writer.WriteEndElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.10.4")]
|
[assembly: AssemblyVersion("10.10.5")]
|
||||||
[assembly: AssemblyFileVersion("10.10.4")]
|
[assembly: AssemblyFileVersion("10.10.5")]
|
||||||
|
|||||||
@@ -195,8 +195,10 @@ public class SkiaEncoder : IImageEncoder
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use FileStream with FileShare.Read instead of having Skia open the file to allow concurrent read access
|
||||||
|
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
// Any larger than 128x128 is too slow and there's no visually discernible difference
|
// Any larger than 128x128 is too slow and there's no visually discernible difference
|
||||||
return BlurHashEncoder.Encode(xComp, yComp, path, 128, 128);
|
return BlurHashEncoder.Encode(xComp, yComp, fileStream, 128, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RequiresSpecialCharacterHack(string path)
|
private bool RequiresSpecialCharacterHack(string path)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Extensions</PackageId>
|
<PackageId>Jellyfin.Extensions</PackageId>
|
||||||
<VersionPrefix>10.10.4</VersionPrefix>
|
<VersionPrefix>10.10.5</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>
|
||||||
|
|||||||
@@ -997,7 +997,9 @@ public class NetworkManager : INetworkManager, IDisposable
|
|||||||
// Get interface matching override subnet
|
// Get interface matching override subnet
|
||||||
var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(x => data.Data.Subnet.Contains(x.Address));
|
var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(x => data.Data.Subnet.Contains(x.Address));
|
||||||
|
|
||||||
if (intf?.Address is not null)
|
if (intf?.Address is not null
|
||||||
|
|| (data.Data.AddressFamily == AddressFamily.InterNetwork && data.Data.Address.Equals(IPAddress.Any))
|
||||||
|
|| (data.Data.AddressFamily == AddressFamily.InterNetworkV6 && data.Data.Address.Equals(IPAddress.IPv6Any)))
|
||||||
{
|
{
|
||||||
// If matching interface is found, use override
|
// If matching interface is found, use override
|
||||||
bindPreference = data.OverrideUri;
|
bindPreference = data.OverrideUri;
|
||||||
@@ -1025,6 +1027,7 @@ public class NetworkManager : INetworkManager, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("{Source}: Matching bind address override found: {Address}", source, bindPreference);
|
_logger.LogDebug("{Source}: Matching bind address override found: {Address}", source, bindPreference);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,7 +1065,7 @@ public class NetworkManager : INetworkManager, IDisposable
|
|||||||
// Check to see if any of the external bind interfaces are in the same subnet as the source.
|
// Check to see if any of the external bind interfaces are in the same subnet as the source.
|
||||||
// If none exists, this will select the first external interface if there is one.
|
// If none exists, this will select the first external interface if there is one.
|
||||||
bindAddress = externalInterfaces
|
bindAddress = externalInterfaces
|
||||||
.OrderByDescending(x => x.Subnet.Contains(source))
|
.OrderBy(x => x.Subnet.Contains(source))
|
||||||
.ThenBy(x => x.Index)
|
.ThenBy(x => x.Index)
|
||||||
.Select(x => x.Address)
|
.Select(x => x.Address)
|
||||||
.First();
|
.First();
|
||||||
@@ -1079,7 +1082,7 @@ public class NetworkManager : INetworkManager, IDisposable
|
|||||||
// Check to see if any of the internal bind interfaces are in the same subnet as the source.
|
// Check to see if any of the internal bind interfaces are in the same subnet as the source.
|
||||||
// If none exists, this will select the first internal interface if there is one.
|
// If none exists, this will select the first internal interface if there is one.
|
||||||
bindAddress = _interfaces.Where(x => IsInLocalNetwork(x.Address))
|
bindAddress = _interfaces.Where(x => IsInLocalNetwork(x.Address))
|
||||||
.OrderByDescending(x => x.Subnet.Contains(source))
|
.OrderBy(x => x.Subnet.Contains(source))
|
||||||
.ThenBy(x => x.Index)
|
.ThenBy(x => x.Index)
|
||||||
.Select(x => x.Address)
|
.Select(x => x.Address)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|||||||
+1
-1
@@ -84,7 +84,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
|
|||||||
await localizationManager.LoadAll();
|
await localizationManager.LoadAll();
|
||||||
var ratings = localizationManager.GetParentalRatings().ToList();
|
var ratings = localizationManager.GetParentalRatings().ToList();
|
||||||
|
|
||||||
Assert.Equal(54, ratings.Count);
|
Assert.Equal(56, ratings.Count);
|
||||||
|
|
||||||
var tvma = ratings.FirstOrDefault(x => x.Name.Equals("TV-MA", StringComparison.Ordinal));
|
var tvma = ratings.FirstOrDefault(x => x.Name.Equals("TV-MA", StringComparison.Ordinal));
|
||||||
Assert.NotNull(tvma);
|
Assert.NotNull(tvma);
|
||||||
|
|||||||
@@ -257,5 +257,23 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers
|
|||||||
|
|
||||||
Assert.Throws<ArgumentException>(() => _parser.Fetch(result, string.Empty, CancellationToken.None));
|
Assert.Throws<ArgumentException>(() => _parser.Fetch(result, string.Empty, CancellationToken.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Parsing_Fields_With_Escaped_Xml_Special_Characters_Success()
|
||||||
|
{
|
||||||
|
var result = new MetadataResult<Video>()
|
||||||
|
{
|
||||||
|
Item = new Movie()
|
||||||
|
};
|
||||||
|
|
||||||
|
_parser.Fetch(result, "Test Data/Lilo & Stitch.nfo", CancellationToken.None);
|
||||||
|
var item = (Movie)result.Item;
|
||||||
|
|
||||||
|
Assert.Equal("Lilo & Stitch", item.Name);
|
||||||
|
Assert.Equal("Lilo & Stitch", item.OriginalTitle);
|
||||||
|
Assert.Equal("Lilo & Stitch Collection", item.CollectionName);
|
||||||
|
Assert.StartsWith(">>", item.Overview, StringComparison.InvariantCulture);
|
||||||
|
Assert.EndsWith("<<", item.Overview, StringComparison.InvariantCulture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<movie>
|
||||||
|
<title>Lilo & Stitch</title>
|
||||||
|
<originaltitle>Lilo & Stitch</originaltitle>
|
||||||
|
<set>Lilo & Stitch Collection</set>
|
||||||
|
<plot>>>As Stitch, a runaway genetic experiment from a faraway planet, wreaks havoc on the Hawaiian Islands, he becomes the mischievous adopted alien "puppy" of an independent little girl named Lilo and learns about loyalty, friendship, and ʻohana, the Hawaiian tradition of family.<<</plot>
|
||||||
|
</movie>
|
||||||
Reference in New Issue
Block a user