From c87ccc2ed757a5da41e7fe34e549af80c2d4bac7 Mon Sep 17 00:00:00 2001 From: soraefir Date: Wed, 22 Nov 2023 06:14:03 +0100 Subject: [PATCH] Radio Widget --- .../home/wayland/apps/eww/bar/css/_radio.scss | 63 +++++++++ modules/home/wayland/apps/eww/bar/eww.scss | 1 + modules/home/wayland/apps/eww/bar/eww.yuck | 3 +- .../wayland/apps/eww/bar/modules/net.yuck | 2 +- .../wayland/apps/eww/bar/modules/sys.yuck | 10 +- .../apps/eww/bar/modules/workspaces.yuck | 2 +- .../home/wayland/apps/eww/bar/scripts/radio | 126 ++++++++++++++++++ .../wayland/apps/eww/bar/windows/radio.yuck | 111 +++++++++++++++ .../wayland/apps/eww/bar/windows/sys.yuck | 2 +- 9 files changed, 311 insertions(+), 9 deletions(-) create mode 100644 modules/home/wayland/apps/eww/bar/css/_radio.scss create mode 100755 modules/home/wayland/apps/eww/bar/scripts/radio create mode 100644 modules/home/wayland/apps/eww/bar/windows/radio.yuck diff --git a/modules/home/wayland/apps/eww/bar/css/_radio.scss b/modules/home/wayland/apps/eww/bar/css/_radio.scss new file mode 100644 index 0000000..5705e9f --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/css/_radio.scss @@ -0,0 +1,63 @@ + +.radio-win { + @include window; + background-color: $bg1; + color: $fg; + margin: $gaps-screen; + padding: .5em; + } + +.album_art { + background-repeat: no-repeat; + background-size: 240px; + min-height: 240px; + min-width: 240px; + margin: $gaps-screen; + border-radius: $border-radius; +} + +.song { + color: $base0C; + font-size: 24px; + font-weight: bold; + margin: 20px 0px 0px 0px; +} + +.artist { + color: $base0E; + font-size: 16px; + font-weight: normal; + margin: 0px 0px $gaps-screen 0px; +} + +.btn_bar { + color: $base05; + font-size: 20px; + font-weight: bold; + margin: $gaps-screen 0px; + +} + +.btn_play { + font-size: 48px; + font-weight: bold; + margin: 0 12px; +} + +.station_list { + border-right-color: $base03; + border-right-style: solid; + border-right-width: $border-width; + margin-right: $gaps-screen; +} + +.station_art { + background-repeat: no-repeat; + background-size: 50px; + min-height: 50px; + min-width: 50px; + margin: $gaps-window; + margin-right: $gaps-screen; + background-color: $base00; + border-radius: $border-radius; +} \ No newline at end of file diff --git a/modules/home/wayland/apps/eww/bar/eww.scss b/modules/home/wayland/apps/eww/bar/eww.scss index 42b2b77..1750531 100644 --- a/modules/home/wayland/apps/eww/bar/eww.scss +++ b/modules/home/wayland/apps/eww/bar/eww.scss @@ -13,6 +13,7 @@ @import 'css/sys'; @import 'css/net'; @import 'css/clock'; +@import 'css/radio'; * { all: unset; diff --git a/modules/home/wayland/apps/eww/bar/eww.yuck b/modules/home/wayland/apps/eww/bar/eww.yuck index 280411d..2d0431b 100644 --- a/modules/home/wayland/apps/eww/bar/eww.yuck +++ b/modules/home/wayland/apps/eww/bar/eww.yuck @@ -6,6 +6,7 @@ (include "windows/calendar.yuck") (include "windows/sys.yuck") +(include "windows/radio.yuck") (defwidget left [] @@ -32,7 +33,7 @@ :orientation "v" :halign "end" :valign "center" - )) + (radio-button))) (defwidget bar-box [] (centerbox diff --git a/modules/home/wayland/apps/eww/bar/modules/net.yuck b/modules/home/wayland/apps/eww/bar/modules/net.yuck index 215416c..f57739a 100644 --- a/modules/home/wayland/apps/eww/bar/modules/net.yuck +++ b/modules/home/wayland/apps/eww/bar/modules/net.yuck @@ -1,4 +1,4 @@ -(deflisten net "scripts/net/net") +(deflisten net :initial '{"name":"","icon":""}'"scripts/net/net") (defwidget net [] (box diff --git a/modules/home/wayland/apps/eww/bar/modules/sys.yuck b/modules/home/wayland/apps/eww/bar/modules/sys.yuck index 48ac4a8..49a19f4 100644 --- a/modules/home/wayland/apps/eww/bar/modules/sys.yuck +++ b/modules/home/wayland/apps/eww/bar/modules/sys.yuck @@ -1,8 +1,8 @@ -(deflisten cpu "scripts/sys/cpu") -(deflisten gpu "scripts/sys/gpu") -(deflisten memory "scripts/sys/memory") +(deflisten cpu :initial '{}' "scripts/sys/cpu") +(deflisten gpu :initial '{"devices":[{"GRBM2":{}}]}' "scripts/sys/gpu") +(deflisten memory :initial '{"human":{"used":"0G","total":"0G"},"used":0.0,"total":1.0}' "scripts/sys/memory") -(deflisten battery "scripts/sys/battery") +(deflisten battery :initial '{"visible":false,"percentage":0.0,"color":"#FFFFFF"}' "scripts/sys/battery") (defwidget sys [] (button @@ -17,7 +17,7 @@ (label :class "icon-text" :text "C")) (circular-progress - :value {gpu.devices[0].GRBM2.CommandProcessor-Graphics.value} + :value {gpu.devices[0].GRBM2?.CommandProcessor-Graphics?.value?:0} :class "gpubar" :thickness 6 (label :class "icon-text" :text "G")) diff --git a/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck b/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck index 604370f..4812acb 100644 --- a/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck +++ b/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck @@ -1,4 +1,4 @@ -(deflisten workspace "scripts/workspaces") +(deflisten workspace :initial '[]' "scripts/workspaces") (defwidget workspaces [] (eventbox diff --git a/modules/home/wayland/apps/eww/bar/scripts/radio b/modules/home/wayland/apps/eww/bar/scripts/radio new file mode 100755 index 0000000..7a1e0e2 --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/scripts/radio @@ -0,0 +1,126 @@ +#!/usr/bin/env bash + +function get_time_ms { + date -u +%s%3N +} + + +URL_BASE="https://www.radiorecord.ru/api" +STATIONS=$(curl -s "$URL_BASE/stations/" | jq --argjson ids '[507,522,523,536,537,42532,42602]' '.result.stations | map(select(.id | IN($ids[]))) | map({id, title, stream_hls, icon_fill_white})') + +MPV_PID_FILE="/tmp/mpv_radio_pid" +RADIO_ID_FILE="/tmp/radio_id" + +get_radio() { + echo "$STATIONS" | jq -r --argjson sel_id "$1" 'map(select(.id == $sel_id)).[0]' +} + +get_song() { + echo $(curl -s "$URL_BASE/station/history/?id=$1" | jq '.result.history[0] | ({id, artist, song, image600})') +} + + +# Function to play audio stream +start() { + radio_url=$(get_radio $1 | jq -r ".stream_hls") + if [ -f "$MPV_PID_FILE" ]; then + mpv_pid=$(cat "$MPV_PID_FILE") + if ps -p "$mpv_pid" > /dev/null; then + kill -SIGTERM "$mpv_pid" + fi + fi + mpv "$radio_url" & echo $! > "$MPV_PID_FILE" + echo $1 > "$RADIO_ID_FILE" +} + +# Function to pause/play the audio stream +pause() { + if [ -f "$MPV_PID_FILE" ]; then + mpv_pid=$(cat "$MPV_PID_FILE") + if ps -p "$mpv_pid" > /dev/null; then + kill -9 "$mpv_pid" + fi + fi + rm -f $MPV_PID_FILE +} + +play() { + pause + radio_id=$(cat "$RADIO_ID_FILE") + start "$radio_id" +} + +toggle() { + PID=$( [ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0 ) + RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) + PAUSED=$(( $PID == 0 && $RADIO_ID > 0 ? 1 : 0 )) + if [ "$PAUSED" = 1 ]; then + play + else + pause + fi +} + +status() { + PID=$( [ -e "$MPV_PID_FILE" ] && cat "$MPV_PID_FILE" || echo 0 ) + RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) + PAUSED=$(( $PID == 0 && $RADIO_ID > 0 ? 1 : 0 )) + INFO=$1 + RES=$(jq -cn --argjson pid "$PID" --argjson stations "$STATIONS" --argjson radio_id "$RADIO_ID" --argjson is_paused "$PAUSED" --argjson info "$INFO" '{"is_paused": $is_paused, "song": $info, "radio": $radio_id, "stations": $stations}') + echo "$RES" +} + + +status_loop() { + RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) + INFO=$(get_song "$RADIO_ID") + status "$INFO" + last_time_info=$(get_time_ms) + last_time=$(get_time_ms) + while true; do + RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) + current_time=$(get_time_ms) + delta=$((current_time - last_time_info)) + if [[ $delta -gt 15000 ]]; then + NEW_INFO=$(get_song $RADIO_ID) + INFO=$(echo "$INFO" "$NEW_INFO" | jq -s ' reduce .[] as $item ( {}; . + ( + reduce ($item | to_entries[]) as $entry ( {}; + if $entry.value != null then .[$entry.key] = $entry.value else . end + )) )') + + last_time_info=$(get_time_ms) + fi + current_time=$(get_time_ms) + delta=$((current_time - last_time)) + if [[ $delta -gt 1000 ]]; then + status "$INFO" + last_time=$(get_time_ms) + fi + done +} + +# Main script +case "$1" in + "start") + start "$2" + ;; + "toggle") + toggle + ;; + "pause") + pause + ;; + "play") + play + ;; + "status") + RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) + INFO=$(get_song $RADIO_ID) + status "$INFO" + ;; + *) + RADIO_ID=$( [ -e "$RADIO_ID_FILE" ] && cat "$RADIO_ID_FILE" || echo 0 ) + echo $(get_song $RADIO_ID) + status_loop + ;; +esac diff --git a/modules/home/wayland/apps/eww/bar/windows/radio.yuck b/modules/home/wayland/apps/eww/bar/windows/radio.yuck new file mode 100644 index 0000000..5513d29 --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/windows/radio.yuck @@ -0,0 +1,111 @@ +(deflisten radio :initial '{"is_paused":1,"song":{"artist":"","song":"","image600":"https://www.radiorecord.ru/upload/stations_images/record_image600_white_fill.png"},"stations":[]}' "scripts/radio") +(defvar radio_rev false) + +(defwidget radio-win [] + (box + :class "radio-win" + (radio))) + +(defwindow radio + :monitor 0 + :geometry (geometry + :x "0%" + :y "0%" + :anchor "bottom right" + :width "200px" + :height "300px") + (radio-win)) + + +(defwidget radio [] + (box + :space-evenly false + :orientation "h" + (revealer + :visible radio_rev + :reveal radio_rev + :transition "slideleft" + (radio-selector)) + (box + :space-evenly false + :orientation "v" + + (box + :class "album_art" + :vexpand "false" + :hexpand "false" + :style "background-size:cover; background-image: url('${radio.song.image600}');") + (box + :space-evenly false + :orientation "v" + (label + :halign "center" + :class "song" + :wrap "true" + :limit-width 25 + :text "${radio.song.song}") + (label + :halign "center" + :class "artist" + :wrap "true" + :limit-width 22 + :text "${radio.song.artist}") + (box + :space-evenly true + :orientation "h" + :halign "center" + :class "btn_bar" + + (button + :class "btn_left" + :onclick "${EWW_CMD} update radio_rev=${!radio_rev}" + (box "󰷐")) + + (button + :class "btn_play" + :timeout "1s" + :onclick "scripts/radio toggle" + "${radio.is_paused==1 ? "󰐌" : "󰏥"}") + + (button + :class "btn_right" + :onclick "" + (box :visible false "󰔶")) + ) + ) + ) + ) +) + + +(defwidget radio-selector [] + (scroll + :active true + :vscroll true + :hscroll false + + (box + :class "station_list" + :space-evenly false + :orientation "v" + + (for station in {radio.stations} + (button + :class "station_art" + :timeout "1s" + :onclick "scripts/radio start ${station.id}" + :tooltip "${station.title}" + :style "background-size:cover; background-image: url('${station.icon_fill_white}');" + ) + ) + ) + ) +) + +(defwidget radio-button [] + (button + :onclick "${EWW_CMD} open --toggle radio" + (box + :class "module" + :orientation "v" + "󰎆"))) \ No newline at end of file diff --git a/modules/home/wayland/apps/eww/bar/windows/sys.yuck b/modules/home/wayland/apps/eww/bar/windows/sys.yuck index 98f63bb..5a61094 100644 --- a/modules/home/wayland/apps/eww/bar/windows/sys.yuck +++ b/modules/home/wayland/apps/eww/bar/windows/sys.yuck @@ -15,7 +15,7 @@ :orientation "h" :flipped true :class "cpu-core-usage" - :tooltip "core${core.core} @ ${core.freq}Mhz" + :tooltip "${core.core} @ ${core.freq}Mhz" ) ) )