Files
plezy/lib/services/playback_session.dart
edde746 a7527718df refactor(services): delete dead branches, write-only fields, and test-only cache/service surface
plex_client.selectStreams' allParts=false branch, download_manager's both-branches-true conditional and unscoped getAllPinnedMetadata tail, playback_source_resolver.preferOffline, and update_service's unreachable catches had no reachable path; PlaybackSession.result/streamHeaders, PlaybackContext.clientScopeId, FileInfoStreams.audioStream, PrefsRepairOutcome.settingsReset/sessionsSalvaged, and JellyfinLiveSessionTracker.playSessionId were write-only; PlexConnection.directUrl, PlexServer.isOnline plus its parse-and-persist presence field, SafStorageService.createDirectory, FullscreenStateManager.stopMonitoring/dispose, the play_queue_launcher re-export shim, track-selection's constant params, and PlexApiCache.unpinForOffline/isPinnedRatingKey (matching the earlier Jellyfin removal) were dead API.
2026-08-17 19:02:25 +02:00

92 lines
3.3 KiB
Dart

import '../media/media_item.dart';
import '../media/media_server_client.dart';
import '../media/media_source_info.dart';
import '../media/media_version.dart';
import '../models/transcode_quality_preset.dart';
import 'playback_context.dart';
import 'playback_subtitle_resolver.dart';
/// Immutable snapshot of everything that describes the item currently loaded
/// in the player: the resolver output plus the effective (post-fallback,
/// post-clamping) source selections.
///
/// Built once per resolve and swapped atomically on the screen — failure
/// before the swap means the previous session (and the state derived from
/// it) stays untouched, which replaces the old field-by-field
/// snapshot/rollback bookkeeping.
class PlaybackSession {
final PlaybackContext context;
/// Effective quality preset — the requested preset, downgraded to
/// original when the backend reported a transcode fallback.
final TranscodeQualityPreset qualityPreset;
/// Effective media version id, refined from the resolver's clamped
/// version index when the version list provides one.
final String? mediaSourceId;
final PlaybackSubtitleSelection subtitleSelection;
const PlaybackSession({
required this.context,
required this.qualityPreset,
this.mediaSourceId,
this.subtitleSelection = const PlaybackSubtitleSelection.off(),
});
/// Derives the effective selections from a resolved [context]:
/// quality falls back to original when the backend rejected the requested
/// preset, and the media source id follows the clamped version index.
factory PlaybackSession.fromContext(
PlaybackContext context, {
required TranscodeQualityPreset requestedQualityPreset,
String? requestedMediaSourceId,
PlaybackSubtitleSelection subtitleSelection = const PlaybackSubtitleSelection.off(),
}) {
final result = context.result;
final fellBackToOriginal = result.fallbackReason != null && !requestedQualityPreset.isOriginal;
return PlaybackSession(
context: context,
qualityPreset: fellBackToOriginal ? TranscodeQualityPreset.original : requestedQualityPreset,
mediaSourceId:
result.selectedMediaSourceId ??
mediaSourceIdForIndex(result.availableVersions, result.selectedMediaIndex) ??
requestedMediaSourceId,
subtitleSelection: subtitleSelection,
);
}
PlaybackSession withSubtitleSelection(PlaybackSubtitleSelection selection) {
return PlaybackSession(
context: context,
qualityPreset: qualityPreset,
mediaSourceId: mediaSourceId,
subtitleSelection: selection,
);
}
static String? mediaSourceIdForIndex(List<MediaVersion> versions, int index) {
if (index < 0 || index >= versions.length) return null;
return versions[index].id;
}
MediaItem get metadata => context.metadata;
MediaServerClient? get reportingClient => context.reportingClient;
bool get isTranscoding => context.result.isTranscoding;
bool get isOffline => context.result.isOffline;
String? get playSessionId => context.result.playSessionId;
String? get playMethod => context.result.playMethod;
int? get audioStreamId => context.result.activeAudioStreamId;
int get mediaIndex => context.result.selectedMediaIndex;
List<MediaVersion> get availableVersions => context.result.availableVersions;
MediaSourceInfo? get mediaInfo => context.result.mediaInfo;
}