aboutsummaryrefslogtreecommitdiff
path: root/working/music-svg-app-design/2026-07-19-music-config-ui-remodel-spec.org
blob: 6e68e10476f352c79f13b1989df2a2940a16c2f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
#+TITLE: Music Config UI Remodel — Spec
#+AUTHOR: Craig Jennings
#+DATE: 2026-07-19
#+TODO: TODO | DONE
#+TODO: DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED

* DRAFT Music Config UI Remodel
:PROPERTIES:
:ID:       bcbb9342-1884-4281-8821-89b06f6f8793
:END:
- 2026-07-19 Sun @ 16:03:13 -0500 — drafted from the approved Dupre Studios design session.

** Prototype iterations

The design session started with working HTML directions, moved through six
distinct visual concepts, and then refined one receiver layout through paired
playlist/radio boards.  The last board is Craig's GIMP refinement and is the
visual authority for this spec.

- [[file:music-svg-directions.html][Initial working SVG directions]]
- [[file:concept-board.html][Six-direction comparison board]]
- [[file:concepts/01-champagne-receiver.png][01 Champagne Receiver]]
- [[file:concepts/02-le-mans-night-cluster.png][02 Le Mans Night Cluster]]
- [[file:concepts/03-geneva-playback-chronograph.png][03 Geneva Playback Chronograph]]
- [[file:concepts/04-mastering-room-reel-console.png][04 Mastering Room Reel Console]]
- [[file:concepts/05-perpetual-calendar-salon.png][05 Perpetual Calendar Salon]]
- [[file:concepts/06-transatlantic-broadcast-navigator.png][06 Transatlantic Broadcast Navigator]]
- [[file:concepts/07-functional-black-glass-receiver.png][07 Functional black-glass receiver]]
- [[file:concepts/08-functional-black-glass-flipped.png][08 Playlist-flipped receiver]]
- [[file:concepts/09-functional-black-glass-retro.png][09 Warmer retro receiver]]
- [[file:concepts/10-warm-black-glass-player-volume.png][10 Player-volume receiver]]
- [[file:concepts/11-illuminated-black-glass-controls.png][11 Illuminated controls]]
- [[file:concepts/12-consolidated-functional-receiver.png][12 Consolidated functional receiver]]
- [[file:concepts/13-black-silver-chronograph-receiver.png][13 Black-silver chronograph]]
- [[file:concepts/14-corrected-luxury-chronograph-receiver.png][14 Corrected luxury chronograph]]
- [[file:concepts/15-champagne-brass-digital-hifi.png][15 Champagne digital hi-fi]]
- [[file:concepts/16-champagne-aluminum-radio-groups.png][16 Explicit radio grouping]]
- [[file:concepts/17-dupre-coltrane-scrollbar.png][17 Long-playlist and scrollbar stress test]]
- [[file:concepts/18-dupre-branding-control-study.png][18 Branding and control study]]
- [[file:concepts/19a-dupre-playlist-state.png][19a Playlist state]] and [[file:concepts/19b-dupre-radio-state.png][19b radio state]]
- [[file:concepts/20-dupre-playlist-radio-comparison.png][20 Long playlist / compact radio comparison]]
- [[file:concepts/21-dupre-semantic-controls-comparison.png][21 Semantic control comparison]]
- [[file:concepts/22-dupre-identity-bay-comparison.png][22 Identity-bay comparison]]
- [[file:concepts/23-dupre-swapped-info-comparison.png][23 Swapped information comparison]]
- [[file:concepts/24-dupre-full-brass-vu-comparison.png][24 Full-brass VU comparison]]
- [[file:concepts/25-dupre-seamless-flush-comparison.png][25 Seamless flush comparison]]
- [[file:concepts/26-dupre-studios-rounded-chrome-comparison.png][26 Dupre Studios comparison]]
- [[file:concepts/27-dupre-studios-leather-analog-header-comparison.png][27 Leather and analog-header comparison]]
- [[file:concepts/28-dupre-studios-balanced-controls-comparison.png][28 Balanced-control comparison]]
- [[file:concepts/29a-dupre-studios-brass-seek-playlist.png][29 Brass seek-thumb pass]]
- [[file:concepts/30a-dupre-studios-user-refined-playlist.png][30 Craig's near-final playlist board (visual authority)]]
- [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][31 Functional local-playlist / radio prototype (acceptance candidate)]]

* Metadata
| Status   | Not ready — first review found one functional-prototype blocker       |
|----------+------------------------------------------------------------------------|
| Owner    | Craig Jennings                                                         |
|----------+------------------------------------------------------------------------|
| Reviewer | Craig Jennings                                                         |
|----------+------------------------------------------------------------------------|
| Related  | [[file:../../todo.org][music: SVG player application design and delivery]]; [[file:../../docs/specs/2026-07-06-fancy-music-player-ui-spec.org][implemented fancy player spec]]; [[file:../../docs/specs/music-config-without-emms-spec.org][EMMS-free architecture spec]] |
|----------+------------------------------------------------------------------------|

* Summary

Replace the current text-and-image EMMS playlist surface with a realistic
Dupre Studios receiver rendered inside Emacs.  The interface uses a raster skin
for leather, glass, brass, and machined controls, then draws all changing
information and illumination in SVG.  Emacs Lisp remains the application
runtime and maps the SVG surface to the existing music-config commands.

The remodel preserves the plain and fancy text views as fallbacks.  It does not
change M3U ownership, radio-browser behavior, or the current EMMS playback model.

* Problem / Context

The implemented fancy player improved names, artwork, and progress, but it is
still a text playlist with a multi-line overlay.  It cannot present the player
as one coherent instrument.  Controls are key hints rather than controls,
playlist management is visually detached from playback, and active state is
limited to text faces and a character-cell progress bar.

Craig wants a bottom-docked application that looks like a manufactured object:
black leather, black glass, champagne brass, lit analog meters, and discreet
controls.  The beauty has to explain state.  A lamp, depressed key, moving
needle, seek position, or selected row must correspond to real music-config or
mpv behavior.  Decorative AM/FM, tone, power, reload, manual URL, and other
unsupported faceplate controls are prohibited.

The final 1916×821 board settles the visual direction.  The remaining design
problem is how to preserve its realism without baking live state into a picture.
An all-vector redraw would lose much of the leather and metal detail.  A single
clickable PNG would preserve the appearance but freeze track data, meter state,
playlist rows, and button feedback.  The chosen design separates the physical
object from its information and behavior.

* Goals and Non-Goals

** Goals

- Match Craig's near-final board closely enough that the running player reads as
  the same manufactured receiver, not a simplified diagram of it.
- Preserve the full music-config workflow: playback, seek, player volume,
  playlist browsing and persistence, radio search, repeat/single/random/consume,
  reordering, add, new, load, save, and delete.
- Make every visible state honest.  Meter needles use real program levels,
  volume lamps use mpv volume, progress uses mpv position, and mode lamps use
  current mode state.
- Keep the hot path compact: album information and controls on the left,
  fourteen playlist rows and playlist actions on the right.
- Keep keyboard operation complete while adding direct mouse interaction.
- Preserve the existing text render for TTY frames, unsupported SVG builds, and
  opt-out/rollback.
- Keep the renderer independent of EMMS objects so the planned EMMS-free/VAMP
  work can replace the controller without replacing the visual layer.

** Non-Goals

- No music library browser, tag editor, lyrics view, waveform editor, or album
  collection database.
- No streaming-service integration.
- No fake receiver functions such as AM/FM tuning, bass, treble, speakers, or
  power.
- No permanent faceplate controls for reload, editing the M3U file, or manual URL
  entry.  Existing keyboard and M-x access may remain.
- No all-vector imitation of leather, brushed metal, or photographic reflections.
- No EMMS removal or VAMP extraction in this project.  Those remain separate
  architecture efforts.
- No alternate narrow/mobile layout in v1.  The player scales as one panoramic
  instrument.

** Scope tiers

- v1: neutral raster skin, SVG renderer, dedicated graphical view buffer,
  complete keyboard/mouse command surface, playlist viewport, seek, persistent
  mpv volume, real stereo VU telemetry, local-file and radio states, diagnostics,
  fallbacks, tests, and live verification.
- Out of scope: library browsing, ratings, per-track menus, editable metadata,
  alternate skins, responsive reflow, and remote control.
- vNext: multiple visual skins, a narrower alternate layout, richer motion
  transitions, and reuse in a future standalone VAMP package.

* Design

** User view

F10 opens the player in the existing bottom side-window position.  In a
graphical frame with the remodel enabled, the buffer is the Dupre Studios
receiver.  The same keys still work.  The visible buttons also work with the
mouse, the playlist scrolls inside its fourteen-row aperture, and selecting a
row starts that track.

A local file shows album art, title, artist, album, label, and year on separate
lines when those fields exist.  It shows elapsed and total time with a draggable
seek control.  A live station shows station art and two ON AIR indications: one
under the art and one in the active station row.  It never shows a seek control
or invented time for a stream.  Missing metadata produces no placeholder word.

The interface behaves like hardware.  Play/Pause sits depressed and glows green
while playing.  Momentary transport controls brighten while pressed.  Active
play modes illuminate the circumference of their brass buttons.  Volume lamps
fill continuously to the current mpv volume.  VU needles move from the actual
left and right audio levels.

The interaction model is available in the [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][functional browser prototype]].  It
switches between a 69-track local fixture and an 18-station radio fixture and
wires transport, playback modes, radio search, playlist actions, row selection,
seek, volume, wheel/keyboard browsing, scrollbar drag, empty state, and delete
confirmation.  Its built-in twelve-check behavior pass is green.  Craig's
hands-on acceptance remains the last prototype gate.

