diff options
36 files changed, 3564 insertions, 0 deletions
diff --git a/.Xresources b/.Xresources new file mode 100644 index 0000000..af21ba2 --- /dev/null +++ b/.Xresources @@ -0,0 +1,91 @@ +XCursor.theme: Adwaita + +URxvt.preeditType:Root +! input method +URxvt.imLocale: ja_JP.utf8 +URxvt.imFont: xft:WenQuanYi Micro Hei Mono:size=12 +URxvt.inputMethod: ibus + +URxvt.*font: xft:Iosevka Term Custom:style=Regular:size=11:antialias=True,xft:Joypixels:pixelsize=10 + +!! true transparency +!!URxvt.depth: 32 +!!URxvt.background: [90]#000000 + +!! no transparency +! light +! URxvt.background: #eeeeee +! URxvt.foreground: #444444 +! dark +URxvt.background: #000000 +URxvt.foreground: #FFFFFF + +!! visuals and colors +/* URxvt.letterSpace: 0 */ +URxvt.letterSpace: 2 +URxvt.scrollBar: False +URxvt.externalBorder: 0 +URxvt.internalBorder: 0 +URxvt.backgroundBorder: 0 +URxvt.borderLess: False +!! colors for dracula theme +!! black +URxvt.color0: #000000 +URxvt.color8: #343636 +!! red +URxvt.color1: #e74c7c +URxvt.color9: #c26f6f +!! green +URxvt.color2: #6bb05d +URxvt.color10: #8dc776 +!! yellow +URxvt.color3: #e59e67 +URxvt.color11: #e7ac7e +!! indigo +URxvt.color4: #5b98a9 +URxvt.color12: #7ab3c3 +!! lavender +URxvt.color5: #b185db +URxvt.color13: #bb84e5 +!! cyan +URxvt.color6: #51a39f +URxvt.color14: #6db0ad +!! white +URxvt.color7: #c4c4c4 +URxvt.color15: #cccccc + +!! colors for papercolor-theme +! !! white and very light gray +! URxvt.color0: #eeeeee +! URxvt.color8: #bcbcbc +! !! red +! URxvt.color1: #af0000 +! URxvt.color9: #d70000 +! !! dark green and magenta +! URxvt.color2: #008700 +! URxvt.color10: #d70087 +! !! murky green and purple +! URxvt.color3: #5f8700 +! URxvt.color11: #8700af +! !! jeans blue and orange +! URxvt.color4: #0087af +! URxvt.color12: #d75f00 +! !! gray and orange +! URxvt.color5: #878787 +! URxvt.color13: #d75f00 +! !! ocean blue +! URxvt.color6: #005f87 +! URxvt.color14: #005faf +! !! dark gray and ocean blue +! URxvt.color7: #444444 +! URxvt.color15: #005f87 + +!! perl extensions +URxvt.perl-ext-common: default,url-select,resize-font,selection-to-clipboard,-confirm-paste +URxvt.matcher.button: 1 +URxvt.keysym.M-u: perl:url-select:select_next +URxvt.url-select.launcher: /usr/bin/xdg-open +URxvt.url-select.underline: true + +URxvt.iso14755: False +URxvt.iso14755_52: False diff --git a/.bash_profile b/.bash_profile new file mode 120000 index 0000000..8486fca --- /dev/null +++ b/.bash_profile @@ -0,0 +1 @@ +.config/shell/profile
\ No newline at end of file @@ -0,0 +1,57 @@ +umask 0077 + +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac + +stty start undef + +export PROMPT_DIRTRIM=2 + +PS1="\[\033[1;33m\][\[\033[1;35m\]\u\[\033[1;32m\]@\[\033[1;36m\]\h\[\033[1;37m\]:\[\033[1;33m\]\w]\[\033[0m\] " + +# append to the history file, don't overwrite it +shopt -s histappend + +# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) +HISTSIZE=1000 +HISTFILESIZE=2000 + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# Enable globbing hidden/dot files (.filename). +shopt -s dotglob + +# make less more friendly for non-text input files, see lesspipe(1) +#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" + +# enable colors +if [ -f ~/.config/dircolors ]; then + eval "`dircolors -b ~/.config/dircolors`" +fi + + +if [ -f ~/.config/shell/aliasrc ]; then + . ~/.config/shell/aliasrc +fi + +if ! shopt -oq posix; then + if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion + elif [ -f /etc/bash_completion ]; then + . /etc/bash_completion + fi +fi + +# fzf configs +[ -f ~/.local/src/fzf/fzf.bash ] && . ~/.local/src/fzf/fzf.bash +export FZF_DEFAULT_OPS="--extended" +export FZF_DEFAULT_COMMAND="find -type f" +export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" + +# NNN +[ -f ~/.config/nnn/nnn.bash ] && . ~/.config/nnn/nnn.bash diff --git a/.config/dunst/dunstrc b/.config/dunst/dunstrc new file mode 100755 index 0000000..ab11296 --- /dev/null +++ b/.config/dunst/dunstrc @@ -0,0 +1,457 @@ +# See dunst(5) for all configuration options + +[global] + ### Display ### + + # Which monitor should the notifications be displayed on. + monitor = 0 + + # Display notification on focused monitor. Possible modes are: + # mouse: follow mouse pointer + # keyboard: follow window with keyboard focus + # none: don't follow anything + # + # "keyboard" needs a window manager that exports the + # _NET_ACTIVE_WINDOW property. + # This should be the case for almost all modern window managers. + # + # If this option is set to mouse or keyboard, the monitor option + # will be ignored. + follow = none + + ### Geometry ### + + # dynamic width from 0 to 300 + # width = (0, 300) + # constant width of 300 + width = (0, 300) + + # The maximum height of a single notification, excluding the frame. + height = 300 + + # Position the notification in the top right corner + origin = top-right + + # Offset from the origin + offset = 10x50 + + # Scale factor. It is auto-detected if value is 0. + scale = 0 + + # Maximum number of notification (0 means no limit) + notification_limit = 0 + + ### Progress bar ### + + # Turn on the progess bar. It appears when a progress hint is passed with + # for example dunstify -h int:value:12 + progress_bar = true + + # Set the progress bar height. This includes the frame, so make sure + # it's at least twice as big as the frame width. + progress_bar_height = 10 + + # Set the frame width of the progress bar + progress_bar_frame_width = 1 + + # Set the minimum width for the progress bar + progress_bar_min_width = 150 + + # Set the maximum width for the progress bar + progress_bar_max_width = 300 + + + # Show how many messages are currently hidden (because of + # notification_limit). + indicate_hidden = yes + + # The transparency of the window. Range: [0; 100]. + # This option will only work if a compositing window manager is + # present (e.g. xcompmgr, compiz, etc.). (X11 only) + transparency = 0 + + # Draw a line of "separator_height" pixel height between two + # notifications. + # Set to 0 to disable. + # If gap_size is greater than 0, this setting will be ignored. + separator_height = 2 + + # Padding between text and separator. + padding = 8 + + # Horizontal padding. + horizontal_padding = 8 + + # Padding between text and icon. + text_icon_padding = 0 + + # Defines width in pixels of frame around the notification window. + # Set to 0 to disable. + frame_width = 3 + + # Defines color of the frame around the notification window. + frame_color = "#aaaaaa" + + # Size of gap to display between notifications - requires a compositor. + # If value is greater than 0, separator_height will be ignored and a border + # of size frame_width will be drawn around each notification instead. + # Click events on gaps do not currently propagate to applications below. + gap_size = 0 + + # Define a color for the separator. + # possible values are: + # * auto: dunst tries to find a color fitting to the background; + # * foreground: use the same color as the foreground; + # * frame: use the same color as the frame; + # * anything else will be interpreted as a X color. + separator_color = frame + + # Sort messages by urgency. + sort = yes + + # Don't remove messages, if the user is idle (no mouse or keyboard input) + # for longer than idle_threshold seconds. + # Set to 0 to disable. + # A client can set the 'transient' hint to bypass this. See the rules + # section for how to disable this if necessary + # idle_threshold = 120 + + ### Text ### + + font = Monospace 10 + + # The spacing between lines. If the height is smaller than the + # font height, it will get raised to the font height. + line_height = 0 + + # Possible values are: + # full: Allow a small subset of html markup in notifications: + # <b>bold</b> + # <i>italic</i> + # <s>strikethrough</s> + # <u>underline</u> + # + # For a complete reference see + # <https://docs.gtk.org/Pango/pango_markup.html>. + # + # strip: This setting is provided for compatibility with some broken + # clients that send markup even though it's not enabled on the + # server. Dunst will try to strip the markup but the parsing is + # simplistic so using this option outside of matching rules for + # specific applications *IS GREATLY DISCOURAGED*. + # + # no: Disable markup parsing, incoming notifications will be treated as + # plain text. Dunst will not advertise that it has the body-markup + # capability if this is set as a global setting. + # + # It's important to note that markup inside the format option will be parsed + # regardless of what this is set to. + markup = full + + # The format of the message. Possible variables are: + # %a appname + # %s summary + # %b body + # %i iconname (including its path) + # %I iconname (without its path) + # %p progress value if set ([ 0%] to [100%]) or nothing + # %n progress value if set without any extra characters + # %% Literal % + # Markup is allowed + format = "<b>%s</b>\n%b" + + # Alignment of message text. + # Possible values are "left", "center" and "right". + alignment = left + + # Vertical alignment of message text and icon. + # Possible values are "top", "center" and "bottom". + vertical_alignment = center + + # Show age of message if message is older than show_age_threshold + # seconds. + # Set to -1 to disable. + show_age_threshold = 60 + + # Specify where to make an ellipsis in long lines. + # Possible values are "start", "middle" and "end". + ellipsize = middle + + # Ignore newlines '\n' in notifications. + ignore_newline = no + + # Stack together notifications with the same content + stack_duplicates = true + + # Hide the count of stacked notifications with the same content + hide_duplicate_count = false + + # Display indicators for URLs (U) and actions (A). + show_indicators = yes + + ### Icons ### + + # Recursive icon lookup. You can set a single theme, instead of having to + # define all lookup paths. + enable_recursive_icon_lookup = true + + # Set icon theme (only used for recursive icon lookup) + icon_theme = Adwaita + # You can also set multiple icon themes, with the leftmost one being used first. + # icon_theme = "Adwaita, breeze" + + # Align icons left/right/top/off + icon_position = left + + # Scale small icons up to this size, set to 0 to disable. Helpful + # for e.g. small files or high-dpi screens. In case of conflict, + # max_icon_size takes precedence over this. + min_icon_size = 32 + + # Scale larger icons down to this size, set to 0 to disable + max_icon_size = 128 + + # Paths to default icons (only neccesary when not using recursive icon lookup) + icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ + + ### History ### + + # Should a notification popped up from history be sticky or timeout + # as if it would normally do. + sticky_history = yes + + # Maximum amount of notifications kept in history + history_length = 20 + + ### Misc/Advanced ### + + # dmenu path. + dmenu = /usr/local/bin/dmenu -p dunst: + + # Browser for opening urls in context menu. + browser = /usr/bin/firefox + + # Context menu + context = ctrl+shift+period + + # Always run rule-defined scripts, even if the notification is suppressed + always_run_script = true + + # Define the title of the windows spawned by dunst + title = Dunst + + # Define the class of the windows spawned by dunst + class = Dunst + + # Define the corner radius of the notification window + # in pixel size. If the radius is 0, you have no rounded + # corners. + # The radius will be automatically lowered if it exceeds half of the + # notification height to avoid clipping text and/or icons. + corner_radius = 0 + + # Ignore the dbus closeNotification message. + # Useful to enforce the timeout set by dunst configuration. Without this + # parameter, an application may close the notification sent before the + # user defined timeout. + ignore_dbusclose = false + + ### Wayland ### + # These settings are Wayland-specific. They have no effect when using X11 + + # Uncomment this if you want to let notications appear under fullscreen + # applications (default: overlay) + # layer = top + + # Set this to true to use X11 output on Wayland. + force_xwayland = false + + ### Legacy + + # Use the Xinerama extension instead of RandR for multi-monitor support. + # This setting is provided for compatibility with older nVidia drivers that + # do not support RandR and using it on systems that support RandR is highly + # discouraged. + # + # By enabling this setting dunst will not be able to detect when a monitor + # is connected or disconnected which might break follow mode if the screen + # layout changes. + force_xinerama = false + + ### mouse + + # Defines list of actions for each mouse event + # Possible values are: + # * none: Don't do anything. + # * do_action: Invoke the action determined by the action_name rule. If there is no + # such action, open the context menu. + # * open_url: If the notification has exactly one url, open it. If there are multiple + # ones, open the context menu. + # * close_current: Close current notification. + # * close_all: Close all notifications. + # * context: Open context menu for the notification. + # * context_all: Open context menu for all notifications. + # These values can be strung together for each mouse event, and + # will be executed in sequence. + mouse_left_click = close_current + mouse_middle_click = open_url + mouse_right_click = close_all + +# Experimental features that may or may not work correctly. Do not expect them +# to have a consistent behaviour across releases. +[experimental] + # Calculate the dpi to use on a per-monitor basis. + # If this setting is enabled the Xft.dpi value will be ignored and instead + # dunst will attempt to calculate an appropriate dpi value for each monitor + # using the resolution and physical size. This might be useful in setups + # where there are multiple screens with very different dpi values. + per_monitor_dpi = false + + +[urgency_low] + # IMPORTANT: colors have to be defined in quotation marks. + # Otherwise the "#" and following would be interpreted as a comment. + background = "#222222" + foreground = "#888888" + timeout = 10 + # Icon for notifications with low urgency, uncomment to enable + #default_icon = /path/to/icon + +[urgency_normal] + background = "#285577" + foreground = "#ffffff" + timeout = 10 + # Icon for notifications with normal urgency, uncomment to enable + #default_icon = /path/to/icon + +[urgency_critical] + background = "#900000" + foreground = "#ffffff" + frame_color = "#ff0000" + timeout = 0 + # Icon for notifications with critical urgency, uncomment to enable + #default_icon = /path/to/icon + +# Every section that isn't one of the above is interpreted as a rules to +# override settings for certain messages. +# +# Messages can be matched by +# appname (discouraged, see desktop_entry) +# body +# category +# desktop_entry +# icon +# match_transient +# msg_urgency +# stack_tag +# summary +# +# and you can override the +# background +# foreground +# format +# frame_color +# fullscreen +# new_icon +# set_stack_tag +# set_transient +# set_category +# timeout +# urgency +# icon_position +# skip_display +# history_ignore +# action_name +# word_wrap +# ellipsize +# alignment +# hide_text +# +# Shell-like globbing will get expanded. +# +# Instead of the appname filter, it's recommended to use the desktop_entry filter. +# GLib based applications export their desktop-entry name. In comparison to the appname, +# the desktop-entry won't get localized. +# +# SCRIPTING +# You can specify a script that gets run when the rule matches by +# setting the "script" option. +# The script will be called as follows: +# script appname summary body icon urgency +# where urgency can be "LOW", "NORMAL" or "CRITICAL". +# +# NOTE: It might be helpful to run dunst -print in a terminal in order +# to find fitting options for rules. + +# Disable the transient hint so that idle_threshold cannot be bypassed from the +# client +#[transient_disable] +# match_transient = yes +# set_transient = no +# +# Make the handling of transient notifications more strict by making them not +# be placed in history. +#[transient_history_ignore] +# match_transient = yes +# history_ignore = yes + +# fullscreen values +# show: show the notifications, regardless if there is a fullscreen window opened +# delay: displays the new notification, if there is no fullscreen window active +# If the notification is already drawn, it won't get undrawn. +# pushback: same as delay, but when switching into fullscreen, the notification will get +# withdrawn from screen again and will get delayed like a new notification +#[fullscreen_delay_everything] +# fullscreen = delay +#[fullscreen_show_critical] +# msg_urgency = critical +# fullscreen = show + +#[espeak] +# summary = "*" +# script = dunst_espeak.sh + +#[script-test] +# summary = "*script*" +# script = dunst_test.sh + +#[ignore] +# # This notification will not be displayed +# summary = "foobar" +# skip_display = true + +#[history-ignore] +# # This notification will not be saved in history +# summary = "foobar" +# history_ignore = yes + +#[skip-display] +# # This notification will not be displayed, but will be included in the history +# summary = "foobar" +# skip_display = yes + +#[signed_on] +# appname = Pidgin +# summary = "*signed on*" +# urgency = low +# +#[signed_off] +# appname = Pidgin +# summary = *signed off* +# urgency = low +# +#[says] +# appname = Pidgin +# summary = *says* +# urgency = critical +# +#[twitter] +# appname = Pidgin +# summary = *twitter.com* +# urgency = normal +# +#[stack-volumes] +# appname = "some_volume_notifiers" +# set_stack_tag = "volume" +# +# vim: ft=cfg diff --git a/.config/fastfetch/config.jsonc b/.config/fastfetch/config.jsonc new file mode 100644 index 0000000..676c183 --- /dev/null +++ b/.config/fastfetch/config.jsonc @@ -0,0 +1,127 @@ +// Modified from: https://github.com/fastfetch-cli/fastfetch/pull/1025#issuecomment-2177566138 +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + // "logo": { + // "color": { + // "1": "#dc0075", + // "2": "#8a8a8a" + // }, + // }, + "display": { + "color": { + "separator": "blue" + }, + "separator": " | ", + "constants": [ + ">-----------<+>------------------------------------<" + ] + }, + "modules": [ + "title", + { + "type": "custom", + "format": "{$1}", + "outputColor": "separator", + }, + { + "type": "os", + "key": " OS ", + "keyColor": "green" + }, + { + "type": "kernel", + "key": " Kernel ", + "keyColor": "green" + }, + { + "type": "uptime", + "key": " Uptime ", + "keyColor": "green" + }, + { + "type": "wm", + "key": " WM ", + "keyColor": "green", + }, + { + "type": "shell", + "key": " Shell ", + "keyColor": "green" + }, + { + "type": "terminal", + "key": " Terminal ", + "keyColor": "green" + }, + { + "type": "packages", + "key": " Packages ", + "keyColor": "green" + }, + { + "type": "custom", + "format": "{$1}", + "outputColor": "separator" + }, + { + "type": "Monitor", + "key": " Monitor ", + "format": "{1}", + "keyColor": "cyan" + }, + { + "type": "cpu", + "key": " CPU ", + "keyColor": "cyan" + }, + { + "type": "gpu", + "key": " GPU ", + "keyColor": "cyan" + }, + { + "type": "memory", + "key": " RAM ", + "keyColor": "cyan" + }, + { + "type": "swap", + "key": " SWAP ", + "keyColor": "cyan" + }, + { + "type": "disk", + "key": " (root) ", + "folders": "/", + "keyColor": "cyan" + }, + { + "type": "disk", + "key": " (home) ", + "folders": "/home", + "keyColor": "cyan" + }, + { + "type": "disk", + "key": " (hdd1) ", + "folders": "/media/hdd", + "keyColor": "cyan" + }, + { + "type": "disk", + "key": " (hdd2) ", + "folders": "/media/seagate", + "keyColor": "cyan" + }, + { + "type": "custom", + "format": "{$1}", + "outputColor": "separator" + }, + "break", + { + "type": "colors", + "paddingLeft": 15 + } + ] +} diff --git a/.config/gtk-3.0/settings.ini b/.config/gtk-3.0/settings.ini new file mode 100644 index 0000000..3bb5a50 --- /dev/null +++ b/.config/gtk-3.0/settings.ini @@ -0,0 +1,4 @@ +[Settings] +gtk-key-theme-name = Emacs +gtk-icon-theme-name = SE98 +gtk-cursor-theme-name = Adwaita diff --git a/.config/i3/config b/.config/i3/config new file mode 100644 index 0000000..297d369 --- /dev/null +++ b/.config/i3/config @@ -0,0 +1,166 @@ +# i3 config file (v4) +# +# Please see https://i3wm.org/docs/userguide.html for a complete reference! + +set $mod Mod4 + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +font pango:Iosevka Term Custom 10 + +for_window [class="mpdinfo"] floating enable +for_window [class="lyrics"] floating enable +for_window [class="Pcmanfm"] floating enable +for_window [class="Tk"] floating enable +for_window [class="MVis"] floating enable +for_window [title="Friends List"] floating enable + +# no_focus [all] +# focus_on_window_activation none + +focus_follows_mouse yes +# control mouse with keyboard +bindsym Mod1+Control+g exec --no-startup-id xdotool click --clearmodifiers 1 +bindsym Mod1+Control+r exec --no-startup-id xdotool click --clearmodifiers 3 +bindsym Mod1+Control+t exec --no-startup-id xdotool mousemove_relative -- 0 20 +bindsym Mod1+Control+c exec --no-startup-id xdotool mousemove_relative -- 0 -20 +bindsym Mod1+Control+h exec --no-startup-id xdotool mousemove_relative -- -20 0 +bindsym Mod1+Control+n exec --no-startup-id xdotool mousemove_relative -- 20 0 +bindsym Mod1+Control+z exec --no-startup-id xdotool mousemove 3200 2104 + +# Use wpctl to adjust volume in Pipewire. +set $refresh_i3status killall -SIGUSR1 i3status +bindsym XF86AudioRaiseVolume exec --no-startup-id wpctl set-volume @DEFAULT_SINK@ 5%+ && $refresh_i3status +bindsym XF86AudioLowerVolume exec --no-startup-id wpctl set-volume @DEFAULT_SINK@ 5%- && $refresh_i3status +bindsym XF86AudioMute exec --no-startup-id wpctl set-mute @DEFAULT_SINK@ toggle && $refresh_i3status +bindsym XF86AudioMicMute exec --no-startup-id wpctl set-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status +bindsym XF86AudioNext exec --no-startup-id mpc next +bindsym XF86AudioPrev exec --no-startup-id mpc prev +bindsym XF86AudioPlay exec --no-startup-id mpc toggle + +# # Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# # move tiling windows via drag & drop by left-clicking into the title bar, +# # or left-clicking anywhere into the window while holding the floating modifier. +tiling_drag modifier titlebar + +# start a terminal +bindsym $mod+Return exec urxvtc + +# start dmenu +bindsym $mod+p exec --no-startup-id dmenu_run -fn "Hack Nerd Font:size=11" -nb "#222222" -nf "#bbbbbb" -sb "#005577" -sf "#eeeeee" + +# kill focused window +bindsym $mod+Shift+C kill + +# application launchers + +bindsym $mod+Shift+F exec firefox -P default-release +bindsym $mod+Shift+B exec firefox -P less-strict +bindsym $mod+Shift+E exec emacsclient -c -a "" +bindsym $mod+Shift+M exec mpdinfo +bindsym $mod+Control+b exec bm -y +bindsym $mod+b exec bm -o +bindsym $mod+m exec mpdmenu +bindsym $mod+z exec boomer +bindsym --release Print exec scrot -u -e 'mv $f ~/pics/' +bindsym --release $mod+Print exec scrot -s -e 'mv $f ~/pics/' + +# change focus +bindsym $mod+h focus left +bindsym $mod+j focus down +bindsym $mod+k focus up +bindsym $mod+l focus right + +# move focused window +bindsym $mod+Shift+H move left +bindsym $mod+Shift+J move down +bindsym $mod+Shift+K move up +bindsym $mod+Shift+L move right + +bindsym $mod+Shift+Control+X exec ~/.local/bin/sw-con + +# split in vertical orientation (i3 names these reversed for some reason) +bindsym $mod+v split h + +# split in horizontal orientation +bindsym $mod+s split v + +# enter fullscreen mode for the focused container +bindsym $mod+f fullscreen toggle + +# change container layout (stacked, tabbed, toggle split) +bindsym $mod+comma layout stacking +bindsym $mod+period layout toggle split +bindsym $mod+t layout tabbed + +workspace_layout tabbed + +# toggle tiling / floating +bindsym $mod+Shift+space floating toggle + +# change focus between tiling / floating windows +bindsym $mod+space focus mode_toggle + +# focus the parent container +bindsym $mod+a focus parent + +# focus the child container +bindsym $mod+d focus child + +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" + +# switch to workspace +bindsym $mod+1 workspace number $ws1 +bindsym $mod+2 workspace number $ws2 +bindsym $mod+3 workspace number $ws3 +bindsym $mod+4 workspace number $ws4 + +# move focused container to workspace +bindsym $mod+Shift+1 move container to workspace number $ws1 +bindsym $mod+Shift+2 move container to workspace number $ws2 +bindsym $mod+Shift+3 move container to workspace number $ws3 +bindsym $mod+Shift+4 move container to workspace number $ws4 + +# reload the configuration file +bindsym $mod+Shift+O reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym $mod+Shift+R restart +# exit i3 (logs you out of your X session) +bindsym $mod+Shift+Control+Q exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'" + +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # Pressing left will shrink the window’s width. + # Pressing right will grow the window’s width. + # Pressing up will shrink the window’s height. + # Pressing down will grow the window’s height. + bindsym h resize shrink width 10 px or 10 ppt + bindsym j resize grow height 10 px or 10 ppt + bindsym k resize shrink height 10 px or 10 ppt + bindsym l resize grow width 10 px or 10 ppt + + # back to normal: Enter or Escape or $mod+r + bindsym Return mode "default" + bindsym Escape mode "default" + bindsym $mod+r mode "default" +} + +bindsym $mod+r mode "resize" + +# Start i3bar to display a workspace bar (plus the system information i3status +# finds out, if available) +bar { + font pango:Hack Nerd Font 9 + position top + tray_output primary + status_command i3status +} diff --git a/.config/i3status/config b/.config/i3status/config new file mode 100644 index 0000000..8fd3248 --- /dev/null +++ b/.config/i3status/config @@ -0,0 +1,62 @@ +# i3status configuration file. +# see "man i3status" for documentation. + +# It is important that this file is edited as UTF-8. +# The following line should contain a sharp s: +# ß +# If the above line is not correctly displayed, fix your editor first! + +general { + colors = true + interval = 2 +} + +order += "ethernet br0" +order += "ethernet tun0" +order += "ethernet wg0" +order += "cpu_temperature 0" +order += "disk /" +order += "load" +order += "memory" +order += "volume master" +order += "tztime local" + +ethernet br0 { + format_up = "E: %ip" + format_down = "E: down" +} + +ethernet wg0 { + format_up = "WG: %ip" + format_down = "WG: down" +} + +cpu_temperature 0 { + format = "tea: %degrees °C" + path = "/sys/class/hwmon/hwmon2/temp1_input" +} + +disk "/" { + format = "porn: %used" +} + +load { + format = "hot loads: %1min" +} + +memory { + memory_used_method = "memavailable" + format = "memory: %used/%total" + threshold_degraded = "3GB" + format_degraded = "MEMORY < %available" +} + +volume master { + format = "♪: %volume" + format_muted = "♪: muted (%volume)" + device = "default" +} + +tztime local { + format = "%A, %F %H:%M " +} diff --git a/.config/mpd/mpd.conf b/.config/mpd/mpd.conf new file mode 100755 index 0000000..ee0daa6 --- /dev/null +++ b/.config/mpd/mpd.conf @@ -0,0 +1,54 @@ +bind_to_address "0.0.0.0" +# bind_to_address "/run/mpd/socket" + +music_directory "/media/hdd/music" +playlist_directory "~/.config/mpd/playlists" +db_file "~/.config/mpd/database" +log_file "~/.config/mpd/log" +pid_file "~/.config/mpd/pid" +state_file "~/.config/mpd/mpdstate" + +# default local output +audio_output { + type "pulse" + name "Default" +} + +# http streaming +#audio_output { +# type "httpd" +# name "HTTP Stream" +# encoder "vorbis" # optional, vorbis or lame +# port "8000" +# quality "8.0" # do not define if bitrate is defined +# bitrate "256" # do not define if quality is defined +# format "44100:16:1" +# always_on "yes" +# tags "yes" +#} + +# visualizer output +audio_output { + type "fifo" + name "Visualizer feed" + path "/tmp/mpd.fifo" + format "44100:16:2" +} + +input { + enabled "no" + plugin "qobuz" +} + +input { + enabled "no" + plugin "tidal" +} + +decoder { + enabled "no" + plugin "wildmidi" + config_file "/etc/timidity/timidity.cfg" +} + +mixer_type "software" diff --git a/.config/mpv/input.conf b/.config/mpv/input.conf new file mode 100644 index 0000000..396711e --- /dev/null +++ b/.config/mpv/input.conf @@ -0,0 +1,23 @@ +# crop.lua +# ========== +# start cropping +c script-message-to crop start-crop hard +alt+c script-message-to crop start-crop soft +# delogo mode can be used like so +l script-message-to crop start-crop delogo +# remove the crop +d vf del -1 + +# or use the ready-made "toggle" binding +C script-message-to crop toggle-crop hard + +# remove the soft zoom +0 set video-pan-x 0; set video-pan-y 0; set video-zoom 0 + +# encode.lua +# ============ +# use default profile (makes vp8 webms) +E script-message-to encode set-timestamp + +# use webm profile +e script-message-to encode set-timestamp encode_webm diff --git a/.config/mpv/mpv.conf b/.config/mpv/mpv.conf new file mode 100644 index 0000000..8196cc7 --- /dev/null +++ b/.config/mpv/mpv.conf @@ -0,0 +1,33 @@ +profile=high-quality + +vo=gpu-next +gpu-api=vulkan +hwdec=vdpau +scale=ewa_lanczossharp +cscale=ewa_lanczossharp +dscale=ewa_lanczossharp + +ao=pipewire +pipewire-buffer=16 +audio-samplerate=192000 +audio-format=float + +keep-open=yes +border=no +no-border +scale-antiring=0.7 + +msg-color=yes +term-osd-bar=yes +cursor-autohide=1000 + +script-opts=ytdl_hook-ytdl_path=yt-dlp + +screenshot-directory="~/pics/" +screenshot-template="%F - [%P]v%#01n" + +[extension.webm] +loop-file=inf + +[extension.gif] +loop-file=inf diff --git a/.config/mpv/script-opts/crop.conf b/.config/mpv/script-opts/crop.conf new file mode 100644 index 0000000..9f75cdf --- /dev/null +++ b/.config/mpv/script-opts/crop.conf @@ -0,0 +1,34 @@ +# default mode to be used if not specified in the script-message +# can be hard, soft or delogo +# in hard mode, a crop filter is applied to the video +# in soft mode, video-zoom, video-pan-x and video-pan-y are modified to simulate the cropping +# in delogo mode, the delogo filter is applied to the selected are +# hard mode interacts nicely with encode.lua, soft mode does not +mode=hard + +draw_crosshair=yes +draw_text=yes +draw_shade=yes +draw_frame=yes +frame_border_width=2 +frame_border_color=EEEEEE +# hexadecimal: 00 is opaque, FF is transparent +shade_opacity=77 +mouse_support=yes + +# movement is defined in pixels in the window +# which explains the mismatch with the text (in video space) +coarse_movement=30 +left_coarse=LEFT +right_coarse=RIGHT +up_coarse=UP +down_coarse=DOWN +fine_movement=1 +left_fine=ALT+LEFT +right_fine=ALT+RIGHT +up_fine=ALT+UP +down_fine=ALT+DOWN + +# these two options accept comma separated list of keys +accept=ENTER,MOUSE_BTN0 +cancel=ESC diff --git a/.config/mpv/script-opts/encode_webm.conf b/.config/mpv/script-opts/encode_webm.conf new file mode 100644 index 0000000..f6d661c --- /dev/null +++ b/.config/mpv/script-opts/encode_webm.conf @@ -0,0 +1,39 @@ +# if yes, only encode the currently active tracks +# for example, mute the player / hide the subtitles if you don't want audio / subs to be part of the extract +only_active_tracks=no + +# whether to preserve some of the applied filters (crop, rotate, flip and mirror) into the extract +# this is pretty useful in combination with crop.lua +# note that you cannot copy video streams and apply filters at the same time +preserve_filters=yes + +# apply another filter after the ones from the previous option if any +# can be used to limit the resolution of the output, for example with +# append_filter=scale=2*trunc(iw/max(1\,sqrt((iw*ih)/(960*540)))/2):-2 +append_filter= + +# additional parameters passed to ffmpeg +codec=-c:v libvpx-vp9 -crf 1 -b:v 1M -c:a libvorbis + +# format of the output filename +# Does basic interpolation on the following variables: $f, $x, $t, $s, $e, $d, $p, $n which respectively represent +# input filename, input extension, title, start timestamp, end timestamp, duration, profile name and an incrementing number in case of conflicts +# if the extension is not among the recognized ones, it will default to mkv +output_format=$f_$n.webm + +# the directory in which to create the extract +# empty means the same directory as the input file +# relative paths are relative to mpv's working directory, absolute ones work like you would expect +output_directory=~/vids/ + +# if yes, the ffmpeg process will run detached from mpv and we won't know if it succeeded or not +# if no, we know the result of calling ffmpeg, but we can only encode one extract at a time and mpv will block on exit +detached=yes + +# executable to run when encoding (or its full path if not in PATH) +# for example, this can be used with a wrapper script that calls ffmpeg and triggers a notification when finished +# note that the executable gets the ffmpeg arguments as-is, and is expected to call ffmpeg itself +ffmpeg_command=ffmpeg + +# if yes, print the ffmpeg call before executing it +print=yes diff --git a/.config/mpv/scripts/autoload.lua b/.config/mpv/scripts/autoload.lua new file mode 100644 index 0000000..27d9d77 --- /dev/null +++ b/.config/mpv/scripts/autoload.lua @@ -0,0 +1,225 @@ +-- This script automatically loads playlist entries before and after the +-- the currently played file. It does so by scanning the directory a file is +-- located in when starting playback. It sorts the directory entries +-- alphabetically, and adds entries before and after the current file to +-- the internal playlist. (It stops if it would add an already existing +-- playlist entry at the same position - this makes it "stable".) +-- Add at most 5000 * 2 files when starting a file (before + after). + +--[[ +To configure this script use file autoload.conf in directory script-opts (the "script-opts" +directory must be in the mpv configuration directory, typically ~/.config/mpv/). + +Example configuration would be: + +disabled=no +images=no +videos=yes +audio=yes +ignore_hidden=yes + +--]] + +MAXENTRIES = 5000 + +local msg = require 'mp.msg' +local options = require 'mp.options' +local utils = require 'mp.utils' + +o = { + disabled = false, + images = true, + videos = true, + audio = true, + ignore_hidden = true +} +options.read_options(o) + +function Set (t) + local set = {} + for _, v in pairs(t) do set[v] = true end + return set +end + +function SetUnion (a,b) + local res = {} + for k in pairs(a) do res[k] = true end + for k in pairs(b) do res[k] = true end + return res +end + +EXTENSIONS_VIDEO = Set { + 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp' +} + +EXTENSIONS_AUDIO = Set { + 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus' +} + +EXTENSIONS_IMAGES = Set { + 'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'webp', 'svg', 'bmp' +} + +EXTENSIONS = Set {} +if o.videos then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_VIDEO) end +if o.audio then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_AUDIO) end +if o.images then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_IMAGES) end + +function add_files_at(index, files) + index = index - 1 + local oldcount = mp.get_property_number("playlist-count", 1) + for i = 1, #files do + mp.commandv("loadfile", files[i], "append") + mp.commandv("playlist-move", oldcount + i - 1, index + i - 1) + end +end + +function get_extension(path) + match = string.match(path, "%.([^%.]+)$" ) + if match == nil then + return "nomatch" + else + return match + end +end + +table.filter = function(t, iter) + for i = #t, 1, -1 do + if not iter(t[i]) then + table.remove(t, i) + end + end +end + +-- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus +-- Released under the MIT License +-- http://www.davekoelle.com/files/alphanum.lua + +-- split a string into a table of number and string values +function splitbynum(s) + local result = {} + for x, y in (s or ""):gmatch("(%d*)(%D*)") do + if x ~= "" then table.insert(result, tonumber(x)) end + if y ~= "" then table.insert(result, y) end + end + return result +end + +function clean_key(k) + k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower() + return splitbynum(k) +end + +-- compare two strings +function alnumcomp(x, y) + local xt, yt = clean_key(x), clean_key(y) + for i = 1, math.min(#xt, #yt) do + local xe, ye = xt[i], yt[i] + if type(xe) == "string" then ye = tostring(ye) + elseif type(ye) == "string" then xe = tostring(xe) end + if xe ~= ye then return xe < ye end + end + return #xt < #yt +end + +local autoloaded = nil + +function find_and_add_entries() + local path = mp.get_property("path", "") + local dir, filename = utils.split_path(path) + msg.trace(("dir: %s, filename: %s"):format(dir, filename)) + if o.disabled then + msg.verbose("stopping: autoload disabled") + return + elseif #dir == 0 then + msg.verbose("stopping: not a local path") + return + end + + local pl_count = mp.get_property_number("playlist-count", 1) + -- check if this is a manually made playlist + if (pl_count > 1 and autoloaded == nil) or + (pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then + msg.verbose("stopping: manually made playlist") + return + else + autoloaded = true + end + + local pl = mp.get_property_native("playlist", {}) + local pl_current = mp.get_property_number("playlist-pos-1", 1) + msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current, + utils.to_string(pl))) + + local files = utils.readdir(dir, "files") + if files == nil then + msg.verbose("no other files in directory") + return + end + table.filter(files, function (v, k) + -- The current file could be a hidden file, ignoring it doesn't load other + -- files from the current directory. + if (o.ignore_hidden and not (v == filename) and string.match(v, "^%.")) then + return false + end + local ext = get_extension(v) + if ext == nil then + return false + end + return EXTENSIONS[string.lower(ext)] + end) + table.sort(files, alnumcomp) + + if dir == "." then + dir = "" + end + + -- Find the current pl entry (dir+"/"+filename) in the sorted dir list + local current + for i = 1, #files do + if files[i] == filename then + current = i + break + end + end + if current == nil then + return + end + msg.trace("current file position in files: "..current) + + local append = {[-1] = {}, [1] = {}} + for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1 + for i = 1, MAXENTRIES do + local file = files[current + i * direction] + local pl_e = pl[pl_current + i * direction] + if file == nil or file[1] == "." then + break + end + + local filepath = dir .. file + if pl_e then + -- If there's a playlist entry, and it's the same file, stop. + msg.trace(pl_e.filename.." == "..filepath.." ?") + if pl_e.filename == filepath then + break + end + end + + if direction == -1 then + if pl_current == 1 then -- never add additional entries in the middle + msg.info("Prepending " .. file) + table.insert(append[-1], 1, filepath) + end + else + msg.info("Adding " .. file) + table.insert(append[1], filepath) + end + end + end + + add_files_at(pl_current + 1, append[1]) + add_files_at(pl_current, append[-1]) +end + +mp.register_event("start-file", find_and_add_entries) + diff --git a/.config/mpv/scripts/crop.lua b/.config/mpv/scripts/crop.lua new file mode 100644 index 0000000..adbfaa3 --- /dev/null +++ b/.config/mpv/scripts/crop.lua @@ -0,0 +1,434 @@ +local opts = { + mode = "hard", -- can be "hard" or "soft". If hard, apply a crop filter, if soft zoom + pan. Or a bonus "delogo" mode + draw_shade = true, + shade_opacity = "77", + draw_frame = false, + frame_border_width = 2, + frame_border_color = "EEEEEE", + draw_crosshair = true, + draw_text = true, + mouse_support = true, + coarse_movement = 30, + left_coarse = "LEFT", + right_coarse = "RIGHT", + up_coarse = "UP", + down_coarse = "DOWN", + fine_movement = 1, + left_fine = "ALT+LEFT", + right_fine = "ALT+RIGHT", + up_fine = "ALT+UP", + down_fine = "ALT+DOWN", + accept = "ENTER,MOUSE_BTN0", + cancel = "ESC", +} +(require 'mp.options').read_options(opts) + +function split(input) + local ret = {} + for str in string.gmatch(input, "([^,]+)") do + ret[#ret + 1] = str + end + return ret +end +local msg = require 'mp.msg' + +opts.accept = split(opts.accept) +opts.cancel = split(opts.cancel) +function mode_ok(mode) + return mode == "soft" or mode == "hard" or mode == "delogo" +end +if not mode_ok(opts.mode) then + msg.error("Invalid mode value: " .. opts.mode) + return +end + +local assdraw = require 'mp.assdraw' +local active = false +local active_mode = "" -- same possible values as opts.mode +local rect_centered = false +local rect_keepaspect = false +local needs_drawing = false +local crop_first_corner = nil -- in normalized video space +local crop_cursor = { + x = 0, + y = 0 +} + +function redraw() + needs_drawing = true +end + +function rect_from_two_points(p1, p2, centered, ratio) + local c1 = {p1.x, p1.y} + local c2 = {p2.x, p2.y} + if ratio then + -- adjust position of p2, such + if math.abs(c2[1] - c1[1]) < ratio * math.abs(c2[2] - c1[2]) then + local is_left = c2[1] < c1[1] and -1 or 1 + c2[1] = c1[1] + is_left * math.abs(c2[2] - c1[2]) * ratio + else + local is_up = c2[2] < c1[2] and -1 or 1 + c2[2] = c1[2] + is_up * math.abs(c2[1] - c1[1]) / ratio + end + end + if centered then + -- p1 is center => convert it into corner + c1[1] = c1[1] - (c2[1] - c1[1]) + c1[2] = c1[2] - (c2[2] - c1[2]) + end + -- sort corners + if c1[1] > c2[1] then c1[1], c2[1] = c2[1], c1[1] end + if c1[2] > c2[2] then c1[2], c2[2] = c2[2], c1[2] end + return { x = c1[1], y = c1[2] }, { x = c2[1], y = c2[2] } +end + +function clamp(low, value, high) + if value <= low then + return low + elseif value >= high then + return high + else + return value + end +end + +function clamp_point(top_left, point, bottom_right) + return { + x = clamp(top_left.x, point.x, bottom_right.x), + y = clamp(top_left.y, point.y, bottom_right.y) + } +end + +function screen_to_video_norm(point, dim) + return { + x = (point.x - dim.ml) / (dim.w - dim.ml - dim.mr), + y = (point.y - dim.mt) / (dim.h - dim.mt - dim.mb) + } +end + +function video_norm_to_screen(point, dim) + return { + x = math.floor(point.x * (dim.w - dim.ml - dim.mr) + dim.ml + 0.5), + y = math.floor(point.y * (dim.h - dim.mt - dim.mb) + dim.mt + 0.5) + } +end + +function draw_shade(ass, unshaded, window) + ass:new_event() + ass:pos(0, 0) + ass:append("{\\an7}") + ass:append("{\\bord0}") + ass:append("{\\shad0}") + ass:append("{\\c&H000000&}") + ass:append("{\\1a&H" .. opts.shade_opacity .. "}") + ass:append("{\\2a&HFF}") + ass:append("{\\3a&HFF}") + ass:append("{\\4a&HFF}") + local c1, c2 = unshaded.top_left, unshaded.bottom_right + local v = window + -- c1.x c2.x + -- +-----+------------+ + -- | | ur | + -- c1.y| ul +-------+----+ + -- | | | | + -- c2.y+-----+-------+ lr | + -- | ll | | + -- +-------------+----+ + ass:draw_start() + ass:rect_cw(v.top_left.x, v.top_left.y, c1.x, c2.y) -- ul + ass:rect_cw(c1.x, v.top_left.y, v.bottom_right.x, c1.y) -- ur + ass:rect_cw(v.top_left.x, c2.y, c2.x, v.bottom_right.y) -- ll + ass:rect_cw(c2.x, c1.y, v.bottom_right.x, v.bottom_right.y) -- lr + ass:draw_stop() + -- also possible to draw a rect over the whole video + -- and \iclip it in the middle, but seemingy slower +end + +function draw_frame(ass, frame) + ass:new_event() + ass:pos(0, 0) + ass:append("{\\an7}") + ass:append("{\\bord0}") + ass:append("{\\shad0}") + ass:append("{\\c&H" .. opts.frame_border_color .. "&}") + ass:append("{\\1a&H00&}") + ass:append("{\\2a&HFF&}") + ass:append("{\\3a&HFF&}") + ass:append("{\\4a&HFF&}") + local c1, c2 = frame.top_left, frame.bottom_right + local b = opts.frame_border_width + ass:draw_start() + ass:rect_cw(c1.x, c1.y - b, c2.x + b, c1.y) + ass:rect_cw(c2.x, c1.y, c2.x + b, c2.y + b) + ass:rect_cw(c1.x - b, c2.y, c2.x, c2.y + b) + ass:rect_cw(c1.x - b, c1.y - b, c1.x, c2.y) + ass:draw_stop() +end + +function draw_crosshair(ass, center, window_size) + ass:new_event() + ass:pos(0, 0) + ass:append("{\\an7}") + ass:append("{\\bord0}") + ass:append("{\\shad0}") + ass:append("{\\c&HBBBBBB&}") + ass:append("{\\1a&H00&}") + ass:append("{\\2a&HFF&}") + ass:append("{\\3a&HFF&}") + ass:append("{\\4a&HFF&}") + ass:draw_start() + ass:rect_cw(center.x - 0.5, 0, center.x + 0.5, window_size.h) + ass:rect_cw(0, center.y - 0.5, window_size.w, center.y + 0.5) + ass:draw_stop() +end + +function draw_position_text(ass, text, position, window_size, offset) + ass:new_event() + local align = 1 + local ofx = 1 + local ofy = -1 + if position.x > window_size.w / 2 then + align = align + 2 + ofx = -1 + end + if position.y < window_size.h / 2 then + align = align + 6 + ofy = 1 + end + ass:append("{\\an"..align.."}") + ass:append("{\\fs26}") + ass:append("{\\bord1.5}") + ass:pos(ofx*offset + position.x, ofy*offset + position.y) + ass:append(text) +end + +function draw_crop_zone() + if needs_drawing then + local dim = mp.get_property_native("osd-dimensions") + if not dim then + cancel_crop() + return + end + + local cursor = { + x = crop_cursor.x, + y = crop_cursor.y, + } + local ass = assdraw.ass_new() + + if crop_first_corner and (opts.draw_shade or opts.draw_frame) then + local frame = {} + frame.top_left, frame.bottom_right = rect_from_two_points( + video_norm_to_screen(crop_first_corner, dim), + cursor, + rect_centered, + rect_keepaspect and dim.w/dim.h) + -- don't draw shade over non-visible video parts + if opts.draw_shade then + local window = { + top_left = { x = 0, y = 0 }, + bottom_right = { x = dim.w, y = dim.h }, + } + draw_shade(ass, frame, window) + end + if opts.draw_frame then + draw_frame(ass, frame) + end + end + + + if opts.draw_crosshair then + draw_crosshair(ass, cursor, { w = dim.w, h = dim.h }) + end + + if opts.draw_text then + local vop = mp.get_property_native("video-out-params") + if vop then + local cursor_norm = screen_to_video_norm(cursor, dim) + local text = string.format("%d, %d", cursor_norm.x * vop.w, cursor_norm.y * vop.h) + if crop_first_corner then + text = string.format("%s (%dx%d)", text, + math.abs((cursor_norm.x - crop_first_corner.x) * vop.w ), + math.abs((cursor_norm.y - crop_first_corner.y) * vop.h ) + ) + end + draw_position_text(ass, text, cursor, { w = dim.w, h = dim.h }, 6) + end + end + + mp.set_osd_ass(dim.w, dim.h, ass.text) + needs_drawing = false + end +end + +function crop_video(x1, y1, x2, y2) + if active_mode == "soft" then + local w = x2 - x1 + local h = y2 - y1 + local dim = mp.get_property_native("osd-dimensions") + if not dim then return end + + local zoom = mp.get_property_number("video-zoom") + local newZoom1 = math.log(dim.h * (2 ^ zoom) / (dim.h - dim.mt - dim.mb) / h) / math.log(2) + local newZoom2 = math.log(dim.w * (2 ^ zoom) / (dim.w - dim.ml - dim.mr) / w) / math.log(2) + mp.set_property("video-zoom", math.min(newZoom1, newZoom2)) + mp.set_property("video-pan-x", 0.5 - (x1 + w / 2)) + mp.set_property("video-pan-y", 0.5 - (y1 + h / 2)) + elseif active_mode == "hard" or active_mode == "delogo" then + x1 = clamp(0, x1, 1) + y1 = clamp(0, y1, 1) + x2 = clamp(0, x2, 1) + y2 = clamp(0, y2, 1) + local vop = mp.get_property_native("video-out-params") + local vf_table = mp.get_property_native("vf") + local x = math.floor(x1 * vop.w + 0.5) + local y = math.floor(y1 * vop.h + 0.5) + local w = math.floor((x2 - x1) * vop.w + 0.5) + local h = math.floor((y2 - y1) * vop.h + 0.5) + if active_mode == "delogo" then + -- delogo is a little special and needs some padding to function + w = math.min(vop.w - 1, w) + h = math.min(vop.h - 1, h) + x = math.max(1, x) + y = math.max(1, y) + if x + w == vop.w then w = w - 1 end + if y + h == vop.h then h = h - 1 end + end + vf_table[#vf_table + 1] = { + name=(active_mode == "hard") and "crop" or "delogo", + params= { x = tostring(x), y = tostring(y), w = tostring(w), h = tostring(h) } + } + mp.set_property_native("vf", vf_table) + end +end + +function update_crop_zone_state() + local dim = mp.get_property_native("osd-dimensions") + if not dim then + cancel_crop() + return + end + local corner = crop_cursor + if crop_first_corner == nil then + crop_first_corner = screen_to_video_norm(crop_cursor, dim) + redraw() + else + local c1, c2 = rect_from_two_points( + video_norm_to_screen(crop_first_corner, dim), + crop_cursor, + rect_centered, + rect_keepaspect and dim.w/dim.h) + local c1norm = screen_to_video_norm(c1, dim) + local c2norm = screen_to_video_norm(c2, dim) + crop_video(c1norm.x, c1norm.y, c2norm.x, c2norm.y) + cancel_crop() + end +end + +local bindings = {} +local bindings_repeat = {} + +function cancel_crop() + crop_first_corner = nil + for key, _ in pairs(bindings) do + mp.remove_key_binding("crop-"..key) + end + for key, _ in pairs(bindings_repeat) do + mp.remove_key_binding("crop-"..key) + end + mp.unobserve_property(redraw) + mp.unregister_idle(draw_crop_zone) + mp.set_osd_ass(1280, 720, '') + active = false +end + +function start_crop(mode) + if active then return end + if not mp.get_property_native("osd-dimensions") then return end + if mode and not mode_ok(mode) then + msg.error("Invalid mode value: " .. mode) + return + end + local mode_maybe = mode or opts.mode + if mode_maybe ~= 'soft' then + local hwdec = mp.get_property("hwdec-current") + if hwdec and hwdec ~= "no" and not string.find(hwdec, "-copy$") then + msg.error("Cannot crop with hardware decoding active (see manual)") + return + end + end + active = true + active_mode = mode_maybe + + if opts.mouse_support then + crop_cursor.x, crop_cursor.y = mp.get_mouse_pos() + end + redraw() + for key, func in pairs(bindings) do + mp.add_forced_key_binding(key, "crop-"..key, func) + end + for key, func in pairs(bindings_repeat) do + mp.add_forced_key_binding(key, "crop-"..key, func, { repeatable = true }) + end + mp.register_idle(draw_crop_zone) + mp.observe_property("osd-dimensions", nil, redraw) +end + +function toggle_crop(mode) + if mode and not mode_ok(mode) then + msg.error("Invalid mode value: " .. mode) + end + local toggle_mode = mode or opts.mode + if toggle_mode == "soft" then return end -- can't toggle soft mode + + local remove_filter = function() + local to_remove = (toggle_mode == "hard") and "crop" or "delogo" + local vf_table = mp.get_property_native("vf") + if #vf_table > 0 then + for i = #vf_table, 1, -1 do + if vf_table[i].name == to_remove then + for j = i, #vf_table-1 do + vf_table[j] = vf_table[j+1] + end + vf_table[#vf_table] = nil + mp.set_property_native("vf", vf_table) + return true + end + end + end + return false + end + if not remove_filter() then + start_crop(mode) + end +end + +-- bindings +if opts.mouse_support then + bindings["MOUSE_MOVE"] = function() crop_cursor.x, crop_cursor.y = mp.get_mouse_pos(); redraw() end +end +for _, key in ipairs(opts.accept) do + bindings[key] = update_crop_zone_state +end +for _, key in ipairs(opts.cancel) do + bindings[key] = cancel_crop +end +function movement_func(move_x, move_y) + return function() + crop_cursor.x = crop_cursor.x + move_x + crop_cursor.y = crop_cursor.y + move_y + redraw() + end +end +bindings_repeat[opts.left_coarse] = movement_func(-opts.coarse_movement, 0) +bindings_repeat[opts.right_coarse] = movement_func(opts.coarse_movement, 0) +bindings_repeat[opts.up_coarse] = movement_func(0, -opts.coarse_movement) +bindings_repeat[opts.down_coarse] = movement_func(0, opts.coarse_movement) +bindings_repeat[opts.left_fine] = movement_func(-opts.fine_movement, 0) +bindings_repeat[opts.right_fine] = movement_func(opts.fine_movement, 0) +bindings_repeat[opts.up_fine] = movement_func(0, -opts.fine_movement) +bindings_repeat[opts.down_fine] = movement_func(0, opts.fine_movement) + + +mp.add_key_binding(nil, "start-crop", start_crop) +mp.add_key_binding(nil, "toggle-crop", toggle_crop) diff --git a/.config/mpv/scripts/encode.lua b/.config/mpv/scripts/encode.lua new file mode 100644 index 0000000..df518d8 --- /dev/null +++ b/.config/mpv/scripts/encode.lua @@ -0,0 +1,315 @@ +local utils = require "mp.utils" +local msg = require "mp.msg" +local options = require "mp.options" + +local ON_WINDOWS = (package.config:sub(1,1) ~= "/") + +local start_timestamp = nil +local profile_start = "" + +-- implementation detail of the osd message +local timer = nil +local timer_duration = 2 + +function append_table(lhs, rhs) + for i = 1,#rhs do + lhs[#lhs+1] = rhs[i] + end + return lhs +end + +function file_exists(name) + local f = io.open(name, "r") + if f ~= nil then + io.close(f) + return true + else + return false + end +end + +function get_extension(path) + local candidate = string.match(path, "%.([^.]+)$") + if candidate then + for _, ext in ipairs({ "mkv", "webm", "mp4", "avi" }) do + if candidate == ext then + return candidate + end + end + end + return "mkv" +end + +function get_output_string(dir, format, input, extension, title, from, to, profile) + local res = utils.readdir(dir) + if not res then + return nil + end + local files = {} + for _, f in ipairs(res) do + files[f] = true + end + local output = format + output = string.gsub(output, "$f", function() return input end) + output = string.gsub(output, "$t", function() return title end) + output = string.gsub(output, "$s", function() return seconds_to_time_string(from, true) end) + output = string.gsub(output, "$e", function() return seconds_to_time_string(to, true) end) + output = string.gsub(output, "$d", function() return seconds_to_time_string(to-from, true) end) + output = string.gsub(output, "$x", function() return extension end) + output = string.gsub(output, "$p", function() return profile end) + if ON_WINDOWS then + output = string.gsub(output, "[/\\|<>?:\"*]", "_") + end + if not string.find(output, "$n") then + return files[output] and nil or output + end + local i = 1 + while true do + local potential_name = string.gsub(output, "$n", tostring(i)) + if not files[potential_name] then + return potential_name + end + i = i + 1 + end +end + +function get_video_filters() + local filters = {} + for _, vf in ipairs(mp.get_property_native("vf")) do + local name = vf["name"] + name = string.gsub(name, '^lavfi%-', '') + local filter + if name == "crop" then + local p = vf["params"] + filter = string.format("crop=%d:%d:%d:%d", p.w, p.h, p.x, p.y) + elseif name == "mirror" then + filter = "hflip" + elseif name == "flip" then + filter = "vflip" + elseif name == "rotate" then + local rotation = vf["params"]["angle"] + -- rotate is NOT the filter we want here + if rotation == "90" then + filter = "transpose=clock" + elseif rotation == "180" then + filter = "transpose=clock,transpose=clock" + elseif rotation == "270" then + filter = "transpose=cclock" + end + end + filters[#filters + 1] = filter + end + return filters +end + +function get_input_info(default_path, only_active) + local accepted = { + video = true, + audio = not mp.get_property_bool("mute"), + sub = mp.get_property_bool("sub-visibility") + } + local ret = {} + for _, track in ipairs(mp.get_property_native("track-list")) do + local track_path = track["external-filename"] or default_path + if not only_active or (track["selected"] and accepted[track["type"]]) then + local tracks = ret[track_path] + if not tracks then + ret[track_path] = { track["ff-index"] } + else + tracks[#tracks + 1] = track["ff-index"] + end + end + end + return ret +end + +function seconds_to_time_string(seconds, full) + local ret = string.format("%02d:%02d.%03d" + , math.floor(seconds / 60) % 60 + , math.floor(seconds) % 60 + , seconds * 1000 % 1000 + ) + if full or seconds > 3600 then + ret = string.format("%d:%s", math.floor(seconds / 3600), ret) + end + return ret +end + +function start_encoding(from, to, settings) + local args = { + settings.ffmpeg_command, + "-loglevel", "panic", "-hide_banner", + } + local append_args = function(table) args = append_table(args, table) end + + local path = mp.get_property("path") + local is_stream = not file_exists(path) + if is_stream then + path = mp.get_property("stream-path") + end + + local track_args = {} + local start = seconds_to_time_string(from, false) + local input_index = 0 + for input_path, tracks in pairs(get_input_info(path, settings.only_active_tracks)) do + append_args({ + "-ss", start, + "-i", input_path, + }) + if settings.only_active_tracks then + for _, track_index in ipairs(tracks) do + track_args = append_table(track_args, { "-map", string.format("%d:%d", input_index, track_index)}) + end + else + track_args = append_table(track_args, { "-map", tostring(input_index)}) + end + input_index = input_index + 1 + end + + append_args({"-to", tostring(to-from)}) + append_args(track_args) + + -- apply some of the video filters currently in the chain + local filters = {} + if settings.preserve_filters then + filters = get_video_filters() + end + if settings.append_filter ~= "" then + filters[#filters + 1] = settings.append_filter + end + if #filters > 0 then + append_args({ "-filter:v", table.concat(filters, ",") }) + end + + -- split the user-passed settings on whitespace + for token in string.gmatch(settings.codec, "[^%s]+") do + args[#args + 1] = token + end + + -- path of the output + local output_directory = settings.output_directory + if output_directory == "" then + if is_stream then + output_directory = "." + else + output_directory, _ = utils.split_path(path) + end + else + output_directory = string.gsub(output_directory, "^~", os.getenv("HOME") or "~") + end + local input_name = mp.get_property("filename/no-ext") or "encode" + local title = mp.get_property("media-title") + local extension = get_extension(path) + local output_name = get_output_string(output_directory, settings.output_format, input_name, extension, title, from, to, settings.profile) + if not output_name then + mp.osd_message("Invalid path " .. output_directory) + return + end + args[#args + 1] = utils.join_path(output_directory, output_name) + + if settings.print then + local o = "" + -- fuck this is ugly + for i = 1, #args do + local fmt = "" + if i == 1 then + fmt = "%s%s" + elseif i >= 2 and i <= 4 then + fmt = "%s" + elseif args[i-1] == "-i" or i == #args or args[i-1] == "-filter:v" then + fmt = "%s '%s'" + else + fmt = "%s %s" + end + o = string.format(fmt, o, args[i]) + end + print(o) + end + if settings.detached then + utils.subprocess_detached({ args = args }) + else + local res = utils.subprocess({ args = args, max_size = 0, cancellable = false }) + if res.status == 0 then + mp.osd_message("Finished encoding succesfully") + else + mp.osd_message("Failed to encode, check the log") + end + end +end + +function clear_timestamp() + timer:kill() + start_timestamp = nil + profile_start = "" + mp.remove_key_binding("encode-ESC") + mp.remove_key_binding("encode-ENTER") + mp.osd_message("", 0) +end + +function set_timestamp(profile) + if not mp.get_property("path") then + mp.osd_message("No file currently playing") + return + end + if not mp.get_property_bool("seekable") then + mp.osd_message("Cannot encode non-seekable media") + return + end + + if not start_timestamp or profile ~= profile_start then + profile_start = profile + start_timestamp = mp.get_property_number("time-pos") + local msg = function() + mp.osd_message( + string.format("encode [%s]: waiting for end timestamp", profile or "default"), + timer_duration + ) + end + msg() + timer = mp.add_periodic_timer(timer_duration, msg) + mp.add_forced_key_binding("ESC", "encode-ESC", clear_timestamp) + mp.add_forced_key_binding("ENTER", "encode-ENTER", function() set_timestamp(profile) end) + else + local from = start_timestamp + local to = mp.get_property_number("time-pos") + if to <= from then + mp.osd_message("Second timestamp cannot be before the first", timer_duration) + timer:kill() + timer:resume() + return + end + clear_timestamp() + mp.osd_message(string.format("Encoding from %s to %s" + , seconds_to_time_string(from, false) + , seconds_to_time_string(to, false) + ), timer_duration) + -- include the current frame into the extract + local fps = mp.get_property_number("container-fps") or 30 + to = to + 1 / fps / 2 + local settings = { + detached = true, + container = "", + only_active_tracks = false, + preserve_filters = true, + append_filter = "", + codec = "-an -sn -c:v libvpx -crf 10 -b:v 1000k", + output_format = "$f_$n.webm", + output_directory = "", + ffmpeg_command = "ffmpeg", + print = true, + } + if profile then + options.read_options(settings, profile) + if settings.container ~= "" then + msg.warn("The 'container' setting is deprecated, use 'output_format' now") + settings.output_format = settings.output_format .. "." .. settings.container + end + settings.profile = profile + else + settings.profile = "default" + end + start_encoding(from, to, settings) + end +end + +mp.add_key_binding(nil, "set-timestamp", set_timestamp) diff --git a/.config/mpv/scripts/exclude.lua b/.config/mpv/scripts/exclude.lua new file mode 100644 index 0000000..7a64028 --- /dev/null +++ b/.config/mpv/scripts/exclude.lua @@ -0,0 +1,10 @@ +mp.observe_property('playlist-count', 'number', function () + local playlist = mp.get_property_native('playlist') + for i = #playlist, 1, -1 do + for _, extension in pairs({'cue', 'txt', 'jpg', 'jpeg', 'png', 'log', 'description', 'en.vtt', 'info.json', 'webp'}) do + if playlist[i].filename:match('%.' .. extension .. '$') then + mp.commandv('playlist-remove', i-1) + end + end + end +end) diff --git a/.config/ncmpcpp/bindings b/.config/ncmpcpp/bindings new file mode 100644 index 0000000..6962dea --- /dev/null +++ b/.config/ncmpcpp/bindings @@ -0,0 +1,543 @@ +############################################################## +## This is the example bindings file. Copy it to ## +## ~/.ncmpcpp/bindings or $XDG_CONFIG_HOME/ncmpcpp/bindings ## +## and set up your preferences ## +############################################################## +## +##### General rules ##### +## +## 1) Because each action has runtime checks whether it's +## ok to run it, a few actions can be bound to one key. +## Actions will be bound in order given in configuration +## file. When a key is pressed, first action in order +## will test itself whether it's possible to run it. If +## test succeeds, action is executed and other actions +## bound to this key are ignored. If it doesn't, next +## action in order tests itself etc. +## +## 2) It's possible to bind more that one action at once +## to a key. It can be done using the following syntax: +## +## def_key "key" +## action1 +## action2 +## ... +## +## This creates a chain of actions. When such chain is +## executed, each action in chain is run until the end of +## chain is reached or one of its actions fails to execute +## due to its requirements not being met. If multiple actions +## and/or chains are bound to the same key, they will be +## consecutively run until one of them gets fully executed. +## +## 3) When ncmpcpp starts, bindings configuration file is +## parsed and then ncmpcpp provides "missing pieces" +## of default keybindings. If you want to disable some +## bindings, there is a special action called 'dummy' +## for that purpose. Eg. if you want to disable ability +## to crop playlists, you need to put the following +## into configuration file: +## +## def_key "C" +## dummy +## +## After that ncmpcpp will not bind any default action +## to this key. +## +## 4) To let you write simple macros, the following special +## actions are provided: +## +## - push_character "character" - pushes given special +## character into input queue, so it will be immediately +## picked by ncmpcpp upon next call to readKey function. +## Accepted values: mouse, up, down, page_up, page_down, +## home, end, space, enter, insert, delete, left, right, +## tab, ctrl-a, ctrl-b, ..., ctrl-z, ctrl-[, ctrl-\\, +## ctrl-], ctrl-^, ctrl-_, f1, f2, ..., f12, backspace. +## In addition, most of these names can be prefixed with +## alt-/ctrl-/shift- to be recognized with the appropriate +## modifier key(s). +## +## - push_characters "string" - pushes given string into +## input queue. +## +## - require_runnable "action" - checks whether given action +## is runnable and fails if it isn't. This is especially +## useful when mixed with previous two functions. Consider +## the following macro definition: +## +## def_key "key" +## push_characters "custom_filter" +## apply_filter +## +## If apply_filter can't be currently run, we end up with +## sequence of characters in input queue which will be +## treated just as we typed them. This may lead to unexpected +## results (in this case 'c' will most likely clear current +## playlist, 'u' will trigger database update, 's' will stop +## playback etc.). To prevent such thing from happening, we +## need to change above definition to this one: +## +## def_key "key" +## require_runnable "apply_filter" +## push_characters "custom_filter" +## apply_filter +## +## Here, first we test whether apply_filter can be actually run +## before we stuff characters into input queue, so if condition +## is not met, whole chain is aborted and we're fine. +## +## - require_screen "screen" - checks whether given screen is +## currently active. accepted values: browser, clock, help, +## media_library, outputs, playlist, playlist_editor, +## search_engine, tag_editor, visualizer, last_fm, lyrics, +## selected_items_adder, server_info, song_info, +## sort_playlist_dialog, tiny_tag_editor. +## +## - run_external_command "command" - runs given command using +## system() function. +## +## 5) In addition to binding to a key, you can also bind actions +## or chains of actions to a command. If it comes to commands, +## syntax is very similar to defining keys. Here goes example +## definition of a command: +## +## def_command "quit" [deferred] +## stop +## quit +## +## If you execute the above command (which can be done by +## invoking action execute_command, typing 'quit' and pressing +## enter), ncmpcpp will stop the player and then quit. Note the +## presence of word 'deferred' enclosed in square brackets. It +## tells ncmpcpp to wait for confirmation (ie. pressing enter) +## after you typed quit. Instead of 'deferred', 'immediate' +## could be used. Then ncmpcpp will not wait for confirmation +## (enter) and will execute the command the moment it sees it. +## +## Note: while command chains are executed, internal environment +## update (which includes current window refresh and mpd status +## update) is not performed for performance reasons. However, it +## may be desirable to do so in some situration. Therefore it's +## possible to invoke by hand by performing 'update enviroment' +## action. +## +## Note: There is a difference between: +## +## def_key "key" +## action1 +## +## def_key "key" +## action2 +## +## and +## +## def_key "key" +## action1 +## action2 +## +## First one binds two single actions to the same key whilst +## second one defines a chain of actions. The behavior of +## these two is different and is described in (1) and (2). +## +## Note: Function def_key accepts non-ascii characters. +## +##### List of unbound actions ##### +## +## The following actions are not bound to any key/command: +## +## - set_volume +## +# +#def_key "mouse" +# mouse_event +# +def_key "k" + scroll_up + +#def_key "shift-up" +# select_item +# scroll_up +# +def_key "j" + scroll_down + +#def_key "shift-down" +# select_item +# scroll_down +# +#def_key "[" +# scroll_up_album +# +#def_key "]" +# scroll_down_album +# +#def_key "{" +# scroll_up_artist +# +#def_key "}" +# scroll_down_artist +# +def_key "u" + page_up + +def_key "d" + page_down + +#def_key "home" +# move_home +# +#def_key "end" +# move_end +# +#def_key "insert" +# select_item +# +#def_key "enter" +# enter_directory +# +#def_key "enter" +# toggle_output +# +#def_key "enter" +# run_action +# +#def_key "enter" +# play_item +# +#def_key "space" +# add_item_to_playlist +# +#def_key "space" +# toggle_lyrics_update_on_song_change +# +#def_key "space" +# toggle_visualization_type +# +#def_key "delete" +# delete_playlist_items +# +#def_key "delete" +# delete_browser_items +# +#def_key "delete" +# delete_stored_playlist +# +#def_key "right" +# next_column +# +#def_key "right" +# slave_screen +# +#def_key "right" +# volume_up +# +#def_key "+" +# volume_up +# +#def_key "left" +# previous_column +# +#def_key "left" +# master_screen +# +#def_key "left" +# volume_down +# +#def_key "-" +# volume_down +# +#def_key ":" +# execute_command +# +#def_key "tab" +# next_screen +# +#def_key "shift-tab" +# previous_screen +# +#def_key "f1" +# show_help +# +#def_key "1" +# show_playlist +# +#def_key "2" +# show_browser +# +#def_key "2" +# change_browse_mode +# +#def_key "3" +# show_search_engine +# +#def_key "3" +# reset_search_engine +# +#def_key "4" +# show_media_library +# +#def_key "4" +# toggle_media_library_columns_mode +# +#def_key "5" +# show_playlist_editor +# +#def_key "6" +# show_tag_editor +# +#def_key "7" +# show_outputs +# +#def_key "8" +# show_visualizer +# +#def_key "=" +# show_clock +# +#def_key "@" +# show_server_info +# +#def_key "s" +# stop +# +#def_key "p" +# pause +# +#def_key ">" +# next +# +#def_key "<" +# previous +# +#def_key "ctrl-h" +# jump_to_parent_directory +# +#def_key "ctrl-h" +# replay_song +# +#def_key "backspace" +# jump_to_parent_directory +# +#def_key "backspace" +# replay_song +# +#def_key "f" +# seek_forward +# +#def_key "b" +# seek_backward +# +#def_key "r" +# toggle_repeat +# +#def_key "z" +# toggle_random +# +#def_key "y" +# save_tag_changes +# +#def_key "y" +# start_searching +# +#def_key "y" +# toggle_single +# +#def_key "R" +# toggle_consume +# +#def_key "Y" +# toggle_replay_gain_mode +# +#def_key "T" +# toggle_add_mode +# +#def_key "|" +# toggle_mouse +# +#def_key "#" +# toggle_bitrate_visibility +# +#def_key "Z" +# shuffle +# +#def_key "x" +# toggle_crossfade +# +#def_key "X" +# set_crossfade +# +def_key "U" + update_database + +#def_key "ctrl-s" +# sort_playlist +# +#def_key "ctrl-s" +# toggle_browser_sort_mode +# +#def_key "ctrl-s" +# toggle_media_library_sort_mode +# +#def_key "ctrl-r" +# reverse_playlist +# +#def_key "ctrl-f" +# apply_filter +# +#def_key "ctrl-_" +# select_found_items +# +#def_key "/" +# find +# +#def_key "/" +# find_item_forward +# +#def_key "?" +# find +# +#def_key "?" +# find_item_backward +# +#def_key "." +# next_found_item +# +#def_key "," +# previous_found_item +# +#def_key "w" +# toggle_find_mode +# +#def_key "e" +# edit_song +# +#def_key "e" +# edit_library_tag +# +#def_key "e" +# edit_library_album +# +#def_key "e" +# edit_directory_name +# +#def_key "e" +# edit_playlist_name +# +#def_key "e" +# edit_lyrics +# +#def_key "i" +# show_song_info +# +#def_key "I" +# show_artist_info +# +#def_key "g" +# jump_to_position_in_song +# +#def_key "l" +# show_lyrics +# +#def_key "ctrl-v" +# select_range +# +#def_key "v" +# reverse_selection +# +#def_key "V" +# remove_selection +# +#def_key "B" +# select_album +# +#def_key "a" +# add_selected_items +# +#def_key "c" +# clear_playlist +# +#def_key "c" +# clear_main_playlist +# +#def_key "C" +# crop_playlist +# +#def_key "C" +# crop_main_playlist +# +#def_key "m" +# move_sort_order_up +# +#def_key "m" +# move_selected_items_up +# +#def_key "n" +# move_sort_order_down +# +#def_key "n" +# move_selected_items_down +# +#def_key "M" +# move_selected_items_to +# +#def_key "A" +# add +# +#def_key "S" +# save_playlist +# +#def_key "o" +# jump_to_playing_song +# +#def_key "G" +# jump_to_browser +# +#def_key "G" +# jump_to_playlist_editor +# +#def_key "~" +# jump_to_media_library +# +#def_key "E" +# jump_to_tag_editor +# +#def_key "U" +# toggle_playing_song_centering +# +#def_key "P" +# toggle_display_mode +# +#def_key "\\" +# toggle_interface +# +#def_key "!" +# toggle_separators_between_albums +# +#def_key "L" +# toggle_lyrics_fetcher +# +#def_key "F" +# fetch_lyrics_in_background +# +#def_key "alt-l" +# toggle_fetching_lyrics_in_background +# +#def_key "ctrl-l" +# toggle_screen_lock +# +#def_key "`" +# toggle_library_tag_type +# +#def_key "`" +# refetch_lyrics +# +#def_key "`" +# add_random_items +# +#def_key "ctrl-p" +# set_selected_items_priority +# +#def_key "q" +# quit +# diff --git a/.config/ncmpcpp/config b/.config/ncmpcpp/config new file mode 100644 index 0000000..69ff9d3 --- /dev/null +++ b/.config/ncmpcpp/config @@ -0,0 +1,41 @@ +# Files +ncmpcpp_directory = ~/.config/ncmpcpp +lyrics_directory = ~/.config/mpd/lyrics + +mpd_host = localhost +mpd_port = 6600 +mpd_music_dir = /media/hdd/music +mpd_connection_timeout = 5 + +# Playlist +playlist_disable_highlight_delay = 0 +playlist_display_mode = classic +playlist_show_remaining_time = yes + +browser_display_mode = columns +autocenter_mode = yes +follow_now_playing_lyrics = yes +lyrics_fetchers = tekstowo, plyrics, justsomelyrics, jahlyrics, zeneszoveg, genius, internet + +# UI and colors +external_editor = $EDITOR +colors_enabled = yes +current_item_prefix = $(blue)$r +current_item_suffix = $/r$(end) +current_item_inactive_column_prefix = $(cyan)$r +current_item_inactive_column_suffix = $/r$(end) +header_window_color = cyan +main_window_color = white +active_window_border = blue +song_columns_list_format = (5)[blue]{l} (35)[green]{t|f:Title} (30)[magenta]{aE} (30)[yellow]{bE} +song_list_format = {$3%n | $9}{$7%a - $9}{$5%t$9}|{$8%f$9}$R{$6 | %b$9}{$3 | %l$9} +volume_color = red +progressbar_color = cyan +progressbar_elapsed_color = white +statusbar_color = white +user_interface = classic +selected_item_prefix = * +now_playing_prefix = "> " +centered_cursor = yes +display_bitrate = yes +enable_window_title = yes diff --git a/.config/nnn/nnn.bash b/.config/nnn/nnn.bash new file mode 100755 index 0000000..2bc60d2 --- /dev/null +++ b/.config/nnn/nnn.bash @@ -0,0 +1,5 @@ +# NNN + +export NNN_PLUG='t:preview-tabbed' + +export NNN_FIFO="/tmp/nnn.fifo" diff --git a/.config/nsxiv/exec/key-handler b/.config/nsxiv/exec/key-handler new file mode 100755 index 0000000..14dda4c --- /dev/null +++ b/.config/nsxiv/exec/key-handler @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +while read -r file +do + case "$1" in + "C-d") rm "$file" ;; + "C-c") cat "$file" | xclip -sel c -t image/png ;; + "C-w") xwallpaper --maximize "$file" ;; + "C-r") mv "$file" "$(dmenu </dev/null -p 'Rename to: ').${file##*.}" + esac +done diff --git a/.config/pipewire/pipewire.conf b/.config/pipewire/pipewire.conf new file mode 100644 index 0000000..173b665 --- /dev/null +++ b/.config/pipewire/pipewire.conf @@ -0,0 +1,269 @@ +# Daemon config file for PipeWire version "0.3.63" # +# +# Copy and edit this file in /etc/pipewire for system-wide changes +# or in ~/.config/pipewire for local changes. +# +# It is also possible to place a file with an updated section in +# /etc/pipewire/pipewire.conf.d/ for system-wide changes or in +# ~/.config/pipewire/pipewire.conf.d/ for local changes. +# + +context.properties = { + ## Configure properties in the system. + #library.name.system = support/libspa-support + #context.data-loop.library.name.system = support/libspa-support + #support.dbus = true + #link.max-buffers = 64 + link.max-buffers = 16 # version < 3 clients can't handle more + #mem.warn-mlock = false + #mem.allow-mlock = true + #mem.mlock-all = false + #clock.power-of-two-quantum = true + #log.level = 2 + #cpu.zero.denormals = false + + core.daemon = true # listening for socket connections + core.name = pipewire-0 # core name and socket name + + ## Properties for the DSP configuration. + default.clock.rate = 44100 + default.clock.allowed-rates = [ 44100 ] + default.clock.quantum = 192 + default.clock.min-quantum = 512 + #default.clock.max-quantum = 2048 + #default.clock.quantum-limit = 8192 + #default.video.width = 640 + #default.video.height = 480 + #default.video.rate.num = 25 + #default.video.rate.denom = 1 + # + #settings.check-quantum = false + #settings.check-rate = false + # + # These overrides are only applied when running in a vm. + #vm.overrides = { + # default.clock.min-quantum = 1024 + #} +} + +context.spa-libs = { + #<factory-name regex> = <library-name> + # + # Used to find spa factory names. It maps an spa factory name + # regular expression to a library name that should contain + # that factory. + # + audio.convert.* = audioconvert/libspa-audioconvert + avb.* = avb/libspa-avb + api.alsa.* = alsa/libspa-alsa + api.v4l2.* = v4l2/libspa-v4l2 + api.libcamera.* = libcamera/libspa-libcamera + #api.bluez5.* = bluez5/libspa-bluez5 + api.vulkan.* = vulkan/libspa-vulkan + #api.jack.* = jack/libspa-jack + support.* = support/libspa-support + #videotestsrc = videotestsrc/libspa-videotestsrc + #audiotestsrc = audiotestsrc/libspa-audiotestsrc +} + +context.modules = [ + #{ name = <module-name> + # [ args = { <key> = <value> ... } ] + # [ flags = [ [ ifexists ] [ nofail ] ] + #} + # + # Loads a module with the given parameters. + # If ifexists is given, the module is ignored when it is not found. + # If nofail is given, module initialization failures are ignored. + # + + # Uses realtime scheduling to boost the audio thread priorities. This uses + # RTKit if the user doesn't have permission to use regular realtime + # scheduling. + { name = libpipewire-module-rt + args = { + nice.level = -11 + #rt.prio = 88 + #rt.time.soft = -1 + #rt.time.hard = -1 + } + flags = [ ifexists nofail ] + } + + # The native communication protocol. + { name = libpipewire-module-protocol-native } + + # The profile module. Allows application to access profiler + # and performance data. It provides an interface that is used + # by pw-top and pw-profiler. + { name = libpipewire-module-profiler } + + # Allows applications to create metadata objects. It creates + # a factory for Metadata objects. + { name = libpipewire-module-metadata } + + # Creates a factory for making devices that run in the + # context of the PipeWire server. + { name = libpipewire-module-spa-device-factory } + + # Creates a factory for making nodes that run in the + # context of the PipeWire server. + { name = libpipewire-module-spa-node-factory } + + # Allows creating nodes that run in the context of the + # client. Is used by all clients that want to provide + # data to PipeWire. + { name = libpipewire-module-client-node } + + # Allows creating devices that run in the context of the + # client. Is used by the session manager. + { name = libpipewire-module-client-device } + + # The portal module monitors the PID of the portal process + # and tags connections with the same PID as portal + # connections. + { name = libpipewire-module-portal + flags = [ ifexists nofail ] + } + + # The access module can perform access checks and block + # new clients. + { name = libpipewire-module-access + args = { + # access.allowed to list an array of paths of allowed + # apps. + #access.allowed = [ + # /usr/bin/pipewire-media-session + #] + + # An array of rejected paths. + #access.rejected = [ ] + + # An array of paths with restricted access. + #access.restricted = [ ] + + # Anything not in the above lists gets assigned the + # access.force permission. + #access.force = flatpak + } + } + + # Makes a factory for wrapping nodes in an adapter with a + # converter and resampler. + { name = libpipewire-module-adapter } + + # Makes a factory for creating links between ports. + { name = libpipewire-module-link-factory } + + # Provides factories to make session manager objects. + { name = libpipewire-module-session-manager } + + # Use libcanberra to play X11 Bell + { name = libpipewire-module-x11-bell + args = { + #sink.name = "" + #sample.name = "bell-window-system" + #x11.display = null + #x11.xauthority = null + } + flags = [ ifexists nofail ] + } +] + +context.objects = [ + #{ factory = <factory-name> + # [ args = { <key> = <value> ... } ] + # [ flags = [ [ nofail ] ] + #} + # + # Creates an object from a PipeWire factory with the given parameters. + # If nofail is given, errors are ignored (and no object is created). + # + #{ factory = spa-node-factory args = { factory.name = videotestsrc node.name = videotestsrc Spa:Pod:Object:Param:Props:patternType = 1 } } + #{ factory = spa-device-factory args = { factory.name = api.jack.device foo=bar } flags = [ nofail ] } + #{ factory = spa-device-factory args = { factory.name = api.alsa.enum.udev } } + #{ factory = spa-node-factory args = { factory.name = api.alsa.seq.bridge node.name = Internal-MIDI-Bridge } } + #{ factory = adapter args = { factory.name = audiotestsrc node.name = my-test } } + #{ factory = spa-node-factory args = { factory.name = api.vulkan.compute.source node.name = my-compute-source } } + + # A default dummy driver. This handles nodes marked with the "node.always-driver" + # property when no other driver is currently active. JACK clients need this. + { factory = spa-node-factory + args = { + factory.name = support.node.driver + node.name = Dummy-Driver + node.group = pipewire.dummy + priority.driver = 20000 + } + } + { factory = spa-node-factory + args = { + factory.name = support.node.driver + node.name = Freewheel-Driver + priority.driver = 19000 + node.group = pipewire.freewheel + node.freewheel = true + } + } + # This creates a new Source node. It will have input ports + # that you can link, to provide audio for this source. + #{ factory = adapter + # args = { + # factory.name = support.null-audio-sink + # node.name = "my-mic" + # node.description = "Microphone" + # media.class = "Audio/Source/Virtual" + # audio.position = "FL,FR" + # } + #} + + # This creates a single PCM source device for the given + # alsa device path hw:0. You can change source to sink + # to make a sink in the same way. + # { factory = adapter + # args = { + # factory.name = api.alsa.pcm.source + # node.name = "alsa-source" + # node.description = "PCM Source" + # media.class = "Audio/Source" + # api.alsa.path = "hw:Creative,0" + # api.alsa.period-size = 1024 + # api.alsa.headroom = 0 + # api.alsa.disable-mmap = false + # api.alsa.disable-batch = false + # audio.format = "S16LE" + # audio.rate = 48000 + # audio.channels = 2 + # audio.position = "FL,FR" + # } + # } + + # { factory = adapter + # args = { + # factory.name = api.alsa.pcm.sink + # node.name = "alsa-dmix-internal" + # node.description = "PCM Internal" + # media.class = "Audio/Sink" + # api.alsa.path = "dmix:Creative,0" + # } + # } +] + +context.exec = [ + #{ path = <program-name> [ args = "<arguments>" ] } + # + # Execute the given program with arguments. + # + # You can optionally start the session manager here, + # but it is better to start it as a systemd service. + # Run the session manager with -h for options. + # + { path = "/usr/bin/wireplumber" args = "" } + # + # You can optionally start the pulseaudio-server here as well + # but it is better to start it as a systemd service. + # It can be interesting to start another daemon here that listens + # on another address with the -a option (eg. -a tcp:4713). + # + { path = "/usr/bin/pipewire" args = "-c pipewire-pulse.conf" } +] diff --git a/.config/shell/aliasrc b/.config/shell/aliasrc new file mode 100644 index 0000000..a6d785a --- /dev/null +++ b/.config/shell/aliasrc @@ -0,0 +1,87 @@ +## MISCELLANEOUS + +# various shortcuts +alias reboot='sudo reboot' +alias poweroff='sudo shutdown -hP now' +alias refresh='. ~/.bashrc' +alias jpwine='LANG=ja_JP.UTF-8 WINEDEBUG=-all wine' +alias emd='/usr/bin/emacs --daemon &' +alias emc='/usr/bin/emacsclient -c -a ""' +alias z='zathura' +alias nnn='nnn -Hde' +alias cl='clear;fastfetch' +alias ea='$EDITOR ~/.config/shell/aliasrc' +alias cam='mpv --profile=low-latency --untimed /dev/video0' +alias df='df -h' +alias tma='tmux a -t' +alias tmn='tmux new-session -A -s' +alias wgu='sudo wg-quick up /etc/wireguard/wg0.conf' +alias wgd='sudo wg-quick down /etc/wireguard/wg0.conf' +alias zzz='sudo zzz' +alias sc='echo -ne "\e[1 q"' +alias ska="ps -u $USER | awk 'NR > 1 { print $1 }' | xargs -t kill" + +alias alert='pw-play /usr/share/sounds/freedesktop/stereo/complete.oga >/dev/null' + +# compiler +alias clang='clang -march=native -O3 -flto=thin' + +# rename files in cwd in their current order to 4-digit numbers +alias ofn='/bin/ls | cat -n | while read n f; do perl-rename "s/${f%.*}/$(printf "%04d" "$n")/" "$f"; done' + +# restart pipewire after suspend if it stops working +alias pw-restart='pkill pipewire && sleep 3s && setsid pipewire &>/dev/null' + +# set preferred keyboard options +alias setkeys='xset r rate 250 30 && setxkbmap -layout us,us -variant dvorak, -option "ctrl:nocaps,compose:rctrl"' + +# pad numbers in filenames with zeros +alias padz='perl-rename "s/\d+/sprintf(\"%02d\",$&)/e"' + +# cp mv and rm always verbose +alias cp='cp -v' +alias mv='mv -v' +alias rm='rm -v' + +# colorize grep output +alias grep='grep --color=auto -i' +alias zgrep='zgrep --color=auto -i' +alias egrep='egrep --color=auto -i' + +# ls shortcuts +alias ls='ls --color=always --group-directories-first' +alias ll='ls -lh' +alias la='ls -A' +alias lla='ll -A' +alias lc='ls | wc -l' + +# control audio +alias headset='wpctl set-default "$(wpctl status | grep Headphones | cut -b11-12)"' +alias speakers='wpctl set-default "$(wpctl status | grep Speakers | cut -b11-12)"' +alias getvol='wpctl get-volume @DEFAULT_SINK@' +alias setvol='wpctl set-volume @DEFAULT_SINK@' + +# shortcut for dotfiles repo +alias dfiles='/usr/bin/git --git-dir=$HOME/.dotfiles --work-tree=$HOME' +alias dcomm='dfiles commit -m' +alias dpush='dfiles push' + +# package management +alias qu='equery u' +alias qd='equery d' +alias qg='equery g' +alias qf='equery f' +alias qb='equery b' +alias qy='equery y' + +alias eli='eix -c --installed' +alias els='eix -c --selected' + +alias esync='sudo emaint sync' +alias pemup='emerge -pvuND @world' +alias emup='sudo emerge -vuND @world' +alias pemin='emerge -pv' +alias emin='sudo emerge -v' +alias pemrm='emerge -pvc' +alias emrm='sudo emerge -vc' +alias emsr='emerge -s' diff --git a/.config/shell/profile b/.config/shell/profile new file mode 100644 index 0000000..b670bb0 --- /dev/null +++ b/.config/shell/profile @@ -0,0 +1,45 @@ +RUBY_VERSION=$(ruby -e 'puts RbConfig::CONFIG["ruby_version"]') +export GEM_HOME="$HOME/.local/share/gem/ruby/$RUBY_VERSION" +export GEM_PATH="$HOME/.local/share/gem/ruby/$RUBY_VERSION" + +export _JAVA_AWT_WM_NONREPARENTING=1 +export EDITOR="vim" +export SUDO_EDITOR="nano" +export TERMINAL="urxvt" +export BROWSER="firefox" +export LESS="-F -X $LESS" + +export XDG_CONFIG_HOME="$HOME/.config" +export XDG_DATA_HOME="$HOME/.local/share" +export XDG_CACHE_HOME="$HOME/.cache" + +export XINITRC="$XDG_CONFIG_HOME/x11/xinitrc" + +export MAIL=~/.mutt/Maildir +export NO_AT_BRIDGE=1 + +export GTK_IM_MODULE='ibus' +export QT_IM_MODULE='ibus' +export XMODIFIERS='@im=ibus' + +export VDPAU_DRIVER=radeonsi + +export EIX_LIMIT=0 +export EIX_LIMIT_COMPACT=0 + +export LC_ALL=en_US.utf8 + +export UV_CACHE_DIR="$HOME/.local/share/uv/cache" +export SQLITE_HISTORY="$HOME/.cache/.sqlite_history" +export PYTHON_HISTORY="$HOME/.cache/.python_history" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/lib64" +export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/lib64/pkgconfig" +export INFOPATH="$INFOPATH:/usr/local/share/info:$HOME/.local/share/info" +export MANPATH="$MANPATH:/usr/local/man" +export GOPATH="$HOME/.local/share/go" +export PATH="$PATH:$HOME/.local/bin:$HOME/.local/src/fzf/bin:$HOME/.npm/bin:/sbin:/usr/sbin:$GOPATH/bin:$HOME/.cargo/bin" + +[ -f $HOME/.bashrc ] && . $HOME/.bashrc + +[ -f /etc/motd.tcl ] && /etc/motd.tcl diff --git a/.config/tmux/tmux.conf b/.config/tmux/tmux.conf new file mode 100644 index 0000000..fe41598 --- /dev/null +++ b/.config/tmux/tmux.conf @@ -0,0 +1,91 @@ +set -g default-command "${SHELL}" + +# Status-bar settings +set -g status-right "%A, %F - %H:%M" +set -g window-status-current-style "underscore" +set -g message-command-style 'fg=#000000,bg=#FFFF00' +set -g message-style 'fg=#000000, bg=#FFFF00' +# dark +set -g status-bg '#333333' +set -g status-fg '#FFFFFF' +# light +# set -g status-bg '#bbbbbb' +# set -g status-fg '#000000' +set -g set-titles on +set -g set-titles-string "#T" +set -g automatic-rename off + +# Enable RGB colour if running in xterm(1) +# set-option -sa terminal-overrides ",xterm*:Tc" + +# Change the default $TERM to tmux-256color +# set -g default-terminal "tmux-256color" + +# Set history-limit +set -g history-limit 30000 + +# enable emacs mode-keys +set -g mode-keys emacs + +# various window option +set -g base-index 1 +set -g pane-base-index 1 +set-window-option -g pane-base-index 1 +set-option -g renumber-windows on +setw -g aggressive-resize on + +## KEYBINDS + +# Change the prefix key to C-a +set -g prefix C-Space +unbind C-b +bind C-Space send-prefix + +unbind C-l + +bind C-s split-window -v -c "#{pane_current_path}" +bind C-v split-window -h -c "#{pane_current_path}" +bind C-w killp +bind C-q killw +bind C-p previous-window +bind C-n next-window +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R +bind -n M-n swap-window -t +1\; select-window -t +1 +bind -n M-p swap-window -t -1\; select-window -t -1 +bind -n M-h resize-pane -L 5 +bind -n M-j resize-pane -D 5 +bind -n M-k resize-pane -U 5 +bind -n M-l resize-pane -R 5 + +# Smart pane switching with awareness of Vim splits. +# See: https://github.com/christoomey/vim-tmux-navigator +# is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ +# | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|l?n?vim?x?)(diff)?$'" +# bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L' +# bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D' +# bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U' +# bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R' +# tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")' +# if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \ +# "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'" +# if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \ +# "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'" + +# bind-key -T copy-mode-vi 'C-H' select-pane -L +# bind-key -T copy-mode-vi 'C-J' select-pane -D +# bind-key -T copy-mode-vi 'C-K' select-pane -U +# bind-key -T copy-mode-vi 'C-L' select-pane -R +# bind-key -T copy-mode-vi 'C-\' select-pane -l + +bind C-l send-keys 'C-l' +bind C-k send-keys 'C-k' + +# Turn the mouse off +set -g mouse off + +# Keys to toggle monitoring activity in a window and the synchronize-panes option +bind m set monitor-activity +bind y set synchronize-panes\; display 'synchronize-panes #{?synchronize-panes,on,off}' diff --git a/.config/wireplumber/wireplumber.conf.d/51-camera-microphone-input-rename.conf b/.config/wireplumber/wireplumber.conf.d/51-camera-microphone-input-rename.conf new file mode 100644 index 0000000..8656458 --- /dev/null +++ b/.config/wireplumber/wireplumber.conf.d/51-camera-microphone-input-rename.conf @@ -0,0 +1,15 @@ +monitor.alsa.rules = [ + { + matches = [ + { + node.name = "alsa_input.usb-SunplusIT_Inc_FHD_Camera_Microphone_01.00.00-02.analog-stereo" + } + ] + actions = { + update-props = { + node.description = "Camera Microphone", + node.nick = "Camera Microphone" + } + } + } +] diff --git a/.config/wireplumber/wireplumber.conf.d/51-soundblaster-output-rename.conf b/.config/wireplumber/wireplumber.conf.d/51-soundblaster-output-rename.conf new file mode 100644 index 0000000..75dd728 --- /dev/null +++ b/.config/wireplumber/wireplumber.conf.d/51-soundblaster-output-rename.conf @@ -0,0 +1,16 @@ +monitor.alsa.rules = [ + { + matches = [ + { + node.name = "alsa_output.pci-0000_29_00.0.analog-stereo" + } + ] + actions = { + update-props = { + node.description = "Headphones", + node.nick = "Headphones" + } + } + } +] + diff --git a/.config/wireplumber/wireplumber.conf.d/51-starshipmatisse-output-rename.conf b/.config/wireplumber/wireplumber.conf.d/51-starshipmatisse-output-rename.conf new file mode 100644 index 0000000..a6c6697 --- /dev/null +++ b/.config/wireplumber/wireplumber.conf.d/51-starshipmatisse-output-rename.conf @@ -0,0 +1,18 @@ +monitor.alsa.rules = [ + { + matches = [ + { + node.name = "alsa_output.pci-0000_31_00.4.iec958-stereo" + } + ] + + actions = { + update-props = { + node.description = "Speakers", + node.nick = "Speakers" + } + } + } +] + + diff --git a/.config/wireplumber/wireplumber.conf.d/52-soundblaster-input-disable.conf b/.config/wireplumber/wireplumber.conf.d/52-soundblaster-input-disable.conf new file mode 100644 index 0000000..b36545c --- /dev/null +++ b/.config/wireplumber/wireplumber.conf.d/52-soundblaster-input-disable.conf @@ -0,0 +1,15 @@ +monitor.alsa.rules = [ + { + matches = [ + { + node.name = "alsa_input.pci-0000_29_00.0.analog-stereo" + } + ] + actions = { + update-props = { + node.disabled = true + } + } + } +] + diff --git a/.config/wireplumber/wireplumber.conf.d/52-starshipmatisse-input-disable.conf b/.config/wireplumber/wireplumber.conf.d/52-starshipmatisse-input-disable.conf new file mode 100644 index 0000000..86cdd32 --- /dev/null +++ b/.config/wireplumber/wireplumber.conf.d/52-starshipmatisse-input-disable.conf @@ -0,0 +1,15 @@ +monitor.alsa.rules = [ + { + matches = [ + { + node.name = "alsa_input.pci-0000_31_00.4.analog-stereo" + } + ] + actions = { + update-props = { + node.disabled = true + } + } + } +] + diff --git a/.config/x11/xinitrc b/.config/x11/xinitrc new file mode 100644 index 0000000..e734be9 --- /dev/null +++ b/.config/x11/xinitrc @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +if command -v dbus-launch > /dev/null && test -z "${DBUS_SESSION_BUS_ADDRESS}"; then + eval $(dbus-launch --sh-syntax --exit-with-session) +fi + +eval "$(gpg-agent --daemon --allow-preset-passphrase)" +eval "$(ssh-agent)" + +#xrandr --addmode HDMI-A-0 1280x1024 +# xrandr --output HDMI-A-0 --mode 1280x960 --primary +# xrandr --output DisplayPort-1 --mode 1920x1080 --left-of HDMI-A-0 +xrandr --output DisplayPort-1 --mode 1920x1080 --primary +xrandr --output HDMI-A-0 --mode 1280x960 --left-of DisplayPort-1 + +xset r rate 250 30 +xset s off -dpms +setxkbmap -option "ctrl:nocaps,compose:rctrl" +xrdb -merge ~/.Xresources + +/usr/bin/dunst & +/usr/bin/ibus-daemon -d -r -x +/usr/bin/otd-daemon & +/usr/bin/urxvtd -q -o -f & +/usr/bin/emacs --daemon & +/usr/bin/pipewire & +/usr/bin/mpd & +$HOME/.local/bin/set-wallpaper & +/usr/libexec/polkit-gnome-authentication-agent-1 & +#$HOME/.cargo/bin/mpd-discord-rpc & + +exec i3 diff --git a/.config/yt-dlp/config b/.config/yt-dlp/config new file mode 100644 index 0000000..aeb3bda --- /dev/null +++ b/.config/yt-dlp/config @@ -0,0 +1 @@ +--verbose -ciw -f bestvideo[ext=mp4][vcodec!*=av01]+bestaudio[ext=m4a]/best[ext=mp4]/best --merge-output-format mkv diff --git a/.config/zathura/zathurarc b/.config/zathura/zathurarc new file mode 100644 index 0000000..96c2ac1 --- /dev/null +++ b/.config/zathura/zathurarc @@ -0,0 +1,29 @@ +set statusbar-h-padding 0 +set statusbar-v-padding 0 +set page-padding 1 +set selection-clipboard clipboard +set database "sqlite" + +map u scroll half-up +map d scroll half-down +map n scroll full-down +map p scroll full-up +map [fullscreen] u scroll half-up +map [fullscreen] d scroll half-down +map [fullscreen] n scroll full-down +map [fullscreen] p scroll full-up +map D toggle_page_mode +map r reload +map R rotate +map i recolor +map ^p print +map g goto top + +#stop at page boundries +set scroll-page-aware true +set scroll-full-overlap 0.01 +set scroll-step 100 + +unmap f +map f toggle_fullscreen +map [fullscreen] f toggle_fullscreen diff --git a/.ratpoisonrc b/.ratpoisonrc new file mode 100644 index 0000000..300f7c6 --- /dev/null +++ b/.ratpoisonrc @@ -0,0 +1,108 @@ +set rudeness 15 + +# set info style +set winname class +set wingravity center +set transgravity center +set border 0 +set bgcolor #000000 +set fgcolor #c4c4c4 + +# Set the escape key to the ctrl-z +escape C-z + +# ALIASES + +# store frames +alias store-fs1 exec ratpoison -c "setenv fs1 `ratpoison -c 'fdump'`" +alias restore-fs1 exec ratpoison -c "frestore `ratpoison -c 'getenv fs1'`" +alias store-fs2 exec ratpoison -c "setenv fs2 `ratpoison -c 'fdump'`" +alias restore-fs2 exec ratpoison -c "frestore `ratpoison -c 'getenv fs2'`" +alias store-fs3 exec ratpoison -c "setenv fs3 `ratpoison -c 'fdump'`" +alias restore-fs3 exec ratpoison -c "frestore `ratpoison -c 'getenv fs3'`" +alias store-fs4 exec ratpoison -c "setenv fs4 `ratpoison -c 'fdump'`" +alias restore-fs4 exec ratpoison -c "frestore `ratpoison -c 'getenv fs4'`" +alias store-fs5 exec ratpoison -c "setenv fs5 `ratpoison -c 'fdump'`" +alias restore-fs5 exec ratpoison -c "frestore `ratpoison -c 'getenv fs5'`" + +## KEYBINDS + +# unbind defaults +unbind b +unbind C-b +unbind a +unbind C-a +unbind p +unbind C-p +unbind n +unbind C-n +unbind f +unbind C-f +unbind m +unbind C-m +unbind l +unbind C-l +unbind c +unbind C-c +unbind exclam +unbind C-exclam +unbind Return +unbind C-Return +unbind N +unbind P + + +# switch between windows and monitors +definekey top s-n next +definekey top s-p prev +definekey top s-Left nextscreen +definekey top s-Right nextscreen + +# manage frames and windows +definekey top s-h focusleft +definekey top s-j focusdown +definekey top s-k focusup +definekey top s-l focusright +definekey top s-H exchangeleft +definekey top s-J exchangedown +definekey top s-K exchangeup +definekey top s-L exchangeright +definekey top s-C delete + +bind M-exclam store-fs1 +bind M-1 restore-fs1 +bind M-at store-fs2 +bind M-2 restore-fs2 +bind M-numbersign store-fs3 +bind M-3 restore-fs3 +bind M-dollar store-fs4 +bind M-4 restore-fs4 +bind M-percent store-fs5 +bind M-5 restore-fs5 + +# volume and media control +definekey top XF86AudioRaiseVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ +definekey top XF86AudioLowerVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- +definekey top XF86AudioMute exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle +definekey top XF86AudioPrev exec mpc prev && exec ratpoison -c "echo $(mpc status)" +definekey top XF86AudioNext exec mpc next && exec ratpoison -c "echo $(mpc status)" +definekey top XF86AudioPlay exec mpc toggle && exec ratpoison -c "echo $(mpc status)" + +# Information +bind C-v exec ratpoison -c "echo $(wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{ print $3,$1,$2*100 }')%" +bind C-a exec ratpoison -c "echo `date +'%A, %F - %H:%M'` `cal | tail -n +2 | sed -e 's/^Su/\n\n Su/' -e 's/.*/ & /' -e \"s/\ $(date +%e) /\<$(date +%e)\>/\"`" +bind C-d exec ratpoison -c "echo $(date +'%A, %F - %H:%M')" +bind C-t exec ratpoison -c "echo $(sensors | sed -n /Tctl/p | sed 's/Tctl: *+/Temp: /')" + +# application keybinds +definekey top s-Return exec urxvtc +definekey top s-z exec boomer +definekey top s-Print exec scrot -s -e 'mv $f ~/pics/' +definekey top Print exec scrot -u -e 'mv $f ~/pics/' +definekey top s-b exec bm -o +definekey top s-B exec bm -y +bind C-f exec firefox -P default-release +bind C-F exec firefox -P less-strict +bind C-e exec emacsclient -c -a "" +bind C-m exec mpdmenu +bind C-p exec dmenu_run -m 0 -fn "xft:Hack Nerd Font:size=11" -nb "#222222" -nf "#bbbbbb" -sb "#005577" -sf "#eeeeee" diff --git a/.vim/vimrc b/.vim/vimrc new file mode 100644 index 0000000..6e6e218 --- /dev/null +++ b/.vim/vimrc @@ -0,0 +1,90 @@ +syntax enable +filetype plugin on + +set nocompatible + +set path+=** +set wildmenu + +set modeline +set modelines=5 +set nobackup +set nowritebackup +set updatetime=300 +set hidden +set noswapfile +set laststatus=2 +set shortmess+=c +set clipboard=unnamedplus + +let g:markdown_fenced_languages = ['javascript', 'js=javascript', 'json=javascript'] + +let $RTP=split(&runtimepath, ',')[0] +let $RC="$HOME/.vim/vimrc" + +call plug#begin() + +Plug 'dracula/vim', { 'as': 'dracula' } +Plug 'NLKNguyen/papercolor-theme' +Plug 'tpope/vim-commentary' +Plug 'tpope/vim-surround' +Plug 'preservim/nerdtree' + +call plug#end() + +" set background=light +" colorscheme PaperColor +" colorscheme catppuccin-latte + +set background=dark +colorscheme dracula + +highlight Normal ctermbg=black +set autoindent +set smartindent +set expandtab +set tabstop=4 +set shiftwidth=4 + +set number +set relativenumber +set showcmd +set cmdheight=1 +set completeopt=menuone,noinsert,noselect +set splitright +set splitbelow +set ignorecase +set smartcase +set showmatch +set signcolumn=yes +set incsearch +set diffopt+=vertical + +" Use ^] to jump to tag under cursor +" Use g^] for ambiguous tags +" Use ^t to jump back up the tag stack +command! MakeTags !ctags -R * + +let mapleader="\<space>" + +nmap <silent> <c-h> <c-w>h +nmap <silent> <c-j> <c-w>j +nmap <silent> <c-k> <c-w>k +nmap <silent> <c-l> <c-w>l + +nmap <leader>Q :bufdo bdelete<CR> +nnoremap <C-c> :bp\|bd #<CR> + +nmap <leader>ve :edit $MYVIMRC<CR> +nmap <leader>vr :source $MYVIMRC <bar> :doautocmd BufRead<CR> + +nnoremap <leader>d :cd %:p:h<CR>:pwd<CR> + +nnoremap <leader><C-n> :NERDTreeToggle<CR> +nnoremap <leader>n :NERDTreeFocus<CR> + +map gf :edit <cfile><CR> + +nmap <leader>x :!xdg-open %<CR><CR> + +nmap <leader>s :!echo -ne "\e[2 q"<CR><CR> diff --git a/.xinitrc b/.xinitrc new file mode 120000 index 0000000..518bb5d --- /dev/null +++ b/.xinitrc @@ -0,0 +1 @@ +.config/x11/xinitrc
\ No newline at end of file |
