diff --git a/.config/niri/config.kdl##hostname.dbox b/.config/niri/config.kdl##hostname.dbox index b30bb22b..a904cf74 100644 --- a/.config/niri/config.kdl##hostname.dbox +++ b/.config/niri/config.kdl##hostname.dbox @@ -1,3 +1,6 @@ +workspace "music" { + open-on-output "Dell" +} // This config is in the KDL format: https://kdl.dev // "/-" comments out the following node. // Check the wiki for a full description of the configuration: @@ -192,6 +195,10 @@ animations { // https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules // Work around WezTerm's initial configure bug // by setting an empty default-column-width. +window-rule { + match app-id="^spotify$" + open-on-workspace "music" +} window-rule { // This regular expression is intentionally made as specific as possible, // since this is the default config, and we want no false positives. @@ -264,6 +271,9 @@ environment { cursor { hide-when-typing } +hotkey-overlay { + skip-at-startup +} binds { // Keys consist of modifiers separated by + signs, followed by an XKB key name // in the end. To find an XKB name for a particular key, you may use a program @@ -449,10 +459,16 @@ binds { focus-workspace-up } Mod+L { - focus-monitor-left + move-workspace-down } Mod+U { - focus-monitor-right + move-workspace-up + } + Mod+J { + move-workspace-to-monitor-left + } + Mod+Y { + move-workspace-to-monitor-right } Mod+Ctrl+Page_Down { move-column-to-workspace-down @@ -689,6 +705,10 @@ binds { // since it will switch twice upon pressing the hotkey (once by xkb, once by niri). // Mod+Space { switch-layout "next"; } // Mod+Shift+Space { switch-layout "prev"; } + // reload waybar + Mod+Shift+W { + spawn "systemctl" "--user" "restart" "waybar" + } Mod+S { screenshot } @@ -699,7 +719,10 @@ binds { screenshot-window } Mod+Alt+S { - spawn "~/scripts/recorder.sh" + spawn "~/scripts/recorder.sh" "screen" + } + Mod+Shift+Alt+S { + spawn "~/scripts/recorder.sh" "region" } Mod+Tab { spawn "~/scripts/niri/window-picker.py" diff --git a/.config/waybar/config b/.config/waybar/config index c5f024a0..240ecef3 100644 --- a/.config/waybar/config +++ b/.config/waybar/config @@ -8,28 +8,70 @@ "niri/window" ], "modules-right": [ + "cava", "cpu", "memory", "pulseaudio", "battery", + "custom/recorder", "tray", "clock" ], "niri/window": { - "max-length": 50 + "max-length": 50, + "separate-outputs": true + }, + "custom/recorder": { + "exec": "~/dev/niri-recorder/recorder.py", + "return-type": "json", + "restart-interval": "never", + "on-click": "~/dev/niri-recorder/recorder.sh screen", + "on-click-right": "~/dev/niri-recorder/recorder.sh region" + }, + "cava": { + "cava_config": "$XDG_CONFIG_HOME/cava/cava.conf", + // "framerate": 30, + // "autosens": 1, + // "sensitivity": 100, + // "bars": 14, + // "lower_cutoff_freq": 50, + // "higher_cutoff_freq": 10000, + // "method": "pulse", + // "source": "auto", + // "stereo": true, + // "reverse": false, + // "bar_delimiter": 0, + // "monstercat": false, + // "waves": false, + // "noise_reduction": 0.77, + // "input_delay": 2, + "format-icons": [ + "▁", + "▂", + "▃", + "▄", + "▅", + "▆", + "▇", + "█" + ], + "actions": { + "on-click-right": "mode" + } }, "niri/workspaces": { - // "format": "{icon}", - // "format-icons": { - // // Named workspaces - // // (you need to configure them in niri) - // "browser": "", - // "discord": "", - // "chat": "", - // // Icons by state - // "active": "", - // "default": "" - // } + "format": "{icon}", + "format-icons": { + // Named workspaces + // (you need to configure them in niri) + // "browser": "", + // "discord": "", + // "chat": "", + // Icons by state + "music": "󰎇", + "active": "", + "default": "" + } }, // "sway/workspaces": { // "disable-scroll" : false, diff --git a/.config/waybar/custom/recorder.py b/.config/waybar/custom/recorder.py new file mode 100755 index 00000000..81b7386a --- /dev/null +++ b/.config/waybar/custom/recorder.py @@ -0,0 +1,93 @@ +#!/bin/env python + +import os +import socket +import json +import asyncio + +def p(obj): + print(json.dumps(obj), flush=True) + +SOCKET = "/tmp/recorder-sock.sock" +DEF_TT = "Click to record screen. Right-click to record region." +DEF_TEXT = "rec" + +# Remove if already exists +try: + os.unlink(SOCKET) +except OSError: + # doesn't exist, we're good + pass + +delayed_task = None + +async def delayed_msg(delay, message): + # print(f"[DEBUG] Starting delayed message task, waiting {delay} seconds...", flush=True) + try: + await asyncio.sleep(delay) + # print(f"[DEBUG] Delayed message task executed! Sending message: {message}", flush=True) + p(message) + except asyncio.CancelledError: + # print("[DEBUG] Delayed message task was cancelled!", flush=True) + pass +def handle_message(data: str, loop): + global delayed_task + if delayed_task: + delayed_task.cancel() + out = {} + out_s = "" + out_t = "" + if data: + if data == "REC": + out_s = "on" + out_t = "Recording in progress. Click to stop." + elif data == "CMP": + out_s = "compressing" + out_t = "Recording is being compressed." + elif data == "CPD": + out_s = "copied" + out_t = "Recording has been copied to clipboard." + elif data == "STP": + out_s = "done" + out_t = "Recording has been stopped." + elif data == "ERR": + out_s = "error" + out_t = "Recording has encountered an error." + else: + # print("this runs a", flush=True) + out_s = "" + out_t = "" + else: + # print("this runs b", flush=True) + out_s = "" + out_t = "" + out["text"] = f"rec: {out_s}" if out_s != "" else DEF_TEXT + out["tooltip"] = out_t if out_t != "" else DEF_TT + p(out) + + if data in ["ERR", "CPD", "STP"]: + if delayed_task: + # print("canceled delayed task", flush=True) + delayed_task.cancel() + delayed_out = {"text": DEF_TEXT, "tooltip": DEF_TT} + # print("debug: creating delayed task", flush=True) + delayed_task = loop.create_task(delayed_msg(5, delayed_out)) + +async def server(): + loop = asyncio.get_running_loop() + + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as server: + server.bind(SOCKET) + server.setblocking(False) + server.listen(1) + + while True: + conn, _ = await loop.sock_accept(server) + with conn: + data = (await loop.sock_recv(conn, 1024)).decode().strip() + handle_message(data, loop) + +async def main(): + p({"text": DEF_TEXT, "tooltip": DEF_TT}) + await server() +asyncio.run(main()) diff --git a/.config/waybar/custom/test.sh b/.config/waybar/custom/test.sh new file mode 100755 index 00000000..44f681bb --- /dev/null +++ b/.config/waybar/custom/test.sh @@ -0,0 +1,14 @@ +#!/bin/env bash + +echo "REC" | socat - UNIX-CONNECT:/tmp/recorder-sock.sock; \ +sleep 2; \ +echo "ERR" | socat - UNIX-CONNECT:/tmp/recorder-sock.sock; \ +sleep 2; \ +echo "REC" | socat - UNIX-CONNECT:/tmp/recorder-sock.sock; \ +sleep 2; \ +echo "STP" | socat - UNIX-CONNECT:/tmp/recorder-sock.sock; \ +sleep 2; \ +echo "CMP" | socat - UNIX-CONNECT:/tmp/recorder-sock.sock; \ +sleep 2; \ +echo "CPD" | socat - UNIX-CONNECT:/tmp/recorder-sock.sock; \ +sleep 2; diff --git a/.config/waybar/modules b/.config/waybar/modules.bak similarity index 100% rename from .config/waybar/modules rename to .config/waybar/modules.bak