** Research and visual sources

The design session compared NAD restraint, Marshall's black-and-brass control
language, McIntosh black glass and meter hierarchy, vintage stereo transport
controls, automobile instrument clusters, and black/silver chronographs.  The
useful lessons were consistent: controls need one visual family, status lights
need stable color meaning, labels belong on the faceplate, and ornament should
make state easier to read.

The local Dupre references are the implementation sources:

- [[file:references/dupre-gallery.png][Dupre component gallery capture]]
- [[file:references/waybar-redesign.png][Waybar redesign capture]]
- [[file:README.org][Design-session decisions and critique log]]
- [[file:concepts/30a-dupre-studios-user-refined-playlist.png][Near-final visual authority]]
- [[file:../../../code/archsetup/docs/prototypes/gallery-widget.el][svg.el Dupre renderer proof of concept]]

** Canonical geometry

The source canvas is 1916×821 with a viewBox of =0 0 1916 821=.  The renderer
preserves that aspect ratio and scales it to the available window width.  It
does not reflow the playlist under the controls or move controls at runtime.
Extra vertical room stays black below the instrument.  A window too short for
legible rendering falls back to the existing fancy text view rather than
shrinking controls into unusable targets.

Craig's final board defines the visual positions.  Phase 1 records them in one
geometry table, including every visual rectangle, label anchor, hit target, and
playlist row.  Rendering and hit testing use the same constants.  No second
hand-maintained map is allowed.

The principal regions are:

| Region                 | Approximate source bounds |
|------------------------+---------------------------|
| Complete instrument    | 0,0 to 1916,821           |
| Player upper glass     | 50,50 to 1170,368         |
| Lower brass deck       | 69,372 to 1147,744        |
| Playlist glass         | 1170,52 to 1862,744       |
| Branding field         | 150,115 to 500,275        |
| Artwork                | 609,108 to 755,281        |
| Metadata               | 780,100 to 1125,275       |
| Seek / ON AIR line     | 608,302 to 1125,330       |
| Playlist viewport      | 1175,126 to 1835,658      |
| Playlist actions       | 1173,671 to 1850,733      |

Exact measured values replace these orientation bounds in the geometry table.

** Rendering layers

The SVG is a scene graph with four layers.

