diff --git a/custom_components/nvidia_shield/ha_adb_common/running_apps.py b/custom_components/nvidia_shield/ha_adb_common/running_apps.py index 48ec272..948691d 100644 --- a/custom_components/nvidia_shield/ha_adb_common/running_apps.py +++ b/custom_components/nvidia_shield/ha_adb_common/running_apps.py @@ -12,6 +12,7 @@ def running_apps_from_tasks( recent_tasks: list[dict], media_sessions: list[MediaSessionInfo] | None = None, foreground_package: str | None = None, + last_known: dict[str, MediaSessionInfo] | None = None, ) -> list[dict] | None: """Build a list of running app dicts from recent tasks + media sessions. @@ -19,6 +20,9 @@ def running_apps_from_tasks( recent_tasks: List of {"package": str} from ADB recent tasks. media_sessions: Optional media sessions for playback state enrichment. foreground_package: The current foreground app package. + last_known: Optional per-package TTL-filtered last-known-state cache + (P3-3b) — apps without a live session carry their last known + playback state as ``last_known_state``/``last_known_title``. Returns None if there are fewer than 2 apps (no point showing a switcher with only one option). @@ -57,6 +61,15 @@ def running_apps_from_tasks( app["artist"] = session.artist else: app["state"] = "running" + # P3-3b: no live session — surface the TTL-capped last-known state + cached = (last_known or {}).get(pkg) + if cached is not None: + if cached.playing: + app["last_known_state"] = "playing" + elif cached.paused: + app["last_known_state"] = "paused" + if cached.title: + app["last_known_title"] = cached.title apps.append(app) diff --git a/custom_components/nvidia_shield/media_player.py b/custom_components/nvidia_shield/media_player.py index af6be8a..c43425d 100644 --- a/custom_components/nvidia_shield/media_player.py +++ b/custom_components/nvidia_shield/media_player.py @@ -651,6 +651,7 @@ class NvidiaShieldMediaPlayer(MediaPlayerEntity): apps, self._manager.active_sessions, foreground_package=self.app_id, + last_known=self._manager.last_known_map(), ) @property diff --git a/tests/test_media_session.py b/tests/test_media_session.py index bc6f808..3eadbd2 100644 --- a/tests/test_media_session.py +++ b/tests/test_media_session.py @@ -158,3 +158,30 @@ class TestAudioPlaybackSection: def test_empty_dump(self): assert parse_audio_playback("") == [] + + +def test_running_apps_last_known_enrichment(): + """P3-3b: apps without a live session carry their TTL-capped last-known state.""" + from nsh.ha_adb_common import MediaSessionInfo, running_apps_from_tasks + + tasks = [ + {"package": "ar.tvplayer.tv"}, + {"package": "com.netflix.ninja"}, + ] + sessions = [MediaSessionInfo(package="com.netflix.ninja", playing=True, title="Movie")] + last_known = { + "ar.tvplayer.tv": MediaSessionInfo( + package="ar.tvplayer.tv", playing=False, paused=True, title="Last show" + ) + } + + apps = running_apps_from_tasks(tasks, sessions, foreground_package=None, last_known=last_known) + + tivi = next(a for a in apps if a["package"] == "ar.tvplayer.tv") + netflix = next(a for a in apps if a["package"] == "com.netflix.ninja") + + assert tivi["state"] == "running" # no live session + assert tivi["last_known_state"] == "paused" + assert tivi["last_known_title"] == "Last show" + assert "last_known_state" not in netflix # live session enriched instead + assert netflix["state"] == "playing"