aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorTim Eisele <Ghost_of_Stone@web.de>2025-05-05 05:21:44 +0200
committerGitHub <noreply@github.com>2025-05-04 21:21:44 -0600
commitd976f13970e034a24c1d0f69384501e31475a127 (patch)
tree8b04bfba52b06c2c8f762beeaa3f7efebc7d6584 /MediaBrowser.Controller
parent0c3ba30de214eddcd6118c3b695b08e5482bf7ed (diff)
Recognize file changes and remove data on change (#13839)
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs40
-rw-r--r--MediaBrowser.Controller/IO/IPathManager.cs10
-rw-r--r--MediaBrowser.Controller/Library/IKeyframeManager.cs37
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs8
-rw-r--r--MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs9
-rw-r--r--MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs6
-rw-r--r--MediaBrowser.Controller/Persistence/IKeyframeRepository.cs8
7 files changed, 104 insertions, 14 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index b90ec8222..16fde9440 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -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;
}
diff --git a/MediaBrowser.Controller/IO/IPathManager.cs b/MediaBrowser.Controller/IO/IPathManager.cs
index 4e4eb514e..eb6743754 100644
--- a/MediaBrowser.Controller/IO/IPathManager.cs
+++ b/MediaBrowser.Controller/IO/IPathManager.cs
@@ -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);
}
diff --git a/MediaBrowser.Controller/Library/IKeyframeManager.cs b/MediaBrowser.Controller/Library/IKeyframeManager.cs
new file mode 100644
index 000000000..b0155efdd
--- /dev/null
+++ b/MediaBrowser.Controller/Library/IKeyframeManager.cs
@@ -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);
+}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index df90f546c..98ed15eb6 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -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);
diff --git a/MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs b/MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs
index 456977b88..6cd6474f7 100644
--- a/MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs
+++ b/MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs
@@ -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.
@@ -46,6 +46,13 @@ public interface IMediaSegmentManager
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>
/// <param name="itemId">The id of the <see cref="BaseItem"/>.</param>
diff --git a/MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs b/MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs
index 39bb58bef..5a6d15d78 100644
--- a/MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs
+++ b/MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs
@@ -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.
diff --git a/MediaBrowser.Controller/Persistence/IKeyframeRepository.cs b/MediaBrowser.Controller/Persistence/IKeyframeRepository.cs
index 4930434a7..2596784ba 100644
--- a/MediaBrowser.Controller/Persistence/IKeyframeRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IKeyframeRepository.cs
@@ -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);
}