Aller au contenu

ADR-0068: Favourite playlists in the music popup — names pushed by the blueprint, links kept in Home Assistant, played on an Apple TV through the YouTube app

Page en anglais

Cette page n'existe qu'en anglais.

Status: Proposed (2026-10-18, asked for by the author; not tried on a tablet when written). Extends the music popup of ADR-0050. Date: 2026-10-18

Context

The author asked for « une liste de playlists dans HA + des boutons sur la tablette »: touch one of his favourite YouTube / YouTube Music playlists in the Music popup and have it play on his Apple TV, which sends the sound to his speakers over AirPlay. The house screen is the Waveshare ESP32-P4 7B (1024×600); the Tab5 (1280×720) is away for repair: both boards must stay right (ADR-0061).

Constraints: push-only and events-only (ADR-0001, ADR-0025) — the firmware names no entity, calls no action and must not receive a link it could be made to play; nothing of a real home in the public HA files (ADR-0024); one swipe mechanism for popups with pages (ADR-0046); colours from the palette; every icon in its font's glyphs: (code rule 9); instant transitions.

Verified on the author's Apple TV 4K (tvOS, apple_tv integration / pyatv) on 2026-10-18, camera in front of the TV and Home Assistant's history (11:17 – 11:19 for the timings):

  • tvOS has no YouTube Music app: YouTube Music plays in the YouTube app.
  • media_player.play_media with media_content_type: url and media_content_id: youtube://www.youtube.com/watch?list=<L> (Home Assistant calls pyatv's launch_app) starts the playlist at its first track, and media_next_track follows the playlist; with v=<V>&list=<L> it starts at that track. An https://… link is refused by tvOS (« Open URL failed »); youtube://watch/<id> without list plays one track, then YouTube's autoplay.
  • After the link the state goes to paused (what was playing) in about 1 s, then to playing with the new track about 2-3 s after the call — from YouTube playing, from the Apple TV home screen and from standby (off).
  • The tvOS dialog « Ouvrir dans « YouTube » ? » (Open selected, nothing starts without OK) appeared on the first two links of the morning and never again (4 tries out of 4 without): handled, not assumed. A select sent with no dialog only shows YouTube's controls; playback goes on.
  • In standby, media_player.turn_on: the state leaves off in 5 to 10 s; a link sent right after starts in 2 to 3 s, with no extra delay (7.8 s from the tap on a sleeping Apple TV, through the script). Woken 4 s after it went to sleep, the Apple TV ignored turn_on for 20 s and refused the link (« Open URL failed »).

