initial commit
This commit is contained in:
commit
4a6050b930
6 changed files with 705 additions and 0 deletions
11
eww/cava.sh
Executable file
11
eww/cava.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash
|
||||||
|
cava -p <(cat <<EOF
|
||||||
|
[general]
|
||||||
|
bars = 26
|
||||||
|
[output]
|
||||||
|
method = raw
|
||||||
|
raw_target = /dev/stdout
|
||||||
|
data_format = ascii
|
||||||
|
ascii_max_range = 6
|
||||||
|
EOF
|
||||||
|
) | sed -u 's/;//g;s/0/▂/g;s/1/▃/g;s/2/▄/g;s/3/▅/g;s/4/▆/g;s/5/▇/g;s/6/█/g;'
|
||||||
180
eww/eww.scss
Normal file
180
eww/eww.scss
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
* {
|
||||||
|
all: unset;
|
||||||
|
font-family: Hack;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
color: #232629;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
background-color: rgba(242, 242, 243, .6);
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 25px;
|
||||||
|
border: 4px solid rgba(196, 214, 226, .6);
|
||||||
|
box-shadow: inset 0 0 2px rgba(0,0,0,0.2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Time, Date, and Weather */
|
||||||
|
|
||||||
|
label.time {
|
||||||
|
font-size: 35px;
|
||||||
|
text-shadow: 0 0 2px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
label.date {
|
||||||
|
font-size: 26px;
|
||||||
|
text-shadow: 0 0 2px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* status bar css */
|
||||||
|
.spacer {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
border: 2px solid rgba(196, 214, 226, .6);
|
||||||
|
border-radius: 25px;
|
||||||
|
}
|
||||||
|
.system .label {
|
||||||
|
font-size: 18px;
|
||||||
|
margin-top: -35px;
|
||||||
|
}
|
||||||
|
.system .label2 {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: -130px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system .progress {
|
||||||
|
margin-bottom: -90px;
|
||||||
|
}
|
||||||
|
.progress progress {
|
||||||
|
min-width: 8px;
|
||||||
|
border-radius: 25px;
|
||||||
|
}
|
||||||
|
.system progress {
|
||||||
|
background-color: #89b4fa;
|
||||||
|
box-shadow: 0 0 2px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.system .progress trough {
|
||||||
|
min-height: 120px;
|
||||||
|
min-width:10px;
|
||||||
|
box-shadow: inset 0 0 3px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.progress trough {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 25px;
|
||||||
|
}
|
||||||
|
/* ----------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Media Player Variables */
|
||||||
|
$bg-color: rgba(242, 242, 243, .5);
|
||||||
|
$primary-neon: #89b4fa; /* Cyan */
|
||||||
|
$secondary-neon: #232629; /* Magenta */
|
||||||
|
$text-color: #232629;
|
||||||
|
$font-family: "Hack";
|
||||||
|
|
||||||
|
.music-widget {
|
||||||
|
background-color: $bg-color;
|
||||||
|
border-radius: 25px;
|
||||||
|
padding: 15px;
|
||||||
|
color: $text-color;
|
||||||
|
font-family: $font-family;
|
||||||
|
border: 5px solid rgba(196, 214, 226, .6);
|
||||||
|
box-shadow: inset 0 0 1.5px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-art {
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
min-width: 155px;
|
||||||
|
min-height: 125px;
|
||||||
|
border-radius: 25px;
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding-right:10px ;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
border: 5px solid rgba(190, 190, 210, 1);
|
||||||
|
box-shadow: 0 0 3px rgba(0,0,0,0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-info {
|
||||||
|
padding: 5px 0;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.song-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $secondary-neon;
|
||||||
|
text-shadow: 0 0 1px rgba($secondary-neon, 0.3);
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artist {
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.70;
|
||||||
|
color: $primary-neon;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
margin: 8px 0;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: $secondary-neon;
|
||||||
|
padding: 0 10px;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
text-shadow: 0 20 60px rgba($secondary-neon, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls button:hover {
|
||||||
|
color: $primary-neon;
|
||||||
|
text-shadow: 0 0 10px rgba($secondary-neon, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.position {
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: 0.75;
|
||||||
|
color: $text-color;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
margin-left: 5px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar trough {
|
||||||
|
background-color: rgba($primary-neon, 0.1);
|
||||||
|
border-radius: 25px;
|
||||||
|
min-height: 12px;
|
||||||
|
min-width: 180px;
|
||||||
|
border: 1px solid rgba($primary-neon, 0.3);
|
||||||
|
box-shadow: inset 0 0 3px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar highlight {
|
||||||
|
background-image: linear-gradient(to right, $primary-neon, $secondary-neon);
|
||||||
|
border-radius: 25px;
|
||||||
|
box-shadow: 0 0 3px $primary-neon;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.cava-visualizer {
|
||||||
|
margin-left: 5px;
|
||||||
|
font-family: "monospace";
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: $primary-neon;
|
||||||
|
text-shadow: 0 0 6px rgba($primary-neon, 0.5);
|
||||||
|
margin-top: 10px;
|
||||||
|
text-shadow: 0 0 3px $primary-neon;
|
||||||
|
}
|
||||||
257
eww/eww.yuck
Normal file
257
eww/eww.yuck
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
;; weather import
|
||||||
|
(defpoll ICON :interval "15m" `~/.config/eww/scripts/weather_info --icon`)
|
||||||
|
(defpoll STAT :interval "15m" `~/.config/eww/scripts/weather_info --stat`)
|
||||||
|
(defpoll TEMP :interval "5m" `~/.config/eww/scripts/weather_info --temp`)
|
||||||
|
(defpoll HEX :interval "15m" `~/.config/eww/scripts/weather_info --hex`)
|
||||||
|
(defpoll QUOTE :interval "15m" `~/.config/eww/scripts/weather_info --quote`)
|
||||||
|
(defpoll QUOTE2 :interval "15m" `~/.config/eww/scripts/weather_info --quote2`)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;;Time Date Weather ------------------------------------------------------
|
||||||
|
|
||||||
|
(defwidget time []
|
||||||
|
(box :class "box"
|
||||||
|
:orientation "h"
|
||||||
|
:space-evenly true
|
||||||
|
(label :class "time" :text "${time}" :halign "center" :hexpand true)))
|
||||||
|
|
||||||
|
(defpoll time :interval "1s"
|
||||||
|
"date '+%I:%M:%S %P'")
|
||||||
|
|
||||||
|
|
||||||
|
(defwindow time
|
||||||
|
:monitor 1
|
||||||
|
:geometry (geometry :x "0.5%"
|
||||||
|
:y "2%"
|
||||||
|
:width "270px"
|
||||||
|
:height "70px"
|
||||||
|
:anchor "bottom left")
|
||||||
|
:stacking "bottom"
|
||||||
|
(time))
|
||||||
|
(defpoll date :interval "1s"
|
||||||
|
"date '+%A %D'")
|
||||||
|
(defwidget date []
|
||||||
|
(box :class "box"
|
||||||
|
:orientation "h"
|
||||||
|
:space-evenly false
|
||||||
|
(label :class "date" :text "${date}" :xalign 0)))
|
||||||
|
(defwidget weather []
|
||||||
|
(box :class "box"
|
||||||
|
:orientation "h"
|
||||||
|
:space-evenly false
|
||||||
|
(label :class "date" :text "${ICON}${TEMP}" :halign "center" :hexpand true)))
|
||||||
|
(defwindow date
|
||||||
|
:monitor 1
|
||||||
|
:geometry (geometry :x "440" :y "2%"
|
||||||
|
:width "467px" :height "70px"
|
||||||
|
:anchor "bottom left")
|
||||||
|
:stacking "bottom"
|
||||||
|
(date))
|
||||||
|
(defwindow weather
|
||||||
|
:monitor 1
|
||||||
|
:geometry (geometry :x "285" :y "2%"
|
||||||
|
:width "145px" :height "70px"
|
||||||
|
:anchor "bottom left")
|
||||||
|
:stacking "bottom"
|
||||||
|
(weather))
|
||||||
|
;; --- Listeners & Polls ---
|
||||||
|
;; Use `deflisten` with `playerctl --follow` to react to player events
|
||||||
|
;; efficiently. When a player quits, `playerctl` exits, and the `|| echo`
|
||||||
|
;; part provides a default value, ensuring the UI updates correctly.
|
||||||
|
(deflisten song_title :initial "No Music Playing"
|
||||||
|
"playerctl metadata --format '{{title}}' --follow || echo 'No Music Playing'")
|
||||||
|
|
||||||
|
(deflisten song_artist :initial "Unknown Artist"
|
||||||
|
"playerctl metadata --format '{{artist}}' --follow || echo 'Unknown Artist'")
|
||||||
|
|
||||||
|
(deflisten player_status :initial "Stopped"
|
||||||
|
"playerctl metadata --format '{{status}}' --follow || echo 'Stopped'")
|
||||||
|
|
||||||
|
;; Polling is still needed for things that change continuously, like position,
|
||||||
|
;; but we can use longer, more efficient intervals.
|
||||||
|
(defpoll song_length_s :interval "2s"
|
||||||
|
:initial "1"
|
||||||
|
"playerctl metadata mpris:length | awk '{print $1 / 1000000}' || echo 1")
|
||||||
|
|
||||||
|
(defpoll song_position_s :initial "0" :interval "1s" "playerctl position || echo 0")
|
||||||
|
|
||||||
|
(defpoll formatted_position :interval "1s" "playerctl position -f '{{duration(position)}}' || echo '0:00'")
|
||||||
|
|
||||||
|
;; Cover art and volume can also be polled at a slower rate.
|
||||||
|
(defpoll cover_art_path :interval "1s" "$HOME/.config/eww/get-cover.sh")
|
||||||
|
|
||||||
|
|
||||||
|
;; Cava runs as a persistent listener, which is correct.
|
||||||
|
(deflisten cava :initial "" "bash $HOME/.config/eww/cava.sh")
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Widget Definition ---
|
||||||
|
|
||||||
|
(defwidget music-widget []
|
||||||
|
(box :class "music-widget" :orientation "h" :space-evenly false
|
||||||
|
(box :class "cover-art" :style "background-image: url('${cover_art_path}');")
|
||||||
|
(box :class "music-info" :orientation "v" :space-evenly false
|
||||||
|
(label :class "song-title" :text song_title :limit-width 25)
|
||||||
|
(label :class "artist" :text song_artist :limit-width 25)
|
||||||
|
|
||||||
|
(box :class "controls" :orientation "h"
|
||||||
|
(button :onclick "playerctl previous" "")
|
||||||
|
(button :onclick "playerctl play-pause" {player_status == "Playing" ? "" : ""})
|
||||||
|
(button :onclick "playerctl next" ""))
|
||||||
|
(label :class "position" :text formatted_position)
|
||||||
|
(scale :class "progress-bar"
|
||||||
|
:min 0
|
||||||
|
:max song_length_s
|
||||||
|
:value song_position_s
|
||||||
|
:onchange "playerctl position {}")
|
||||||
|
(label :class "cava-visualizer" :text cava)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Window Definition ---
|
||||||
|
|
||||||
|
(defwindow music-widget
|
||||||
|
:monitor 1
|
||||||
|
:stacking "bottom"
|
||||||
|
:geometry (
|
||||||
|
geometry :x "467px"
|
||||||
|
:y "10px"
|
||||||
|
:width "440px"
|
||||||
|
:height "120px"
|
||||||
|
)
|
||||||
|
:wm-ignore true
|
||||||
|
(music-widget))
|
||||||
|
|
||||||
|
;;----------------------------------------------------------------------------------------
|
||||||
|
;;status widget
|
||||||
|
|
||||||
|
(defwidget spacer []
|
||||||
|
(box :class "spacer"))
|
||||||
|
|
||||||
|
(defwidget cpu []
|
||||||
|
(system-progress
|
||||||
|
:class "cpu"
|
||||||
|
:tip "CPU ${round(EWW_CPU.avg,1)}%"
|
||||||
|
:value {round(EWW_CPU.avg, 0)}
|
||||||
|
:icon ""
|
||||||
|
:pct "${round(EWW_CPU.avg, 0)}%"))
|
||||||
|
(defwidget cput []
|
||||||
|
(system-progress
|
||||||
|
:class "cput"
|
||||||
|
:tip "CPU Temp ${EWW_TEMPS["CORETEMP_PACKAGE_ID_0"]}°C"
|
||||||
|
:value {((EWW_TEMPS["CORETEMP_PACKAGE_ID_0"] - 25) / 75) * 100}
|
||||||
|
:icon ""
|
||||||
|
:pct "${EWW_TEMPS["CORETEMP_PACKAGE_ID_0"]}°"))
|
||||||
|
(defpoll gput :interval "2s" :initial "0"
|
||||||
|
"nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits")
|
||||||
|
(defwidget gput []
|
||||||
|
(system-progress
|
||||||
|
:class "gput"
|
||||||
|
:tip "GPU Temp ${gput}°C"
|
||||||
|
:value {((gput - 25) / 75) * 100}
|
||||||
|
:icon ""
|
||||||
|
:pct "${gput}°"))
|
||||||
|
(defpoll gpu :interval "2s" :initial "0"
|
||||||
|
"nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits")
|
||||||
|
(defwidget gpu []
|
||||||
|
(system-progress
|
||||||
|
:class "gpu"
|
||||||
|
:tip "GPU ${gpu}%"
|
||||||
|
:value {gpu}
|
||||||
|
:icon ""
|
||||||
|
:pct "${gpu}%"))
|
||||||
|
(defwidget ram []
|
||||||
|
(system-progress
|
||||||
|
:class "ram"
|
||||||
|
:tip "RAM ${round(EWW_RAM.used_mem / 1048576, 1)}MB"
|
||||||
|
:value {round(EWW_RAM.used_mem_perc, 0)}
|
||||||
|
:icon ""
|
||||||
|
:pct "${round(EWW_RAM.used_mem / 34359738368 * 100, 0)}%"))
|
||||||
|
(defwidget swap []
|
||||||
|
(system-progress
|
||||||
|
:class "swap"
|
||||||
|
:tip "Swap ${round((EWW_RAM.total_swap - EWW_RAM.free_swap) / 1048576, 1)}MB"
|
||||||
|
:value {round((EWW_RAM.total_swap - EWW_RAM.free_swap) / EWW_RAM.total_swap * 100, 0)}
|
||||||
|
:icon ""
|
||||||
|
:pct "${round((EWW_RAM.total_swap - EWW_RAM.free_swap) / EWW_RAM.total_swap * 100, 0)}%"))
|
||||||
|
(defwidget netdown []
|
||||||
|
(system-progress
|
||||||
|
:class "netdown"
|
||||||
|
:tip "Down ${round(EWW_NET["eno1"].NET_DOWN / 1048576, 1)} MB/s"
|
||||||
|
:value {min(max(log(EWW_NET["eno1"].NET_DOWN / 1024 + 1, 10000) * 100, 0), 100)}
|
||||||
|
:icon ""
|
||||||
|
:pct {EWW_NET["eno1"].NET_DOWN / 1048576 > 1 ? "${round(EWW_NET["eno1"].NET_DOWN / 1048576, 1)}M" : "${round(EWW_NET["eno1"].NET_DOWN / 1024, 0)}Kb"}))
|
||||||
|
(defwidget netup []
|
||||||
|
(system-progress
|
||||||
|
:class "netup"
|
||||||
|
:tip "Up ${round(EWW_NET["eno1"].NET_UP / 1048576, 1)} MB/s"
|
||||||
|
:value {min(max(log(EWW_NET["eno1"].NET_UP / 1024 + 1, 10000) * 100, 0), 100)}
|
||||||
|
:icon ""
|
||||||
|
:pct {EWW_NET["eno1"].NET_UP / 1048576 > 1 ? "${round(EWW_NET["eno1"].NET_UP / 1048576, 1)}M" : "${round(EWW_NET["eno1"].NET_UP / 1024, 0)}Kb"}))
|
||||||
|
(defwidget disk []
|
||||||
|
(system-progress
|
||||||
|
:class "disk"
|
||||||
|
:tip "SSD ${round(EWW_DISK["/"].used_perc, 1)}%"
|
||||||
|
:value {round(EWW_DISK["/"].used_perc, 0)}
|
||||||
|
:icon ""
|
||||||
|
:pct "${round(EWW_DISK["/"].used_perc, 1)}%"))
|
||||||
|
|
||||||
|
;;--------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(defwidget systemwidget []
|
||||||
|
(box
|
||||||
|
:class "system box"
|
||||||
|
:orientation "h"
|
||||||
|
:spacing 10
|
||||||
|
:space-evenly false
|
||||||
|
(box :orientation "v" :spacing 8 :space-evenly false :hexpand false
|
||||||
|
(image :path "/home/lorkan/cpu.svg" :image-width 40 :image-height 40)
|
||||||
|
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
|
||||||
|
(cpu)
|
||||||
|
(cput)))
|
||||||
|
(box :class "spacer" :orientation "v" :hexpand false)
|
||||||
|
(box :orientation "v" :spacing 8 :space-evenly false :hexpand false
|
||||||
|
(image :path "/home/lorkan/gpu.svg" :image-width 40 :image-height 40)
|
||||||
|
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
|
||||||
|
(gpu)
|
||||||
|
(gput)))
|
||||||
|
(box :class "spacer" :orientation "v" :hexpand false)
|
||||||
|
(box :orientation "v" :spacing 8 :space-evenly false :hexpand false
|
||||||
|
(image :class "svg" :path "/home/lorkan/ram.png" :image-width 40 :image-height 40)
|
||||||
|
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
|
||||||
|
(ram)
|
||||||
|
(swap)))
|
||||||
|
(box :class "spacer" :orientation "v" :hexpand false)
|
||||||
|
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
|
||||||
|
(netdown)
|
||||||
|
(netup)
|
||||||
|
(disk))))
|
||||||
|
(defwidget system-progress [class value icon pct tip]
|
||||||
|
(box
|
||||||
|
:class "progress"
|
||||||
|
:orientation "v"
|
||||||
|
:spacing 0
|
||||||
|
(progress
|
||||||
|
:orientation "v"
|
||||||
|
:flipped true
|
||||||
|
:class class
|
||||||
|
:value value
|
||||||
|
:halign "center"
|
||||||
|
:tooltip tip)
|
||||||
|
(box
|
||||||
|
:orientation "v"
|
||||||
|
(label :class "label" :text icon :halign "center")
|
||||||
|
(label :class "label2" :text pct :halign "center"))))
|
||||||
|
|
||||||
|
(defwindow status
|
||||||
|
:monitor 1
|
||||||
|
:geometry (geometry :x "10px" :y "10px" :width "80px" :height "30px"
|
||||||
|
:anchor "top l")
|
||||||
|
:stacking "bottom"
|
||||||
|
(systemwidget))
|
||||||
65
eww/get-cover.sh
Executable file
65
eww/get-cover.sh
Executable file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script fetches and caches album art for the current song.
|
||||||
|
# It's designed to be called by EWW and is optimized to minimize
|
||||||
|
# network and disk I/O.
|
||||||
|
|
||||||
|
WIDGET_DIR=$(dirname "$0")
|
||||||
|
DEFAULT_COVER="$WIDGET_DIR/assets/DEFAULTImage.jpeg"
|
||||||
|
CACHE_DIR="$HOME/.cache/eww/music-widget"
|
||||||
|
mkdir -p "$CACHE_DIR"
|
||||||
|
|
||||||
|
# Function to safely exit with the default cover
|
||||||
|
show_default_cover() {
|
||||||
|
echo "$DEFAULT_COVER"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the art URL. Exit if player is not running or no URL is available.
|
||||||
|
COVER_URL=$(playerctl metadata mpris:artUrl 2>/dev/null)
|
||||||
|
if [[ -z "$COVER_URL" ]]; then
|
||||||
|
show_default_cover
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If it's a local file (file://), decode the path and use it directly.
|
||||||
|
if [[ "$COVER_URL" == file://* ]]; then
|
||||||
|
# URL-decode the path to handle special characters like spaces
|
||||||
|
LOCAL_PATH=$(printf '%b' "${COVER_URL#file://}")
|
||||||
|
if [[ -f "$LOCAL_PATH" ]]; then
|
||||||
|
echo "$LOCAL_PATH"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
show_default_cover
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For web URLs, we hash the URL to create a unique filename for caching.
|
||||||
|
URL_HASH=$(echo -n "$COVER_URL" | md5sum | awk '{print $1}')
|
||||||
|
# Try to get a file extension from the URL, default to .jpg if it's weird.
|
||||||
|
EXTENSION="${COVER_URL##*.}"
|
||||||
|
if [[ "$EXTENSION" == "$COVER_URL" ]] || [[ ${#EXTENSION} -gt 5 ]]; then
|
||||||
|
EXTENSION="jpg"
|
||||||
|
fi
|
||||||
|
CACHED_COVER="$CACHE_DIR/$URL_HASH.$EXTENSION"
|
||||||
|
|
||||||
|
# If the cover is not already cached, download it.
|
||||||
|
if [ ! -f "$CACHED_COVER" ]; then
|
||||||
|
# Download with a 5-second timeout. If it fails or the downloaded file is empty,
|
||||||
|
# clean up and show the default cover.
|
||||||
|
curl -s -L --max-time 5 "$COVER_URL" -o "$CACHED_COVER"
|
||||||
|
if [[ $? -ne 0 ]] || [[ ! -s "$CACHED_COVER" ]]; then
|
||||||
|
rm -f "$CACHED_COVER"
|
||||||
|
show_default_cover
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# As a final sanity check, ensure the cached file is a valid image.
|
||||||
|
# If not, remove the junk file and show the default cover.
|
||||||
|
if file "$CACHED_COVER" | grep -qE 'image|jpeg|png|jpg|gif'; then
|
||||||
|
echo "$CACHED_COVER"
|
||||||
|
else
|
||||||
|
rm -f "$CACHED_COVER"
|
||||||
|
show_default_cover
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
147
eww/scripts/weather_info
Executable file
147
eww/scripts/weather_info
Executable file
|
|
@ -0,0 +1,147 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
## Collect data
|
||||||
|
cache_dir="$HOME/.cache/eww/weather"
|
||||||
|
cache_weather_stat=${cache_dir}/weather-stat
|
||||||
|
cache_weather_degree=${cache_dir}/weather-degree
|
||||||
|
cache_weather_quote=${cache_dir}/weather-quote
|
||||||
|
cache_weather_hex=${cache_dir}/weather-hex
|
||||||
|
cache_weather_icon=${cache_dir}/weather-icon
|
||||||
|
|
||||||
|
## Weather data
|
||||||
|
KEY="527ef08abfd3b851a188de297cbae02c"
|
||||||
|
ID="5342992"
|
||||||
|
UNIT="imperial" # Available options : 'metric' or 'imperial'
|
||||||
|
|
||||||
|
## Make cache dir
|
||||||
|
if [[ ! -d "$cache_dir" ]]; then
|
||||||
|
mkdir -p ${cache_dir}
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Get data
|
||||||
|
get_weather_data() {
|
||||||
|
weather=`curl -sf "http://api.openweathermap.org/data/2.5/weather?APPID="$KEY"&id="$ID"&units="$UNIT""`
|
||||||
|
echo ${weather}
|
||||||
|
|
||||||
|
if [ ! -z "$weather" ]; then
|
||||||
|
weather_temp=`echo "$weather" | jq ".main.temp" | cut -d "." -f 1`
|
||||||
|
weather_icon_code=`echo "$weather" | jq -r ".weather[].icon" | head -1`
|
||||||
|
weather_description=`echo "$weather" | jq -r ".weather[].description" | head -1 | sed -e "s/\b\(.\)/\u\1/g"`
|
||||||
|
|
||||||
|
#Big long if statement of doom
|
||||||
|
if [ "$weather_icon_code" == "50d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="Forecast says it's misty \nMake sure you don't get lost on your way..."
|
||||||
|
weather_hex="#84afdb"
|
||||||
|
elif [ "$weather_icon_code" == "50n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="Forecast says it's a misty night \nDon't go anywhere tonight or you might get lost..."
|
||||||
|
weather_hex="#84afdb"
|
||||||
|
elif [ "$weather_icon_code" == "01d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's a sunny day, gonna be fun! \nDon't go wandering all by yourself though..."
|
||||||
|
weather_hex="#ffd86b"
|
||||||
|
elif [ "$weather_icon_code" == "01n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's a clear night \nYou might want to take a evening stroll to relax..."
|
||||||
|
weather_hex="#fcdcf6"
|
||||||
|
elif [ "$weather_icon_code" == "02d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's cloudy, sort of gloomy \nYou'd better get a book to read..."
|
||||||
|
weather_hex="#adadff"
|
||||||
|
elif [ "$weather_icon_code" == "02n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's a cloudy night \nHow about some hot chocolate and a warm bed?"
|
||||||
|
weather_hex="#adadff"
|
||||||
|
elif [ "$weather_icon_code" == "03d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's cloudy, sort of gloomy \nYou'd better get a book to read..."
|
||||||
|
weather_hex="#adadff"
|
||||||
|
elif [ "$weather_icon_code" == "03n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's a cloudy night \nHow about some hot chocolate and a warm bed?"
|
||||||
|
weather_hex="#adadff"
|
||||||
|
elif [ "$weather_icon_code" == "04d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's cloudy, sort of gloomy \nYou'd better get a book to read..."
|
||||||
|
weather_hex="#adadff"
|
||||||
|
elif [ "$weather_icon_code" == "04n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's a cloudy night \nHow about some hot chocolate and a warm bed?"
|
||||||
|
weather_hex="#adadff"
|
||||||
|
elif [ "$weather_icon_code" == "09d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's rainy, it's a great day! \nGet some ramen and watch as the rain falls..."
|
||||||
|
weather_hex="#6b95ff"
|
||||||
|
elif [ "$weather_icon_code" == "09n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote=" It's gonna rain tonight it seems \nMake sure your clothes aren't still outside..."
|
||||||
|
weather_hex="#6b95ff"
|
||||||
|
elif [ "$weather_icon_code" == "10d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's rainy, it's a great day! \nGet some ramen and watch as the rain falls..."
|
||||||
|
weather_hex="#6b95ff"
|
||||||
|
elif [ "$weather_icon_code" == "10n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote=" It's gonna rain tonight it seems \nMake sure your clothes aren't still outside..."
|
||||||
|
weather_hex="#6b95ff"
|
||||||
|
elif [ "$weather_icon_code" == "11d" ]; then
|
||||||
|
weather_icon=""
|
||||||
|
weather_quote="There's storm for forecast today \nMake sure you don't get blown away..."
|
||||||
|
weather_hex="#ffeb57"
|
||||||
|
elif [ "$weather_icon_code" == "11n" ]; then
|
||||||
|
weather_icon=""
|
||||||
|
weather_quote="There's gonna be storms tonight \nMake sure you're warm in bed and the windows are shut..."
|
||||||
|
weather_hex="#ffeb57"
|
||||||
|
elif [ "$weather_icon_code" == "13d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's gonna snow today \nYou'd better wear thick clothes and make a snowman as well!"
|
||||||
|
weather_hex="#e3e6fc"
|
||||||
|
elif [ "$weather_icon_code" == "13n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="It's gonna snow tonight \nMake sure you get up early tomorrow to see the sights..."
|
||||||
|
weather_hex="#e3e6fc"
|
||||||
|
elif [ "$weather_icon_code" == "40d" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="Forecast says it's misty \nMake sure you don't get lost on your way..."
|
||||||
|
weather_hex="#84afdb"
|
||||||
|
elif [ "$weather_icon_code" == "40n" ]; then
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="Forecast says it's a misty night \nDon't go anywhere tonight or you might get lost..."
|
||||||
|
weather_hex="#84afdb"
|
||||||
|
else
|
||||||
|
weather_icon=" "
|
||||||
|
weather_quote="Sort of odd, I don't know what to forecast \nMake sure you have a good time!"
|
||||||
|
weather_hex="#adadff"
|
||||||
|
fi
|
||||||
|
echo "$weather_icon" > ${cache_weather_icon}
|
||||||
|
echo "$weather_description" > ${cache_weather_stat}
|
||||||
|
echo "$weather_temp""°F" > ${cache_weather_degree}
|
||||||
|
echo -e "$weather_quote" > ${cache_weather_quote}
|
||||||
|
echo "$weather_hex" > ${cache_weather_hex}
|
||||||
|
else
|
||||||
|
echo "Weather Unavailable" > ${cache_weather_stat}
|
||||||
|
echo " " > ${cache_weather_icon}
|
||||||
|
echo -e "Ah well, no weather huh? \nEven if there's no weather, it's gonna be a great day!" > ${cache_weather_quote}
|
||||||
|
echo "-" > ${cache_weather_degree}
|
||||||
|
echo "#adadff" > ${tcache_weather_hex}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
## Execute
|
||||||
|
if [[ "$1" == "--getdata" ]]; then
|
||||||
|
get_weather_data
|
||||||
|
elif [[ "$1" == "--icon" ]]; then
|
||||||
|
cat ${cache_weather_icon}
|
||||||
|
elif [[ "$1" == "--temp" ]]; then
|
||||||
|
cat ${cache_weather_degree}
|
||||||
|
elif [[ "$1" == "--hex" ]]; then
|
||||||
|
cat ${cache_weather_hex}
|
||||||
|
elif [[ "$1" == "--stat" ]]; then
|
||||||
|
cat ${cache_weather_stat}
|
||||||
|
elif [[ "$1" == "--quote" ]]; then
|
||||||
|
cat ${cache_weather_quote} | head -n1
|
||||||
|
elif [[ "$1" == "--quote2" ]]; then
|
||||||
|
cat ${cache_weather_quote} | tail -n1
|
||||||
|
fi
|
||||||
|
|
||||||
45
eww/volumecontroller.sh
Executable file
45
eww/volumecontroller.sh
Executable file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# A script to control volume using pamixer.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# volumecontroller.sh <command> [value]
|
||||||
|
#
|
||||||
|
# Commands:
|
||||||
|
# up - Increase volume by 'step'
|
||||||
|
# down - Decrease volume by 'step'
|
||||||
|
# mute - Toggle mute
|
||||||
|
# get - Get current volume percentage
|
||||||
|
# set - Set volume to a specific percentage [value]
|
||||||
|
|
||||||
|
set -e # Exit immediately if a command exits with a non-zero status.
|
||||||
|
|
||||||
|
COMMAND="$1"
|
||||||
|
VALUE="$2"
|
||||||
|
STEP=5
|
||||||
|
|
||||||
|
case $COMMAND in
|
||||||
|
up)
|
||||||
|
pamixer -i "${VALUE:-$STEP}"
|
||||||
|
;;
|
||||||
|
down)
|
||||||
|
pamixer -d "${VALUE:-$STEP}"
|
||||||
|
;;
|
||||||
|
mute)
|
||||||
|
pamixer -t
|
||||||
|
;;
|
||||||
|
get)
|
||||||
|
pamixer --get-volume
|
||||||
|
;;
|
||||||
|
set)
|
||||||
|
if [ -z "$VALUE" ]; then
|
||||||
|
echo "Usage: $0 set <0-100>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
pamixer --set-volume "$VALUE"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 <up|down|mute|get|set> [value]" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Loading…
Add table
Add a link
Reference in a new issue