1. The physical shell is raster.  It contains the leather chassis, compressed
   seams, black glass texture, fine low-contrast champagne micro-brush, recessed
   grooves, fixed branding,
   engraved labels, neutral control bodies, neutral volume knob, and empty VU
   scales.  The application embeds the assets with =svg-embed= and caches their
   encoded data for the Emacs session.

2. Static vector geometry supplies clip paths, hit-region outlines used only in
   debug mode, row separators, and any simple lines that need to stay sharp at
   different scales.

3. Dynamic SVG supplies album/station art, metadata, playlist header and rows,
   progress, brass seek thumb, scrollbar, transport glyphs, pressed states,
   lamps, VU needles, and meter light.  No live text, needle, lamp, selected row,
   scrollbar, or progress state is baked into the raster shell.

4. Emacs Lisp supplies behavior.  SVG rendered through librsvg does not run
   browser JavaScript.  A buffer-local keymap receives mouse events,
   =posn-object-x-y= returns pixel coordinates inside the displayed image, and
   one scale transform maps them back to the source coordinate system.

The near-final PNG cannot be embedded unchanged.  Phase 1 creates a neutral
layered source by removing metadata, playlist text, active lamps, VU needles,
progress, and selection from the final board.  The source stays editable.  The
editable source stays one full-resolution instrument.  Runtime rendering uses
three aligned image regions: upper player glass, lower control deck, and
playlist.  A compact control sprite sheet and neutral VU face supplement those
regions.  The current 1916×821 art is treated as a two-times source for a typical
roughly 958×410 rendered dock.  Opaque runtime crops may be exported at their
display size after a PNG/JPEG visual comparison.  V1 does not upscale beyond the
native source pixels.

** Module and state boundary

The SVG view lives in a new =modules/music-svg-ui.el= module.  It requires
=svg=, =dom=, and ordinary Emacs image support, but it does not require EMMS.
Its pure entry points accept plain data:

- =cj/music-svg-render= takes a state snapshot and viewport.
- =cj/music-svg-hit-target= maps source coordinates to an action description.
- =cj/music-svg-truncate= fits display text to a fixed pixel/character budget.
- =cj/music-svg-scrollbar= computes thumb length and position.
- =cj/music-svg-vu-angle= maps a smoothed dB value to the meter scale.

=modules/music-config.el= remains the controller.  It builds an ephemeral
=cj/music-ui-state= snapshot from the current EMMS playlist and player state,
then dispatches renderer actions back to existing commands.  The snapshot owns
no durable music data.  EMMS and M3U files remain authoritative in v1.

The snapshot contains:

- playback status and track kind
- current track identity and metadata
- art path, elapsed time, duration, and seekability
- playlist name/file, total count, rows, selected index, and viewport offset
- repeat, single, random, and consume state
- player volume
- left/right meter values
- transient pressed/focused target

The graphical view is a dedicated =*Music Player*= special-mode buffer.  The
hidden EMMS playlist buffer continues to own playlist markers and track order.
Controller helpers translate a visible row index to an EMMS buffer position
before selection, playback, reorder, or deletion.  This avoids making a single
image character pretend to be fourteen editable EMMS rows, and it leaves a
clean seam for the EMMS-free state API later.

** Metadata and typography

Berkeley Mono is the default instrument typeface because it is the Dupre token
font and is installed on the target system.  Missing font support falls back to
=monospace=.  The cursive Dupre Studios mark remains raster in the physical
shell.

Title, artist, album, label, and year each get one line.  Empty values disappear
without closing the line spacing above them.  The title receives the largest
width budget and truncates with a literal ellipsis.  The renderer uses the
fixed-width font metrics and the measured metadata box, not a guessed character
count from the current window.

The playlist shows fourteen one-line rows.  Each row is number, title, artist,
and duration on one line.  The row text truncates before the duration column.
Inactive text is soft white.  The active row is amber and carries the triangular
play marker.  There are no decorative status dots.

The header is the only coffee/cream instrument card.  It shows the current
collection or search name and item count, but never labels the source as a
playlist or radio.  Four concealed warm-light pools are part of the static skin,
but the text is SVG because the name and count change.  Its champagne surface is
smooth metal with a fine linear micro-brush, never coarse or wavy wood grain.

** Playlist viewport

The UI keeps a buffer-local first-visible index.  The current track is kept in
view after track changes unless the user is actively browsing elsewhere.  Mouse
wheel moves three rows.  Up/Down moves the UI cursor one row.  Page Up/Page Down
moves fourteen.  Home/End goes to the first/last track.  A row click selects and
starts that track.  The existing keyboard play command remains available.

For =N= tracks and fourteen visible rows, the scrollbar thumb fraction is
=min(1, 14/N)=.  Its position is =offset/(N-14)= when =N > 14=.  Dragging the
thumb changes the viewport but never changes the playing track.  No scrollbar
appears for fourteen or fewer tracks.

** Control behavior

The visible controls map to existing behavior:

| Surface       | Action |
|---------------+--------|
| PREV          | =cj/music-previous= |
| PLAY/PAUSE    | start selected/current track, or =emms-pause= while playing |
| STOP          | =emms-stop= |
| NEXT          | =cj/music-next= |
| REPEAT        | =emms-toggle-repeat-playlist= |
| SINGLE        | =emms-toggle-repeat-track= |
| RANDOM        | =emms-toggle-random-playlist= |
| CONSUME       | =cj/music-toggle-consume= |
| NAME          | =cj/music-radio-search-by-name= |
| TAGS          | =cj/music-radio-search-by-tag= |
| ADD           | =cj/music-fuzzy-select-and-add= |
| NEW           | =cj/music-playlist-clear=, including its file-association reset |
| LOAD          | =cj/music-playlist-load= |
| SAVE          | =cj/music-playlist-save= |
| DELETE        | =cj/music-delete-playlist= with its existing strong confirmation |

Mouse press immediately renders the physical pressed state.  Release inside the
same target dispatches the command.  Release elsewhere cancels it.  The
Play/Pause key remains depressed while playback is active.  PREV and NEXT only
brighten during a press.  STOP has no latched light.

