refactor(live-tv): split optional DVR support

This commit is contained in:
edde746
2026-07-12 08:42:25 +02:00
parent a5449a1430
commit 359a6bf02a
15 changed files with 305 additions and 479 deletions
+18 -8
View File
@@ -115,29 +115,31 @@ class LiveTvStreamResolution {
}
/// Backend-neutral live-TV operations. Implementations are obtained via
/// [MediaServerClient.liveTv]; the getter returns `null` when the server has no
/// live-TV support configured.
/// [MediaServerClient.liveTv]. Runtime availability is reported by
/// [isAvailable]; recording and DVR administration are exposed separately by
/// the optional [dvr] adapter.
///
/// Plex servers expose multiple per-DVR lineups (`/livetv/dvrs`), Jellyfin
/// servers expose a single flat channel list. The interface flattens both:
/// callers that need DVR identity for Plex's per-lineup channel fetch use
/// [fetchDvrs]; callers that only need the channel list pass the optional
/// [lineup] (Plex provider identifier) to [fetchChannels].
/// [LiveTvDvrSupport.fetchDvrs]; callers that only need the channel list pass
/// the optional [lineup] (Plex provider identifier) to [fetchChannels].
///
/// Stream URL resolution differs sharply by backend: Plex's DVR allocates a
/// transcode session and returns a session-scoped path; Jellyfin negotiates
/// a direct-play URL. [startPlayback] owns that difference behind
/// [LiveTvPlaybackSession] — it is the only entry playback callers use.
abstract class LiveTvSupport {
/// Recording and DVR administration, when implemented by this backend.
/// Jellyfin's channel, guide, and playback support remains available while
/// this is `null` until its recording API is wired.
LiveTvDvrSupport? get dvr;
/// Fast probe — `true` when this server has live-TV configured. Plex calls
/// `/livetv/dvrs` and returns true when any DVR exists; Jellyfin probes
/// `/LiveTv/Channels?limit=1`.
Future<bool> isAvailable();
/// Plex returns one entry per configured DVR; Jellyfin returns an empty
/// list (it has no per-DVR partitioning).
Future<List<LiveTvDvr>> fetchDvrs();
/// Channel list. Plex callers may pass [lineup] (the EPG provider
/// identifier from a DVR's lineup) to scope to a specific provider's
/// channels. Jellyfin ignores [lineup] and returns the flat list.
@@ -183,7 +185,15 @@ abstract class LiveTvSupport {
/// `/UserFavoriteItems/{channelId}?userId=...` flag and saves the order
/// locally.
Future<void> setFavoriteChannels(List<FavoriteChannel> channels);
}
/// Optional Plex-style recording and DVR administration capability.
///
/// Kept separate from [LiveTvSupport] so backends that support channels,
/// guide data, and playback do not need placeholder methods for unsupported
/// recording APIs.
abstract class LiveTvDvrSupport {
Future<List<LiveTvDvr>> fetchDvrs();
Future<LiveTvServerStatus> fetchLiveTvServerStatus();
Future<LiveTvDvr?> fetchDvr(String dvrId);
Future<LiveTvActivityResult<LiveTvDvr?>> createDvr({
+9 -1
View File
@@ -619,7 +619,8 @@ abstract class MediaServerClient {
/// Backend-neutral live-TV operations. Always returns a wrapper; consult
/// [LiveTvSupport.isAvailable] to find out whether the server actually
/// has live TV configured before calling other methods.
/// has live TV configured before calling other methods. Recording and DVR
/// administration are available through [MediaServerClientLiveTv.liveTvDvr].
LiveTvSupport get liveTv;
/// Resolve the download URL for [item]'s primary video file along with
@@ -681,6 +682,13 @@ extension MediaServerClientScope on MediaServerClient {
}
}
extension MediaServerClientLiveTv on MediaServerClient {
/// Optional recording/admin adapter, gated by the backend capability flag.
/// Call sites use this rather than assuming every Live TV backend supports
/// Plex's DVR surface.
LiveTvDvrSupport? get liveTvDvr => capabilities.liveTvDvr ? liveTv.dvr : null;
}
/// Optional capability for clients that can fetch a season's episodes without
/// listing generic children. Jellyfin uses this to avoid mixing local extras or
/// missing/virtual placeholders into normal season episode rails.