mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-20 00:55:13 +01:00
Merge branch 'master' into h265
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when an attempt to authenticate fails.
|
||||
/// </summary>
|
||||
public class AuthenticationException : Exception
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public AuthenticationException() : base()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public AuthenticationException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public AuthenticationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,10 @@ namespace MediaBrowser.Controller.Authentication
|
||||
string Name { get; }
|
||||
bool IsEnabled { get; }
|
||||
Task<ProviderAuthenticationResult> Authenticate(string username, string password);
|
||||
Task<bool> HasPassword(User user);
|
||||
bool HasPassword(User user);
|
||||
Task ChangePassword(User user, string newPassword);
|
||||
void ChangeEasyPassword(User user, string newPassword, string newPasswordHash);
|
||||
string GetEasyPasswordHash(User user);
|
||||
}
|
||||
|
||||
public interface IRequiresResolvedUser
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace MediaBrowser.Controller.Authentication
|
||||
Task<ForgotPasswordResult> StartForgotPasswordProcess(User user, bool isInNetwork);
|
||||
Task<PinRedeemResult> RedeemPasswordResetPin(string pin);
|
||||
}
|
||||
|
||||
public class PasswordPinCreationResult
|
||||
{
|
||||
public string PinFile { get; set; }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using MediaBrowser.Common.Progress;
|
||||
@@ -14,14 +15,14 @@ namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
if (user.Policy.BlockedChannels != null)
|
||||
{
|
||||
if (user.Policy.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
|
||||
if (user.Policy.BlockedChannels.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!user.Policy.EnableAllChannels && !user.Policy.EnabledChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
|
||||
if (!user.Policy.EnableAllChannels && !user.Policy.EnabledChannels.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -60,7 +61,7 @@ namespace MediaBrowser.Controller.Channels
|
||||
|
||||
public static string GetInternalMetadataPath(string basePath, Guid id)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata");
|
||||
return System.IO.Path.Combine(basePath, "channels", id.ToString("N", CultureInfo.InvariantCulture), "metadata");
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
|
||||
@@ -17,16 +17,6 @@ namespace MediaBrowser.Controller.Drawing
|
||||
/// <value>The supported output formats.</value>
|
||||
IReadOnlyCollection<ImageFormat> SupportedOutputFormats { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the image.
|
||||
/// </summary>
|
||||
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the image collage.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
void CreateImageCollage(ImageCollageOptions options);
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
@@ -46,5 +36,16 @@ namespace MediaBrowser.Controller.Drawing
|
||||
bool SupportsImageEncoding { get; }
|
||||
|
||||
ImageDimensions GetImageSize(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the image.
|
||||
/// </summary>
|
||||
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the image collage.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
void CreateImageCollage(ImageCollageOptions options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,15 @@ namespace MediaBrowser.Controller.Drawing
|
||||
/// Gets the image enhancers.
|
||||
/// </summary>
|
||||
/// <value>The image enhancers.</value>
|
||||
IImageEnhancer[] ImageEnhancers { get; }
|
||||
IReadOnlyCollection<IImageEnhancer> ImageEnhancers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [supports image collage creation].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value>
|
||||
bool SupportsImageCollageCreation { get; }
|
||||
|
||||
IImageEncoder ImageEncoder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dimensions of the image.
|
||||
@@ -50,19 +58,13 @@ namespace MediaBrowser.Controller.Drawing
|
||||
/// <returns>ImageDimensions</returns>
|
||||
ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info, bool updateItem);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the parts.
|
||||
/// </summary>
|
||||
/// <param name="enhancers">The enhancers.</param>
|
||||
void AddParts(IEnumerable<IImageEnhancer> enhancers);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported enhancers.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <returns>IEnumerable{IImageEnhancer}.</returns>
|
||||
IImageEnhancer[] GetSupportedEnhancers(BaseItem item, ImageType imageType);
|
||||
IEnumerable<IImageEnhancer> GetSupportedEnhancers(BaseItem item, ImageType imageType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image cache tag.
|
||||
@@ -80,7 +82,7 @@ namespace MediaBrowser.Controller.Drawing
|
||||
/// <param name="image">The image.</param>
|
||||
/// <param name="imageEnhancers">The image enhancers.</param>
|
||||
/// <returns>Guid.</returns>
|
||||
string GetImageCacheTag(BaseItem item, ItemImageInfo image, IImageEnhancer[] imageEnhancers);
|
||||
string GetImageCacheTag(BaseItem item, ItemImageInfo image, IReadOnlyCollection<IImageEnhancer> imageEnhancers);
|
||||
|
||||
/// <summary>
|
||||
/// Processes the image.
|
||||
@@ -109,7 +111,7 @@ namespace MediaBrowser.Controller.Drawing
|
||||
/// <summary>
|
||||
/// Gets the supported image output formats.
|
||||
/// </summary>
|
||||
/// <returns>IReadOnlyCollection{ImageOutput}.</returns>
|
||||
/// <returns><see cref="IReadOnlyCollection{ImageOutput}" />.</returns>
|
||||
IReadOnlyCollection<ImageFormat> GetSupportedImageOutputFormats();
|
||||
|
||||
/// <summary>
|
||||
@@ -118,14 +120,6 @@ namespace MediaBrowser.Controller.Drawing
|
||||
/// <param name="options">The options.</param>
|
||||
void CreateImageCollage(ImageCollageOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [supports image collage creation].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value>
|
||||
bool SupportsImageCollageCreation { get; }
|
||||
|
||||
IImageEncoder ImageEncoder { get; set; }
|
||||
|
||||
bool SupportsTransparency(string path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
@@ -33,9 +34,9 @@ namespace MediaBrowser.Controller.Drawing
|
||||
|
||||
public int Quality { get; set; }
|
||||
|
||||
public IImageEnhancer[] Enhancers { get; set; }
|
||||
public IReadOnlyCollection<IImageEnhancer> Enhancers { get; set; }
|
||||
|
||||
public ImageFormat[] SupportedOutputFormats { get; set; }
|
||||
public IReadOnlyCollection<ImageFormat> SupportedOutputFormats { get; set; }
|
||||
|
||||
public bool AddPlayedIndicator { get; set; }
|
||||
|
||||
|
||||
@@ -503,7 +503,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
foreach (var folder in collectionFolders)
|
||||
{
|
||||
if (allowed.Contains(folder.Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
|
||||
if (allowed.Contains(folder.Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -664,10 +664,10 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
if (SourceType == SourceType.Channel)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "channels", ChannelId.ToString("N"), Id.ToString("N"));
|
||||
return System.IO.Path.Combine(basePath, "channels", ChannelId.ToString("N", CultureInfo.InvariantCulture), Id.ToString("N", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
var idString = Id.ToString("N");
|
||||
var idString = Id.ToString("N", CultureInfo.InvariantCulture);
|
||||
|
||||
basePath = System.IO.Path.Combine(basePath, "library");
|
||||
|
||||
@@ -1095,7 +1095,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var info = new MediaSourceInfo
|
||||
{
|
||||
Id = item.Id.ToString("N"),
|
||||
Id = item.Id.ToString("N", CultureInfo.InvariantCulture),
|
||||
Protocol = protocol ?? MediaProtocol.File,
|
||||
MediaStreams = MediaSourceManager.GetMediaStreams(item.Id),
|
||||
Name = GetMediaSourceName(item),
|
||||
@@ -1113,7 +1113,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
if (info.Protocol == MediaProtocol.File)
|
||||
{
|
||||
info.ETag = item.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
|
||||
info.ETag = item.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
var video = item as Video;
|
||||
@@ -1626,7 +1626,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public virtual string CreatePresentationUniqueKey()
|
||||
{
|
||||
return Id.ToString("N");
|
||||
return Id.ToString("N", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
@@ -2736,7 +2736,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var list = GetEtagValues(user);
|
||||
|
||||
return string.Join("|", list.ToArray()).GetMD5().ToString("N");
|
||||
return string.Join("|", list.ToArray()).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
protected virtual List<string> GetEtagValues(User user)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -177,7 +178,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
if (user.Policy.BlockedMediaFolders != null)
|
||||
{
|
||||
if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) ||
|
||||
if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase) ||
|
||||
|
||||
// Backwards compatibility
|
||||
user.Policy.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
|
||||
@@ -187,7 +188,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
|
||||
if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
@@ -29,7 +30,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
if (string.IsNullOrEmpty(child.Path))
|
||||
{
|
||||
child.LibraryItemId = item.Id.ToString("N");
|
||||
child.LibraryItemId = item.Id.ToString("N", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
return child;
|
||||
@@ -37,7 +38,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public LinkedChild()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString("N");
|
||||
Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -91,7 +92,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
}
|
||||
|
||||
var folders = LibraryManager.GetCollectionFolders(this)
|
||||
.Select(i => i.Id.ToString("N"))
|
||||
.Select(i => i.Id.ToString("N", CultureInfo.InvariantCulture))
|
||||
.ToArray();
|
||||
|
||||
if (folders.Length == 0)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -16,13 +17,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
public class User : BaseItem
|
||||
{
|
||||
public static IUserManager UserManager { get; set; }
|
||||
public static IXmlSerializer XmlSerializer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// From now on all user paths will be Id-based.
|
||||
/// This is for backwards compatibility.
|
||||
/// </summary>
|
||||
public bool UsesIdForConfigurationPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the password.
|
||||
@@ -30,7 +24,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <value>The password.</value>
|
||||
public string Password { get; set; }
|
||||
public string EasyPassword { get; set; }
|
||||
public string Salt { get; set; }
|
||||
|
||||
// Strictly to remove IgnoreDataMember
|
||||
public override ItemImageInfo[] ImageInfos
|
||||
@@ -147,46 +140,23 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public Task Rename(string newName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(newName))
|
||||
if (string.IsNullOrWhiteSpace(newName))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(newName));
|
||||
}
|
||||
|
||||
// If only the casing is changing, leave the file system alone
|
||||
if (!UsesIdForConfigurationPath && !string.Equals(newName, Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
UsesIdForConfigurationPath = true;
|
||||
|
||||
// Move configuration
|
||||
var newConfigDirectory = GetConfigurationDirectoryPath(newName);
|
||||
var oldConfigurationDirectory = ConfigurationDirectoryPath;
|
||||
|
||||
// Exceptions will be thrown if these paths already exist
|
||||
if (Directory.Exists(newConfigDirectory))
|
||||
{
|
||||
Directory.Delete(newConfigDirectory, true);
|
||||
}
|
||||
|
||||
if (Directory.Exists(oldConfigurationDirectory))
|
||||
{
|
||||
Directory.Move(oldConfigurationDirectory, newConfigDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.CreateDirectory(newConfigDirectory);
|
||||
}
|
||||
throw new ArgumentException("Username can't be empty", nameof(newName));
|
||||
}
|
||||
|
||||
Name = newName;
|
||||
|
||||
return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem))
|
||||
{
|
||||
ReplaceAllMetadata = true,
|
||||
ImageRefreshMode = MetadataRefreshMode.FullRefresh,
|
||||
MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
|
||||
ForceSave = true
|
||||
return RefreshMetadata(
|
||||
new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem))
|
||||
{
|
||||
ReplaceAllMetadata = true,
|
||||
ImageRefreshMode = MetadataRefreshMode.FullRefresh,
|
||||
MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
|
||||
ForceSave = true
|
||||
|
||||
}, CancellationToken.None);
|
||||
},
|
||||
CancellationToken.None);
|
||||
}
|
||||
|
||||
public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
|
||||
@@ -215,20 +185,15 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var parentPath = ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath;
|
||||
|
||||
// Legacy
|
||||
if (!UsesIdForConfigurationPath)
|
||||
// TODO: Remove idPath and just use usernamePath for future releases
|
||||
var usernamePath = System.IO.Path.Combine(parentPath, username);
|
||||
var idPath = System.IO.Path.Combine(parentPath, Id.ToString("N", CultureInfo.InvariantCulture));
|
||||
if (!Directory.Exists(usernamePath) && Directory.Exists(idPath))
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(username));
|
||||
}
|
||||
|
||||
var safeFolderName = FileSystem.GetValidFilename(username);
|
||||
|
||||
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName);
|
||||
Directory.Move(idPath, usernamePath);
|
||||
}
|
||||
|
||||
return System.IO.Path.Combine(parentPath, Id.ToString("N"));
|
||||
return usernamePath;
|
||||
}
|
||||
|
||||
public bool IsParentalScheduleAllowed()
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Playlists;
|
||||
using MediaBrowser.Controller.TV;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
@@ -17,7 +16,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
public static ITVSeriesManager TVSeriesManager;
|
||||
public static IPlaylistManager PlaylistManager;
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string CollectionType => ViewType;
|
||||
@@ -38,6 +36,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
list.Add(Id);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -65,7 +64,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
|
||||
}
|
||||
|
||||
return new UserViewBuilder(UserViewManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager, PlaylistManager)
|
||||
return new UserViewBuilder(UserViewManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager)
|
||||
.GetUserItems(parent, this, CollectionType, query);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Playlists;
|
||||
using MediaBrowser.Controller.TV;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
@@ -21,9 +21,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
private readonly IUserDataManager _userDataManager;
|
||||
private readonly ITVSeriesManager _tvSeriesManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IPlaylistManager _playlistManager;
|
||||
|
||||
public UserViewBuilder(IUserViewManager userViewManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, IServerConfigurationManager config, IPlaylistManager playlistManager)
|
||||
public UserViewBuilder(
|
||||
IUserViewManager userViewManager,
|
||||
ILibraryManager libraryManager,
|
||||
ILogger logger,
|
||||
IUserDataManager userDataManager,
|
||||
ITVSeriesManager tvSeriesManager,
|
||||
IServerConfigurationManager config)
|
||||
{
|
||||
_userViewManager = userViewManager;
|
||||
_libraryManager = libraryManager;
|
||||
@@ -31,7 +36,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
_userDataManager = userDataManager;
|
||||
_tvSeriesManager = tvSeriesManager;
|
||||
_config = config;
|
||||
_playlistManager = playlistManager;
|
||||
}
|
||||
|
||||
public QueryResult<BaseItem> GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query)
|
||||
@@ -110,6 +114,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return GetResult(GetMediaFolders(user).OfType<Folder>().SelectMany(i => i.GetChildren(user, true)), queryParent, query);
|
||||
}
|
||||
|
||||
return queryParent.GetItems(query);
|
||||
}
|
||||
}
|
||||
@@ -983,7 +988,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private UserView GetUserViewWithName(string name, string type, string sortName, BaseItem parent)
|
||||
{
|
||||
return _userViewManager.GetUserSubView(parent.Id, parent.Id.ToString("N"), type, sortName);
|
||||
return _userViewManager.GetUserSubView(parent.Id, parent.Id.ToString("N", CultureInfo.InvariantCulture), type, sortName);
|
||||
}
|
||||
|
||||
private UserView GetUserView(string type, string localizationKey, string sortName, BaseItem parent)
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Services;
|
||||
|
||||
namespace MediaBrowser.Controller
|
||||
{
|
||||
public interface IResourceFileManager
|
||||
{
|
||||
Task<object> GetStaticFileResult(IRequest request, string basePath, string virtualPath, string contentType, TimeSpan? cacheDuration);
|
||||
|
||||
Stream GetResourceFileStream(string basePath, string virtualPath);
|
||||
|
||||
string ReadAllText(string basePath, string virtualPath);
|
||||
string GetResourcePath(string basePath, string virtualPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.System;
|
||||
|
||||
namespace MediaBrowser.Controller
|
||||
@@ -59,7 +59,7 @@ namespace MediaBrowser.Controller
|
||||
/// Gets the local ip address.
|
||||
/// </summary>
|
||||
/// <value>The local ip address.</value>
|
||||
Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken);
|
||||
Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local API URL.
|
||||
@@ -77,13 +77,13 @@ namespace MediaBrowser.Controller
|
||||
/// <summary>
|
||||
/// Gets the local API URL.
|
||||
/// </summary>
|
||||
string GetLocalApiUrl(IpAddressInfo address);
|
||||
string GetLocalApiUrl(IPAddress address);
|
||||
|
||||
void LaunchUrl(string url);
|
||||
|
||||
void EnableLoopback(string appName);
|
||||
|
||||
WakeOnLanInfo[] GetWakeOnLanInfo();
|
||||
IEnumerable<WakeOnLanInfo> GetWakeOnLanInfo();
|
||||
|
||||
string ExpandVirtualPath(string path);
|
||||
string ReverseVirtualPath(string path);
|
||||
|
||||
@@ -22,6 +22,12 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <value>The users.</value>
|
||||
IEnumerable<User> Users { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user ids.
|
||||
/// </summary>
|
||||
/// <value>The users ids.</value>
|
||||
IEnumerable<Guid> UsersIds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [user updated].
|
||||
/// </summary>
|
||||
@@ -92,7 +98,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>User.</returns>
|
||||
/// <exception cref="ArgumentNullException">name</exception>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
Task<User> CreateUser(string name);
|
||||
User CreateUser(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the user.
|
||||
@@ -101,7 +107,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="ArgumentNullException">user</exception>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
Task DeleteUser(User user);
|
||||
void DeleteUser(User user);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the password.
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
|
||||
var info = new MediaSourceInfo
|
||||
{
|
||||
Id = Id.ToString("N"),
|
||||
Id = Id.ToString("N", CultureInfo.InvariantCulture),
|
||||
Protocol = PathProtocol ?? MediaProtocol.File,
|
||||
MediaStreams = new List<MediaStream>(),
|
||||
Name = Name,
|
||||
@@ -111,7 +111,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata");
|
||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N", CultureInfo.InvariantCulture), "metadata");
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
@@ -188,7 +189,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
|
||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
public override bool CanDelete()
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -613,7 +613,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
|
||||
// TODO: Perhaps also use original_size=1920x800 ??
|
||||
return string.Format("subtitles=filename='{0}'{1}{2}{3}",
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"subtitles=filename='{0}'{1}{2}",
|
||||
_mediaEncoder.EscapeSubtitleFilterPath(subtitlePath),
|
||||
charsetParam,
|
||||
// fallbackFontParam,
|
||||
@@ -622,7 +624,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
var mediaPath = state.MediaPath ?? string.Empty;
|
||||
|
||||
return string.Format("subtitles='{0}:si={1}'{2}",
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"subtitles='{0}:si={1}'{2}",
|
||||
_mediaEncoder.EscapeSubtitleFilterPath(mediaPath),
|
||||
state.InternalSubtitleStreamOffset.ToString(_usCulture),
|
||||
// fallbackFontParam,
|
||||
@@ -1135,27 +1139,51 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
var bitrate = request.VideoBitRate;
|
||||
|
||||
// If specific values were requested, then force the caller to supply a bitrate as well
|
||||
if (request.Height.HasValue && request.Width.HasValue)
|
||||
{
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
if (videoStream != null)
|
||||
{
|
||||
if (bitrate.HasValue)
|
||||
{
|
||||
var inputVideoCodec = videoStream.Codec;
|
||||
bitrate = ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
|
||||
var isUpscaling = request.Height.HasValue && videoStream.Height.HasValue &&
|
||||
request.Height.Value > videoStream.Height.Value && request.Width.HasValue && videoStream.Width.HasValue &&
|
||||
request.Width.Value > videoStream.Width.Value;
|
||||
|
||||
// If a max bitrate was requested, don't let the scaled bitrate exceed it
|
||||
if (request.VideoBitRate.HasValue)
|
||||
// Don't allow bitrate increases unless upscaling
|
||||
if (!isUpscaling)
|
||||
{
|
||||
if (bitrate.HasValue && videoStream.BitRate.HasValue)
|
||||
{
|
||||
bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
|
||||
bitrate = GetMinBitrate(videoStream.BitRate.Value, bitrate.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bitrate.HasValue)
|
||||
{
|
||||
var inputVideoCodec = videoStream.Codec;
|
||||
bitrate = ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
|
||||
|
||||
// If a max bitrate was requested, don't let the scaled bitrate exceed it
|
||||
if (request.VideoBitRate.HasValue)
|
||||
{
|
||||
bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
private int GetMinBitrate(int sourceBitrate, int requestedBitrate)
|
||||
{
|
||||
// these values were chosen from testing to improve low bitrate streams
|
||||
if (sourceBitrate <= 2000000)
|
||||
{
|
||||
sourceBitrate = Convert.ToInt32(sourceBitrate * 2.5);
|
||||
}
|
||||
else if (sourceBitrate <= 3000000)
|
||||
{
|
||||
sourceBitrate = Convert.ToInt32(sourceBitrate * 2);
|
||||
}
|
||||
|
||||
var bitrate = Math.Min(sourceBitrate, requestedBitrate);
|
||||
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
|
||||
@@ -374,14 +374,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (AudioStream != null)
|
||||
{
|
||||
return AudioStream.SampleRate;
|
||||
}
|
||||
}
|
||||
|
||||
else if (BaseRequest.AudioSampleRate.HasValue)
|
||||
{
|
||||
// Don't exceed what the encoder supports
|
||||
@@ -397,7 +397,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (AudioStream != null)
|
||||
{
|
||||
@@ -405,13 +406,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
}
|
||||
|
||||
//else if (BaseRequest.AudioSampleRate.HasValue)
|
||||
//{
|
||||
// // Don't exceed what the encoder supports
|
||||
// // Seeing issues of attempting to encode to 88200
|
||||
// return Math.Min(44100, BaseRequest.AudioSampleRate.Value);
|
||||
//}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -446,7 +440,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VideoStream?.BitDepth;
|
||||
}
|
||||
@@ -463,7 +458,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VideoStream?.RefFrames;
|
||||
}
|
||||
@@ -479,7 +475,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VideoStream == null ? null : (VideoStream.AverageFrameRate ?? VideoStream.RealFrameRate);
|
||||
}
|
||||
@@ -545,7 +542,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VideoStream?.CodecTag;
|
||||
}
|
||||
@@ -558,7 +556,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VideoStream?.IsAnamorphic;
|
||||
}
|
||||
@@ -571,14 +570,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
var codec = OutputVideoCodec;
|
||||
|
||||
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VideoStream?.Codec;
|
||||
}
|
||||
|
||||
return codec;
|
||||
return OutputVideoCodec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,14 +583,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
var codec = OutputAudioCodec;
|
||||
|
||||
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return AudioStream?.Codec;
|
||||
}
|
||||
|
||||
return codec;
|
||||
return OutputAudioCodec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +596,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BaseRequest.Static || string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
if (BaseRequest.Static
|
||||
|| string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VideoStream?.IsInterlaced;
|
||||
}
|
||||
@@ -636,6 +632,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue);
|
||||
}
|
||||
|
||||
return GetMediaStreamCount(MediaStreamType.Video, 1);
|
||||
}
|
||||
}
|
||||
@@ -648,17 +645,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue);
|
||||
}
|
||||
|
||||
return GetMediaStreamCount(MediaStreamType.Audio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public int HlsListSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public int HlsListSize => 0;
|
||||
|
||||
private int? GetMediaStreamCount(MediaStreamType type, int limit)
|
||||
{
|
||||
@@ -677,10 +669,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
Progress.Report(percentComplete.Value);
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -18,10 +19,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async void StartStreamingLog(EncodingJobInfo state, Stream source, Stream target)
|
||||
public async Task StartStreamingLog(EncodingJobInfo state, Stream source, Stream target)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (target)
|
||||
using (var reader = new StreamReader(source))
|
||||
{
|
||||
while (!reader.EndOfStream && reader.BaseStream.CanRead)
|
||||
@@ -97,8 +99,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
var currentMs = startMs + val.TotalMilliseconds;
|
||||
|
||||
var percentVal = currentMs / totalMs;
|
||||
percent = 100 * percentVal;
|
||||
percent = 100.0 * currentMs / totalMs;
|
||||
|
||||
transcodingPosition = val;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using MediaBrowser.Model.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace MediaBrowser.Controller.Net
|
||||
{
|
||||
@@ -33,7 +34,7 @@ namespace MediaBrowser.Controller.Net
|
||||
/// <param name="request">The http request wrapper</param>
|
||||
/// <param name="response">The http response wrapper</param>
|
||||
/// <param name="requestDto">The request DTO</param>
|
||||
public void RequestFilter(IRequest request, IResponse response, object requestDto)
|
||||
public void RequestFilter(IRequest request, HttpResponse response, object requestDto)
|
||||
{
|
||||
AuthService.Authenticate(request, this);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace MediaBrowser.Controller.Net
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public Task ProcessMessage(WebSocketMessageInfo message)
|
||||
public Task ProcessMessageAsync(WebSocketMessageInfo message)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
@@ -74,7 +74,7 @@ namespace MediaBrowser.Controller.Net
|
||||
Stop(message);
|
||||
}
|
||||
|
||||
return Task.FromResult(true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
@@ -12,6 +12,6 @@ namespace MediaBrowser.Controller.Net
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task ProcessMessage(WebSocketMessageInfo message);
|
||||
Task ProcessMessageAsync(WebSocketMessageInfo message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -239,7 +240,7 @@ namespace MediaBrowser.Controller.Playlists
|
||||
return base.IsVisible(user);
|
||||
}
|
||||
|
||||
var userId = user.Id.ToString("N");
|
||||
var userId = user.Id.ToString("N", CultureInfo.InvariantCulture);
|
||||
foreach (var share in shares)
|
||||
{
|
||||
if (string.Equals(share.UserId, userId, StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
@@ -55,7 +56,7 @@ namespace MediaBrowser.Controller.Providers
|
||||
|
||||
foreach (var i in UserDataList)
|
||||
{
|
||||
if (string.Equals(userId, i.UserId.ToString("N"), StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(userId, i.UserId.ToString("N", CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
userData = i;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,12 @@ namespace MediaBrowser.Controller.Resolvers
|
||||
/// </summary>
|
||||
public interface IResolverIgnoreRule
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks whether or not the file should be ignored.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo">The file information.</param>
|
||||
/// <param name="parent">The parent BaseItem.</param>
|
||||
/// <returns>True if the file should be ignored.</returns>
|
||||
bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user