mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-05-31 12:58:28 +01:00
Recognize file changes and remove data on change (#13839)
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
OpenAPI / OpenAPI - HEAD (push) Waiting to run
OpenAPI / OpenAPI - BASE (push) Waiting to run
OpenAPI / OpenAPI - Difference (push) Blocked by required conditions
OpenAPI / OpenAPI - Publish Unstable Spec (push) Blocked by required conditions
OpenAPI / OpenAPI - Publish Stable Spec (push) Blocked by required conditions
Tests / run-tests (macos-latest) (push) Waiting to run
Tests / run-tests (ubuntu-latest) (push) Waiting to run
Tests / run-tests (windows-latest) (push) Waiting to run
Project Automation / Project board (push) Waiting to run
Merge Conflict Labeler / Labeling (push) Waiting to run
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
OpenAPI / OpenAPI - HEAD (push) Waiting to run
OpenAPI / OpenAPI - BASE (push) Waiting to run
OpenAPI / OpenAPI - Difference (push) Blocked by required conditions
OpenAPI / OpenAPI - Publish Unstable Spec (push) Blocked by required conditions
OpenAPI / OpenAPI - Publish Stable Spec (push) Blocked by required conditions
Tests / run-tests (macos-latest) (push) Waiting to run
Tests / run-tests (ubuntu-latest) (push) Waiting to run
Tests / run-tests (windows-latest) (push) Waiting to run
Project Automation / Project board (push) Waiting to run
Merge Conflict Labeler / Labeling (push) Waiting to run
This commit is contained in:
@@ -25,6 +25,7 @@ using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.MediaSegments;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Dto;
|
||||
@@ -1265,7 +1266,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base implementation to refresh metadata for local trailers.
|
||||
/// The base implementation to refresh metadata.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
@@ -1362,9 +1363,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
protected virtual FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
|
||||
{
|
||||
var path = ContainingFolderPath;
|
||||
|
||||
return directoryService.GetFileSystemEntries(path);
|
||||
return directoryService.GetFileSystemEntries(ContainingFolderPath);
|
||||
}
|
||||
|
||||
private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||
@@ -1393,6 +1392,23 @@ namespace MediaBrowser.Controller.Entities
|
||||
return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken);
|
||||
});
|
||||
|
||||
// Cleanup removed extras
|
||||
var removedExtraIds = item.ExtraIds.Where(e => !newExtraIds.Contains(e)).ToArray();
|
||||
if (removedExtraIds.Length > 0)
|
||||
{
|
||||
var removedExtras = LibraryManager.GetItemList(new InternalItemsQuery()
|
||||
{
|
||||
ItemIds = removedExtraIds
|
||||
});
|
||||
foreach (var removedExtra in removedExtras)
|
||||
{
|
||||
LibraryManager.DeleteItem(removedExtra, new DeleteOptions()
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
item.ExtraIds = newExtraIds;
|
||||
@@ -1407,6 +1423,22 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public virtual bool RequiresRefresh()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Path) || DateModified == default)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var info = FileSystem.GetFileSystemInfo(Path);
|
||||
if (info.Exists)
|
||||
{
|
||||
if (info.IsDirectory)
|
||||
{
|
||||
return info.LastWriteTimeUtc != DateModified;
|
||||
}
|
||||
|
||||
return info.LastWriteTimeUtc != DateModified && info.Length != (Size ?? 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Interface ITrickplayManager.
|
||||
/// Interface IPathManager.
|
||||
/// </summary>
|
||||
public interface IPathManager
|
||||
{
|
||||
@@ -60,4 +61,11 @@ public interface IPathManager
|
||||
/// <param name="chapterPositionTicks">The chapter position.</param>
|
||||
/// <returns>The chapter images data path.</returns>
|
||||
public string GetChapterImagePath(BaseItem item, long chapterPositionTicks);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the paths of extracted data folders.
|
||||
/// </summary>
|
||||
/// <param name="item">The base item.</param>
|
||||
/// <returns>The absolute paths.</returns>
|
||||
public IReadOnlyList<string> GetExtractedDataPaths(BaseItem item);
|
||||
}
|
||||
|
||||
37
MediaBrowser.Controller/Library/IKeyframeManager.cs
Normal file
37
MediaBrowser.Controller/Library/IKeyframeManager.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.MediaEncoding.Keyframes;
|
||||
|
||||
namespace MediaBrowser.Controller.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Interface IKeyframeManager.
|
||||
/// </summary>
|
||||
public interface IKeyframeManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the keyframe data.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <returns>The keyframe data.</returns>
|
||||
IReadOnlyList<KeyframeData> GetKeyframeData(Guid itemId);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the keyframe data.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <param name="data">The keyframe data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The task object representing the asynchronous operation.</returns>
|
||||
Task SaveKeyframeDataAsync(Guid itemId, KeyframeData data, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the keyframe data.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The task object representing the asynchronous operation.</returns>
|
||||
Task DeleteKeyframeDataAsync(Guid itemId, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -220,13 +220,13 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <param name="resolvers">The resolvers.</param>
|
||||
/// <param name="introProviders">The intro providers.</param>
|
||||
/// <param name="itemComparers">The item comparers.</param>
|
||||
/// <param name="postscanTasks">The postscan tasks.</param>
|
||||
/// <param name="postScanTasks">The post scan tasks.</param>
|
||||
void AddParts(
|
||||
IEnumerable<IResolverIgnoreRule> rules,
|
||||
IEnumerable<IItemResolver> resolvers,
|
||||
IEnumerable<IIntroProvider> introProviders,
|
||||
IEnumerable<IBaseItemComparer> itemComparers,
|
||||
IEnumerable<ILibraryPostScanTask> postscanTasks);
|
||||
IEnumerable<ILibraryPostScanTask> postScanTasks);
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the specified items.
|
||||
@@ -593,11 +593,11 @@ namespace MediaBrowser.Controller.Library
|
||||
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the file.
|
||||
/// Checks if the file is ignored.
|
||||
/// </summary>
|
||||
/// <param name="file">The file.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
/// <returns><c>true</c> if ignored, <c>false</c> otherwise.</returns>
|
||||
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
|
||||
|
||||
Guid GetStudioId(string name);
|
||||
|
||||
@@ -7,7 +7,7 @@ using Jellyfin.Database.Implementations.Enums;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.MediaSegments;
|
||||
|
||||
namespace MediaBrowser.Controller;
|
||||
namespace MediaBrowser.Controller.MediaSegments;
|
||||
|
||||
/// <summary>
|
||||
/// Defines methods for interacting with media segments.
|
||||
@@ -45,6 +45,13 @@ public interface IMediaSegmentManager
|
||||
/// <returns>a task.</returns>
|
||||
Task DeleteSegmentAsync(Guid segmentId);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all media segments of an item.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The <see cref="BaseItem.Id"/> to delete all segments for.</param>
|
||||
/// <returns>a task.</returns>
|
||||
Task DeleteSegmentsAsync(Guid itemId);
|
||||
|
||||
/// <summary>
|
||||
/// Obtains all segments associated with the itemId.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model;
|
||||
using MediaBrowser.Model.MediaSegments;
|
||||
|
||||
namespace MediaBrowser.Controller;
|
||||
namespace MediaBrowser.Controller.MediaSegments;
|
||||
|
||||
/// <summary>
|
||||
/// Provides methods for Obtaining the Media Segments from an Item.
|
||||
|
||||
@@ -26,4 +26,12 @@ public interface IKeyframeRepository
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The task object representing the asynchronous operation.</returns>
|
||||
Task SaveKeyframeDataAsync(Guid itemId, KeyframeData data, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the keyframe data.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The task object representing the asynchronous operation.</returns>
|
||||
Task DeleteKeyframeDataAsync(Guid itemId, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user