Merge branch 'jellyfin:master' into BDMV-pgs
This commit is contained in:
@@ -173,10 +173,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
var validName = normalizeName ? GetItemByNameFolderName(name) : name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName);
|
||||
}
|
||||
|
||||
@@ -80,10 +80,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
var validName = normalizeName ? GetItemByNameFolderName(name) : name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.MusicGenrePath, validName);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,10 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public const string ThemeSongFileName = "theme";
|
||||
|
||||
// Well below the 255 byte limit of the common Linux filesystems and the 255 character limit
|
||||
// of Windows, so the files inside the folder still fit within MAX_PATH.
|
||||
private const int MaxItemByNameFolderNameBytes = 128;
|
||||
|
||||
/// <summary>
|
||||
/// The supported image extensions.
|
||||
/// </summary>
|
||||
@@ -941,6 +945,43 @@ namespace MediaBrowser.Controller.Entities
|
||||
return GetSortName(Name, EnableAlphaNumericSorting, ConfigurationManager.Configuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns an item-by-name entity's name into a folder name every supported filesystem accepts.
|
||||
/// </summary>
|
||||
/// <param name="name">The entity's name.</param>
|
||||
/// <returns>The folder name.</returns>
|
||||
public static string GetItemByNameFolderName(string name)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = FileSystem.GetValidFilename(name).Trim().TrimEnd('.');
|
||||
|
||||
// Most Linux filesystems cap a path component at 255 bytes, so a name past that cannot be
|
||||
// turned into a folder at all - and an entity with no folder can never be created, which
|
||||
// leaves the credit behind it stuck: not refreshable, not deletable, retried on every scan.
|
||||
// Only broken provider data gets this long, but it still has to resolve to something, so
|
||||
// keep a readable prefix and let a hash of the whole name tell two of them apart.
|
||||
if (Encoding.UTF8.GetByteCount(validName) <= MaxItemByNameFolderNameBytes)
|
||||
{
|
||||
return validName;
|
||||
}
|
||||
|
||||
var suffix = "-" + validName.GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
||||
var budget = MaxItemByNameFolderNameBytes - suffix.Length;
|
||||
var length = Math.Min(validName.Length, budget);
|
||||
while (length > 0 && Encoding.UTF8.GetByteCount(validName.AsSpan(0, length)) > budget)
|
||||
{
|
||||
length--;
|
||||
}
|
||||
|
||||
// Never cut a surrogate pair in half, the lone half is not a valid file name character.
|
||||
if (length > 0 && char.IsHighSurrogate(validName[length - 1]))
|
||||
{
|
||||
length--;
|
||||
}
|
||||
|
||||
return string.Concat(validName.AsSpan(0, length).TrimEnd().TrimEnd('.'), suffix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans a raw name into its sortable form by applying the configured sort rules.
|
||||
/// </summary>
|
||||
|
||||
@@ -83,10 +83,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
var validName = normalizeName ? GetItemByNameFolderName(name) : name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GenrePath, validName);
|
||||
}
|
||||
|
||||
@@ -98,10 +98,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validFilename = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
var validFilename = normalizeName ? GetItemByNameFolderName(name) : name;
|
||||
|
||||
string subFolderPrefix = null;
|
||||
|
||||
|
||||
@@ -78,10 +78,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
var validName = normalizeName ? GetItemByNameFolderName(name) : name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.StudioPath, validName);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
@@ -89,15 +90,14 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
|
||||
if (!string.IsNullOrEmpty(groupingKey))
|
||||
{
|
||||
return AppendPreferredLanguage(groupingKey);
|
||||
return AddLibrariesToPresentationUniqueKey(groupingKey);
|
||||
}
|
||||
}
|
||||
|
||||
return base.CreatePresentationUniqueKey();
|
||||
}
|
||||
|
||||
// The owning libraries are deliberately NOT part of the key.
|
||||
private string AppendPreferredLanguage(string key)
|
||||
private string AddLibrariesToPresentationUniqueKey(string key)
|
||||
{
|
||||
var lang = GetPreferredMetadataLanguage();
|
||||
if (!string.IsNullOrEmpty(lang))
|
||||
@@ -105,7 +105,17 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
key += "-" + lang;
|
||||
}
|
||||
|
||||
return key;
|
||||
var folders = LibraryManager.GetCollectionFolders(this)
|
||||
.Select(i => i.Id.ToString("N", CultureInfo.InvariantCulture))
|
||||
.Order(StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
|
||||
if (folders.Length == 0)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
return key + "-" + string.Join('-', folders);
|
||||
}
|
||||
|
||||
private string GetNameBasedGroupingKey()
|
||||
@@ -125,20 +135,19 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
var seriesKey = GetUniqueSeriesKey(this);
|
||||
|
||||
var result = LibraryManager.GetCount(new InternalItemsQuery(user)
|
||||
var result = LibraryManager.GetItemIds(new InternalItemsQuery(user)
|
||||
{
|
||||
AncestorWithPresentationUniqueKey = null,
|
||||
SeriesPresentationUniqueKey = seriesKey,
|
||||
IncludeItemTypes = new[] { BaseItemKind.Season },
|
||||
IsVirtualItem = false,
|
||||
Limit = 0,
|
||||
DtoOptions = new DtoOptions(false)
|
||||
{
|
||||
EnableImages = false
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
return result.Count;
|
||||
}
|
||||
|
||||
public override int GetRecursiveChildCount(User user)
|
||||
|
||||
@@ -85,10 +85,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public static string GetPath(string name, bool normalizeName)
|
||||
{
|
||||
// Trim the period at the end because windows will have a hard time with that
|
||||
var validName = normalizeName ?
|
||||
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
||||
name;
|
||||
var validName = normalizeName ? GetItemByNameFolderName(name) : name;
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.YearPath, validName);
|
||||
}
|
||||
|
||||
@@ -605,6 +605,12 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>List<System.String>.</returns>
|
||||
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes every credit that no item maps to any more.
|
||||
/// </summary>
|
||||
/// <returns>The number of credits that were deleted.</returns>
|
||||
int DeleteOrphanedCredits();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the distinct people names per item for multiple items.
|
||||
/// </summary>
|
||||
|
||||
@@ -1318,7 +1318,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
arg.Append(canvasArgs);
|
||||
}
|
||||
|
||||
arg.Append(" -i file:\"").Append(subtitlePath).Append('\"');
|
||||
arg.Append(" -i file:\"").Append(subtitlePath.EscapeProcessArgument()).Append('\"');
|
||||
}
|
||||
|
||||
if (state.AudioStream is not null && state.AudioStream.IsExternal)
|
||||
@@ -1330,7 +1330,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
arg.Append(' ').Append(seekAudioParam);
|
||||
}
|
||||
|
||||
arg.Append(" -i \"").Append(state.AudioStream.Path).Append('"');
|
||||
arg.Append(" -i \"").Append(state.AudioStream.Path.EscapeProcessArgument()).Append('"');
|
||||
}
|
||||
|
||||
// Disable auto inserted SW scaler for HW decoders in case of changed resolution.
|
||||
|
||||
@@ -33,6 +33,12 @@ public interface IPeopleRepository
|
||||
/// <returns>The list of people names matching the filter.</returns>
|
||||
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes every credit that no item maps to any more.
|
||||
/// </summary>
|
||||
/// <returns>The number of credits that were deleted.</returns>
|
||||
int DeleteOrphanedCredits();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the distinct people names per item for multiple items efficiently by querying from the mapping table.
|
||||
/// </summary>
|
||||
|
||||
@@ -16,11 +16,6 @@ namespace MediaBrowser.Controller.Providers
|
||||
private List<(string Url, ImageType Type)> _remoteImages;
|
||||
private List<PersonInfo> _people;
|
||||
|
||||
public MetadataResult()
|
||||
{
|
||||
ResultLanguage = "en";
|
||||
}
|
||||
|
||||
public List<LocalImageInfo> Images
|
||||
{
|
||||
get => _images ??= [];
|
||||
@@ -43,6 +38,9 @@ namespace MediaBrowser.Controller.Providers
|
||||
|
||||
public T Item { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the language the fetched metadata is in.
|
||||
/// </summary>
|
||||
public string ResultLanguage { get; set; }
|
||||
|
||||
public string Provider { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user