From 1619da056a70ad8a9400353ccc8333d7e6416474 Mon Sep 17 00:00:00 2001 From: Supratim Samanta Date: Tue, 18 Aug 2026 13:21:31 -0400 Subject: [PATCH 1/2] style(eww): revamp mpd player widget design and animations - Redesigned player play/pause SVGs to filled black circles with colored icons - Stylized the expand arrow with a blue fill and glowing hover effect - Shrunk expand arrow spacing to bring it closer to the player circle - Added active state scale/opacity clicks to player shape buttons - Switched popup revealers from crossfade to slideup Co-authored-by: Gemini --- .config/eww/assets/player-expand.svg | 7 +------ .config/eww/assets/player-pause.svg | 12 +++--------- .config/eww/assets/player-play.svg | 12 ++---------- .config/eww/eww.scss | 15 ++++++++++++--- .config/eww/eww.yuck | 6 +++--- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/.config/eww/assets/player-expand.svg b/.config/eww/assets/player-expand.svg index be89569..51255ef 100644 --- a/.config/eww/assets/player-expand.svg +++ b/.config/eww/assets/player-expand.svg @@ -1,8 +1,3 @@ - - - - + diff --git a/.config/eww/assets/player-pause.svg b/.config/eww/assets/player-pause.svg index fad66c1..e9e79b7 100644 --- a/.config/eww/assets/player-pause.svg +++ b/.config/eww/assets/player-pause.svg @@ -1,11 +1,5 @@ - - - - - - - + + + diff --git a/.config/eww/assets/player-play.svg b/.config/eww/assets/player-play.svg index 653f172..2f56e25 100644 --- a/.config/eww/assets/player-play.svg +++ b/.config/eww/assets/player-play.svg @@ -1,12 +1,4 @@ - - - - - - + + diff --git a/.config/eww/eww.scss b/.config/eww/eww.scss index e360298..7c9e595 100644 --- a/.config/eww/eww.scss +++ b/.config/eww/eww.scss @@ -67,6 +67,7 @@ box-shadow: none; padding: 0; margin: 0; + transition: all 0.15s ease; } .player-shape-btn:hover { @@ -74,6 +75,11 @@ SVG, reintroducing exactly the shape this design avoids. */ background-color: transparent; background-image: none; + opacity: 0.85; +} + +.player-shape-btn:active { + opacity: 0.6; } /* Defines the collapsed state's overall footprint (it is the overlay's @@ -85,8 +91,8 @@ top-left, and the triangle's lower tip ends at ~18px. */ .player-collapsed-sizer { background-color: transparent; - min-width: 72px; - min-height: 72px; + min-width: 68px; + min-height: 68px; } /* The separate expand triangle -- no negative margin: it is positioned @@ -99,11 +105,14 @@ box-shadow: none; padding: 0; margin: 0; + border-radius: 50%; + transition: all 0.2s ease; } .player-expand-arrow:hover { - background-color: transparent; + background-color: rgba(0, 162, 255, 0.15); background-image: none; + box-shadow: 0 0 12px 4px rgba(0, 162, 255, 0.4); } /* Expanded state: a taller card. */ diff --git a/.config/eww/eww.yuck b/.config/eww/eww.yuck index 18bb3ed..dff3812 100644 --- a/.config/eww/eww.yuck +++ b/.config/eww/eww.yuck @@ -87,7 +87,7 @@ ;; :visible false drops the widget from allocation entirely; the ;; revealer inside it still provides the reveal animation. (box :visible {!player_expanded} - (revealer :transition "crossfade" :duration "250ms" :reveal {!player_expanded} + (revealer :transition "slideup" :duration "250ms" :reveal {!player_expanded} ;; The sizer is the overlay's first (size-determining) child: ;; a bit larger than the 64px circle, so the arrow can sit in ;; the empty upper-left corner *outside* the circle's arc @@ -110,7 +110,7 @@ ;; toggle/stop pair, plus collapse (back to the circle) and close ;; (this instance only, see win-id above) in the corner. (box :visible {player_expanded} - (revealer :transition "crossfade" :duration "300ms" :reveal {player_expanded} + (revealer :transition "slideup" :duration "300ms" :reveal {player_expanded} (overlay (box :orientation "v" :space-evenly false :halign "center" :class "player-card" (image :class "player-albumart" :path {mpd_status.albumart} :image-width 120 :image-height 120) @@ -131,7 +131,7 @@ ;; different widths too, not just heights, and a fixed width would ;; leave the small circle floating in the middle of reserved space ;; instead of flush against the corner. - :geometry (geometry :x "5px" :y "15px" :width "1px" :height "1px" :anchor "bottom right") + :geometry (geometry :x "10px" :y "15px" :width "1px" :height "1px" :anchor "bottom right") :stacking "fg" :windowtype "normal" (mpd-player-widget :win-id win-id)) From 5cbf078a29aa6b7e2ec94f28378ab1be53453a11 Mon Sep 17 00:00:00 2001 From: Supratim Samanta Date: Tue, 18 Aug 2026 15:00:58 -0400 Subject: [PATCH 2/2] feat(eww): implement native mpd search dashboard - Replaced old mpd-player-card with a massive dashboard layout. - Added native text input search mapped to `mpc search`. - Added tabs for filtering by Track, Playlist, and Artist. - Added background listen script for real-time json search results. - Fixed button geometry shifting during play/pause toggles. Co-authored-by: Gemini --- .config/eww/eww.scss | 3 + .config/eww/eww.yuck | 17 +- .config/eww/mpd-dashboard.scss | 217 ++++++++++++++++++ .config/eww/mpd-dashboard.yuck | 96 ++++++++ .config/eww/scripts/dashboard-action.sh | 22 ++ .config/eww/scripts/dashboard-queue-listen.sh | 33 +++ .../eww/scripts/dashboard-search-listen.sh | 48 ++++ .config/eww/scripts/lyrics-listen.sh | 10 +- .config/eww/scripts/mpd-player-status.sh | 11 +- 9 files changed, 441 insertions(+), 16 deletions(-) create mode 100644 .config/eww/mpd-dashboard.scss create mode 100644 .config/eww/mpd-dashboard.yuck create mode 100755 .config/eww/scripts/dashboard-action.sh create mode 100755 .config/eww/scripts/dashboard-queue-listen.sh create mode 100755 .config/eww/scripts/dashboard-search-listen.sh diff --git a/.config/eww/eww.scss b/.config/eww/eww.scss index 7c9e595..819a494 100644 --- a/.config/eww/eww.scss +++ b/.config/eww/eww.scss @@ -156,6 +156,8 @@ padding: 2px 8px; margin: 0 2px; border-radius: 6px; + min-width: 20px; + min-height: 20px; } .mpd-btn:hover { @@ -174,3 +176,4 @@ color: #ffffff; background-color: rgba(255, 255, 255, 0.15); } +@import "mpd-dashboard"; diff --git a/.config/eww/eww.yuck b/.config/eww/eww.yuck index dff3812..e6c87d8 100644 --- a/.config/eww/eww.yuck +++ b/.config/eww/eww.yuck @@ -1,3 +1,4 @@ +(include "./mpd-dashboard.yuck") ;; Lyrics scroll widget -- pinned always-on-top overlay showing the ;; current synced (.lrc) lyrics line with 1 line of context above and 2 ;; below, sourced from "mpdtui -lyrics-line" via scripts/lyrics-listen.sh @@ -44,13 +45,14 @@ :geometry (geometry :x "0%" :y "4%" :width "620px" :height "1px" :anchor "top center") :stacking "fg" :windowtype "normal" + (lyrics-widget)) ;; Collapsible player, bottom-right. "mpc toggle" flips play<->pause in ;; one command (matches every real media player's own single toggle ;; button rather than separate always-visible Play/Pause buttons, which ;; would be redundant given the state is already known). -(deflisten mpd_status :initial "{\"state\": \"stop\", \"artist\": \"\", \"title\": \"\", \"albumart\": \"/tmp/eww-mpd-albumart-placeholder.png\"}" +(deflisten mpd_status :initial "{\"state\": \"stop\", \"artist\": \"\", \"title\": \"\", \"albumart\": \"/tmp/eww-mpd-albumart-placeholder.png\", \"year\": \"\", \"composer\": \"\", \"queue_length\": \"0\"}" "~/.config/eww/scripts/mpd-player-status.sh") ;; Shared across both monitor instances (not per-window/[win-id]-scoped @@ -106,19 +108,11 @@ (image :path "${player_assets}/player-expand.svg" :image-width 20 :image-height 20))))) - ;; Expanded: a taller card -- album art, title, artist, the same - ;; toggle/stop pair, plus collapse (back to the circle) and close - ;; (this instance only, see win-id above) in the corner. + ;; Expanded: the new massive dashboard (box :visible {player_expanded} (revealer :transition "slideup" :duration "300ms" :reveal {player_expanded} (overlay - (box :orientation "v" :space-evenly false :halign "center" :class "player-card" - (image :class "player-albumart" :path {mpd_status.albumart} :image-width 120 :image-height 120) - (label :class "player-title" :text {mpd_status.title == "" ? "Nothing playing" : mpd_status.title} :limit-width 28) - (label :class "player-artist" :text {mpd_status.artist} :limit-width 28) - (box :orientation "h" :space-evenly false :halign "center" :class "player-controls" - (button :class "mpd-btn" :onclick "mpc toggle" {mpd_status.state == "playing" ? "⏸" : "▶"}) - (button :class "mpd-btn" :onclick "mpc stop" "⏹"))) + (mpd-dashboard-widget) (box :orientation "h" :halign "end" :valign "start" :class "player-card-actions" (button :class "mpd-close" :onclick "eww update player_expanded=false" "⌄") (button :class "mpd-close" :onclick "eww close ${win-id}" "✕"))))))) @@ -134,4 +128,5 @@ :geometry (geometry :x "10px" :y "15px" :width "1px" :height "1px" :anchor "bottom right") :stacking "fg" :windowtype "normal" + :focusable true (mpd-player-widget :win-id win-id)) diff --git a/.config/eww/mpd-dashboard.scss b/.config/eww/mpd-dashboard.scss new file mode 100644 index 0000000..4af35a7 --- /dev/null +++ b/.config/eww/mpd-dashboard.scss @@ -0,0 +1,217 @@ +.dashboard-container { + background-color: rgba(20, 20, 20, 0.95); + border-radius: 12px; + padding: 20px; + color: #ffffff; + font-family: "DejaVu Sans", sans-serif; + min-height: 450px; + min-width: 950px; +} + +.dashboard-left { + padding-right: 20px; + border-right: 1px solid rgba(255, 255, 255, 0.1); +} + +.dashboard-now-playing { + margin-bottom: 20px; +} + +.dashboard-albumart { + border-radius: 8px; + margin-right: 15px; +} + +.dashboard-title { + font-size: 16px; + font-weight: bold; + margin-bottom: 5px; +} + +.dashboard-album, .dashboard-year, .dashboard-composer { + font-size: 13px; + color: #aaaaaa; + margin-bottom: 2px; +} + +.dashboard-controls { + margin-top: 10px; +} + +.dashboard-progress-container { + margin-top: 15px; + margin-bottom: 5px; + padding-right: 15px; +} + +.dashboard-time { + font-size: 11px; + color: #888888; + margin-bottom: 2px; +} + +.dashboard-progress { + background-color: rgba(255, 255, 255, 0.1); + border-radius: 4px; +} + +.dashboard-progress trough { + background-color: rgba(255, 255, 255, 0.1); + border-radius: 4px; + min-height: 4px; +} + +.dashboard-progress highlight { + background-color: #00a2ff; + border-radius: 4px; +} + +.dashboard-lyrics { + background-color: rgba(0, 0, 0, 0.3); + border-radius: 8px; + padding: 10px; +} + +.dashboard-lyrics-title { + font-weight: bold; + color: #888; + margin-bottom: 10px; + font-size: 12px; +} + +.dashboard-lyrics-content label { + margin-bottom: 4px; +} + +.dashboard-lyrics-current { + color: #ffe66d; + font-weight: bold; +} + +.dashboard-right { + padding-left: 20px; +} + +.dashboard-search-bar { + margin-bottom: 15px; + margin-right: 70px; +} + +.dashboard-search-input { + background-color: rgba(255, 255, 255, 0.1); + border-radius: 6px; + padding: 8px 12px; + color: white; + border: 1px solid transparent; +} + +.dashboard-search-input:focus { + border: 1px solid #00a2ff; +} + +.dashboard-search-btn { + background-color: #00a2ff; + color: white; + border-radius: 6px; + padding: 6px 16px; + margin-left: 10px; + font-weight: bold; +} + +.dashboard-filters { + margin-bottom: 20px; +} + +.dashboard-filter, .dashboard-filter-active { + padding: 6px 16px; + border-radius: 20px; + margin: 0 5px; + font-size: 13px; + background-color: rgba(255, 255, 255, 0.05); + transition: all 0.2s ease; +} + +.dashboard-filter:hover { + background-color: rgba(255, 255, 255, 0.15); +} + +.dashboard-filter-active { + background-color: #00a2ff; + color: white; + font-weight: bold; +} + +.dashboard-tab, .dashboard-tab-active { + padding: 2px 12px; + margin-bottom: 5px; + font-size: 11px; + transition: all 0.2s ease; + border-radius: 12px; + background-color: rgba(255, 255, 255, 0.05); +} + +.dashboard-tab:hover { + background-color: rgba(255, 255, 255, 0.1); + color: #ffffff; +} + +.dashboard-tab-active { + background-color: #00a2ff; + color: white; + font-weight: bold; +} + +.dashboard-pagination { + margin-top: 10px; + font-size: 13px; + color: #aaaaaa; +} + +.dashboard-queue { + font-size: 13px; + color: #888888; + margin-left: 15px; +} + +.dashboard-results-list { + background-color: rgba(0, 0, 0, 0.2); + border-radius: 8px; + padding: 10px; +} + +.dashboard-track-row { + padding: 8px 10px; + border-bottom: 1px solid rgba(255, 255, 255, 0.05); +} + +.dashboard-track-row:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.dashboard-track-title { + font-size: 11px; + font-weight: bold; + color: #ffffff; + margin-bottom: 2px; +} + +.dashboard-track-row .dashboard-album { + font-size: 10px; + color: #888888; +} + +.dashboard-track-play { + color: #25d366; + margin-right: 15px; + font-size: 14px; +} + +.dashboard-track-add { + color: #aaa; + font-size: 16px; + padding: 0 5px; +} + +.dashboard-track-add:hover { + color: white; +} diff --git a/.config/eww/mpd-dashboard.yuck b/.config/eww/mpd-dashboard.yuck new file mode 100644 index 0000000..a760516 --- /dev/null +++ b/.config/eww/mpd-dashboard.yuck @@ -0,0 +1,96 @@ +(defvar dashboard_search_filter "track") +(defvar dashboard_search_query "") + +(defvar dashboard_left_tab "lyrics") +(defvar dashboard_queue_page 0) +(defvar dashboard_queue_total_pages 1) + + +(deflisten dashboard_queue :initial "[]" + "~/.config/eww/scripts/dashboard-queue-listen.sh") + +(deflisten dashboard_search_results :initial "[]" + "~/.config/eww/scripts/dashboard-search-listen.sh") + +(defwidget mpd-dashboard-widget [] + (box :class "dashboard-container" :orientation "h" :space-evenly false + ;; Left Pane: Now Playing & Lyrics + (box :class "dashboard-left" :orientation "v" :space-evenly false :width 450 + (box :class "dashboard-now-playing" :orientation "h" :space-evenly false + (image :class "dashboard-albumart" :path {mpd_status.albumart} :image-width 160 :image-height 160) + (box :orientation "v" :space-evenly false :vexpand true :class "dashboard-meta" + (label :class "dashboard-title" :text {mpd_status.title == "" ? "Nothing playing" : mpd_status.title} :limit-width 30 :halign "start") + (label :class "dashboard-album" :text "👤 ${mpd_status.artist}" :limit-width 30 :halign "start") + (label :class "dashboard-year" :text "📅 ${mpd_status.year}" :halign "start" :visible {mpd_status.year != ""}) + (label :class "dashboard-composer" :text "🎼 ${mpd_status.composer}" :limit-width 30 :halign "start" :visible {mpd_status.composer != ""}) + (box :vexpand true) + (box :orientation "v" :space-evenly false :class "dashboard-progress-container" + (label :class "dashboard-time" :text {mpd_status.time} :halign "end") + (scale :class "dashboard-progress" :value {mpd_status.progress} :min 0 :max 101 :onchange "mpc seek {}%")) + (box :orientation "h" :space-evenly false :halign "start" :class "dashboard-controls" + (button :class "mpd-btn" :onclick "mpc prev" "⏮") + (button :class "mpd-btn" :onclick "mpc toggle" {mpd_status.state == "playing" ? "⏸" : "▶"}) + (button :class "mpd-btn" :onclick "mpc stop" "⏹") + (button :class "mpd-btn" :onclick "mpc next" "⏭")))) + (box :class "dashboard-tabs" :orientation "h" :space-evenly false :spacing 10 + (button :class {dashboard_left_tab == "lyrics" ? "dashboard-tab-active" : "dashboard-tab"} :onclick "eww update dashboard_left_tab='lyrics'" "Lyrics") + (button :class {dashboard_left_tab == "queue" ? "dashboard-tab-active" : "dashboard-tab"} :onclick "eww update dashboard_left_tab='queue'" "Queue")) + + (box :class "dashboard-left-content" :orientation "v" :space-evenly false :vexpand true + (box :visible {dashboard_left_tab == "lyrics"} :class "dashboard-lyrics" :orientation "v" :space-evenly false :vexpand true + (scroll :vscroll true :hscroll false :vexpand true + (box :orientation "v" :space-evenly false :class "dashboard-lyrics-content" + (label :text {lyrics.above} :limit-width 100) + (label :class "dashboard-lyrics-current" + :text {lyrics.current} + :style "font-size: ${lyrics.current_size}px; opacity: ${lyrics.reveal ? 1.0 : 0.0}; transition: opacity 300ms ease-in-out;" + :limit-width 100) + (label :text {lyrics.below1} :limit-width 100) + (label :text {lyrics.below2} :limit-width 100)))) + + (box :visible {dashboard_left_tab == "queue"} :class "dashboard-queue-view" :orientation "v" :space-evenly false :vexpand true + (scroll :vscroll true :hscroll false :vexpand true + (box :orientation "v" :space-evenly false :class "dashboard-results-list" + (for item in dashboard_queue + (box :class "dashboard-track-row" :orientation "h" :space-evenly false + (button :class "dashboard-track-play" :onclick "mpc play ${item.pos}" "▶") + (box :orientation "v" :space-evenly false :hexpand true + (label :class "dashboard-track-title" :text {item.title} :halign "start" :limit-width 30) + (label :class "dashboard-album" :text {item.artist} :halign "start" :limit-width 30)))))) + (box :class "dashboard-pagination" :orientation "h" :space-evenly true + (button :onclick "eww update dashboard_queue_page=${dashboard_queue_page > 0 ? dashboard_queue_page - 1 : 0}" "◀") + (label :text "Page ${dashboard_queue_page + 1} of ${dashboard_queue_total_pages}") + (button :onclick "eww update dashboard_queue_page=${dashboard_queue_page + 1 < dashboard_queue_total_pages ? dashboard_queue_page + 1 : dashboard_queue_page}" "▶"))))) + + ;; Right Pane: Search & Library + (box :class "dashboard-right" :orientation "v" :space-evenly false :hexpand true + (box :class "dashboard-search-bar" :orientation "h" :space-evenly false + (input :class "dashboard-search-input" :value dashboard_search_query :onchange "eww update dashboard_search_query='{}'" :hexpand true) + (button :class "dashboard-search-btn" :onclick "eww update dashboard_search_query=''" "Clear")) + + (box :class "dashboard-filters-container" :orientation "h" :space-evenly false :hexpand true + (box :class "dashboard-filters" :orientation "h" :space-evenly false :halign "start" :hexpand true + (button :class {dashboard_search_filter == "track" ? "dashboard-filter-active" : "dashboard-filter"} + :onclick "eww update dashboard_search_filter='track'" "Track") + (button :class {dashboard_search_filter == "playlist" ? "dashboard-filter-active" : "dashboard-filter"} + :onclick "eww update dashboard_search_filter='playlist'" "Playlist") + (button :class {dashboard_search_filter == "artist" ? "dashboard-filter-active" : "dashboard-filter"} + :onclick "eww update dashboard_search_filter='artist'" "Artist")) + (label :class "dashboard-queue" :text "${mpd_status.queue_length} in queue" :halign "end")) + + (scroll :vscroll true :hscroll false :vexpand true :class "dashboard-results-scroll" + (box :orientation "v" :space-evenly false :class "dashboard-results-list" + (for track in dashboard_search_results + (box :class "dashboard-track-row" :orientation "h" :space-evenly false + (button :class "dashboard-track-play" :onclick "~/.config/eww/scripts/dashboard-action.sh play '${dashboard_search_filter}' '${track.file}'" "▶") + (box :orientation "v" :space-evenly false :hexpand true + (label :class "dashboard-track-title" :text {track.title} :halign "start" :limit-width 35) + (label :class "dashboard-album" :text {track.artist} :halign "start" :limit-width 35)) + (button :class "dashboard-track-add" :onclick "~/.config/eww/scripts/dashboard-action.sh add '${dashboard_search_filter}' '${track.file}'" "+")))))))) + +(defwindow mpd-dashboard-window + :monitor 0 + :geometry (geometry :x "0" :y "0" :width "750px" :height "450px" :anchor "center") + :stacking "fg" + :windowtype "normal" + (mpd-dashboard-widget)) diff --git a/.config/eww/scripts/dashboard-action.sh b/.config/eww/scripts/dashboard-action.sh new file mode 100755 index 0000000..db7e6b5 --- /dev/null +++ b/.config/eww/scripts/dashboard-action.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Handles play and add actions for dashboard items + +action="$1" # 'play' or 'add' +filter="$2" # 'track', 'playlist', or 'artist' +file="$3" + +if [ "$action" = "play" ]; then + mpc clear +fi + +if [ "$filter" = "track" ]; then + mpc add "$file" +elif [ "$filter" = "playlist" ]; then + mpc load "$file" +elif [ "$filter" = "artist" ]; then + mpc findadd artist "$file" +fi + +if [ "$action" = "play" ]; then + mpc play +fi diff --git a/.config/eww/scripts/dashboard-queue-listen.sh b/.config/eww/scripts/dashboard-queue-listen.sh new file mode 100755 index 0000000..60a0d3b --- /dev/null +++ b/.config/eww/scripts/dashboard-queue-listen.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Listens for pagination changes and queue changes, outputs queue JSON + +prev_page="" +prev_pl="" + +echo "[]" + +while true; do + page=$(eww get dashboard_queue_page 2>/dev/null || echo "0") + pl_hash=$(mpc status | grep -oP 'playlist: \K[0-9]+' || mpc playlist | wc -c) + + if [ "$page" != "$prev_page" ] || [ "$pl_hash" != "$prev_pl" ]; then + offset=$((page * 20)) + + mpc playlist -f "%position%\t%title%\t%artist%" | tail -n +$((offset + 1)) | head -n 20 | \ + jq -R -s -c ' + [ + split("\n")[:-1][] | split("\t") | + {pos: .[0], title: .[1], artist: .[2]} + ]' + + total=$(mpc playlist | wc -l) + total_pages=$(( (total + 19) / 20 )) + [ "$total_pages" -eq 0 ] && total_pages=1 + + eww update dashboard_queue_total_pages="$total_pages" 2>/dev/null + + prev_page="$page" + prev_pl="$pl_hash" + fi + sleep 0.5 +done diff --git a/.config/eww/scripts/dashboard-search-listen.sh b/.config/eww/scripts/dashboard-search-listen.sh new file mode 100755 index 0000000..c6703b5 --- /dev/null +++ b/.config/eww/scripts/dashboard-search-listen.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Listens for eww variable changes and outputs JSON search results + +prev_query="" +prev_filter="" + +# Echo an empty array to start +echo "[]" + +while true; do + query=$(eww get dashboard_search_query 2>/dev/null) + filter=$(eww get dashboard_search_filter 2>/dev/null || echo "track") + + if [ "$query" != "$prev_query" ] || [ "$filter" != "$prev_filter" ]; then + if [ -z "$query" ]; then + echo "[]" + else + if [ "$filter" = "track" ]; then + mpc -f "%title%\t%artist%\t%file%" search any "$query" | head -n 20 | \ + jq -R -s -c ' + [ + split("\n")[:-1][] | split("\t") | + {title: (if .[0] == "" then .[2] else .[0] end), artist: .[1], file: .[2]} + ]' || echo "[]" + + elif [ "$filter" = "playlist" ]; then + mpc lsplaylists | grep -i "$query" | head -n 20 | \ + jq -R -s -c ' + [ + split("\n")[:-1][] | + {title: ., artist: "Playlist", file: .} + ]' || echo "[]" + + elif [ "$filter" = "artist" ]; then + mpc list artist | grep -i "$query" | head -n 20 | \ + jq -R -s -c ' + [ + split("\n")[:-1][] | + {title: ., artist: "Artist", file: .} + ]' || echo "[]" + fi + fi + + prev_query="$query" + prev_filter="$filter" + fi + sleep 0.5 +done diff --git a/.config/eww/scripts/lyrics-listen.sh b/.config/eww/scripts/lyrics-listen.sh index 9768e15..0eae41e 100755 --- a/.config/eww/scripts/lyrics-listen.sh +++ b/.config/eww/scripts/lyrics-listen.sh @@ -70,15 +70,21 @@ while true; do current_size=$(font_size_for "${#current}") if [ "$current" != "$prev_current" ] && [ -n "$prev_current" ]; then - jq -cn --argjson visible "$playing" --argjson size "$current_size" --arg above "$above" --arg current "$prev_current" --arg below1 "$below1" --arg below2 "$below2" \ + # Fade out the old current line, keeping the old context + jq -cn --argjson visible "$playing" --argjson size "$prev_size" --arg above "$prev_above" --arg current "$prev_current" --arg below1 "$prev_below1" --arg below2 "$prev_below2" \ '{visible: $visible, reveal: false, current_size: $size, above: $above, current: $current, below1: $below1, below2: $below2}' - sleep 0.2 + sleep 0.3 fi + # Fade in the new current line with the new context jq -cn --argjson visible "$playing" --argjson size "$current_size" --arg above "$above" --arg current "$current" --arg below1 "$below1" --arg below2 "$below2" \ '{visible: $visible, reveal: true, current_size: $size, above: $above, current: $current, below1: $below1, below2: $below2}' prev_current="$current" + prev_above="$above" + prev_below1="$below1" + prev_below2="$below2" + prev_size="$current_size" else jq -cn --argjson visible "$playing" \ '{visible: $visible, reveal: true, current_size: 15, above: "", current: "", below1: "", below2: ""}' diff --git a/.config/eww/scripts/mpd-player-status.sh b/.config/eww/scripts/mpd-player-status.sh index c92620f..f759415 100755 --- a/.config/eww/scripts/mpd-player-status.sh +++ b/.config/eww/scripts/mpd-player-status.sh @@ -25,6 +25,11 @@ while true; do artist=$(mpc current -f '%artist%' 2>/dev/null) title=$(mpc current -f '%title%' 2>/dev/null) file=$(mpc current -f '%file%' 2>/dev/null) + year=$(mpc current -f '%date%' 2>/dev/null) + composer=$(mpc current -f '%composer%' 2>/dev/null) + queue_length=$(mpc playlist 2>/dev/null | wc -l) + progress=$(mpc status 2>/dev/null | grep -oP '\(\K[0-9]+(?=%\))' || echo "0") + time_str=$(mpc status 2>/dev/null | grep -oP '\d+:\d+/\d+:\d+' | sed 's|/| / |' || echo "0:00 / 0:00") if [ -n "$file" ]; then # Only re-extract when the track actually changed -- ffmpeg+convert @@ -48,10 +53,10 @@ while true; do albumart="$PLACEHOLDER_PATH" [ -s "$ALBUMART_PATH" ] && albumart="$ALBUMART_PATH" - line="${state}|${artist}|${title}|${file}" + line="${state}|${artist}|${title}|${file}|${year}|${composer}|${queue_length}|${progress}|${time_str}" if [ "$line" != "$prev" ]; then - jq -cn --arg state "$state" --arg artist "$artist" --arg title "$title" --arg albumart "$albumart" \ - '{state: $state, artist: $artist, title: $title, albumart: $albumart}' + jq -cn --arg state "$state" --arg artist "$artist" --arg title "$title" --arg albumart "$albumart" --arg year "$year" --arg composer "$composer" --arg queue "$queue_length" --arg progress "$progress" --arg time "$time_str" \ + '{state: $state, artist: $artist, title: $title, albumart: $albumart, year: $year, composer: $composer, queue_length: $queue, progress: $progress, time: $time}' prev="$line" fi