mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-20 09:04:42 +01:00
add more methods to file system interface
This commit is contained in:
@@ -37,8 +37,10 @@ namespace MediaBrowser.Controller.Drawing
|
||||
|
||||
public bool AddPlayedIndicator { get; set; }
|
||||
|
||||
public int? PercentPlayed { get; set; }
|
||||
public int? UnplayedCount { get; set; }
|
||||
|
||||
public double? PercentPlayed { get; set; }
|
||||
|
||||
public string BackgroundColor { get; set; }
|
||||
|
||||
public bool HasDefaultOptions()
|
||||
@@ -56,6 +58,7 @@ namespace MediaBrowser.Controller.Drawing
|
||||
IsOutputFormatDefault &&
|
||||
!AddPlayedIndicator &&
|
||||
!PercentPlayed.HasValue &&
|
||||
!UnplayedCount.HasValue &&
|
||||
string.IsNullOrEmpty(BackgroundColor);
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
public DateTime DateModified { get; set; }
|
||||
|
||||
public DateTime DateLastSaved { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The logger
|
||||
/// </summary>
|
||||
@@ -327,21 +327,18 @@ namespace MediaBrowser.Controller.Entities
|
||||
// When resolving the root, we need it's grandchildren (children of user views)
|
||||
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
|
||||
|
||||
args.FileSystemDictionary = FileData.GetFilteredFileSystemEntries(args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
|
||||
var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
|
||||
|
||||
// Need to remove subpaths that may have been resolved from shortcuts
|
||||
// Example: if \\server\movies exists, then strip out \\server\movies\action
|
||||
if (isPhysicalRoot)
|
||||
{
|
||||
var paths = args.FileSystemDictionary.Keys.ToList();
|
||||
var paths = LibraryManager.NormalizeRootPathList(fileSystemDictionary.Keys);
|
||||
|
||||
foreach (var subPath in paths
|
||||
.Where(subPath => !subPath.EndsWith(":\\", StringComparison.OrdinalIgnoreCase) && paths.Any(i => subPath.StartsWith(i.TrimEnd(System.IO.Path.DirectorySeparatorChar) + System.IO.Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))))
|
||||
{
|
||||
Logger.Info("Ignoring duplicate path: {0}", subPath);
|
||||
args.FileSystemDictionary.Remove(subPath);
|
||||
}
|
||||
fileSystemDictionary = paths.Select(i => (FileSystemInfo)new DirectoryInfo(i)).ToDictionary(i => i.FullName);
|
||||
}
|
||||
|
||||
args.FileSystemDictionary = fileSystemDictionary;
|
||||
}
|
||||
|
||||
//update our dates
|
||||
@@ -1016,14 +1013,18 @@ namespace MediaBrowser.Controller.Entities
|
||||
return lang;
|
||||
}
|
||||
|
||||
public virtual bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return ConfigurationManager.Configuration.SaveLocalMeta;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a given user has access to this item
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="localizationManager">The localization manager.</param>
|
||||
/// <returns><c>true</c> if [is parental allowed] [the specified user]; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">user</exception>
|
||||
public bool IsParentalAllowed(User user, ILocalizationManager localizationManager)
|
||||
public bool IsParentalAllowed(User user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
@@ -1049,7 +1050,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return !GetBlockUnratedValue(user.Configuration);
|
||||
}
|
||||
|
||||
var value = localizationManager.GetRatingLevel(rating);
|
||||
var value = LocalizationManager.GetRatingLevel(rating);
|
||||
|
||||
// Could not determine the integer value
|
||||
if (!value.HasValue)
|
||||
@@ -1084,7 +1085,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
return IsParentalAllowed(user, LocalizationManager);
|
||||
return IsParentalAllowed(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -519,80 +519,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
Tuple<BaseItem, bool> currentTuple = tuple;
|
||||
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var child = currentTuple.Item1;
|
||||
try
|
||||
{
|
||||
//refresh it
|
||||
await child.RefreshMetadata(cancellationToken, forceSave: currentTuple.Item2, forceRefresh: forceRefreshMetadata, resetResolveArgs: false).ConfigureAwait(false);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.ErrorException("Error refreshing {0}", ex, child.Path ?? child.Name);
|
||||
}
|
||||
|
||||
// Refresh children if a folder and the item changed or recursive is set to true
|
||||
var refreshChildren = child.IsFolder && (currentTuple.Item2 || (recursive.HasValue && recursive.Value));
|
||||
|
||||
if (refreshChildren)
|
||||
{
|
||||
// Don't refresh children if explicitly set to false
|
||||
if (recursive.HasValue && recursive.Value == false)
|
||||
{
|
||||
refreshChildren = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshChildren)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var innerProgress = new ActionableProgress<double>();
|
||||
|
||||
innerProgress.RegisterAction(p =>
|
||||
{
|
||||
lock (percentages)
|
||||
{
|
||||
percentages[child.Id] = p / 100;
|
||||
|
||||
var percent = percentages.Values.Sum();
|
||||
percent /= list.Count;
|
||||
|
||||
progress.Report((90 * percent) + 10);
|
||||
}
|
||||
});
|
||||
|
||||
await ((Folder)child).ValidateChildren(innerProgress, cancellationToken, recursive, forceRefreshMetadata).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
// Some folder providers are unable to refresh until children have been refreshed.
|
||||
await child.RefreshMetadata(cancellationToken, resetResolveArgs: false).ConfigureAwait(false);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.ErrorException("Error refreshing {0}", ex, child.Path ?? child.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (percentages)
|
||||
{
|
||||
percentages[child.Id] = 1;
|
||||
|
||||
var percent = percentages.Values.Sum();
|
||||
percent /= list.Count;
|
||||
|
||||
progress.Report((90 * percent) + 10);
|
||||
}
|
||||
}
|
||||
|
||||
}, cancellationToken));
|
||||
tasks.Add(RefreshChild(tuple, progress, percentages, list.Count, cancellationToken, recursive, forceRefreshMetadata));
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -600,6 +527,78 @@ namespace MediaBrowser.Controller.Entities
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task RefreshChild(Tuple<BaseItem, bool> currentTuple, IProgress<double> progress, Dictionary<Guid, double> percentages, int childCount, CancellationToken cancellationToken, bool? recursive, bool forceRefreshMetadata = false)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var child = currentTuple.Item1;
|
||||
try
|
||||
{
|
||||
//refresh it
|
||||
await child.RefreshMetadata(cancellationToken, forceSave: currentTuple.Item2, forceRefresh: forceRefreshMetadata, resetResolveArgs: false).ConfigureAwait(false);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.ErrorException("Error refreshing {0}", ex, child.Path ?? child.Name);
|
||||
}
|
||||
|
||||
// Refresh children if a folder and the item changed or recursive is set to true
|
||||
var refreshChildren = child.IsFolder && (currentTuple.Item2 || (recursive.HasValue && recursive.Value));
|
||||
|
||||
if (refreshChildren)
|
||||
{
|
||||
// Don't refresh children if explicitly set to false
|
||||
if (recursive.HasValue && recursive.Value == false)
|
||||
{
|
||||
refreshChildren = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshChildren)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var innerProgress = new ActionableProgress<double>();
|
||||
|
||||
innerProgress.RegisterAction(p =>
|
||||
{
|
||||
lock (percentages)
|
||||
{
|
||||
percentages[child.Id] = p / 100;
|
||||
|
||||
var percent = percentages.Values.Sum();
|
||||
percent /= childCount;
|
||||
|
||||
progress.Report((90 * percent) + 10);
|
||||
}
|
||||
});
|
||||
|
||||
await ((Folder)child).ValidateChildren(innerProgress, cancellationToken, recursive, forceRefreshMetadata).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
// Some folder providers are unable to refresh until children have been refreshed.
|
||||
await child.RefreshMetadata(cancellationToken, resetResolveArgs: false).ConfigureAwait(false);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.ErrorException("Error refreshing {0}", ex, child.Path ?? child.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (percentages)
|
||||
{
|
||||
percentages[child.Id] = 1;
|
||||
|
||||
var percent = percentages.Values.Sum();
|
||||
percent /= childCount;
|
||||
|
||||
progress.Report((90 * percent) + 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified path is offline.
|
||||
/// </summary>
|
||||
@@ -646,7 +645,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private bool ContainsPath(string parent, string path)
|
||||
{
|
||||
return string.Equals(parent, path, StringComparison.OrdinalIgnoreCase) || path.IndexOf(parent.TrimEnd(System.IO.Path.DirectorySeparatorChar) + System.IO.Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) != -1;
|
||||
return string.Equals(parent, path, StringComparison.OrdinalIgnoreCase) || FileSystem.ContainsSubPath(parent, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// Gets the path.
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
string Path { get; }
|
||||
|
||||
string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the identifier.
|
||||
/// </summary>
|
||||
@@ -100,7 +100,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return item.HasImage(imageType, 0);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the image path.
|
||||
/// </summary>
|
||||
|
||||
@@ -320,5 +320,12 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <param name="items">The items.</param>
|
||||
/// <returns>IEnumerable{System.String}.</returns>
|
||||
IEnumerable<string> GetAllArtists(IEnumerable<BaseItem> items);
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the root path list.
|
||||
/// </summary>
|
||||
/// <param name="paths">The paths.</param>
|
||||
/// <returns>IEnumerable{System.String}.</returns>
|
||||
IEnumerable<string> NormalizeRootPathList(IEnumerable<string> paths);
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>LiveTvRecording.</returns>
|
||||
Task<LiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken);
|
||||
Task<ILiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recording stream.
|
||||
|
||||
26
MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
Normal file
26
MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public interface ILiveTvRecording : IHasImages, IHasMediaStreams
|
||||
{
|
||||
string ServiceName { get; set; }
|
||||
|
||||
string MediaType { get; }
|
||||
|
||||
LocationType LocationType { get; }
|
||||
|
||||
RecordingInfo RecordingInfo { get; set; }
|
||||
|
||||
string GetClientTypeName();
|
||||
|
||||
string GetUserDataKey();
|
||||
|
||||
bool IsParentalAllowed(User user);
|
||||
|
||||
Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true);
|
||||
}
|
||||
}
|
||||
52
MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
Normal file
52
MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class LiveTvAudioRecording : Audio, ILiveTvRecording
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
public override string GetUserDataKey()
|
||||
{
|
||||
return GetClientTypeName() + "-" + Name;
|
||||
}
|
||||
|
||||
public RecordingInfo RecordingInfo { get; set; }
|
||||
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
public override string MediaType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Model.Entities.MediaType.Audio;
|
||||
}
|
||||
}
|
||||
|
||||
public override LocationType LocationType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Path))
|
||||
{
|
||||
return base.LocationType;
|
||||
}
|
||||
|
||||
return LocationType.Remote;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetClientTypeName()
|
||||
{
|
||||
return "Recording";
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class LiveTvRecording : BaseItem
|
||||
public class LiveTvVideoRecording : Video, ILiveTvRecording
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
@@ -23,7 +22,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
get
|
||||
{
|
||||
return RecordingInfo.ChannelType == ChannelType.Radio ? Model.Entities.MediaType.Audio : Model.Entities.MediaType.Video;
|
||||
return Model.Entities.MediaType.Video;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +30,11 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Path))
|
||||
{
|
||||
return base.LocationType;
|
||||
}
|
||||
|
||||
return LocationType.Remote;
|
||||
}
|
||||
}
|
||||
@@ -39,5 +43,10 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
return "Recording";
|
||||
}
|
||||
|
||||
public override bool IsSaveLocalMetadataEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,8 @@
|
||||
<Compile Include="Library\ItemUpdateType.cs" />
|
||||
<Compile Include="Library\IUserDataManager.cs" />
|
||||
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
||||
<Compile Include="LiveTv\ILiveTvRecording.cs" />
|
||||
<Compile Include="LiveTv\LiveTvAudioRecording.cs" />
|
||||
<Compile Include="LiveTv\LiveTvChannel.cs" />
|
||||
<Compile Include="LiveTv\ChannelInfo.cs" />
|
||||
<Compile Include="LiveTv\ILiveTvManager.cs" />
|
||||
@@ -115,7 +117,7 @@
|
||||
<Compile Include="LiveTv\LiveTvException.cs" />
|
||||
<Compile Include="LiveTv\StreamResponseInfo.cs" />
|
||||
<Compile Include="LiveTv\LiveTvProgram.cs" />
|
||||
<Compile Include="LiveTv\LiveTvRecording.cs" />
|
||||
<Compile Include="LiveTv\LiveTvVideoRecording.cs" />
|
||||
<Compile Include="LiveTv\ProgramInfo.cs" />
|
||||
<Compile Include="LiveTv\RecordingInfo.cs" />
|
||||
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
|
||||
|
||||
Reference in New Issue
Block a user