From d3f34301de042fc976fa5e86981030b3f6ea9b12 Mon Sep 17 00:00:00 2001 From: mux Date: Mon, 20 Oct 2025 23:27:25 -0300 Subject: [PATCH] initial commit --- .config/emacs/config.org | 629 +++++++++++++++++++++++++++++++++ .config/emacs/dash.gif | Bin 0 -> 23889 bytes .config/emacs/early-init.el | 1 + .config/emacs/init.el | 12 + .config/fastfetch/config.jsonc | 44 +++ .config/mako/config | 7 + .config/sway/config | 170 +++++++++ .config/waybar/config.jsonc | 87 +++++ .config/waybar/mediaplayer.py | 196 ++++++++++ .config/waybar/style.css | 35 ++ 10 files changed, 1181 insertions(+) create mode 100644 .config/emacs/config.org create mode 100644 .config/emacs/dash.gif create mode 100644 .config/emacs/early-init.el create mode 100644 .config/emacs/init.el create mode 100644 .config/fastfetch/config.jsonc create mode 100644 .config/mako/config create mode 100644 .config/sway/config create mode 100644 .config/waybar/config.jsonc create mode 100755 .config/waybar/mediaplayer.py create mode 100644 .config/waybar/style.css diff --git a/.config/emacs/config.org b/.config/emacs/config.org new file mode 100644 index 0000000..16dd86b --- /dev/null +++ b/.config/emacs/config.org @@ -0,0 +1,629 @@ +#+TITLE: >." . ignore)) + (meow-leader-define-key + '("1" . meow-digit-argument) + '("2" . meow-digit-argument) + '("3" . meow-digit-argument) + '("4" . meow-digit-argument) + '("5" . meow-digit-argument) + '("6" . meow-digit-argument) + '("7" . meow-digit-argument) + '("8" . meow-digit-argument) + '("9" . meow-digit-argument) + '("0" . meow-digit-argument) + '("/" . meow-keypad-describe-key) + '("?" . meow-cheatsheet)) + + (meow-thing-register 'angle + '(pair ("<") (">")) + '(pair ("<") (">"))) + + (setq meow-char-thing-table + '((?f . round) + (?d . square) + (?s . curly) + (?a . angle) + (?r . string) + (?v . paragraph) + (?c . line) + (?x . buffer))) + + (meow-normal-define-key + ;; Expansion + '("0" . meow-expand-0) + '("1" . meow-expand-1) + '("2" . meow-expand-2) + '("3" . meow-expand-3) + '("4" . meow-expand-4) + '("5" . meow-expand-5) + '("6" . meow-expand-6) + '("7" . meow-expand-7) + '("8" . meow-expand-8) + '("9" . meow-expand-9) + '("'" . meow-reverse) + + ;; Movement + '("i" . meow-prev) + '("k" . meow-next) + '("j" . meow-left) + '("l" . meow-right) + '("y" . meow-search) + '("/" . meow-visit) + + ;; Expansion + '("I" . meow-prev-expand) + '("K" . meow-next-expand) + '("J" . meow-left-expand) + '("L" . meow-right-expand) + + '("u" . meow-back-word) + '("U" . meow-back-symbol) + '("o" . meow-next-word) + '("O" . meow-next-symbol) + + '("a" . meow-mark-word) + '("A" . meow-mark-symbol) + '("s" . meow-line) + '("S" . meow-goto-line) + '("w" . meow-block) + '("q" . meow-join) + '("g" . meow-grab) + '("G" . meow-pop-grab) + '("m" . meow-swap-grab) + '("M" . meow-sync-grab) + '("p" . meow-cancel-selection) + '("P" . meow-pop-selection) + + '("x" . meow-till) + '("z" . meow-find) + + '("," . meow-beginning-of-thing) + '("." . meow-end-of-thing) + '("<" . meow-inner-of-thing) + '(">" . meow-bounds-of-thing) + + ;; Editing + '("d" . meow-kill) + '("f" . meow-change) + '("t" . meow-delete) + '("c" . meow-save) + '("v" . meow-yank) + '("V" . meow-yank-pop) + + '("e" . meow-insert) + '("E" . meow-open-above) + '("r" . meow-append) + '("R" . meow-open-below) + + '("h" . undo-only) + '("H" . undo-redo) + + '("b" . open-line) + '("B" . split-line) + + '("[" . indent-rigidly-left-to-tab-stop) + '("]" . indent-rigidly-right-to-tab-stop) + + ;; Prefix commands + '("nf" . meow-comment) + '("nt" . meow-start-kmacro-or-insert-counter) + '("nr" . meow-start-kmacro) + '("ne" . meow-end-or-call-kmacro) + + '(";f" . save-buffer) + '(";F" . save-some-buffers) + '(";d" . meow-query-replace-regexp) + + ;; Buffer navigation + '(";[b" . previous-buffer) + '(";]b" . next-buffer) + '(";b" . switch-to-buffer) + '(";nb" . rename-buffer) + '(";B" . revert-buffer) + + '("" . ignore))) + + :config + (meow-ergo-setup) + (meow-global-mode 1)) +#+end_src + +** Formatter +#+begin_src emacs-lisp + (use-package format-all + :ensure t + :preface + (defun refmt () + "Auto-format whole buffer." + (interactive) + (cond + ((derived-mode-p 'prolog-mode) + (prolog-indent-buffer)) + ((derived-mode-p 'emacs-lisp-mode) + (indent-region (point-min) (point-max))) + ((derived-mode-p 'org-mode) + (org-indent-region (point-min) (point-max))) + (t + (format-all-buffer)))) + :config + (global-set-key (kbd "M-f") #'refmt) + (add-hook 'prog-mode-hook #'format-all-ensure-formatter)) +#+end_src + +* PROGRAMMING FEATURES +** Syntax highlighting +#+begin_src emacs-lisp + (use-package treesit-auto + :ensure t + :custom + (treesit-auto-install 'prompt) + :config + (treesit-auto-add-to-auto-mode-alist 'all) + (global-treesit-auto-mode)) +#+end_src + +** LSP +#+begin_src emacs-lisp + (use-package lsp-mode + :ensure t + :hook + (prog-mode . lsp-deferred) + (lsp-mode . lsp-enable-which-key-integration) + :commands (lsp lsp-deferred) + :init + (setq lsp-keymap-prefix "C-c l") + :custom + (lsp-idle-delay 0.500) + (lsp-log-io nil) + (lsp-completion-provider :none) + (lsp-headerline-breadcrumb-enable nil)) + + (use-package flycheck + :ensure t + :config + (global-flycheck-mode +1)) +#+end_src + +** Indentation preferences +#+begin_src emacs-lisp + (setq-default + indent-tabs-mode t + tab-width 4 + standard-indent 4) + (setq tab-always-indent 1) + + (use-package dtrt-indent + :ensure t + :hook (prog-mode . dtrt-indent-mode)) + + (use-package whitespace + :hook (prog-mode . whitespace-mode) + :custom + (whitespace-style '(face tabs tab-mark trailing)) + (whitespace-display-mappings + '((tab-mark ?\t [?→ ?\t] [?> ?\t])))) +#+end_src + +* COMPLETION SYSTEM +** Helpful documentation +#+begin_src emacs-lisp + (use-package helpful + :ensure t + :bind + ([remap describe-function] . helpful-callable) + ([remap describe-variable] . helpful-variable) + ([remap describe-key] . helpful-key)) +#+end_src + +** Minibuffer completion (Vertico + Marginalia) +#+begin_src emacs-lisp + (use-package marginalia + :ensure t + :bind (:map minibuffer-local-map + ("M-A" . marginalia-cycle)) + :init + (marginalia-mode)) + + (use-package vertico + :ensure t + :custom + (vertico-cycle t) + :init + (vertico-mode)) + + (use-package savehist + :init + (savehist-mode)) + + (use-package orderless + :ensure t + :custom + (completion-styles '(orderless basic)) + (completion-category-defaults nil) + (completion-category-overrides '((file (styles partial-completion))))) +#+end_src + +** Minibuffer settings +#+begin_src emacs-lisp + (use-package emacs + :custom + (context-menu-mode t) + (enable-recursive-minibuffers t) + (read-extended-command-predicate #'command-completion-default-include-p) + (text-mode-ispell-word-completion nil) + (minibuffer-prompt-properties + '(read-only t cursor-intangible t face minibuffer-prompt))) +#+end_src + +** In-buffer completion (Corfu + Cape) +#+begin_src emacs-lisp + (use-package corfu + :ensure t + :custom + (corfu-auto t) + (corfu-cycle t) + (corfu-preselect 'prompt) + :init + (global-corfu-mode) + (corfu-history-mode) + (corfu-popupinfo-mode) + :bind + (:map corfu-map + ("TAB" . corfu-next) + ([tab] . corfu-next) + ("S-TAB" . corfu-previous) + ([backtab] . corfu-previous))) + + (use-package cape + :ensure t + :bind ("C-c p" . cape-prefix-map) + :hook + ((completion-at-point-functions . cape-dabbrev) + (completion-at-point-functions . cape-file) + (completion-at-point-functions . cape-elisp-block))) + +#+end_src + +#+RESULTS: +: [nil 26870 55996 618175 nil elpaca-process-queues nil nil 712000 nil] + +* VISUAL APPEARANCE +** Theme and colors +#+begin_src emacs-lisp + (use-package doom-themes + :ensure t + :custom + (doom-themes-enable-bold t) + (doom-themes-enable-italic t) + :config + (load-theme 'doom-moonlight t) + (doom-themes-visual-bell-config) + (doom-themes-org-config) + + (let ((bg "#16191C") + (fg "#C5CACE") + (bg-alt "#252A2E") + (fg-alt "#A3AAAF") + (fg-muted "#50555A")) + (custom-set-faces + `(default ((t (:background ,bg :foreground ,fg)))) + `(fringe ((t (:background ,bg)))) + `(hl-line ((t (:background ,bg-alt)))) + `(mode-line ((t (:background ,bg-alt :foreground ,fg)))) + `(mode-line-inactive ((t (:background ,bg :foreground ,fg-muted)))) + `(line-number ((t (:foreground ,fg-muted :background ,bg)))) + `(line-number-current-line ((t (:foreground ,fg-alt :background ,bg-alt :weight bold)))) + `(font-lock-comment-face ((t (:foreground ,fg-alt))))))) + + (add-hook 'org-mode-hook + (lambda () + (set-face-background 'org-block "#16191C") + (set-face-foreground 'org-block "#C5CACE") + (set-face-background 'org-block-begin-line "#252A2E") + (set-face-foreground 'org-block-begin-line "#A3AAAF") + (set-face-background 'org-block-end-line "#252A2E") + (set-face-foreground 'org-block-end-line "#A3AAAF"))) +#+end_src + +** Modeline +#+begin_src emacs-lisp + (use-package doom-modeline + :ensure t + :init (doom-modeline-mode +1)) +#+end_src + +** Color preview +#+begin_src emacs-lisp + (use-package colorful-mode + :ensure t + :custom + (colorful-use-prefix t) + (colorful-only-strings 'only-prog) + (css-fontify-colors nil) + :config + (global-colorful-mode t) + (add-to-list 'global-colorful-modes 'helpful-mode)) + + (use-package rainbow-delimiters + :ensure t + :hook (prog-mode . rainbow-delimiters-mode)) +#+end_src + +#+RESULTS: +: [nil 26870 59644 357807 nil elpaca-process-queues nil nil 727000 nil] + +* INTEGRATIONS & UTILITIES +** Discord presence +#+begin_src emacs-lisp + (use-package elcord + :ensure t + :config + (elcord-mode +1)) +#+end_src + +** Project management +#+begin_src emacs-lisp + (use-package projectile + :ensure t + :config + (projectile-mode +1) + (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)) + + (use-package editorconfig + :ensure t + :config + (editorconfig-mode 1)) +#+end_src +** Dashboard +#+begin_src emacs-lisp + (use-package page-break-lines + :ensure t + :config + (page-break-lines-mode +1)) + + (use-package all-the-icons + :ensure t + :if (display-graphic-p)) + + (use-package dashboard + :ensure t + :custom + (dashboard-banner-logo-title "DMs~ ;)") + (dashboard-startup-banner "~/.config/emacs/dash.gif") + :config + (add-hook 'elpaca-after-init-hook #'dashboard-insert-startupify-lists) + (add-hook 'elpaca-after-init-hook #'dashboard-initialize) + (dashboard-setup-startup-hook)) +#+end_src + +** File tree +#+begin_src emacs-lisp + (use-package treemacs + :ensure t + :bind ("C-c t" . treemacs) + :config + (setq treemacs-width 30)) + + (use-package treemacs-projectile + :ensure t + :after (treemacs projectile)) + + (use-package treemacs-all-the-icons + :ensure t + :after (treemacs all-the-icons) + :config + (treemacs-load-theme "all-the-icons")) + + (use-package treemacs-icons-dired + :ensure t + :hook (dired-mode . treemacs-icons-dired-enable-once)) + +#+end_src + +#+RESULTS: +: [nil 26870 60289 404113 nil elpaca-process-queues nil nil 420000 nil] diff --git a/.config/emacs/dash.gif b/.config/emacs/dash.gif new file mode 100644 index 0000000000000000000000000000000000000000..bcc31d22874424cf403b572c62d89dd8d7efeb3d GIT binary patch literal 23889 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 literal 0 HcmV?d00001 diff --git a/.config/emacs/early-init.el b/.config/emacs/early-init.el new file mode 100644 index 0000000..512068a --- /dev/null +++ b/.config/emacs/early-init.el @@ -0,0 +1 @@ +(setq package-enable-at-startup nil) diff --git a/.config/emacs/init.el b/.config/emacs/init.el new file mode 100644 index 0000000..3b74f4e --- /dev/null +++ b/.config/emacs/init.el @@ -0,0 +1,12 @@ +;(add-to-list 'load-path +; (expand-file-name +; "tao-theme-emacs/" +; user-emacs-directory)) +; +;(load "tao-yin-theme.el") +;(load-theme 'tao-yin t) + +(org-babel-load-file + (expand-file-name + "config.org" + user-emacs-directory)) diff --git a/.config/fastfetch/config.jsonc b/.config/fastfetch/config.jsonc new file mode 100644 index 0000000..b56569c --- /dev/null +++ b/.config/fastfetch/config.jsonc @@ -0,0 +1,44 @@ +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "modules": [ + "title", + "break", + { + "type": "kernel", + "key": "system" + }, + { + "type": "uptime", + "key": "uptime" + }, + { + "type": "packages", + "key": "bloatware" + }, + { + "type": "wm", + "key": "compositor" + }, + { + "type": "cpu", + "key": "cpu" + }, + { + "type": "gpu", + "key": "gpu" + } + ], + "logo": { + "type": "small", + "color": { + "1": "#9e9b93" + } + }, + "display": { + "separator": " ", // Separator between keys and values + "color": { + "keys": "#9e9b93", // Key color + "title": "#9e9b93" // Title color + } + } +} diff --git a/.config/mako/config b/.config/mako/config new file mode 100644 index 0000000..33ee734 --- /dev/null +++ b/.config/mako/config @@ -0,0 +1,7 @@ +background-color=#16191C +border-color=#252A2E +icons=0 +ignore-timeout=1 +sort=-time +text-color=#A3AAAF +margin=4 diff --git a/.config/sway/config b/.config/sway/config new file mode 100644 index 0000000..0abc3cb --- /dev/null +++ b/.config/sway/config @@ -0,0 +1,170 @@ +exec autotiling + +exec systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP +exec dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway + +### Variables +# +# Logo key. Use Mod1 for Alt. +set $mod Mod4 +set $left j +set $down k +set $up i +set $right l +# Your preferred terminal emulator +set $term alacritty +# Your preferred application launcher +set $menu wmenu-run + +default_border pixel 1 +client.focused #252a2e #171717 #E9E9E9 #262626 #252a2e +client.focused_inactive #252a2e #171717 #E9E9E9 #262626 #262626 +client.unfocused #252a2e #171717 #E9E9E9 #262626 #262626 +client.urgent #252a2e #171717 #E9E9E9 #262626 #262626 +client.placeholder #252a2e #171717 #E9E9E9 #262626 #262626 + +gaps inner 2 +gaps outer 2 + +input type:pointer { + accel_profile "flat" + pointer_accel 0.0 +} + +output * bg #02060A solid_color + +input type:keyboard { + xkb_layout "us" + xkb_variant "intl" + xkb_options "caps:swapescape" +} + +floating_modifier $mod normal + +bindsym $mod+Shift+c reload + +bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit' + +# +# Workspaces mode: +# +mode "normal" { + # Switch to workspace + bindsym 1 workspace number 1; mode "default" + bindsym 2 workspace number 2; mode "default" + bindsym 3 workspace number 3; mode "default" + bindsym 4 workspace number 4; mode "default" + bindsym 5 workspace number 5; mode "default" + bindsym 6 workspace number 6; mode "default" + bindsym 7 workspace number 7; mode "default" + bindsym 8 workspace number 8; mode "default" + bindsym 9 workspace number 9; mode "default" + bindsym 0 workspace number 10; mode "default" + + # Move focused container to workspace + bindsym Shift+1 move container to workspace number 1; mode "default" + bindsym Shift+2 move container to workspace number 2; mode "default" + bindsym Shift+3 move container to workspace number 3; mode "default" + bindsym Shift+4 move container to workspace number 4; mode "default" + bindsym Shift+5 move container to workspace number 5; mode "default" + bindsym Shift+6 move container to workspace number 6; mode "default" + bindsym Shift+7 move container to workspace number 7; mode "default" + bindsym Shift+8 move container to workspace number 8; mode "default" + bindsym Shift+9 move container to workspace number 9; mode "default" + bindsym Shift+0 move container to workspace number 10; mode "default" + + # + # Moving around: + # + # Move your focus + bindsym left focus left; mode "default" + bindsym down focus down; mode "default" + bindsym up focus up; mode "default" + bindsym right focus right; mode "default" + + # Move the focused window + bindsym Shift+left move left; mode "default" + bindsym Shift+down move down; mode "default" + bindsym Shift+up move up; mode "default" + bindsym Shift+right move right; mode "default" + + bindsym Return exec $term; mode "default" + bindsym q kill; mode "default" + + # + # Layout stuff: + # + bindsym b splith; mode "default" # horizontal split + bindsym v splitv; mode "default" # vertical split + bindsym s layout stacking; mode "default" + bindsym w layout tabbed; mode "default" + bindsym e layout toggle split; mode "default" + bindsym f fullscreen; mode "default" + bindsym Shift+space floating toggle; mode "default" + bindsym space focus mode_toggle; mode "default" + bindsym a focus parent; mode "default" + + bindsym d exec $menu; mode "default" + + # Exit mode back to default + bindsym Escape mode "default" +} + +# Activate workspaces mode with Super+x +bindsym $mod+x mode "normal" + +# +# Resizing containers: +# +mode "resize" { + # left will shrink the containers width + # right will grow the containers width + # up will shrink the containers height + # down will grow the containers height + bindsym $left resize shrink width 10px + bindsym $down resize grow height 10px + bindsym $up resize shrink height 10px + bindsym $right resize grow width 10px + + # Ditto, with arrow keys + bindsym Left resize shrink width 10px + bindsym Down resize grow height 10px + bindsym Up resize shrink height 10px + bindsym Right resize grow width 10px + + # Return to default mode + bindsym Return mode "default" + bindsym Escape mode "default" + + bindsym p exec shotman --capture window + bindsym Shift+p exec shotman --capture region + bindsym Ctrl+p exec shotman --capture output +} +bindsym $mod+r mode "resize" +# +# Utilities: +# + # Special keys to adjust volume via PulseAudio + bindsym --locked XF86AudioMute exec pactl set-sink-mute \@DEFAULT_SINK@ toggle + bindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume \@DEFAULT_SINK@ -5% + bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume \@DEFAULT_SINK@ +5% + bindsym --locked XF86AudioMicMute exec pactl set-source-mute \@DEFAULT_SOURCE@ toggle + + # Special key to take a screenshot with grim + bindsym $mod+z exec grim -g "$(slurp)" + bindsym $mod+y exec grim - | wl-copy + +# +# Status Bar: +# +# Read `man 5 sway-bar` for more information about this section. +bar { + position top + swaybar_command waybar +} + +output * { + mode 1920x1080@120Hz +} + +include /usr/local/etc/sway/config.d/* diff --git a/.config/waybar/config.jsonc b/.config/waybar/config.jsonc new file mode 100644 index 0000000..b55ded3 --- /dev/null +++ b/.config/waybar/config.jsonc @@ -0,0 +1,87 @@ +// -*- mode: jsonc -*- +{ + // "layer": "top", // Waybar at top layer + "position": "top", // Waybar position (top|bottom|left|right) + "height": 30, // Waybar height (to be removed for auto height) + "spacing": 4, // Gaps between modules (4px) + "margin-left": 4, + "margin-right": 4, + "margin-top": 4, + "modules-left": [ + "sway/workspaces", + "sway/mode" + ], + "modules-center": [ + "custom/media" + ], + "modules-right": [ + "pulseaudio", + "clock", + "tray" + ], + // Modules configuration + // "sway/workspaces": { + // "disable-scroll": true, + // "all-outputs": true, + // "warp-on-scroll": false, + // "format": "{name}: {icon}", + // "format-icons": { + // "1": "", + // "2": "", + // "3": "", + // "4": "", + // "5": "", + // "urgent": "", + // "focused": "", + // "default": "" + // } + // }, + "sway/mode": { + "format": "{}" + }, + "tray": { + // "icon-size": 21, + "spacing": 10, + // "icons": { + // "blueman": "bluetooth", + // "TelegramDesktop": "$HOME/.local/share/icons/hicolor/16x16/apps/telegram.png" + // } + }, + "clock": { + // "timezone": "America/New_York", + "format": " {:%H:%M}", + "format-alt": "{:%A, %B %d, %Y (%R)}" + }, + "pulseaudio": { + // "scroll-step": 1, // %, can be a float + "format": "{icon} {volume}%", + "format-bluetooth": "{volume}% {icon} {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": " 0%", + "format-source": "{volume}% ", + "format-source-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pavucontrol" + }, + "custom/media": { + "format": "{text}", + "return-type": "json", + "max-length": 40, + "format-icons": { + "spotify": "", + "default": "🎜" + }, + "escape": true, + "exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null", + "on-click": "playerctl play-pause" // Script in resources folder + // "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name + }, +} diff --git a/.config/waybar/mediaplayer.py b/.config/waybar/mediaplayer.py new file mode 100755 index 0000000..524d4d2 --- /dev/null +++ b/.config/waybar/mediaplayer.py @@ -0,0 +1,196 @@ +#!/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 +from typing import List + +logger = logging.getLogger(__name__) + +def signal_handler(sig, frame): + logger.info("Received signal to stop, exiting") + sys.stdout.write("\n") + sys.stdout.flush() + # loop.quit() + sys.exit(0) + + +class PlayerManager: + def __init__(self, selected_player=None, excluded_player=[]): + 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)) + + 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.init_players() + + 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 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}") + + output = {"text": text, + "class": "custom-" + player.props.player_name, + "alt": player.props.player_name} + + sys.stdout.write(json.dumps(output) + "\n") + sys.stdout.flush() + + def clear_output(self): + 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() + + 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() + artist = artist.replace("&", "&") + title = player.get_title() + title = title.replace("&", "&") + + 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"{artist} - {title}" + else: + track_info = title + + 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") + + 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") + + # 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() + + # 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") + + # 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)) + + 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) + player.run() + + +if __name__ == "__main__": + main() diff --git a/.config/waybar/style.css b/.config/waybar/style.css new file mode 100644 index 0000000..15ece98 --- /dev/null +++ b/.config/waybar/style.css @@ -0,0 +1,35 @@ +* { + min-height: 0; + min-width: 0; + font-family: "ShureTechMono Nerd Font"; + font-size: 16px; + font-weight: 500; +} + +window#waybar { + background-color: transparent; +} + +#workspaces, +#custom-media, +#clock, +#pulseaudio, +#mode, +#tray +{ + padding: 0.5em 1.25em; + background-color: #16191C; + border: 1px solid #252A2E; + color: #A3AAAF; +} + +#workspaces button, +#mode { + color: #50555A; + font-weight: 400; +} + +#workspaces button.visible { + color: #A3AAAF; + font-weight: 600; +}