The single net8.0 build compiled against Jellyfin 10.9.11 still loads on
10.11 and 12, so channels and browsing keep working, but 10.11 changed
APIs in ways that only fail at runtime. A binary audit of the DLL against
the real server assemblies found 9 broken references on both 10.11 and
12 (none on 10.9/10.10):
- TaskTriggerInfo.Type became an enum. GetDefaultTriggers throws, so
Jellyfin silently gives every SRF task a 24h fallback trigger. The
recording scheduler therefore ran about once a day and scheduled
recordings never started.
- ILibraryManager.GetItemList changed its return type: the expiration
check crashed on every run.
- Jellyfin.Data.Entities.User moved (IUserManager.Users, GetUserData,
SaveUserData, PlaybackProgressEventArgs.Users): resume cleanup returned
500 and the playback-stop guard threw on every stop.
Jellyfin 12 also rejects the legacy X-Emby-Token header with an empty
401, which the recordings UI surfaced as "Unexpected end of JSON input".
The pages now send Authorization: MediaBrowser Token="...", verified on
10.9, 10.11 and 12.
The plugin now multi-targets net8.0/net9.0/net10.0 against Jellyfin
10.9.11/10.11.0/12.0.0 (the oldest package of each line, so each DLL
loads on every patch release of it), with JELLYFIN_10_11_OR_GREATER and
JELLYFIN_12_OR_GREATER for the differences. Trigger construction moves
into Utilities/TaskTriggers so the version switch lives in one place.
.gitea/scripts/build-plugins.sh builds one zip per generation. jprm has
no targetAbi flag, so it rewrites build.yaml per flavour and restores
it. Jellyfin installs the highest version whose targetAbi it satisfies,
so the flavour code goes into the last version segment:
release v1.2.0 -> 1.2.0.9 / 1.2.0.11 / 1.2.0.12
nightly -> 1.0.<date>.<run>09 / 11 / 12
The PR, nightly and release workflows use the script and publish one
manifest entry per zip. Verified end to end against a three-entry
manifest: 10.11 installs the .11 build, 12.1 installs the .12 build.
The existing .NET 10 builder image builds all three unchanged.
Supporting changes: the test project multi-targets too, because jprm
publishes the whole solution for one framework at a time, and it drops
its Microsoft.Extensions.Logging 8.0.1 pin, which is a NU1605 downgrade
under the newer Jellyfin packages. CA1873 (new in the .NET 10 analyzers)
is silenced beside CA1848. The release manifest step checks out
origin/master like the nightly does since 7e1973a.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
58 lines
2.6 KiB
C#
58 lines
2.6 KiB
C#
using System.Collections.Generic;
|
|
using System.Threading;
|
|
#if JELLYFIN_10_11_OR_GREATER
|
|
using Jellyfin.Database.Implementations.Entities;
|
|
#else
|
|
using Jellyfin.Data.Entities;
|
|
#endif
|
|
using Jellyfin.Plugin.SRFPlay.Api.Models;
|
|
using MediaBrowser.Controller.Entities;
|
|
|
|
namespace Jellyfin.Plugin.SRFPlay.Services.Interfaces;
|
|
|
|
/// <summary>
|
|
/// Removes stale plugin-owned resume points so ended livestreams and abandoned playback
|
|
/// stop accumulating in every user's "Continue Watching" row.
|
|
/// </summary>
|
|
public interface IResumeCleanupService
|
|
{
|
|
/// <summary>
|
|
/// Scans every user's resumable items and clears the resume point of those owned by this
|
|
/// plugin that match a staleness rule. Items belonging to other plugins or to the regular
|
|
/// library are never touched.
|
|
/// </summary>
|
|
/// <param name="clearAll">
|
|
/// When true every plugin-owned resume point is cleared regardless of the staleness rules.
|
|
/// Used by the "Clear all" maintenance action.
|
|
/// </param>
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
/// <returns>A summary of what was inspected and cleared.</returns>
|
|
ResumeCleanupResult Cleanup(bool clearAll, CancellationToken cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Clears the resume point of a single item for the given users.
|
|
/// </summary>
|
|
/// <param name="item">The item whose resume point should be reset.</param>
|
|
/// <param name="users">The users to clear it for.</param>
|
|
/// <param name="reason">A short reason, logged for traceability.</param>
|
|
/// <returns>The number of resume points actually cleared.</returns>
|
|
int ClearResumePoint(BaseItem item, IEnumerable<User> users, string reason);
|
|
|
|
/// <summary>
|
|
/// Determines whether an item belongs to this plugin (an SRG channel item or a recording).
|
|
/// </summary>
|
|
/// <param name="item">The item to test.</param>
|
|
/// <returns>True if the item is owned by this plugin.</returns>
|
|
bool IsPluginItem(BaseItem item);
|
|
|
|
/// <summary>
|
|
/// Clears the resume point if the item is one of this plugin's livestreams and livestream
|
|
/// cleanup is enabled. Called right after playback stops so an ended broadcast never reaches
|
|
/// "Continue Watching" in the first place, instead of waiting for the nightly task.
|
|
/// </summary>
|
|
/// <param name="item">The item that just stopped playing.</param>
|
|
/// <param name="users">The users the playback was attributed to.</param>
|
|
/// <returns>The number of resume points cleared.</returns>
|
|
int ClearLiveStreamResumePoint(BaseItem item, IEnumerable<User> users);
|
|
}
|