Decision

  • Written in the blueprint. A new input of « Tab5 — emplacements », « Playlists favorites · Favourite playlists » (playlists, multi-line text, empty by default, section « TV, téléphone »): one playlist per line, « Name | link » (the name is what precedes the last « | »; a line with the link alone gets « Playlist N »; empty lines, lines without a link and lines starting with « # » are skipped), the link copied in YouTube or YouTube Music (Share → Copy link), eight at most. One template, playlists, reads the lines; the push and the command read the same list, so a rank means the same line on both sides.
  • Only the names reach the tablet. A key of tab5_maj_emplacements, pushed with every state like telecommandes (ADR-0056): playlists|name|name|…;, « | » and « ; » replaced in the names, 40 characters each at most, pushed even empty (playlists|; removes the page). Read in pure C++ by playlists_lire() (Tab5/socle/tab5_parse.*, section 16; cases in tools/test_parse.cpp, fuzzed by tools/fuzz/fuzz_parse.cpp): fields kept in place, empty names included (the screen writes « Playlist N »), the rest ignored past eight. Nothing in NVS: until Home Assistant pushes, no Playlists page.
  • A page of the Music popup, « Playlists », only when at least one playlist was pushed. The page change is the shared brick (PagesPopup + pages_brancher(), left / right swipe, no second gesture handler); the popup always opens on « Lecture ». Since the merge with ADR-0067 (2026-10-18), one brick serves the popup's four pages, in this order: Lecture, Playlists, Pièces, Bibliothèque (tab5_musique.cpp, which asks lecteur_playlists_nb()); their names sit on the title line against the ×, each as wide as its name (96 to 200 px), pages_onglet.yaml buttons (musique_onglet_0..3) and choix_peindre(): pages_onglets() places names on the modal card, and the music card (940 × 536, the same on both boards) is not that card. The application chip moves to their left and the player's name loses the same width (cut with « … »). On the Playlists page the cover and the player chips stay; the right column (508 × 360, the cover's height) shows one button per playlist (lecteur_playlist.yaml, eight): one column of four rows up to four playlists, two columns beyond, the playlist-music icon and the name cut with « … ».
  • A tap sends the rank, nothing else: the existing event esphome.tab5_lecteur with action: playlist, lecteur: "-1", valeur: "<rank>". The button turns to the accent colour at once (and stays so for 30 s), and the popup comes back to « Lecture » 600 ms later (musique_retour_lecture(), cancelled by a page change).
  • The blueprint resolves the rank (an if « La tablette lance une playlist favorite » at the start of the music branch, whose single condition trigger.id == 'lecteur' lets tools/contrat_api.py tie the fields read to their event): the link of the line of that rank in its own input, never a link or an entity from the event; a rank outside the list does nothing. It starts script.tab5_lecteur_playlist (packages/tab5_lecteur.yaml) with lien. script.tab5_lecteur_commande (via tab5_evenements.yaml) has no branch for playlist: it does nothing.
  • script.tab5_lecteur_playlist (mode: restart): list= and v= read from the link (music.youtube.com, www / m.youtube.com, youtu.be; si= and other parameters ignored), youtube://www.youtube.com/watch?[v=V&]list=L; no list= → a persistent notification that says what to fix, and stop. The target: the shown player (sensor.tab5_lecteur_montre) if it belongs to integration_entities('apple_tv') and its source_list has « YouTube », otherwise the first player of « Tab5 · lecteurs de musique » that does; its remote is the remote.* of the same device; none → a notification, stop; unavailable → a notification, stop. Then, the sequence measured above: input_text.tab5_lecteur_actif = the Apple TV at the start (the popup shows it at once instead of 3 to 30 s later); off / standby → media_player.turn_on, then wait up to 10 s for it to leave those states, else a second turn_on and up to 15 s more (an Apple TV woken 4 s after it went to sleep ignored the first one, 18/10/2026); play_media; wait up to 6 s for playing with a last_changed after the call; otherwise remote.send_command: select (the tvOS dialog, or a track loaded paused), wait up to 5 s, then media_player.media_play. Every player and remote action has continue_on_error.

Rejected

  • Links on the tablet, or an entity in the event: against ADR-0025 — another ESPHome device could send any link; the tablet would need the links to send them back.
  • A « Tab5 · » list or an input_text per playlist: a list's options are entity IDs, not links, and eight helpers are eight things to create by hand; the blueprint input is one text box the author fills once.
  • pages_onglets() for the page names: it places names on the modal card (from 1148 px on the Tab5), the music card is 940 px wide; a second set of constants for one popup would be a copy, not a reuse.
  • An https:// link or the YouTube Music app: refused by tvOS / does not exist on tvOS.
  • Other players (Chromecast, a smart TV, Spotify): not asked for and not tried; one more player = one more branch of the script.

Consequences

  • API contract unchanged (1.3.0): no action or field added; tab5_maj_emplacements carries one more key, which an older firmware ignores, and esphome.tab5_lecteur one more action value, which an older blueprint ignores. Both orders work: a new firmware with an older blueprint shows no Playlists page; an older firmware with the new blueprint shows none either. The script needs the package and the blueprint of the same version.
  • Without playlists the popup has no Playlists page. Since the merge with ADR-0067 the page brick (which stops the swipe at the popup) is wired at the popup's first opening, playlists or not: a swipe on the popup no longer reaches the forecasts behind it, as in every other popup with pages, and does nothing below two pages.
  • Three screen texts in six languages (« lecteur|Lecture », « Playlists », « Playlist {n} »); the playlist-music glyph (F0CB8) in mdi_font_32.
  • The off-device render captures the page names on « Lecture » and the Playlists page (musique-avec-playlists, musique-playlists); the demo has no music player and pushes none.
  • Not checked on a tablet when written: the page names next to a long player name and an application chip, the swipe on the cover, the grid on the 7B, the whole chain from a tap to the Apple TV (tests/test_playlists.py renders the blueprint and the script's templates; the sequence's timings come from the author's Apple TV, not from this script running).