made some changes (yet again)

This commit is contained in:
Ludwig Lehnert 2025-04-21 12:13:08 +00:00
parent c2edb5060e
commit 61b35b0405
15 changed files with 191 additions and 294 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.venv/

View File

@ -7,3 +7,5 @@ alias tmux="tmux -2"
alias json-get="curl --request GET -H 'Content-Type: application/json'"
alias json-post="curl --request POST -H 'Content-Type: application/json'"
set -x TERM xterm-256color

View File

@ -27,13 +27,18 @@ monitor=,preferred,auto,auto
# Set programs that you use
$terminal = kitty
$fileManager = nautilus
$menu = wofi -S drun -i -I -s .config/wofi/style.css
$menu = wofi -S drun -i -I -s $HOME/.config/wofi/style.css
exec-once = waybar
exec-once = $HOME/.config/waybar/start.sh
exec-once = hypridle
exec-once = hyprpaper
exec-once = nm-applet
exec-once = blueman-applet
# Some default env vars.
env = HYPRCURSOR_ENABLED,0
env = XCURSOR_THEME,Bibata-Modern-Ice
env = XCURSOR_SIZE,24
env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that
@ -80,10 +85,10 @@ decoration {
passes = 1
}
drop_shadow = yes
shadow_range = 4
shadow_render_power = 3
col.shadow = rgba(1a1a1aee)
#drop_shadow = yes
#shadow_range = 4
#shadow_render_power = 3
#col.shadow = rgba(1a1a1aee)
}
animations {
@ -109,7 +114,7 @@ dwindle {
master {
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
new_is_master = true
#new_is_master = true
}
gestures {
@ -209,4 +214,4 @@ bind = , XF86AudioMute, exec, pactl -- set-sink-mute @DEFAULT_SINK@ toggle
bind = , XF86MonBrightnessUp, exec, light -A 5
bind = , XF86MonBrightnessDown, exec, light -U 5
bind = , Print, exec, grim -g "$(slurp)" - | wl-copy
bind = , Print, exec, hyprshot -m region --clipboard-only

View File

@ -117,9 +117,10 @@ label {
label {
monitor =
#text = 31% 
text = cmd[update:1000] ~/.config/waybar/battery.sh once
color = $foreground
font_size = 24
font_size = 20
font_family = JetBrains Mono
position = -10, -10
halign = right

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 MiB

After

Width:  |  Height:  |  Size: 2.9 MiB

65
install
View File

@ -1,62 +1,7 @@
#!/usr/bin/bash
#!/usr/bin/env bash
DIR=$(dirname $(realpath "$0"))
if [[ -f /etc/os-release && $1 == "packages" ]]; then
. /etc/os-release
distro=${NAME,,}
if [[ $distro == "ubuntu" ]]; then
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update && sudo apt-get -y install --no-install-recommends wget curl
# install pfetch
curl -s https://raw.githubusercontent.com/dylanaraps/pfetch/master/pfetch > "$HOME/.local/bin/pfetch"
chmod +x "$HOME/.local/bin/pfetch"
# TODO: further setup
# add google chrome repository
curl -s https://dl-ssl.google.com/linux/linux_signing_key.pub > /tmp/google.pub
gpg --no-default-keyring --keyring /etc/apt/keyrings/google-chrome.gpg --import /tmp/google.pub
echo 'deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main' | sudo tee /etc/apt/sources.list.d/google-chrome.list
sudo add-apt-repository ppa:maveonair/helix-editor
sudo apt-get update && sudo apt-get -y install --no-install-recommends \
fish grim slurp wl-clipboard sway swaylock swaybg alacritty rofi \
light network-manager network-manager-openvpn google-chrome-stable xournalpp \
php python3 helix openjdk-21-jdk openjdk-21-jre gdm3 gnome seahorse
sudo systemctl enable gdm3
sudo systemctl enable NetworkManager
sudo apt-get upgrade -y
elif [[ $distro == "arch linux" ]]; then
sudo pacman -Sy --noconfirm
sudo pacman -S git curl wget --noconfirm
sudo pacman --noconfirm -S \
fish networkmanager networkmanager-openvpn \
gdm gnome helix docker docker-buildx \
flatpak gnome-software \
distrobox
sudo systemctl enable gdm
sudo systemctl enable NetworkManager
sudo systemctl enable docker
fi
sudo usermod -aG video $USER
sudo usermod -aG docker $USER
fi
cd $DIR
DIR="$(dirname $(realpath "$0"))"
cd "$DIR"
# install config files
for filename in $(ls -p | grep -v "install" | grep -v "/" | grep -v "README.md"); do
@ -73,11 +18,15 @@ cp ./backgrounds/* "$HOME/.local/share/wallpapers/"
mkdir -p "$HOME/.local/bin"
# install pfetch
if [[ ! -e "$HOME/.local/bin/pfetch" ]]; then
curl -s https://raw.githubusercontent.com/dylanaraps/pfetch/master/pfetch > "$HOME/.local/bin/pfetch"
chmod +x "$HOME/.local/bin/pfetch"
fi
# provide rickroll
if [[ ! -e "$HOME/.local/bin/rickroll" ]]; then
curl -s https://raw.githubusercontent.com/keroserene/rickrollrc/master/roll.sh > "$HOME/.local/bin/rickroll"
chmod +x "$HOME/.local/bin/rickroll"
fi

View File

@ -3,28 +3,24 @@ font_family GoMono
window_margin_width 0
background #323232
foreground #ffffff
cursor #d6d6d6
selection_background #5b5b5b
selection_foreground #323232
color0 #353535
color8 #535353
color1 #d25252
color9 #f00c0c
color2 #a4c161
color10 #c1df74
color3 #ffc56d
color11 #e1e48a
color4 #6c99ba
color12 #8ab6d9
color5 #d096d9
color13 #efb5f7
color6 #bdd6ff
color14 #dbf4ff
color7 #ededec
background #131313
foreground #d6dae4
cursor #b9b9b9
selection_background #1f1f1f
color0 #1f1f1f
color8 #d6dae4
color1 #f71118
color9 #de342e
color2 #2cc55d
color10 #1dd260
color3 #ecb90f
color11 #f2bd09
color4 #2a84d2
color12 #0f80d5
color5 #4e59b7
color13 #524fb9
color6 #0f80d5
color14 #0f7cda
color7 #d6dae4
color15 #ffffff
active_tab_foreground #ffffff
active_tab_background #535353
inactive_tab_foreground #ffffff
inactive_tab_background #353535
selection_foreground #131313

View File

@ -1,7 +1,7 @@
#!/bin/bash
#!/usr/bin/env bash
print_status() {
echo $(upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep percentage | sed 's/percentage://g') " "
echo $(upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep percentage | sed 's/percentage://g') " "
}
print_status

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
print_status() {
echo "$(light -G | xargs printf %.0f)%" " "

View File

@ -1,7 +1,7 @@
{
"modules-left": ["hyprland/workspaces", "hyprland/window"],
"modules-center": ["clock", "custom/lock"],
"modules-right": ["tray", "custom/spotify", "pulseaudio", "custom/brightness", "battery"],
"modules-right": ["tray", "custom/spotify", "custom/ram", "custom/cpu", "pulseaudio", "custom/brightness", "battery"],
"network": {
"format-wifi": "{essid} ({signalStrength}%) ",
@ -11,10 +11,10 @@
"on-click": "kitty -e 'nmtui'"
},
// "tray": {
// "icon-size": 15,
// "spacing": 10
// },
"tray": {
"icon-size": 15,
"spacing": 2
},
"clock": {
// "tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
@ -60,6 +60,16 @@
"format-icons": [" ", " ", " "]
},
"custom/ram": {
"return-type": "text",
"exec": "~/.config/waybar/ram.sh"
},
"custom/cpu": {
"return-type": "text",
"exec": "~/.config/waybar/cpu.sh"
},
// "custom/battery": {
// "return-type": "text",
// "exec": "~/.config/waybar/battery.sh"

15
waybar-cpu.sh Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
print_status() {
top -bn1 | awk '/^%Cpu/ {printf "%d%%  \n", 100 - $8}'
}
print_status
if [ -z "$1" ] || [ "$1" -ne "once" ]; then
while sleep 1; do
print_status
done
fi

View File

@ -1,203 +1,90 @@
#!/usr/bin/env python3
import gi
gi.require_version("Playerctl", "2.0")
from gi.repository import Playerctl, GLib
from gi.repository.Playerctl import Player
import argparse
import logging
import sys
import signal
import gi
import json
import os
import io
import json
from typing import List
import time
import argparse
import subprocess
logger = logging.getLogger(__name__)
LIMIT = 23
def signal_handler(sig, frame):
logger.info("Received signal to stop, exiting")
sys.stdout.write("\n")
sys.stdout.flush()
# loop.quit()
sys.exit(0)
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('--player', type=str, required=True)
return parser.parse_args()
def query_status(player: str) -> str:
try:
return subprocess.check_output(["playerctl", "-p", player, "status"], stderr=subprocess.DEVNULL).decode().strip().lower()
except:
return 'no players found'
class PlayerManager:
def __init__(self, selected_player=None, excluded_player=[], limit=35):
self.manager = Playerctl.PlayerManager()
self.loop = GLib.MainLoop()
self.manager.connect(
"name-appeared", lambda *args: self.on_player_appeared(*args))
self.manager.connect(
"player-vanished", lambda *args: self.on_player_vanished(*args))
def query_metadata(player: str) -> dict[str, str]:
try:
raw = subprocess.check_output(["playerctl", "-p", player, "metadata"], stderr=subprocess.DEVNULL).decode().strip()
except:
return {}
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
self.selected_player = selected_player
self.excluded_player = excluded_player.split(',') if excluded_player else []
self.limit = limit
results = {}
for line in raw.split('\n'):
line = line[line.index(' ')+1:]
key = line[:line.index(' ')].strip()
value = line[line.index(' ')+1:].strip()
results[key] = value
self.init_players()
return results
def init_players(self):
for player in self.manager.props.player_names:
if player.name in self.excluded_player:
continue
if self.selected_player is not None and self.selected_player != player.name:
logger.debug(f"{player.name} is not the filtered player, skipping it")
continue
self.init_player(player)
def write_text(player: str, text: str, last_text = str | None) -> str:
if text == last_text: return text
def run(self):
logger.info("Starting main loop")
self.loop.run()
def init_player(self, player):
logger.info(f"Initialize new player: {player.name}")
player = Playerctl.Player.new_from_name(player)
player.connect("playback-status",
self.on_playback_status_changed, None)
player.connect("metadata", self.on_metadata_changed, None)
self.manager.manage_player(player)
self.on_metadata_changed(player, player.props.metadata)
def get_players(self) -> List[Player]:
return self.manager.props.players
def write_output(self, text, player):
logger.debug(f"Writing output: {text}")
if len(text) > self.limit:
text = text[:self.limit] + ''
output = {"text": text,
"class": "custom-" + player.props.player_name,
"alt": player.props.player_name}
sys.stdout.write(json.dumps(output) + "\n")
sys.stdout.write(json.dumps({
"text": text,
"class": player,
"alt": player
}))
sys.stdout.write('\n')
sys.stdout.flush()
def clear_output(self):
sys.stdout.write("\n")
return text
def print_info(player: str, last_text = str | None) -> str | None:
status = query_status(player)
if status == 'no players found':
if last_text is not None:
sys.stdout.write('\n')
sys.stdout.flush()
def on_playback_status_changed(self, player, status, _=None):
logger.debug(f"Playback status changed for player {player.props.player_name}: {status}")
self.on_metadata_changed(player, player.props.metadata)
def get_first_playing_player(self):
players = self.get_players()
logger.debug(f"Getting first playing player from {len(players)} players")
if len(players) > 0:
# if any are playing, show the first one that is playing
# reverse order, so that the most recently added ones are preferred
for player in players[::-1]:
if player.props.status == "Playing":
return player
# if none are playing, show the first one
return players[0]
else:
logger.debug("No players found")
return None
def show_most_important_player(self):
logger.debug("Showing most important player")
# show the currently playing player
# or else show the first paused player
# or else show nothing
current_player = self.get_first_playing_player()
if current_player is not None:
self.on_metadata_changed(current_player, current_player.props.metadata)
else:
self.clear_output()
metadata = query_metadata(player)
artist = metadata.get('xesam:artist')
title = metadata.get('xesam:title').replace("&", "&amp;")
album = metadata.get('xesam:album')
def on_metadata_changed(self, player, metadata, _=None):
logger.debug(f"Metadata changed for player {player.props.player_name}")
player_name = player.props.player_name
artist = player.get_artist()
title = player.get_title()
title = title.replace("&", "&amp;")
icon = '' if status == 'playing' else ''
track_info = ""
if player_name == "spotify" and "mpris:trackid" in metadata.keys() and ":ad:" in player.props.metadata["mpris:trackid"]:
track_info = "Advertisement"
elif artist is not None and title is not None:
track_info = f"{title}{artist}"
else:
track_info = title
text = f'{title} {artist}' if artist and title else title
if len(text) > LIMIT:
text = text[:LIMIT] + ''
if track_info:
if player.props.status == "Playing":
track_info = "" + track_info
else:
track_info = "" + track_info
# only print output if no other player is playing
current_playing = self.get_first_playing_player()
if current_playing is None or current_playing.props.player_name == player.props.player_name:
self.write_output(track_info, player)
else:
logger.debug(f"Other player {current_playing.props.player_name} is playing, skipping")
return write_text(player, f'{icon} {text}', last_text)
def on_player_appeared(self, _, player):
logger.info(f"Player has appeared: {player.name}")
if player.name in self.excluded_player:
logger.debug(
"New player appeared, but it's in exclude player list, skipping")
return
if player is not None and (self.selected_player is None or player.name == self.selected_player):
self.init_player(player)
else:
logger.debug(
"New player appeared, but it's not the selected player, skipping")
def on_player_vanished(self, _, player):
logger.info(f"Player {player.props.player_name} has vanished")
self.show_most_important_player()
def parse_arguments():
parser = argparse.ArgumentParser()
# Increase verbosity with every occurrence of -v
parser.add_argument("-v", "--verbose", action="count", default=0)
parser.add_argument("-x", "--exclude", "- Comma-separated list of excluded player")
parser.add_argument("-l", "--limit", "- Limit resulting text length", default=25, type=int)
# Define for which player we"re listening
parser.add_argument("--player")
parser.add_argument("--enable-logging", action="store_true")
return parser.parse_args()
def main():
arguments = parse_arguments()
args = parse_args()
# Initialize logging
if arguments.enable_logging:
logfile = os.path.join(os.path.dirname(
os.path.realpath(__file__)), "media-player.log")
logging.basicConfig(filename=logfile, level=logging.DEBUG,
format="%(asctime)s %(name)s %(levelname)s:%(lineno)d %(message)s")
sys.stdout.write('\n')
sys.stdout.flush()
# Logging is set by default to WARN and higher.
# With every occurrence of -v it's lowered by one
logger.setLevel(max((3 - arguments.verbose) * 10, 0))
try:
text = None
while True:
try: text = print_info(args.player, text)
except: pass
time.sleep(0.5)
except KeyboardInterrupt:
pass
logger.info("Creating player manager")
if arguments.player:
logger.info(f"Filtering for player: {arguments.player}")
if arguments.exclude:
logger.info(f"Exclude player {arguments.exclude}")
player = PlayerManager(arguments.player, arguments.exclude, arguments.limit)
player.run()
if __name__ == "__main__":
main()

15
waybar-ram.sh Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
print_status() {
free -m | awk '/^Mem:/ {printf "%.2f GiB  \n", $3 / 1024}'
}
print_status
if [ -z "$1" ] || [ "$1" -ne "once" ]; then
while sleep 1; do
print_status
done
fi

5
waybar-start.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
cd "$(dirname "$0")"
ls * | entr -r sh -c 'killall waybar; waybar &'

View File

@ -2,7 +2,7 @@
border: none;
font-family: Font Awesome, Roboto, Arial, sans-serif;
font-size: 13px;
color: #ffffff;
color: white;
border-radius: 20px;
}
@ -47,14 +47,24 @@ window#waybar {
padding: 0 10px;
}
#tray * {
color: #303030;
}
#custom-cpu {
min-width: 48px;
}
#clock,
#battery,
#pulseaudio,
#custom-lock,
#custom-media,
#custom-spotify,
#custom-brightness {
padding: 0 6px;
#custom-brightness,
#custom-cpu,
#custom-ram {
padding: 0 4px;
}
#pulseaudio.muted {
color: #cc3436;