The four play-mode controls are alternate-action pushbuttons, not lamps or
rotary controls.  Each has an unmarked spun-brass cap matching the volume cap, a
fixed collar, and a narrow dark travel seam; the faceplate label identifies its
function.  Off stands slightly proud and casts a small lower shadow.  On sits
nearly flush, collapses that shadow, and illuminates a thin desaturated-green
ring inside the cap/collar gap.  Play/Pause uses the same warm instrument green
through its cut-out symbol with a tight internal bloom; the depressed key
remains the primary playing cue.

The SVG mode retains the full existing keyboard surface, including commands not
placed on the faceplate: manual station creation, reload, edit, append to another
playlist, shuffle, track removal, and track reordering.  Which-key/help text
documents those commands.  The faceplate stays limited to the approved controls.

** Seek and volume

Local files show elapsed time, total duration, an amber progress line, and a
narrow vertical machined-brass grip.  Clicking or dragging the slider sends an
mpv =seek= command in
=absolute-percent= mode.  The displayed thumb is computed from mpv =time-pos=
and =duration=.  While dragging, the local preview follows the pointer; the next
mpv response confirms or corrects it.

URL tracks always use the radio presentation.  The slider and times disappear.
One red =ON AIR= line appears under the station art, and the active playlist row
contains the second =ON AIR=.  No other ON AIR label is rendered.

Player volume is separate from the system mixer.  Add
=cj/music-player-volume=, default 100, and apply it to every new mpv process.
The knob has no number or pointer.  Its equally spaced lamps show the stored
0–100 value.  Click/drag around the arc sets volume, the mouse wheel changes it
by five, and the existing +/− bindings call the same player-volume commands.
Setting volume writes mpv's =volume= property and updates the stored value so a
track change does not reset it.

Every volume position is one fixed lamp well.  Dark and illuminated states use
the same center and mounting bezel; the lit state replaces the dark lens rather
than adding another dot or adjacent glow.  The neutral raster skin contains no
baked lamp cores or light spill.

** Real VU telemetry

mpv starts with a labeled FFmpeg audio filter:

#+begin_src text
--af-add=@meter:lavfi=[astats=metadata=1:reset=1:measure_perchannel=RMS_level+Peak_level:measure_overall=none]
#+end_src

The UI reads =af-metadata/meter= over mpv JSON IPC.  FFmpeg supplies
=lavfi.astats.1.RMS_level= and =lavfi.astats.2.RMS_level= (plus peak values).
Mono duplicates channel one to both meters.  Missing or nonnumeric data rests
the needles and records one diagnostic; it never invents motion.

This path was verified locally on 2026-07-19 with mpv 0.41.0 and FFmpeg 8.1.2.
A synthetic stereo source returned distinct left/right RMS and peak values
through the labeled property.  The official references are:

