;; Now-playing widget for the thin client. Installed to ;; /home//.config/eww/eww.yuck by build-thin-client-iso.sh. ;; ;; Data source: /usr/local/bin/now-playing-json, a separate `playerctl --follow` ;; process, NOT thinclient_agent's MprisBridge. The agent is a *system* service that ;; deliberately outlives the compositor, whereas this widget is session-scoped and dies ;; with sway; wiring the widget to the agent would mean either restarting the agent ;; whenever the widget restarts, or opening a second inbound control channel into it, ;; which the security boundary in mqtt_discovery.py rules out. The cost is one extra ;; playerctl subscription, which is negligible. ;; ;; The :onclick strings below are fixed constants in this file. Nothing from MQTT, HA, ;; or player metadata is ever interpolated into them. (defvar players "mpv,spotifyd,%any") (deflisten nowplaying :initial '{"visible":false,"title":"","artist":"","art":"","controls":false}' "/usr/local/bin/now-playing-json") (defwidget np-meta [] (box :orientation "vertical" :space-evenly false :halign "start" :valign "center" :hexpand true (label :class "np-title" :text nowplaying.title :halign "start" :limit-width 34 :truncate true) (label :class "np-artist" :text nowplaying.artist :halign "start" :limit-width 34 :truncate true))) ;; Hidden rather than absent when the player exposes no transport control (some ;; sources only report metadata) — the widget then degrades to art + text. (defwidget np-controls [] (box :class "np-controls" :orientation "horizontal" :space-evenly true :spacing 4 :visible {nowplaying.controls} :valign "center" (button :class "np-btn" :onclick "playerctl -p ${players} previous" "⏮") (button :class "np-btn" :onclick "playerctl -p ${players} play-pause" "⏯") (button :class "np-btn" :onclick "playerctl -p ${players} next" "⏭"))) (defwidget np-root [] (box :class "np-root" :orientation "horizontal" :space-evenly false :spacing 12 :visible {nowplaying.visible} (image :class "np-art" :path nowplaying.art :image-width 72 :image-height 72) (np-meta) (np-controls))) ;; :exclusive false — the widget floats over whatever is on screen and must never ;; reserve layer-shell space, or it would shrink the fullscreen media surfaces this ;; whole image exists to show. Visibility is owned by fullscreen-watcher.sh, which ;; opens and closes this window; the :visible binding above only handles "nothing is ;; playing at all". (defwindow now-playing :monitor 0 :geometry (geometry :x "24px" :y "24px" :anchor "bottom left" :width "420px" :height "96px") :stacking "overlay" :exclusive false :focusable false (np-root))