From f4d940af10e87566e13f871909bd118035c0f772 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:21:08 +0100 Subject: [PATCH] fix(tv): add diagnostic logging for multi-DVR issues Also remove suspicious Uri.decodeComponent on lineup parameter. --- lib/screens/livetv/live_tv_screen.dart | 7 +++++++ lib/screens/video_player_screen.dart | 3 ++- lib/services/plex_client.dart | 10 +++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/screens/livetv/live_tv_screen.dart b/lib/screens/livetv/live_tv_screen.dart index 1b9515e2..41edfae2 100644 --- a/lib/screens/livetv/live_tv_screen.dart +++ b/lib/screens/livetv/live_tv_screen.dart @@ -109,12 +109,19 @@ class _LiveTvScreenState extends State with SingleTickerProviderSt final allChannels = []; final seenChannels = {}; + appLogger.d('Live TV DVRs: ${liveTvServers.map((s) => '${s.serverId}/${s.dvrKey} lineup=${s.lineup}').join(', ')}'); + for (final serverInfo in liveTvServers) { try { final client = multiServer.getClientForServer(serverInfo.serverId); if (client == null) continue; final channels = await client.getEpgChannels(lineup: serverInfo.lineup); + appLogger.d('Channels from DVR ${serverInfo.dvrKey}: ${channels.length} channels'); + if (channels.isNotEmpty) { + final sample = channels.first; + appLogger.d('Sample channel: key=${sample.key} identifier=${sample.identifier} number=${sample.number} slug=${sample.slug}'); + } for (final channel in channels) { final dedupKey = '${serverInfo.serverId}:${channel.identifier ?? channel.key}'; if (seenChannels.add(dedupKey)) { diff --git a/lib/screens/video_player_screen.dart b/lib/screens/video_player_screen.dart index 55cb3083..71cd8a69 100644 --- a/lib/screens/video_player_screen.dart +++ b/lib/screens/video_player_screen.dart @@ -868,6 +868,7 @@ class VideoPlayerScreenState extends State with WidgetsBindin } final channel = channels[channelIndex]; final channelId = channel.identifier ?? channel.key; + appLogger.d('Tune: dvrKey=${widget.liveDvrKey} channelId=$channelId (identifier=${channel.identifier}, key=${channel.key})'); final client = widget.liveClient!; final result = await client.tuneChannel(widget.liveDvrKey!, channelId); if (result == null) throw Exception('Failed to tune channel'); @@ -1722,7 +1723,7 @@ class VideoPlayerScreenState extends State with WidgetsBindin final channel = channels[newIndex]; final channelId = channel.identifier ?? channel.key; - appLogger.d('Switching to channel: ${channel.displayName} ($channelId)'); + appLogger.d('Switching to channel: ${channel.displayName} ($channelId) (identifier=${channel.identifier}, key=${channel.key})'); setState(() => _hasFirstFrame.value = false); diff --git a/lib/services/plex_client.dart b/lib/services/plex_client.dart index f8fec703..8d9c3de1 100644 --- a/lib/services/plex_client.dart +++ b/lib/services/plex_client.dart @@ -1996,12 +1996,15 @@ class PlexClient { /// Get EPG channels for a specific lineup Future> getEpgChannels({String? lineup}) async { final queryParams = {}; - if (lineup != null) queryParams['lineup'] = Uri.decodeComponent(lineup); + if (lineup != null) queryParams['lineup'] = lineup; return _wrapListApiCall( () => _dio.get('/livetv/epg/channels', queryParameters: queryParams), (response) { final container = _getMediaContainer(response); + if (container != null && container['Channel'] is List && (container['Channel'] as List).isNotEmpty) { + appLogger.d('EPG channel sample: ${(container['Channel'] as List).first}'); + } if (container != null && container['Channel'] != null) { return (container['Channel'] as List) .map((json) => LiveTvChannel.fromJson(json as Map) @@ -2063,6 +2066,7 @@ class PlexClient { } _epgProviders = results; + appLogger.d('Discovered ${results.length} EPG provider(s)'); if (results.isEmpty) { appLogger.w('No EPG providers found'); } @@ -2094,6 +2098,9 @@ class PlexClient { () => _dio.get(provider.gridEndpoint, queryParameters: queryParams), (response) { final container = _getMediaContainer(response); + if (container != null && container['Metadata'] is List && (container['Metadata'] as List).isNotEmpty) { + appLogger.d('EPG grid sample from ${provider.identifier}: ${(container['Metadata'] as List).first}'); + } final programs = []; if (container != null && container['Metadata'] != null) { for (final item in container['Metadata'] as List) { @@ -2118,6 +2125,7 @@ class PlexClient { }, 'Failed to get EPG grid from ${provider.identifier}', ); + appLogger.d('EPG grid from ${provider.identifier}: ${programs.length} programs'); allPrograms.addAll(programs); } catch (e) { appLogger.e('Failed to get EPG grid from provider ${provider.identifier}', error: e);