Compare commits
No commits in common. "master" and "main" have entirely different histories.
8 changed files with 1 additions and 267 deletions
|
|
@ -1,2 +1,2 @@
|
||||||
# coding
|
# coding
|
||||||
just some nice little coding projects, mostly bash (and vibecoded lol)
|
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import subprocess, threading, urllib.request
|
|
||||||
import dbus, dbus.service, dbus.mainloop.glib
|
|
||||||
from gi.repository import GLib
|
|
||||||
|
|
||||||
class MusicNotifier:
|
|
||||||
def __init__(self):
|
|
||||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
|
||||||
bus = dbus.SessionBus()
|
|
||||||
obj = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
|
|
||||||
self.iface = dbus.Interface(obj, "org.freedesktop.Notifications")
|
|
||||||
self.notif_id = dbus.UInt32(0)
|
|
||||||
|
|
||||||
bus.add_signal_receiver(
|
|
||||||
self.on_action,
|
|
||||||
dbus_interface="org.freedesktop.Notifications",
|
|
||||||
signal_name="ActionInvoked"
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_art(self, url):
|
|
||||||
if not url:
|
|
||||||
return ""
|
|
||||||
try:
|
|
||||||
if url.startswith("file://"):
|
|
||||||
return url[7:]
|
|
||||||
path = "/tmp/music_art.jpg"
|
|
||||||
urllib.request.urlretrieve(url, path)
|
|
||||||
return path
|
|
||||||
except:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def notify(self, artist, title, art_url, status):
|
|
||||||
art = self.get_art(art_url)
|
|
||||||
play_label = "⏸ Pause" if status == "Playing" else "▶ Play"
|
|
||||||
actions = ["prev", "⏮ Zurück", "toggle", play_label, "next", "⏭ Weiter"]
|
|
||||||
hints = {"image-path": dbus.String(art)} if art else {}
|
|
||||||
|
|
||||||
self.notif_id = self.iface.Notify(
|
|
||||||
"music", self.notif_id, art,
|
|
||||||
title, artist,
|
|
||||||
actions, hints, 0
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_action(self, notif_id, action):
|
|
||||||
if notif_id != self.notif_id:
|
|
||||||
return
|
|
||||||
cmds = {"prev": "previous", "toggle": "play-pause", "next": "next"}
|
|
||||||
if action in cmds:
|
|
||||||
subprocess.run(["playerctl", cmds[action]])
|
|
||||||
|
|
||||||
def monitor(self):
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
["playerctl", "--follow", "metadata", "--format",
|
|
||||||
"{{artist}}||{{title}}||{{mpris:artUrl}}||{{status}}"],
|
|
||||||
stdout=subprocess.PIPE, text=True
|
|
||||||
)
|
|
||||||
prev = ""
|
|
||||||
for line in proc.stdout:
|
|
||||||
parts = line.strip().split("||")
|
|
||||||
if len(parts) != 4:
|
|
||||||
continue
|
|
||||||
artist, title, art_url, status = parts
|
|
||||||
if title != prev:
|
|
||||||
prev = title
|
|
||||||
self.notify(artist, title, art_url, status)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
threading.Thread(target=self.monitor, daemon=True).start()
|
|
||||||
GLib.MainLoop().run()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
MusicNotifier().run()
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
# wallpaper-picker.sh
|
|
||||||
|
|
||||||
WALLPAPER_DIR="$HOME/Pictures/wallpaper"
|
|
||||||
EXTENSIONS="jpg|jpeg|png|gif|webp|bmp|tiff|tga|svg|avif"
|
|
||||||
|
|
||||||
declare -A wall_map
|
|
||||||
while IFS= read -r path; do
|
|
||||||
name=$(basename "$path")
|
|
||||||
wall_map["$name"]="$path"
|
|
||||||
done < <(find "$WALLPAPER_DIR" -maxdepth 1 -type f \
|
|
||||||
-regextype posix-extended -iregex ".*\.($EXTENSIONS)" | sort)
|
|
||||||
|
|
||||||
chosen=$(printf '%s\n' "${!wall_map[@]}" | sort | \
|
|
||||||
wofi \
|
|
||||||
--dmenu \
|
|
||||||
--prompt " Wallpaper" \
|
|
||||||
--insensitive \
|
|
||||||
--no-actions \
|
|
||||||
--width 500 \
|
|
||||||
--height 400 \
|
|
||||||
)
|
|
||||||
|
|
||||||
[[ -z "$chosen" ]] && exit 0
|
|
||||||
|
|
||||||
full_path="${wall_map[$chosen]}"
|
|
||||||
[[ ! -f "$full_path" ]] && {
|
|
||||||
notify-send "wallpaper-picker" "Not found: $full_path" --urgency=critical
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
awww img "$full_path" --transition-type grow --transition-step 90
|
|
||||||
|
|
||||||
persist="$HOME/.config/hypr/wallpaper-restore.sh"
|
|
||||||
printf '#!/bin/bash\nawww-daemon &\nsleep 0.5\nawww img "%s" --transition-type simple\n' "$full_path" > "$persist"
|
|
||||||
chmod +x "$persist"
|
|
||||||
|
|
||||||
notify-send "Wallpaper" "$chosen" --urgency=low
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# Wallpaper-Picker on Niri
|
|
||||||
|
|
||||||
arch: yay -S awww rofi libnotify
|
|
||||||
|
|
||||||
nix: environment.systemPackages = with pkgs; [
|
|
||||||
rofi-wayland
|
|
||||||
awww
|
|
||||||
libnotify
|
|
||||||
];
|
|
||||||
|
|
||||||
put wallpaper.rasi in ~/home/.config/rofi/wallpaper.rasi
|
|
||||||
|
|
||||||
wallpapers should stay in ~/home/$USER/Pictures/wallpaper
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
WALLPAPER_DIR="${HOME}/Pictures/wallpaper"
|
|
||||||
EXTENSIONS="jpg|jpeg|png|gif|webp|bmp|tiff|tga|svg|avif"
|
|
||||||
|
|
||||||
declare -A wall_map
|
|
||||||
|
|
||||||
while IFS= read -r -d '' path; do
|
|
||||||
name="$(basename "$path")"
|
|
||||||
wall_map["$name"]="$path"
|
|
||||||
done < <(
|
|
||||||
find "$WALLPAPER_DIR" -maxdepth 1 -type f \
|
|
||||||
-regextype posix-extended \
|
|
||||||
-iregex ".*\.(${EXTENSIONS})" \
|
|
||||||
-print0 | sort -z
|
|
||||||
)
|
|
||||||
|
|
||||||
chosen="$(
|
|
||||||
for name in "${!wall_map[@]}"; do
|
|
||||||
printf '%s\0icon\x1fthumbnail://%s\n' "$name" "${wall_map[$name]}"
|
|
||||||
done | sort | rofi \
|
|
||||||
-dmenu \
|
|
||||||
-show-icons \
|
|
||||||
-i \
|
|
||||||
-p "wallpaper" \
|
|
||||||
-theme "$HOME/.config/rofi/wallpaper.rasi" \
|
|
||||||
-kb-accept-entry "Return,KP_Enter" \
|
|
||||||
-kb-element-next "Tab" \
|
|
||||||
-kb-element-prev "ISO_Left_Tab"
|
|
||||||
)"
|
|
||||||
|
|
||||||
[[ -z "${chosen:-}" ]] && exit 0
|
|
||||||
|
|
||||||
full_path="${wall_map[$chosen]:-}"
|
|
||||||
if [[ -z "${full_path}" || ! -f "${full_path}" ]]; then
|
|
||||||
notify-send "wallpaper-picker" "Not found: $chosen" --urgency=critical
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
awww img "$full_path" --transition-type grow --transition-step 90
|
|
||||||
|
|
||||||
persist="$HOME/.config/niri/wallpaper-restore.sh"
|
|
||||||
mkdir -p "$(dirname "$persist")"
|
|
||||||
|
|
||||||
cat > "$persist" <<EOF
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
pgrep -x awww-daemon >/dev/null || awww-daemon &
|
|
||||||
sleep 0.5
|
|
||||||
awww img "$full_path" --transition-type simple
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x "$persist"
|
|
||||||
|
|
||||||
notify-send "Wallpaper" "$chosen" --urgency=low
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
configuration {
|
|
||||||
show-icons: true;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
bg: #0f1115ee;
|
|
||||||
bg-alt: #171a21ff;
|
|
||||||
fg: #e6eaf2ff;
|
|
||||||
fg-muted: #aab4c3ff;
|
|
||||||
accent: #89b4faff;
|
|
||||||
border: #2a2f3aff;
|
|
||||||
selected: #1e2530ff;
|
|
||||||
|
|
||||||
background-color: transparent;
|
|
||||||
text-color: @fg;
|
|
||||||
}
|
|
||||||
|
|
||||||
window {
|
|
||||||
location: center;
|
|
||||||
anchor: center;
|
|
||||||
width: 28%;
|
|
||||||
border: 2px;
|
|
||||||
border-radius: 14px;
|
|
||||||
border-color: @border;
|
|
||||||
background-color: @bg;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
mainbox {
|
|
||||||
children: [ inputbar, listview ];
|
|
||||||
spacing: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputbar {
|
|
||||||
children: [ prompt, entry ];
|
|
||||||
spacing: 8px;
|
|
||||||
padding: 10px 12px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background-color: @bg-alt;
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt {
|
|
||||||
text-color: @accent;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry {
|
|
||||||
text-color: @fg;
|
|
||||||
placeholder: "search...";
|
|
||||||
placeholder-color: @fg-muted;
|
|
||||||
}
|
|
||||||
|
|
||||||
listview {
|
|
||||||
columns: 3;
|
|
||||||
lines: 1;
|
|
||||||
dynamic: false;
|
|
||||||
cycle: false;
|
|
||||||
scrollbar: true;
|
|
||||||
spacing: 10px;
|
|
||||||
layout: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
element {
|
|
||||||
orientation: vertical;
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
element normal.normal {
|
|
||||||
background-color: transparent;
|
|
||||||
text-color: @fg-muted;
|
|
||||||
}
|
|
||||||
|
|
||||||
element selected.normal {
|
|
||||||
background-color: @selected;
|
|
||||||
text-color: @fg;
|
|
||||||
}
|
|
||||||
|
|
||||||
element-icon {
|
|
||||||
size: 120px;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
element-text {
|
|
||||||
horizontal-align: 0.5;
|
|
||||||
vertical-align: 0.5;
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue