import 'package:flutter/foundation.dart'; /// Read-only snapshot of the active Android media session. @immutable class MediaPlayback { const MediaPlayback({ this.hasAccess = false, this.hasSession = false, this.playing = false, this.title, this.artist, this.packageName, this.durationMs = 0, this.positionMs = 0, }); final bool hasAccess; final bool hasSession; final bool playing; final String? title; final String? artist; final String? packageName; final int durationMs; final int positionMs; bool get hasTitle => (title?.trim().isNotEmpty ?? false); String? get displayTitle { final name = title?.trim(); if (name == null || name.isEmpty) return null; final by = artist?.trim(); return by == null || by.isEmpty ? name : '$name — $by'; } double get progress { if (durationMs <= 0) return 0; return (positionMs / durationMs).clamp(0.0, 1.0); } @override bool operator ==(Object other) { return other is MediaPlayback && other.hasAccess == hasAccess && other.hasSession == hasSession && other.playing == playing && other.title == title && other.artist == artist && other.packageName == packageName && other.durationMs == durationMs && other.positionMs == positionMs; } @override int get hashCode => Object.hash( hasAccess, hasSession, playing, title, artist, packageName, durationMs, positionMs, ); factory MediaPlayback.fromMap(Map map) { int integer(String key) => (map[key] as num?)?.toInt() ?? 0; String? string(String key) { final value = (map[key] as String?)?.trim(); return value == null || value.isEmpty ? null : value; } return MediaPlayback( hasAccess: map['hasAccess'] == true, hasSession: map['hasSession'] == true, playing: map['playing'] == true, title: string('title'), artist: string('artist'), packageName: string('packageName'), durationMs: integer('durationMs'), positionMs: integer('positionMs'), ); } }