Live-TV bekommt einen neutralen Vertrag
Zwei Protokolle statt eines: LiveTVBackend für Sender, Programm und Einschalten, LiveTVRecordingBackend für Aufnahmen. Getrennt, weil Plex das eine kann und das andere nicht — ein as? sagt die Wahrheit, eine Methode, die bei Plex nur wirft, verspricht etwas und bricht es dann. Plex zieht um, ohne umgebaut zu werden. Der Suchlauf, der die Senderliste findet, bleibt Zeile für Zeile, wo er ist; davor liegt jetzt ein Actor, der sich Empfänger und Sender merkt. Nötig, weil PlexBackend ein struct ist und tune() den echten PlexChannel braucht — ohne Gedächtnis liefe der Suchlauf bei jedem Antippen neu. Jellyfin ist neu und deutlich kürzer, weil es dort nichts zu suchen gibt. Die Endpunkte stammen aus der OpenAPI-Spec des Servers. Beim Vormerken wird die Vorlage des Servers roh weitergereicht statt entschlüsselt und neu zusammengesetzt: welche Felder Pflicht sind, sagt die Beschreibung nicht, und ein verlorenes fiele erst an einer Aufnahme auf, die nicht startet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9df58ed5a6
commit
24765a5afc
@@ -35,6 +35,36 @@ public struct JellyfinItem: Decodable, Sendable {
|
||||
public let mediaSources: [JellyfinMediaSource]?
|
||||
public let collectionType: String?
|
||||
|
||||
// MARK: - Live-TV
|
||||
//
|
||||
// Sender **und** Sendungen kommen bei Jellyfin als derselbe Typ wie
|
||||
// Filme und Folgen. Deshalb stehen ihre Felder hier und nicht in einem
|
||||
// eigenen Modell: ein zweites, das zu neunzig Prozent dasselbe trägt,
|
||||
// wäre eine Kopie mit Pflegeaufwand.
|
||||
|
||||
/// Zu welchem Sender eine Sendung gehört.
|
||||
public let channelID: String?
|
||||
public let channelName: String?
|
||||
/// Die Nummer, unter der ein Sender im Programm steht — „3" oder „11.1".
|
||||
public let channelNumber: String?
|
||||
/// Dasselbe, aber am Sender selbst statt an der Sendung.
|
||||
public let number: String?
|
||||
public let startDate: Date?
|
||||
public let endDate: Date?
|
||||
/// Was auf diesem Sender gerade läuft.
|
||||
///
|
||||
/// Kommt nur, wenn die Senderliste mit `addCurrentProgram` geholt wurde —
|
||||
/// dann aber gleich mit, und die Liste braucht keinen zweiten Aufruf.
|
||||
public let currentProgram: JellyfinCurrentProgram?
|
||||
/// Ob die Sendung zu einem laufenden Serien-Timer gehört.
|
||||
public let seriesTimerID: String?
|
||||
public let isMovie: Bool?
|
||||
public let isSeries: Bool?
|
||||
public let isNews: Bool?
|
||||
public let isSports: Bool?
|
||||
public let isKids: Bool?
|
||||
public let isLive: Bool?
|
||||
|
||||
public struct Person: Decodable, Sendable {
|
||||
public let id: String?
|
||||
public let name: String?
|
||||
@@ -78,6 +108,30 @@ public struct JellyfinItem: Decodable, Sendable {
|
||||
case parentBackdropItemID = "ParentBackdropItemId"
|
||||
case seriesPrimaryImageTag = "SeriesPrimaryImageTag"
|
||||
case mediaSources = "MediaSources", collectionType = "CollectionType"
|
||||
case channelID = "ChannelId", channelName = "ChannelName"
|
||||
case channelNumber = "ChannelNumber", number = "Number"
|
||||
case startDate = "StartDate", endDate = "EndDate"
|
||||
case currentProgram = "CurrentProgram", seriesTimerID = "SeriesTimerId"
|
||||
case isMovie = "IsMovie", isSeries = "IsSeries", isNews = "IsNews"
|
||||
case isSports = "IsSports", isKids = "IsKids", isLive = "IsLive"
|
||||
}
|
||||
}
|
||||
|
||||
/// Was auf einem Sender gerade läuft.
|
||||
///
|
||||
/// Ein eigenes, schmales Modell statt eines verschachtelten `JellyfinItem`:
|
||||
/// ein Struct darf sich nicht selbst enthalten — seine Größe wäre unendlich.
|
||||
/// Gebraucht werden hier ohnehin nur fünf Felder.
|
||||
public struct JellyfinCurrentProgram: Decodable, Sendable {
|
||||
public let id: String
|
||||
public let name: String?
|
||||
public let overview: String?
|
||||
public let startDate: Date?
|
||||
public let endDate: Date?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id = "Id", name = "Name", overview = "Overview"
|
||||
case startDate = "StartDate", endDate = "EndDate"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user