Live-TV: die Sender waren da, zwei eigene Fehler haben sie verschluckt
Der Abzug vom Server zeigt beides schwarz auf weiß. Erstens: /media/grabbers/devices/1/channels antwortet mit 278 Sendern — unter dem Sammelnamen `DeviceChannel`. Die Hülle kannte nur `Channel` und hat die vollständige Liste als leer verworfen. Zweitens: das Programmraster antwortet, aber nicht auf `type=1`. Die 1 steht bei Plex für Film, und im Programm laufen auch Folgen, Sport und Nachrichten — der Filter hat das Raster geleert. Ohne ihn kommen die Sendungen samt Sendername, Nummer, Logo und Kennung. Das Raster hat jetzt Vorrang vor der Tunerliste, auch wenn beide antworten: nur dort gehören Sender und Programm zusammen, es enthält ohnehin nur die eingeschalteten Sender, und die Tunerliste führt alle 278. Einschalten läuft über die Adresse der laufenden Sendung beim Programmanbieter — Plex behandelt eine laufende Sendung wie einen Film. Die Adresse wird einmal entpackt, bevor sie in die Anfrage geht: sonst kodiert URLComponents ein zweites Mal, und aus %3A wird %253A. Die Tests stehen jetzt auf den echten Antworten aus dem Abzug, nicht auf erfundenen: DeviceChannel mit `name` und `key`, Rastereinträge mit channelVcn, channelID und einer Folge neben einem Film. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7e36f37506
commit
2362865ba9
@@ -71,7 +71,7 @@ struct LiveTVView: View {
|
||||
channels: channels,
|
||||
programs: programs,
|
||||
tuning: isTuning,
|
||||
onTune: { channel in Task { await tune(channel) } }
|
||||
onTune: { channel, program in Task { await tune(channel, program: program) } }
|
||||
)
|
||||
} else {
|
||||
channelList
|
||||
@@ -180,13 +180,20 @@ struct LiveTVView: View {
|
||||
trace = guide.trace
|
||||
}
|
||||
|
||||
private func tune(_ channel: PlexChannel) async {
|
||||
private func tune(_ channel: PlexChannel, program: PlexProgram? = nil) async {
|
||||
guard let server = session.server, isTuning == nil else { return }
|
||||
isTuning = channel.id
|
||||
defer { isTuning = nil }
|
||||
|
||||
// Die laufende Sendung mitgeben: über ihre Adresse beim
|
||||
// Programmanbieter führt der direkte Weg zum Strom.
|
||||
let running = program ?? programs[channel.id]?.first { $0.isRunning() }
|
||||
let policy = settings.policy(for: network)
|
||||
guard (try? await server.tune(channel: channel, maximumBitrate: policy.maximumBitrate)) != nil
|
||||
guard (try? await server.tune(
|
||||
channel: channel,
|
||||
program: running,
|
||||
maximumBitrate: policy.maximumBitrate
|
||||
)) != nil
|
||||
else { return }
|
||||
|
||||
// Live-TV läuft über denselben Player wie alles andere. Der Schlüssel
|
||||
|
||||
@@ -18,7 +18,7 @@ struct ProgramGuide: View {
|
||||
let channels: [PlexChannel]
|
||||
let programs: [String: [PlexProgram]]
|
||||
let tuning: String?
|
||||
let onTune: (PlexChannel) -> Void
|
||||
let onTune: (PlexChannel, PlexProgram?) -> Void
|
||||
|
||||
@Environment(FlixySession.self) private var session
|
||||
@Environment(\.flixyAccent) private var accent
|
||||
@@ -53,7 +53,7 @@ struct ProgramGuide: View {
|
||||
channel: selection.channel,
|
||||
program: selection.program,
|
||||
isRunning: selection.program.isRunning(at: now),
|
||||
onTune: { onTune(selection.channel) }
|
||||
onTune: { onTune(selection.channel, selection.program) }
|
||||
)
|
||||
}
|
||||
// Die Fortschrittsbalken und die Jetzt-Linie stimmen sonst nach ein
|
||||
@@ -105,10 +105,15 @@ struct ProgramGuide: View {
|
||||
.background(Color.flixyCanvas)
|
||||
}
|
||||
|
||||
/// Was auf diesem Sender gerade läuft.
|
||||
private func running(on channel: PlexChannel) -> PlexProgram? {
|
||||
programs[channel.id]?.first { $0.isRunning(at: now) }
|
||||
}
|
||||
|
||||
private var channelColumn: some View {
|
||||
VStack(spacing: 0) {
|
||||
ForEach(channels) { channel in
|
||||
Button { onTune(channel) } label: {
|
||||
Button { onTune(channel, running(on: channel)) } label: {
|
||||
HStack(spacing: FlixySpacing.snug) {
|
||||
FlixyArtwork(
|
||||
url: session.server?.artworkURL(path: channel.thumb, width: 120, height: 120),
|
||||
|
||||
Reference in New Issue
Block a user