- [[https://mpv.io/manual/master/#command-interface-af-metadata][mpv af-metadata property]]
- [[https://ffmpeg.org/ffmpeg-filters.html#astats-1][FFmpeg astats filter]]

The renderer maps dB to the printed meter scale (−40 through +3).  A 300 ms
attack and slower 600 ms release approximate a physical VU movement.  Values
below the scale rest at the left stop.  Values above +3 clamp at the right stop.

Telemetry uses one persistent, nonblocking IPC connection with request IDs and
line-buffered JSON replies.  It polls only while the player view is visible and
audio is running.  It closes when playback stops or the view is hidden.  The
existing one-shot IPC helpers remain valid for infrequent commands.

** Refresh and render budget

Hooks trigger immediate redraws for track, playlist, playback, mode, and art
changes.  Progress updates four times per second while a seekable file plays.
Meters target ten updates per second while visible and playing.  Paused, stopped,
hidden, and TTY states run no animation timer.

The [[file:prototypes/2026-07-19-music-config-ui-remodel-benchmark.org][prototype benchmark]] measured full-image and tiled refresh for one minute
each at the real dock size.  Full refresh failed at 133.616 ms median and
139.822 ms p95.  A display-sized lower-deck tile passed at 35.513 ms median and
38.221 ms p95.  The application therefore uses three aligned images: upper
player glass, lower control deck, and playlist.  Each image includes the
matching raster crop.  Meter ticks refresh only the lower deck; hooks refresh
the other regions.  The source geometry and user-visible layout do not change.

** Errors and empty states

An empty queue shows the receiver, =UNTITLED=, =0 TRACKS=, and fourteen blank
rows.  Playlist actions and radio search remain enabled.  Transport, seek, and
mode actions that require a track are visibly inactive and report a short
message if invoked by key.

Missing artwork uses the existing vinyl placeholder.  Missing metadata is
omitted.  The UI never displays =Unknown=, =N/A=, a raw nil, or a raw stream URL
as program information.

If SVG, librsvg, the raster shell, or a minimum legible viewport is unavailable,
F10 opens the implemented fancy/text playlist instead and reports why once.  If
mpv IPC is unavailable, seek, volume telemetry, and meters disable without
stopping playback.  A command reports the failed operation and the next step,
for example: =Music seek unavailable: mpv IPC socket is not connected; start a
track and try again.=

=M-x cj/music-ui-doctor= reports graphical/SVG support, resolved assets and font,
view size, last render time, mpv socket state, meter filter state, telemetry
timer state, and the last telemetry error.  It does not log private file paths
or stream URLs unless called with a debug prefix.

* Alternatives Considered

** Hybrid raster skin plus dynamic SVG (chosen)

- Good, because it preserves the leather, glass, brass grain, and machined
  highlights from the approved board while keeping every changing value honest.
- Bad, because the neutral raster source and SVG geometry must stay aligned.
- Neutral, because the result is still one SVG application document even though
  the document embeds raster assets.

** Rebuild the complete receiver as vector geometry

- Good, because every surface would scale without raster limits and theme tokens
  could recolor everything.
- Bad, because reproducing leather, brushed brass, glass, and irregular reflected
  light would take much longer and would look less like the approved board.
- Neutral, because simple Dupre controls still supply useful vector geometry
  inside the hybrid renderer.

** Use the final PNG as one clickable background

- Good, because it would match the approved image immediately.
- Bad, because the PNG contains one track, one playlist, lit volume segments,
  meter needles, progress, and button state.  Painting over those areas would
  flatten the material texture and produce visible patches.
- Neutral, because a cleaned neutral derivative of the PNG is the chosen shell.

** Browser/xwidget application

- Good, because browser SVG supports native DOM events and partial element
  updates.
- Bad, because it introduces a browser runtime inside Emacs, complicates window
  integration, and weakens TTY and configuration portability.
- Neutral, because browser prototypes remain useful before the svg.el port.

** Replace the EMMS playlist buffer in place

- Good, because no second buffer name or adapter is needed.
- Bad, because EMMS commands depend on point and text markers while the SVG is
  one displayed image glyph.  Mixing invisible rows and image coordinates would
  be brittle.
- Neutral, because the dedicated view still delegates every operation to the
  existing EMMS buffer in v1.

* Decisions [10/10]

** DONE Hybrid raster/SVG rendering
- Context: the final board's realism comes from material texture and reflected
  light, while live state must remain replaceable.
- Decision: We will embed a neutral raster skin in an SVG scene and render all
  changing information, needles, lights, and selection as SVG.
- Consequences: easier, the running UI can closely match the board.  Harder, the
  asset export and SVG geometry need one measured coordinate system.

** DONE Craig's final board is the visual authority
- Context: the design session produced many useful directions, but implementation
  needs one source for proportion and material treatment.
- Decision: We will use concept 30, Craig's 1916×821 GIMP refinement, as the
  layout and appearance authority.
- Consequences: easier, visual disputes can be checked against one board.  Harder,
  the radio state must be derived without drifting from that hardware.

** DONE Neutral physical shell
- Context: the final flattened PNG contains transient information and active
  state.
- Decision: We will create an editable neutral source and export a clean shell,
  control sprites, and neutral VU face.  No live state remains in those assets.
- Consequences: easier, texture stays realistic.  Harder, Phase 1 includes careful
  image cleanup before application code can look finished.

** DONE Dedicated graphical view buffer
- Context: EMMS playlist operations are point/marker based and cannot treat one
  SVG image as fourteen text rows.
- Decision: We will render into =*Music Player*= and use controller adapters to
  operate on the hidden EMMS playlist buffer.
- Consequences: easier, the SVG renderer stays clean and future-backend ready.
  Harder, selection and reorder commands need explicit index-to-marker adapters.

** DONE One geometry table for drawing and input
- Context: separate hand-maintained visual and hit maps will drift.
- Decision: We will measure the final board once and derive rendering, hit tests,
  clipping, and scaling from the same constants.
- Consequences: easier, controls stay clickable after scaling.  Harder, geometry
  extraction is a named deliverable rather than ad hoc coordinates in draw code.

** DONE Direct control semantics
- Context: every faceplate control must perform real music-config behavior.
- Decision: We will map the approved transport, modes, radio search, playlist
  actions, seek, and volume controls directly to their existing commands or the
  named mpv additions in this spec.
- Consequences: easier, the interface is self-explanatory.  Harder, commands not
  approved for the faceplate remain keyboard/M-x only and need discoverable help.

** DONE Persistent per-player volume
- Context: the existing +/- path can change the system mixer, while the design's
  knob is the player's volume and mpv restarts for each track.
- Decision: We will store volume in music-config, write mpv's volume property,
  and apply the stored value when every new mpv process starts.
- Consequences: easier, the knob is truthful and track changes preserve level.
  Harder, one more piece of runtime state must stay synchronized with mpv.

** DONE Real meter data through mpv astats
- Context: random needle animation would violate the design's functional-lighting
  rule.
- Decision: We will read left/right RMS metadata from a labeled FFmpeg astats
  filter over mpv IPC and apply physical needle smoothing.
- Consequences: easier, the VUs convey real program level.  Harder, a visible
  view needs a small persistent IPC telemetry client and bounded refresh timer.

** DONE Current text views remain fallbacks
- Context: TTY frames and SVG/asset failures need a usable player, and the
  implemented fancy text UI already works.
- Decision: We will add an SVG enable flag and fall back to the current fancy or
  plain text path without changing M3U or playback state.
- Consequences: easier, rollout and rollback are safe.  Harder, the text path
  remains maintained alongside the SVG application.

** DONE Three-region render path after measurement
- Context: =svg-possibly-update-image= rerasterizes an SVG image, so ten full
  receiver renders per second may exceed the dock's CPU budget.
- Decision: The prototype benchmark measured the full receiver at 133.616 ms
  median / 139.822 ms p95 and the display-sized lower-deck tile at 35.513 ms
  median / 38.221 ms p95.  We will use three aligned regions and refresh only
  the lower deck at meter cadence.
- Consequences: easier, meter animation passes the render budget with margin.
  Harder, the renderer places three images and the asset export must hide their
  boundaries exactly.

* Review findings [0/1]

** TODO The final interaction model has no working two-state prototype :blocking:

The design session produced extensive static boards and established concept 30
as the visual authority, but the final geometry has not been exercised as a
working local-playlist and radio prototype.  That leaves click targets, drag
behavior, playlist scrolling, long-text clipping, local/radio state changes,
and the full-image render budget unproven.  Starting implementation now would
make the first build phase answer product and performance questions that belong
in the design gate.

Smallest resolution: create one functional prototype using concept 30's
geometry and neutral skin.  It may be a browser prototype or an Emacs SVG proof,
but it must switch between a long local playlist and a live-radio fixture; wire
transport, modes, radio search, playlist actions, row and scrollbar navigation,
seek, and volume interaction; show all pressed and latched states; stress long
metadata; and record one minute of render timing at the intended dock size.
Link the accepted prototype under Prototype iterations and Design, record any
geometry or performance changes here, then repeat spec review.

Progress on 2026-07-19: [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][prototype 1]] now supplies both fixtures and the named
interactions; its twelve-check behavior pass is green.  The [[file:prototypes/2026-07-19-music-config-ui-remodel-benchmark.org][librsvg benchmark]]
records a full-render failure and a passing lower-deck tile, so the spec now
requires the three-region renderer.  Craig's hands-on acceptance is the only
remaining part of this finding.

* Implementation phases

** Phase 1 — Neutral skin and geometry manifest

Create the editable neutral source from concept 30.  Export aligned upper-glass,
lower-deck, and playlist crops plus control sprites and the VU face under final
dated asset names.  Record measured
source rectangles, anchors, clip boxes, and hit targets in one Lisp geometry
table.  Add an asset/geometry debug command that renders target outlines over the
skin.  The phase ends with a static SVG in Emacs that matches the final board and
contains no baked live state.

** Phase 2 — Pure SVG renderer and view mode

Add =modules/music-svg-ui.el=, the state structs, pure layout helpers, raster
embedding cache, text clipping, dynamic node construction, and
=cj/music-svg-mode=.  F10 can show/hide the static graphical view while the
existing fancy/text path remains available.  Add unit tests for scale transforms,
hit testing, truncation, scrollbar math, mode colors, and VU angle mapping.

** Phase 3 — Controller snapshot and playlist viewport

Build state snapshots from EMMS without exposing EMMS objects to the renderer.
Render metadata, album art, header, fourteen rows, selection, and the exact
scrollbar.  Implement keyboard and mouse scrolling, row selection/play, and
index-to-EMMS-marker adapters.  Characterize existing reorder/removal behavior
before routing those keys through the graphical view.

** Phase 4 — Transport, modes, radio search, and playlist actions

Wire the approved faceplate controls and pressed/latched rendering.  Preserve
the remaining keyboard-only commands and add a concise help surface.  Cover
empty-queue behavior, destructive Delete confirmation, command errors, and
state refresh hooks.  The phase ends with a complete functional control surface
using the existing backend.

** Phase 5 — Seek and persistent mpv volume

Add player-owned volume state and apply it on process start.  Route +/−, wheel,
click, and drag through the same volume setters.  Add absolute seek and drag
confirmation using mpv time/duration.  Render local progress and the exact brass
thumb.  Unit-test value/coordinate mapping and use a fake IPC ledger for command
order.

** Phase 6 — Stereo telemetry and timed refresh

Add the labeled astats filter, persistent nonblocking telemetry connection,
JSON request/reply routing, meter parsing, dB mapping, and needle ballistics.
Run progress and meter timers only while visible and active.  Measure the render
budget for one minute and use the documented three-region fallback if needed.
Test with the synthetic no-audio-output source used during spec research.

** Phase 7 — Radio state, failures, and diagnostics

Render the matched live-radio state with exactly two ON AIR labels and no seek
surface.  Handle missing art/metadata, unavailable SVG/assets/font, lost mpv IPC,
missing meter metadata, hidden-window timer shutdown, and an empty queue.  Add
=cj/music-ui-doctor= and verify that fallback never mutates playback or playlist
state.

** Phase 8 — Integration, documentation, and live verification

Run the focused music tests, batch load, byte compilation, TTY fallback, and GUI
daemon verification.  Exercise a long local playlist, a short radio playlist,
seek, volume across track changes, every control, scrolling, reorder, deletion,
and one-hour timer stability.  Update music documentation and key hints.  Make
the SVG view the graphical default only after Craig accepts the live result.

* Acceptance criteria

- [ ] F10 opens the Dupre Studios receiver in the bottom side window on a
  graphical frame and toggles it closed without changing playback.
- [ ] The running receiver matches concept 30 in proportion, material character,
  spacing, typography, and control placement at the normal dock size.
- [ ] Leather, glass, brass, fixed engraving, and neutral hardware come from the
  raster skin; live information and illumination are not baked into it.
- [ ] The UI remains fully usable from the keyboard.
- [ ] Every visible button maps to the command named in this spec.
- [ ] Pressed, playing, and latched mode states are physically and chromatically
  distinct.
- [ ] Local metadata uses separate lines and omits missing values.  No visible
  program field says Unknown or N/A.
- [ ] Long metadata and playlist rows truncate with an ellipsis before colliding
  with adjacent fields.
- [ ] The analog header card shows only the collection/search name and item
  count; it never adds a PLAYLIST or RADIO type label.
- [ ] Champagne surfaces use a fine low-contrast metallic micro-brush and never
  read as wood grain.
- [ ] The playlist shows fourteen one-line rows with artist inline, selected row
  amber, and a functional scrollbar whose size and position follow the formulas.
- [ ] Mouse wheel, keyboard navigation, scrollbar drag, row click/play, reorder,
  and removal operate on the intended EMMS tracks.
- [ ] ADD, NEW, LOAD, SAVE, and DELETE preserve current playlist/M3U semantics.
- [ ] DELETE uses the existing strong confirmation and reports which playlist was
  deleted.
- [ ] A local track displays actual elapsed/duration and supports click/drag seek.
- [ ] The seek thumb is brass and its position comes from mpv state.
- [ ] A live station has no slider or times and shows exactly two ON AIR labels.
- [ ] The volume knob controls mpv, not the system mixer, and persists across
  track changes.
- [ ] Volume segments fill cumulatively to the stored mpv volume and have no
  numeric display.
- [ ] VU needles use distinct real left/right RMS values, rest on missing data,
  and never use random animation.
- [ ] Paused, stopped, hidden, and TTY states run no meter/progress timer.
- [ ] Full or tiled rendering meets the median/95th-percentile budget during a
  one-minute meter run.
- [ ] Empty playlist, missing art, missing metadata, missing SVG/assets, and lost
  mpv IPC each have the fallback or actionable error defined in this spec.
- [ ] =cj/music-ui-doctor= reports the renderer and telemetry state without
  exposing file paths or stream URLs by default.
- [ ] Setting the SVG enable flag off restores the implemented fancy/text UI.
- [ ] Existing music-config tests pass, and new pure tests cover geometry,
  snapshots, hit targets, clipping, scrolling, volume, seek, meter mapping, and
  timer lifecycle.
- [ ] Craig accepts both a long local-playlist state and a live-radio state in the
  real Emacs side window before the SVG view becomes the default.

* Readiness dimensions

- Data model & ownership: EMMS and M3U remain authoritative.  The SVG snapshot,
  pressed target, viewport offset, meter smoothing, and render timing are
  generated runtime state.  Player volume is music-config runtime state applied
  to each mpv process.  Raster source assets are project-authored and versioned.
- Errors, empty states & failure: defined in the Errors and empty states section.
  Playback continues if rendering or meter telemetry fails.  Destructive
  playlist deletion retains the existing strong confirmation.
- Security & privacy: no credentials are added.  Diagnostics omit local paths and
  stream URLs by default.  Album art and radio favicons stay in the existing
  local cache.
- Observability: =cj/music-ui-doctor= exposes assets, font, viewport, render
  timing, socket/filter/timer state, and last telemetry error.  The UI itself
  exposes player state through lamps, needles, progress, and selection.
- Performance & scale: fourteen visible rows from playlists tested through at
  least 1,000 tracks.  SVG refresh has explicit median/95th-percentile budgets,
  a one-minute test, and a pre-approved tiled fallback.  Hidden views do no timed
  work.
- Reuse & lost opportunities: reuses the current music commands, EMMS state,
  M3U/radio/art code, bottom side window, Dupre tokens, =svg.el=, and the gallery
  widget proof.  It deliberately does not wait for the EMMS-free/VAMP rewrite.
- Architecture fit & weak points: new renderer module is pure at its boundary;
  music-config owns EMMS adaptation and mpv effects.  Weak points are raster/SVG
  alignment, point-based EMMS adapters, full-image rerasterization, and telemetry
  lifecycle.  Geometry sharing, adapter tests, tiled fallback, and visibility-
  scoped IPC mitigate them.
- Config surface: add =cj/music-svg-ui= (boolean, default off until live acceptance,
  then on) and =cj/music-player-volume= (integer 0–100, default 100).  Keep
  =cj/music-fancy-ui= as the fallback selector.  Refresh rates and geometry are
  internal until real use proves a customization need.
- Documentation plan: update music-config commentary/docstrings, F10/keybinding
  notes, the music VERIFY task, and the design README.  The final spec and dated
  runtime assets remain linked from the parent task.
- Dev tooling: use the existing ERT/byte-compile commands, focused music test
  files, Emacs daemon live verification, and a deterministic synthetic mpv meter
  script/fixture with =ao=null=.  No network or audible output in the normal
  suite.
- Rollout, compatibility & rollback: SVG is additive and initially disabled.
  Fallback is automatic.  Rollback is setting =cj/music-svg-ui= nil or reverting
  the new renderer/controller changes; M3U files and cached art do not migrate.
- External APIs & deps: built-in Emacs 30.2 =svg.el= and librsvg are the render
  path.  mpv 0.41 and FFmpeg 8.1 were checked locally.  Official mpv and FFmpeg
  documentation confirms labeled audio-filter metadata and astats keys.

* Risks, Rabbit Holes, and Drawbacks

- Cleaning a neutral skin from a flattened final board can produce visible
  texture patches.  Keep the layered source, use broad material samples rather
  than small clone spots, and approve the neutral shell before wiring state.
- Full-image librsvg refresh may be too expensive at meter cadence.  Measure in
  the prototype.  Use the specified three-region split rather than lowering the
  meter to a decorative crawl.
- EMMS commands expect point in the playlist buffer.  Keep every index-to-marker
  translation in one controller adapter and test reorder/remove against the same
  logical track.
- SVG text metrics can differ from Emacs face metrics.  Use the installed Dupre
  fixed-width font, fixed boxes, clipping paths, and visual stress fixtures with
  long titles.
- An mpv filter may fail for an unusual audio format.  Playback wins: leave the
  meter at rest, show the failure in the doctor, and never stop the track.
- The raster skin limits infinite scaling and alternate themes.  V1 targets the
  current dock and approved aesthetic.  Multiple skins and responsive reflow are
  separate work.

* Testing / Verification / Rollout

Pure ERT tests cover layout transforms, geometry/hit agreement, text fitting,
playlist window/scrollbar math, state-to-color mapping, volume/seek conversion,
VU dB/angle mapping, ballistics, and timer state.  Controller tests use an EMMS
fixture or stubs and an mpv IPC ledger so they do not play sound.

Integration tests build representative local and radio snapshots, render SVG
strings, and assert required IDs, text, clip paths, and state classes.  They do
not use pixel-perfect screenshots as the main contract because librsvg/font
versions can change antialiasing.  A small set of manual reference screenshots
supports the visual acceptance step.

The live pass runs in the real bottom side window with the normal long playlist
and a radio playlist.  It covers every faceplate control, keyboard parity,
scrolling, long strings, seek, persistent volume, two-channel meters, exactly two
ON AIR states, hidden-window timer shutdown, and fallback.  The SVG flag changes
to default-on only after that pass.

* References / Appendix

- [[file:../../docs/specs/2026-07-06-fancy-music-player-ui-spec.org][Implemented fancy music-player UI spec]]
- [[file:../../docs/specs/music-config-without-emms-spec.org][Music-config without EMMS architecture spec]]
- [[file:README.org][Music SVG design record]]
- [[file:concepts/30a-dupre-studios-user-refined-playlist.png][Near-final playlist board]]
- [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][Functional two-state prototype]]
- [[file:prototypes/2026-07-19-music-config-ui-remodel-benchmark.org][Prototype librsvg benchmark]]
- [[https://www.gnu.org/software/emacs/manual/html_node/elisp/SVG-Images.html][Emacs Lisp SVG images]]
- [[https://mpv.io/manual/master/#json-ipc][mpv JSON IPC]]
- [[https://mpv.io/manual/master/#command-interface-af-metadata][mpv audio-filter metadata]]
- [[https://ffmpeg.org/ffmpeg-filters.html#astats-1][FFmpeg astats]]

* Review and iteration history

** 2026-07-19 Sun @ 19:11:57 -0500 — Codex (emacs-d) — hardware-depth correction
- What: changed the upper boundary of the lower deck from a raised champagne
  rim to a dark glass reveal descending into the brass faceplate.  Unified all
  four play-mode and both radio-search controls as blank, circularly machined
  brass pushbutton caps.  Removed the returned search glyphs and expanded then
  tightened the source crop to preserve the volume knob's complete black
  knurled skirt without importing the old faceplate halo.
- Why: the prior neutral-faceplate overlay flattened the glass/metal depth,
  allowed the small-control treatments to diverge, and clipped the knob at a
  perfect circle that hid its physical knurling.  These changes restore a
  believable assembly hierarchy while retaining state-owned lamps.
- Artifacts: updated [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][functional prototype 1]]; twelve-check interaction regression green.

** 2026-07-19 Sun @ 18:43:00 -0500 — Codex (emacs-d) — prototype refinement
- What: replaced the baked lower-deck faceplate with a neutral SVG-owned
  champagne micro-brush surface, then restored only the approved volume knob
  through a circular crop.  Re-engraved the fixed control labels on the new
  surface and reduced the volume arc to small dark wells with state-owned amber
  cores and local glow.  Verified both local and radio layouts and reran the
  twelve-check headless interaction pass successfully.
- Why: masking individual source-image lamps left visible baked illumination and
  made the faceplate look patched.  Owning the complete neutral deck surface in
  SVG removes the conflicting lamp state and the woodlike raster grain while
  retaining the realistic machined knob from the approved visual authority.
- Artifacts: updated [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][functional prototype 1]]; local and radio state screenshots.

** 2026-07-19 Sun @ 18:39:41 -0500 — Codex (emacs-d) — prototype refinement
- What: applied Craig's second hands-on pass.  Removed source-type words and the
  separator from the analog card; changed radio fixture naming to =NAME SEARCH=;
  replaced the circular seek ornament with a vertical machined-brass grip;
  removed all mode-cap glyphs and matched their smooth spun-brass finish to the
  volume cap; and rebuilt the volume arc as dark recessed wells whose amber core
  and glow exist only for lit positions.
- Why: the card should identify the current collection/search rather than report
  an internal playlist/radio type.  The prior seek coin had no hardware model,
  the mode symbols duplicated their faceplate labels, and baked light spill made
  some nominally dark volume positions glow.  The spec now also rejects coarse,
  wavy champagne texture that reads as wood grain.
- Artifacts: updated [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][functional prototype 1]]; Craig's 18:29–18:32 screenshots.

** 2026-07-19 Sun @ 18:19:28 -0500 — Codex (emacs-d) — prototype refinement
- What: incorporated Craig's first hands-on notes.  Rebuilt play modes as
  alternate-action brass pushbuttons with engraved glyphs, visible travel, and
  a restrained inset green ring; tightened Play/Pause illumination; aligned
  each volume lamp's dark and lit state to one physical well; restored four
  concealed warm-light pools on a darker coffee/cream playlist card; and made
  the prototype's synthetic-VU / production-signal distinction explicit.
- Why: the prior controls read as glowing domes, the green looked like a neon
  outline, the flattened source and live volume arcs produced double lamps, and
  the playlist card had lost its analog illumination model.  Production VUs
  remain tied to real mpv astats RMS data as already specified.
- Artifacts: updated [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][functional prototype 1]]; Craig's 17:59–18:03 screenshots.

** 2026-07-19 Sun @ 17:56:27 -0500 — Codex (emacs-d) — prototype author
- What: built functional prototype 1 from concept 30 with local and radio
  fixtures, all approved faceplate controls, long-string stress data, exactly
  fourteen visible rows, scrollbar and seek/volume drag, pressed/latched states,
  empty/delete flows, keyboard navigation, and synthetic stereo needle motion.
  Its built-in twelve-check behavior pass is green.  Measured librsvg for one
  minute per path: full receiver 133.616 ms median / 139.822 ms p95 (fail),
  display-sized lower deck 35.513 ms median / 38.221 ms p95 (pass).
- Why: this supplies the interaction and performance evidence requested by the
  first review finding.  The measured result makes the three-region renderer a
  requirement rather than a contingency.  Craig's hands-on prototype acceptance
  remains pending, so the finding stays open and the spec stays DRAFT.
- Artifacts: [[file:prototypes/2026-07-19-music-config-ui-remodel-prototype-1.html][functional prototype 1]]; [[file:prototypes/2026-07-19-music-config-ui-remodel-benchmark.org][benchmark record]];
  [[file:2026-07-19-music-config-ui-remodel-render-fixture.svg][full-render fixture template]].

** 2026-07-19 Sun @ 16:16:57 -0500 — Codex (emacs-d) — reviewer
- What: completed the first implementation-readiness review after reading the
  current music-config render, EMMS playlist, radio, mpv IPC, and volume paths.
  Assigned =Not ready= and recorded one blocking finding: the approved final
  board is static, so its two application states, hit/drag/scroll behavior, and
  rendering budget have not passed the project's functional-prototype gate.
- Why: the architecture, ownership, failure handling, telemetry source, rollout,
  acceptance criteria, and eight phase boundaries are otherwise specific enough
  to implement.  A working prototype is the smallest remaining test of the
  design rather than an invitation to redesign it during Phase 1.
- Artifacts: =* Review findings [0/1]= in this spec; source checks in
  =modules/music-config.el=; Dupre =gallery-widget.el= SVG proof; verified mpv
  =af-metadata/meter= / FFmpeg =astats= telemetry path.

** 2026-07-19 Sun @ 16:03:13 -0500 — Codex (emacs-d) — author
- What: drafted the Music Config UI Remodel spec from Craig's selected concept,
  manual GIMP refinement, and hybrid raster/SVG decision.  Verified the real VU
  telemetry path against the installed mpv/FFmpeg stack and primary docs.
- Why: the visual design is settled closely enough to define the renderer,
  controller boundary, interaction surface, phases, and test contract before
  implementation.
- Artifacts: [[file:concepts/30a-dupre-studios-user-refined-playlist.png][concept 30]]; local mpv astats IPC check; parent music SVG task.