summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilotterytea <ilotterytea@proton.me>2024-05-26 20:10:26 +0500
committerilotterytea <ilotterytea@proton.me>2024-05-26 20:10:26 +0500
commit036c889c4a4f7f59d1e1a592586b54c5c5e93005 (patch)
treeaa76d678790abc79f24edf83c17a564eb2c6f65d
initial commitHEADmaster
-rw-r--r--alacritty/alacritty.toml41
-rw-r--r--alacritty/alacritty.yml110
-rwxr-xr-xbspwm/autostart17
-rwxr-xr-xbspwm/bspwmrc85
-rw-r--r--bspwm/noswallow1
-rw-r--r--bspwm/terminals2
-rw-r--r--btop/btop.conf248
-rw-r--r--btop/btop.log24
-rw-r--r--conky/conky-center.conf51
-rw-r--r--conky/conky-old.conf96
-rw-r--r--conky/conky.conf53
-rw-r--r--conky/conky_minimal_left.conf49
-rw-r--r--conky/conky_notes.conf90
-rw-r--r--conky/conky_stats.conf50
-rwxr-xr-xconky/start-conky.desktop13
-rwxr-xr-xconky/start-conky.sh3
-rw-r--r--conky/system-all.conf141
-rw-r--r--conky/test.conf42
-rw-r--r--dunst/dunstrc63
-rw-r--r--lf/lfrc187
-rw-r--r--mpd/mpd.conf31
-rw-r--r--mpv/input.conf132
-rw-r--r--mpv/lua-modules/auto-profiles-functions.lua122
-rw-r--r--mpv/lua-modules/scroll-list.lua236
-rw-r--r--mpv/lua-modules/user-input-module.lua49
-rw-r--r--mpv/mpv.conf177
-rw-r--r--mpv/scripts/auto-audio-device.lua36
-rw-r--r--mpv/scripts/auto-profiles.lua198
-rw-r--r--mpv/scripts/auto-save-state.lua55
-rw-r--r--mpv/scripts/autodeint.lua158
-rw-r--r--mpv/scripts/betterchapters.lua21
-rw-r--r--mpv/scripts/blacklist-extensions.lua80
-rw-r--r--mpv/scripts/cycle-profiles.lua103
-rw-r--r--mpv/scripts/music-mode.lua192
-rw-r--r--mpv/scripts/user-input.lua664
-rw-r--r--mpv/scripts/youtube-quality.lua275
-rw-r--r--mpv/scripts/youtube-serarch.lua149
-rw-r--r--ncmpcpp/config101
-rw-r--r--neofetch/config.conf864
-rw-r--r--picom/picom.conf148
-rw-r--r--polybar/colors.ini21
-rw-r--r--polybar/config.ini78
-rwxr-xr-xpolybar/launch.sh22
-rw-r--r--polybar/modules.ini218
-rwxr-xr-xpolybar/scripts/micfn34
-rwxr-xr-xpolybar/scripts/mpris_tail.py535
-rw-r--r--redshift.conf14
-rw-r--r--rofi/colors.rasi13
-rw-r--r--rofi/config.rasi1
-rw-r--r--rofi/iconic.rasi119
-rw-r--r--rofi/simple.rasi90
-rw-r--r--sxhkd/sxhkdrc229
52 files changed, 6531 insertions, 0 deletions
diff --git a/alacritty/alacritty.toml b/alacritty/alacritty.toml
new file mode 100644
index 0000000..8c65901
--- /dev/null
+++ b/alacritty/alacritty.toml
@@ -0,0 +1,41 @@
+[font]
+size = 7.0
+
+[font.bold]
+family = "Cascadia Mono"
+
+[font.glyph_offset]
+x = 0
+y = 0
+
+[font.italic]
+family = "Cascadia Mono"
+
+[font.normal]
+family = "Cascadia Mono"
+
+[font.offset]
+x = 0
+y = 0
+
+[mouse]
+hide_when_typing = false
+
+[scrolling]
+history = 100000
+multiplier = 3
+
+[window]
+decorations = "none"
+dynamic_padding = true
+startup_mode = "Windowed"
+title = "Alacritty"
+opacity = 0.95
+
+[window.dimensions]
+columns = 100
+lines = 25
+
+[window.padding]
+x = 5
+y = 5
diff --git a/alacritty/alacritty.yml b/alacritty/alacritty.yml
new file mode 100644
index 0000000..a32f0b2
--- /dev/null
+++ b/alacritty/alacritty.yml
@@ -0,0 +1,110 @@
+# Alacritty Configuration
+env:
+ TERM: xterm-256color
+
+# Windows
+window:
+ dimensions:
+ columns: 100
+ lines: 25
+ padding:
+ x: 5
+ y: 5
+ dynamic_padding: true
+ decorations: none
+ startup_mode: Windowed
+ title: Alacritty
+
+# Scrolling
+scrolling:
+ # Maximum number of lines in the scrollback buffer.
+ # Specifying '0' will disable scrolling.
+ history: 100000
+
+ # Number of lines the viewport will move for every line scrolled when
+ # scrollback is enabled (history > 0).
+ multiplier: 3
+
+# Visual Bell
+bell:
+ animation: EaseOutExpo
+ color: '0xffffff'
+ duration: 0
+
+# Background opacity
+background_opacity: 0.96
+
+# Font Configuration
+font:
+ normal:
+ family: Sarasa Term K
+ # style: Nerd
+
+ bold:
+ family: Sarasa Term K
+ italic:
+ family: Sarasa Term K
+ # style: "Medium Italic"
+
+ size: 14.0
+
+ offset:
+ x: 0
+ y: 0
+
+ glyph_offset:
+ x: 0
+ y: 0
+
+draw_bold_text_with_bright_colors: true
+
+mouse:
+ # Click settings
+ #
+ # The `double_click` and `triple_click` settings control the time
+ # alacritty should wait for accepting multiple clicks as one double
+ # or triple click.
+ double_click: { threshold: 300 }
+ triple_click: { threshold: 300 }
+ hide_when_typing: false
+
+#cursor:
+ style:
+ # Cursor shape
+ #
+ # Values for `shape`:
+ # - ▇ Block
+ # - _ Underline
+ # - | Beam
+ shape: Beam
+ blinking: On
+ blink_interval: 750
+
+# Selection colors
+colors:
+ # Default colors
+ primary:
+ background: '0x2a2f33'
+ foreground: '0xb3cfa7'
+
+ # Normal colors
+ normal:
+ black: '0x212529'
+ red: '0xea5252'
+ green: '0xacb765'
+ yellow: '0xc1bf89'
+ blue: '0x82abbc'
+ magenta: '0xb18a97'
+ cyan: '0x88b482'
+ white: '0xb3cfa7'
+
+ # Bright colors
+ bright:
+ black: '0x31363b'
+ red: '0xea5252'
+ green: '0xacb765'
+ yellow: '0xc1bf89'
+ blue: '0x82abbc'
+ magenta: '0xb18a97'
+ cyan: '0x89b482'
+ white: '0xb3cfa7'
diff --git a/bspwm/autostart b/bspwm/autostart
new file mode 100755
index 0000000..e3fb541
--- /dev/null
+++ b/bspwm/autostart
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Applications
+pgrep conky || conky &
+
+# pidof clight || clight --lat=26.83 --lon=80.92 &
+pidof redshift || redshift &
+xrdb ~/.Xresources
+firefox &
+# syncthing serve --no-browser --logfile=default &
+
+setxkbmap -layout us,ru -option grp:alt_shift_toggle &
+
+~/.local/scripts/mpd_start &
+
+xautolock -detectsleep -time 5 -locker lock.sh -notify 30 -notifier "notify-send -u critical -t 10000 -- 'LOCKING screen in 30 seconds'" &
+# mailsync &
+~/.config/polybar/launch.sh &
diff --git a/bspwm/bspwmrc b/bspwm/bspwmrc
new file mode 100755
index 0000000..570b688
--- /dev/null
+++ b/bspwm/bspwmrc
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+#### MONITORS ####
+bspc monitor -d 1 2 3 4 5 6 7 8 9
+
+external_monitor=$(xrandr --query | grep 'DP-1')
+
+if [[ $external_monitor = DP-1\ connected* ]]; then
+ xrandr --output HDMI-1 --primary --mode 1920x1080 --output DP-1 --mode 1920x1080 --left-of HDMI-1
+ bspc monitor HDMI-1 -d 1 2 3 4 5 6
+ bspc monitor DP-1 -d 7 8 9
+else
+ xrandr --output HDMI-1 --auto
+ bspc monitor HDMI-1 -d 1 2 3 4 5 6 7 8 9
+fi
+
+# Truncate a couple of common commands that are used herein.
+_bc() {
+ bspc config "$@"
+}
+
+
+#### BSPWM configuration ####
+_bc window_gap 8
+_bc top_padding 36
+_bc top_monocle_padding 0
+_bc border_width 1
+_bc bottom_padding 0
+_bc left_padding 0
+_bc right_padding 0
+_bc single_monocle false
+_bc click_to_focus false
+_bc split_ratio 0.50
+_bc borderless_monocle true
+_bc gapless_monocle true
+_bc focus_by_distance true
+_bc paddingless_monocle true
+_bc focus_follows_pointer true
+_bc ignore_ewmh_focus true
+_bc history_aware_focus true
+_bc remove_disabled_monitors true
+_bc merge_overlapping_monitors true
+_bc pointer_follows_monitor true
+_bc pointer_modifier mod1
+_bc pointer_action1 move
+_bc pointer_action2 resize_side
+_bc pointer_action3 resize_corner
+
+# Colors
+bspc config active_border_color "#474f54"
+bspc config focused_border_color "#8bdfff"
+bspc config normal_border_color "#373d41"
+bspc config presel_feedback_color "#373d41"
+
+# Rules
+bspc rule -a firefox -o desktop=2
+bspc rule -a discord desktop='^8'
+bspc rule -a feh state='floating'
+bspc rule -a mpv state='floating'
+bspc rule -a openssh-askpass state='floating'
+bspc rule -a "Iwgtk" state='floating'
+bspc rule -a Zathura state='tiled'
+bspc rule -a Pavucontrol state='floating'
+bspc rule -a flameshot state='floating'
+bspc rule -a *:SPLASH state=floating
+bspc rule -a logsplease state='floating'
+bspc rule -a maxoning state='floating'
+bspc rule -a roguelike state='floating'
+bspc desktop -f 1
+
+# INIT-DAEMONS
+xsetroot -cursor_name left_ptr &
+sxhkd &
+# xcompmgr -cCfF -t -2 -l -2 -r 2.8 -o 0.55 -D 5 &
+picom --experimental-backends &
+dunst &
+
+# Replace caps lock with Esc
+# setxkbmap -option caps:escape
+# setxkbmap -option caps:backspace
+
+# AUTOSTART
+# set wallpaper using hsetroot
+hsetroot -fill ~/.wallpapers/urban.jpg &
+~/.config/bspwm/autostart &
diff --git a/bspwm/noswallow b/bspwm/noswallow
new file mode 100644
index 0000000..dbfb8f9
--- /dev/null
+++ b/bspwm/noswallow
@@ -0,0 +1 @@
+firefox
diff --git a/bspwm/terminals b/bspwm/terminals
new file mode 100644
index 0000000..4fe8cd5
--- /dev/null
+++ b/bspwm/terminals
@@ -0,0 +1,2 @@
+kitty
+Alacritty
diff --git a/btop/btop.conf b/btop/btop.conf
new file mode 100644
index 0000000..26400f6
--- /dev/null
+++ b/btop/btop.conf
@@ -0,0 +1,248 @@
+#? Config file for btop v. 1.3.2
+
+#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
+#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
+color_theme = "Default"
+
+#* If the theme set background should be shown, set to False if you want terminal background transparency.
+theme_background = False
+
+#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
+truecolor = True
+
+#* Set to true to force tty mode regardless if a real tty has been detected or not.
+#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols.
+force_tty = False
+
+#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
+#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
+#* Use whitespace " " as separator between different presets.
+#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty"
+presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"
+
+#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
+#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
+vim_keys = False
+
+#* Rounded corners on boxes, is ignored if TTY mode is ON.
+rounded_corners = True
+
+#* Default symbols to use for graph creation, "braille", "block" or "tty".
+#* "braille" offers the highest resolution but might not be included in all fonts.
+#* "block" has half the resolution of braille but uses more common characters.
+#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY.
+#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view.
+graph_symbol = "braille"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_cpu = "default"
+
+# Graph symbol to use for graphs in gpu box, "default", "braille", "block" or "tty".
+graph_symbol_gpu = "braille"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_mem = "default"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_net = "default"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_proc = "default"
+
+#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace.
+shown_boxes = "proc mem net cpu"
+
+#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs.
+update_ms = 500
+
+#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
+#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
+proc_sorting = "pid"
+
+#* Reverse sorting order, True or False.
+proc_reversed = False
+
+#* Show processes as a tree.
+proc_tree = False
+
+#* Use the cpu graph colors in the process list.
+proc_colors = True
+
+#* Use a darkening gradient in the process list.
+proc_gradient = True
+
+#* If process cpu usage should be of the core it's running on or usage of the total available cpu power.
+proc_per_core = False
+
+#* Show process memory as bytes instead of percent.
+proc_mem_bytes = True
+
+#* Show cpu graph for each process.
+proc_cpu_graphs = True
+
+#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
+proc_info_smaps = False
+
+#* Show proc box on left side of screen instead of right.
+proc_left = False
+
+#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop).
+proc_filter_kernel = False
+
+#* In tree-view, always accumulate child process resources in the parent process.
+proc_aggregate = False
+
+#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
+#* Select from a list of detected attributes from the options menu.
+cpu_graph_upper = "Auto"
+
+#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available.
+#* Select from a list of detected attributes from the options menu.
+cpu_graph_lower = "Auto"
+
+#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off".
+show_gpu_info = "Auto"
+
+#* Toggles if the lower CPU graph should be inverted.
+cpu_invert_lower = True
+
+#* Set to True to completely disable the lower CPU graph.
+cpu_single_graph = False
+
+#* Show cpu box at bottom of screen instead of top.
+cpu_bottom = False
+
+#* Shows the system uptime in the CPU box.
+show_uptime = True
+
+#* Show cpu temperature.
+check_temp = True
+
+#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors.
+cpu_sensor = "Auto"
+
+#* Show temperatures for cpu cores also if check_temp is True and sensors has been found.
+show_coretemp = True
+
+#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
+#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
+#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries.
+#* Example: "4:0 5:1 6:3"
+cpu_core_map = ""
+
+#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine".
+temp_scale = "celsius"
+
+#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
+base_10_sizes = False
+
+#* Show CPU frequency.
+show_cpu_freq = True
+
+#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
+#* Special formatting: /host = hostname | /user = username | /uptime = system uptime
+clock_format = "%X"
+
+#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort.
+background_update = True
+
+#* Custom cpu model name, empty string to disable.
+custom_cpu_name = ""
+
+#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
+#* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user".
+disks_filter = ""
+
+#* Show graphs instead of meters for memory values.
+mem_graphs = True
+
+#* Show mem box below net box instead of above.
+mem_below_net = False
+
+#* Count ZFS ARC in cached and available memory.
+zfs_arc_cached = True
+
+#* If swap memory should be shown in memory box.
+show_swap = True
+
+#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
+swap_disk = True
+
+#* If mem box should be split to also show disks info.
+show_disks = True
+
+#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
+only_physical = True
+
+#* Read disks list from /etc/fstab. This also disables only_physical.
+use_fstab = True
+
+#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)
+zfs_hide_datasets = False
+
+#* Set to true to show available disk space for privileged users.
+disk_free_priv = False
+
+#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
+show_io_stat = True
+
+#* Toggles io mode for disks, showing big graphs for disk read/write speeds.
+io_mode = False
+
+#* Set to True to show combined read/write io graphs in io mode.
+io_graph_combined = False
+
+#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ".
+#* Example: "/mnt/media:100 /:20 /boot:1".
+io_graph_speeds = ""
+
+#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False.
+net_download = 100
+
+net_upload = 100
+
+#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
+net_auto = True
+
+#* Sync the auto scaling for download and upload to whichever currently has the highest scale.
+net_sync = True
+
+#* Starts with the Network Interface specified here.
+net_iface = ""
+
+#* Show battery stats in top right if battery is present.
+show_battery = True
+
+#* Which battery to use if multiple are present. "Auto" for auto detection.
+selected_battery = "Auto"
+
+#* Show power stats of battery next to charge indicator.
+show_battery_watts = True
+
+#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
+#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
+log_level = "WARNING"
+
+#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
+nvml_measure_pcie_speeds = True
+
+#* Horizontally mirror the GPU graph.
+gpu_mirror_graph = True
+
+#* Custom gpu0 model name, empty string to disable.
+custom_gpu_name0 = ""
+
+#* Custom gpu1 model name, empty string to disable.
+custom_gpu_name1 = ""
+
+#* Custom gpu2 model name, empty string to disable.
+custom_gpu_name2 = ""
+
+#* Custom gpu3 model name, empty string to disable.
+custom_gpu_name3 = ""
+
+#* Custom gpu4 model name, empty string to disable.
+custom_gpu_name4 = ""
+
+#* Custom gpu5 model name, empty string to disable.
+custom_gpu_name5 = ""
diff --git a/btop/btop.log b/btop/btop.log
new file mode 100644
index 0000000..f8d6211
--- /dev/null
+++ b/btop/btop.log
@@ -0,0 +1,24 @@
+
+2024/02/12 (17:24:38) | ===> btop++ v.1.3.1
+2024/02/12 (17:24:38) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
+
+2024/02/12 (19:23:36) | ===> btop++ v.1.3.1
+2024/02/12 (19:23:36) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
+
+2024/02/12 (22:13:50) | ===> btop++ v.1.3.1
+2024/02/12 (22:13:50) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
+
+2024/02/13 (00:27:44) | ===> btop++ v.1.3.1
+2024/02/13 (00:27:44) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
+
+2024/02/13 (00:42:32) | ===> btop++ v.1.3.1
+2024/02/13 (00:42:32) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
+
+2024/02/15 (01:45:13) | ===> btop++ v.1.3.1
+2024/02/15 (01:45:13) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
+
+2024/02/15 (01:46:16) | ===> btop++ v.1.3.1
+2024/02/15 (01:46:16) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
+
+2024/02/15 (02:11:35) | ===> btop++ v.1.3.1
+2024/02/15 (02:11:35) | WARNING: ROCm SMI: Dynamic loading only supported for version 5 and 6
diff --git a/conky/conky-center.conf b/conky/conky-center.conf
new file mode 100644
index 0000000..ca38b57
--- /dev/null
+++ b/conky/conky-center.conf
@@ -0,0 +1,51 @@
+# Conky Configuration
+
+conky.config = {
+ alignment = 'middle_middle',
+ background = false,
+ border_width = 0,
+ cpu_avg_samples = 2,
+ default_color = 'BFDDB2',
+ default_outline_color = 'white',
+ default_shade_color = 'white',
+ double_buffer = true,
+ draw_borders = false,
+ draw_graph_borders = true,
+ draw_outline = false,
+ draw_shades = false,
+ extra_newline = false,
+ font = 'Sarasa Mono K:size=12',
+ gap_x = 0,
+ gap_y = 80,
+ minimum_height = 5,
+ minimum_width = 5,
+ net_avg_samples = 2,
+ no_buffers = true,
+ out_to_console = false,
+ out_to_ncurses = false,
+ out_to_stderr = false,
+ out_to_x = true,
+ own_window = true,
+ own_window_class = 'Conky',
+ own_window_type = 'desktop',
+ own_window = true,
+ own_window_transparent = false,
+ own_window_colour = '#2a2f33',
+ own_window_argb_visual = false,
+ own_window_argb_value = 200,
+ own_window_type = 'desktop',
+ show_graph_range = false,
+ show_graph_scale = false,
+ stippled_borders = 0,
+ update_interval = 3.0,
+ uppercase = false,
+ use_spacer = 'none',
+ use_xft = true,
+}
+
+conky.text = [[
+${font Sarasa Mono K:weight=Regular:size=64}${time %H:%M}${font} ${voffset -50}${alignc}${font MesloLGS NF:size=12} ${font} ${font Sarasa Mono K:weight=Regular:size=14}${time %A, %d %b}${font}
+${offset 215} ${voffset 2}${font MesloLGS NF:size=12} ${font}${mem} ${font MesloLGS NF:size=12} ${font}${cpu cpu0}%
+${offset 215} ${voffset 2}${font MesloLGS NF:size=12} ${font}${font Sarasa Mono K:size=12}${exec vnstat --short | grep "today" | awk '{print $2, $3}'}${font} ${font MesloLGS NF:size=12} ${font}${font Sarasa Mono K:size=12}${texeci 60 exec vnstat --short | grep "today" | awk '{print $5, $6}'}${font}
+${voffset 20}${alignc}${texeci 360 exec curl "https://api.quotable.io/random?maxLength=66" 2> /dev/null | jq '.content'}
+]]
diff --git a/conky/conky-old.conf b/conky/conky-old.conf
new file mode 100644
index 0000000..fc4a997
--- /dev/null
+++ b/conky/conky-old.conf
@@ -0,0 +1,96 @@
+conky.config = {
+
+ --Various settings
+
+ background = true, -- forked to background
+ cpu_avg_samples = 2,
+ diskio_avg_samples = 10,
+ double_buffer = true,
+ if_up_strictness = 'address',
+ net_avg_samples = 2,
+ no_buffers = true,
+ temperature_unit = 'celsius',
+ text_buffer_size = 2048,
+ update_interval = 1,
+ imlib_cache_size = 0, --spotify cove
+
+ --Placement
+
+ alignment = 'bottom_left',
+ gap_x = 15,
+ gap_y = 15,
+ minimum_height = 280,
+ minimum_width = 600,
+ maximum_width = 700,
+
+ --Graphical
+
+ border_inner_margin = 10, -- margin between border and text
+ border_outer_margin = 0, -- margin between border and edge of window
+ border_width = 0, -- border width in pixels
+ default_bar_width = 280,
+ default_bar_height = 10,
+ default_gauge_height = 25,
+ default_gauge_width =40,
+ default_graph_height = 40,
+ default_graph_width = 153,
+ default_shade_color = '#000000',
+ default_outline_color = '#000000',
+ draw_borders = false, --draw borders around text
+ draw_graph_borders = true,
+ draw_shades = false,
+ draw_outline = false,
+ stippled_borders = 0,
+
+ --Textual
+
+ extra_newline = false,
+ format_human_readable = true,
+ font = 'Feena Casual',
+ max_text_width = 0,
+ max_user_text = 16384,
+ override_utf8_locale = true,
+ short_units = true,
+ top_name_width = 21,
+ top_name_verbose = false,
+ uppercase = false,
+ use_spacer = 'none',
+ use_xft = true,
+ xftalpha = 1,
+
+ --Windows
+
+ own_window = true,
+ own_window_argb_value = 00,
+ own_window_argb_visual = true,
+ own_window_class = 'Conky',
+ own_window_colour = '#000000',
+ own_window_hints = 'undecorated,below,sticky,skip_taskbar,skip_pager',
+ own_window_transparent = no,
+ own_window_title = 'system_conky',
+ own_window_type = 'desktop',-- # options are: normal/override/dock/desktop/panel
+
+
+ --Colours
+
+ default_color = '#ECEFF4', -- default color and border color
+ color1 = '#d4be98',
+ color2 = '#ea6962',
+ color3 = '#888888',
+ color4 = '#BDBDBD',
+ color5 = '#CCCCCC',
+ color6 = '#FFFFFF',
+
+ --Signal Colours
+ color7 = '#1F7411', --green
+ color8 = '#FFA726', --orange
+ color9 = '#F1544B', --firebrick
+};
+
+
+conky.text = [[
+${goto 35}${color1}${font Feena Casual:size=100}${time %I }${font Feena Casual:size=45}${color1}${time %A}${color2}${goto 35}${voffset 55}${color2}${font Feena Casual:size=22}${time %d} ${font Feena Casual:size=65}${voffset -15}${color2}${time %B} ${font Feena Casual:size=22}${goto 65}${voffset 34}${color2}${time %Y}${font Feena Casual:size=100}${goto 155}${voffset -54}${color1}${time %M}${font Feena Casual:size=25}${color2} ${time %P}
+
+
+#${goto 60}${voffset -65}${font Feena Casual:size=23} ${time %A} | #${time %B %d %Y}
+]]
diff --git a/conky/conky.conf b/conky/conky.conf
new file mode 100644
index 0000000..76bad48
--- /dev/null
+++ b/conky/conky.conf
@@ -0,0 +1,53 @@
+# Conky Configuration
+
+conky.config = {
+ alignment = 'top_left',
+ background = false,
+ border_width = 0,
+ cpu_avg_samples = 2,
+ default_color = 'aadae0',
+ default_outline_color = 'white',
+ default_shade_color = 'white',
+ double_buffer = true,
+ draw_borders = false,
+ draw_graph_borders = true,
+ draw_outline = false,
+ draw_shades = false,
+ extra_newline = false,
+ font = 'FiraSans:size=12',
+ gap_x = 30,
+ gap_y = 60,
+ minimum_height = 256,
+ minimum_width = 256,
+ net_avg_samples = 2,
+ no_buffers = true,
+ out_to_console = false,
+ out_to_ncurses = false,
+ out_to_stderr = false,
+ out_to_x = true,
+ own_window = true,
+ own_window_class = 'Conky',
+ own_window_type = 'desktop',
+ own_window = true,
+ own_window_transparent = true,
+ own_window_argb_visual = true,
+ own_window_type = 'desktop',
+ show_graph_range = false,
+ show_graph_scale = false,
+ stippled_borders = 0,
+ update_interval = 3.0,
+ uppercase = false,
+ use_spacer = 'none',
+ use_xft = true,
+ xinerama_head = 1;
+}
+
+conky.text = [[
+${image ~/.face -p 0,0 -s 128x128 -n}
+${voffset 90}
+${font FiraSans:weight=Semibold:size=24}Hi, ${exec whoami}${font}
+
+${font FiraSans:weight=Semibold:size=28}It's ${time %H:%M}${font}
+${font FiraSans:weight=Medium:size=20}${time %A}${font}
+${font FiraSans:weight=Regular:size=20}${time %d %b}${font}
+]]
diff --git a/conky/conky_minimal_left.conf b/conky/conky_minimal_left.conf
new file mode 100644
index 0000000..3400c73
--- /dev/null
+++ b/conky/conky_minimal_left.conf
@@ -0,0 +1,49 @@
+# Conky Configuration
+
+conky.config = {
+ alignment = 'bottom_left',
+ background = false,
+ border_width = 0,
+ cpu_avg_samples = 2,
+ default_color = 'BFDDB2',
+ default_outline_color = 'white',
+ default_shade_color = 'white',
+ double_buffer = true,
+ draw_borders = false,
+ draw_graph_borders = true,
+ draw_outline = false,
+ draw_shades = false,
+ extra_newline = false,
+ font = 'Sarasa Mono K:size=12',
+ gap_x = 30,
+ gap_y = 30,
+ minimum_height = 5,
+ minimum_width = 5,
+ net_avg_samples = 2,
+ no_buffers = true,
+ out_to_console = false,
+ out_to_ncurses = false,
+ out_to_stderr = false,
+ out_to_x = true,
+ own_window = true,
+ own_window_class = 'Conky',
+ own_window_type = 'desktop',
+ own_window = true,
+ own_window_transparent = true,
+ own_window_argb_visual = true,
+ own_window_type = 'desktop',
+ show_graph_range = false,
+ show_graph_scale = false,
+ stippled_borders = 0,
+ update_interval = 3.0,
+ uppercase = false,
+ use_spacer = 'none',
+ use_xft = true,
+}
+
+conky.text = [[
+${font Sarasa Mono K:weight=Regular:size=24}${time %H:%M}${font}
+${voffset 2}${font Sarasa Mono K:weight=Regular:size=14}${time %A, %d %b}${font}
+${voffset 2}${font MesloLGS NF:size=12} ${font}${mem} ${font MesloLGS NF:size=12} ${font}${cpu cpu0}%
+${voffset 2}${font MesloLGS NF:size=12} ${font}${font Sarasa Mono K:size=12}${exec vnstat --short | grep "today" | awk '{print $2, $3}'}${font} ${font MesloLGS NF:size=12} ${font}${font Sarasa Mono K:size=12}${texeci 60 exec vnstat --short | grep "today" | awk '{print $5, $6}'}${font}
+]]
diff --git a/conky/conky_notes.conf b/conky/conky_notes.conf
new file mode 100644
index 0000000..c30ff90
--- /dev/null
+++ b/conky/conky_notes.conf
@@ -0,0 +1,90 @@
+conky.config = {
+
+ --Various settings
+
+ background = true, -- forked to background
+ cpu_avg_samples = 2,
+ diskio_avg_samples = 10,
+ double_buffer = true,
+ if_up_strictness = 'address',
+ net_avg_samples = 2,
+ no_buffers = true,
+ temperature_unit = 'celsius',
+ text_buffer_size = 2048,
+ update_interval = 2,
+ imlib_cache_size = 0,
+
+ --Placement
+
+ alignment = 'top_right',
+ gap_x = 30,
+ gap_y = 50,
+ minimum_height = 200,
+ minimum_width = 200,
+ maximum_width = 550,
+
+ --Graphical
+
+ border_inner_margin = 10,
+
+ -- margin between border and text
+ border_outer_margin = 0,
+ -- margin between border and edge of window
+ border_width = 0,
+ -- border width in pixels
+ default_bar_width = 280,
+ default_bar_height = 2,
+ default_gauge_height = 25,
+ default_gauge_width =40,
+ default_graph_height = 40,
+ default_graph_width = 153,
+ default_shade_color = '#000000',
+ default_outline_color = '#828282',
+ draw_borders = false,
+ --draw borders around text
+ draw_graph_borders = true,
+ draw_shades = false,
+ draw_outline = false,
+ stippled_borders = 0,
+
+ --Textual
+
+ extra_newline = false,
+ format_human_readable = true,
+ font = 'Open Sans',
+ max_text_width = 0,
+ max_user_text = 16384,
+ override_utf8_locale = false,
+ short_units = true,
+ top_name_width = 21,
+ top_name_verbose = false,
+ uppercase = false,
+ use_spacer = 'none',
+ use_xft = true,
+ xftalpha = 1,
+
+ --Windows
+
+ own_window = true,
+ own_window_argb_value = 0,
+ own_window_argb_visual = true,
+ own_window_class = 'Conky',
+ own_window_colour = '#000000',
+ own_window_hints = 'undecorated,below,sticky,skip_taskbar,skip_pager',
+ own_window_transparent = yes,
+ own_window_title = 'Conky',
+ own_window_type = 'desktop',
+
+
+ --Colors
+
+ default_color = '#BFDDB2',
+ color1 = '#BFDDB2',
+};
+
+
+conky.text = [[
+${alignc}${font Sarasa Mono K:weight=Regular:size=24}Todo${color0}${font}
+${voffset 15}${font Sarasa Mono K:weight=Light:size=18}${color1}\
+${exec awk '{printf "%d. %s\n", NR, $0}' < "$HOME/todo.md" | fmt --width=30 -s}${color1}${font}
+]]
diff --git a/conky/conky_stats.conf b/conky/conky_stats.conf
new file mode 100644
index 0000000..bf46c59
--- /dev/null
+++ b/conky/conky_stats.conf
@@ -0,0 +1,50 @@
+# Conky Configuration
+
+conky.config = {
+ alignment = 'bottom_right',
+ background = false,
+ border_width = 0,
+ cpu_avg_samples = 2,
+ default_color = 'aadae0',
+ default_outline_color = 'white',
+ default_shade_color = 'white',
+ double_buffer = true,
+ draw_borders = false,
+ draw_graph_borders = true,
+ draw_outline = false,
+ draw_shades = false,
+ extra_newline = false,
+ font = 'FiraSans:size=12',
+ gap_x = 30,
+ gap_y = 30,
+ minimum_height = 5,
+ minimum_width = 5,
+ net_avg_samples = 2,
+ no_buffers = true,
+ out_to_console = false,
+ out_to_ncurses = false,
+ out_to_stderr = false,
+ out_to_x = true,
+ own_window = true,
+ own_window_class = 'Conky',
+ own_window_type = 'desktop',
+ own_window = true,
+ own_window_transparent = true,
+ own_window_argb_visual = true,
+ own_window_type = 'desktop',
+ show_graph_range = false,
+ show_graph_scale = false,
+ stippled_borders = 0,
+ update_interval = 3.0,
+ uppercase = false,
+ use_spacer = 'none',
+ use_xft = true,
+ xinerama_head = 1;
+}
+
+conky.text = [[
+${font Symbols Nerd Font:size=12}${font} ${mem}
+${font Symbols Nerd Font:size=12}${font} ${cpu cpu0}%
+${font Symbols Nerd Font:size=12}${font} ${exec vnstat --short | grep "today" | awk '{print $2, $3}'} ${font Symbols Nerd Font:size=12}${font} ${texeci 60 exec vnstat --short | grep "today" | awk '{print $5, $6}'}
+]]
+
diff --git a/conky/start-conky.desktop b/conky/start-conky.desktop
new file mode 100755
index 0000000..46638e7
--- /dev/null
+++ b/conky/start-conky.desktop
@@ -0,0 +1,13 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Type=Application
+Exec=conky
+Icon=conky
+X-GNOME-Autostart-enabled=true
+X-MATE-Autostart-enabled=true
+NoDisplay=false
+Hidden=false
+Name[en_US]=start-conky
+Comment[en_US]=
+X-GNOME-Autostart-Delay=0
diff --git a/conky/start-conky.sh b/conky/start-conky.sh
new file mode 100755
index 0000000..f78d51d
--- /dev/null
+++ b/conky/start-conky.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+conky -c $HOME/.config/conky/conky.conf &
+conky -c $HOME/.config/conky/conky_stats.conf &
diff --git a/conky/system-all.conf b/conky/system-all.conf
new file mode 100644
index 0000000..6d2b791
--- /dev/null
+++ b/conky/system-all.conf
@@ -0,0 +1,141 @@
+use_xft yes
+xftfont DejaVu Sans:size=12
+xftalpha 0.8
+text_buffer_size 2048
+
+# Update interval in seconds
+update_interval 1
+
+# This is the number of times Conky will update before quitting.
+total_run_times 0
+
+own_window yes
+own_window_transparent yes
+#own_window_type override
+#own_window_type desktop
+own_window_type desktop #use this if you want a nice shadow to appear around conky
+
+# If own_window is yes, these window manager hints may be used
+own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager
+
+# Use double buffering (reduces flicker, may not work for everyone)
+double_buffer yes
+
+# Minimum size of text area
+minimum_size 220 0
+#maximum_width 200
+
+# Draw shades?
+draw_shades no
+
+# Draw outlines?
+draw_outline no
+
+# Draw borders around text
+draw_borders no
+
+# Stippled borders?
+stippled_borders 0
+
+# border margins
+border_margin 5
+
+# border width
+border_width 1
+
+# Default colors and also border colors
+default_color #5d5861
+#default_shade_color black
+#default_outline_color grey
+own_window_colour 000000
+
+# Text alignment, other possible values are commented
+#alignment top_left
+alignment top_left
+#alignment bottom_left
+#alignment bottom_right
+#alignment middle_right
+
+# Gap between borders of screen and text
+# same thing as passing -x at command line
+gap_x 20
+gap_y 50
+
+# Subtract file system buffers from used memory?
+no_buffers yes
+
+# set to yes if you want all text to be in uppercase
+uppercase no
+
+# number of cpu samples to average
+# set to 1 to disable averaging
+cpu_avg_samples 2
+
+# number of net samples to average
+# set to 1 to disable averaging
+net_avg_samples 2
+
+# Force UTF8? note that UTF8 support required XFT
+override_utf8_locale yes
+
+# Add spaces to keep things from moving about? This only affects certain objects.
+use_spacer none
+
+own_window_argb_value 0
+own_window_argb_visual yes
+TEXT
+${font Zekton:Regular:size=11}SYSTEM ${hr 2}
+#Command exec cut .. know the distribution
+${font Zekton:Regular:size=12}${alignc 0}${exec cut -d '\' -f 1 /etc/issue}
+${voffset -10}${font OpenLogos:size=40}
+#Hostname
+${voffset -85}${alignc =10}${font Capture it:size=16}${nodename}
+#PC
+${font Zekton:Regular:size=12}${alignc 0}ASUS
+${font Zekton:Regular:size=12}${alignc 0}
+${font DejaVu Sans:Regular:size=13}K${font} Kernel: ${alignr}${kernel}
+
+${font StyleBats:Regular:size=16}A${font} CPU 1: ${cpu cpu1}% ${alignr}${cpubar cpu1 8,60}
+${font StyleBats:Regular:size=16}A${font} CPU 2: ${cpu cpu2}% ${alignr}${cpubar cpu2 8,60}
+
+${font StyleBats:Regular:size=16}g${font} RAM: $mem $memperc% ${alignr}${membar 8,60}
+${font StyleBats:Regular:size=16}j${font} SWAP: $swap $swapperc% ${alignr}${swapbar 8,60}
+
+${font Webdings:Regular:size=16}~${font}Battery: ${battery_percent BAT0}% ${alignr}${battery_bar 8,60 BAT0}
+${font StyleBats:Regular:size=16}q${font} Uptime: ${alignr}${uptime}
+
+${font Zekton:Regular:size=11}DATE ${hr 2}
+
+${alignc 0}${font Capture it:size=32}${time %H:%M}${font Zekton:size=10}
+${voffset 2}${alignc}${time %A, %d %B %Y}
+
+${font Zekton:Regular:size=11}HD ${hr 2}
+
+${voffset 4}${font Pie charts for maps:Regular:size=14}7${font} ${voffset -5}Root:
+${voffset 4}${fs_used /}/${fs_size /} ${alignr}${fs_bar 8,60 /}
+
+${font Pie charts for maps:Regular:size=14}m${font} ${voffset -5}Home:
+${voffset 4}${fs_free /home}/${fs_size /home} ${alignr}${fs_bar 8,60 /home}
+
+${font Zekton:Regular:size=11}NETWORK ${hr 2}
+#Aquí tengo que aclarar algo mis interfaces de red son
+#Wired = enp2s0 and WiFi = wlp3s0
+
+${if_existing /proc/net/route enp2s0}
+
+${voffset -15}${alignc 0}${font Capture it:size=12}W i r e d
+${font PizzaDude Bullets:size=14}O${font} Up: ${upspeed enp2s0}${alignr}${upspeedgraph enp2s0 8,60 black black}
+${voffset 4}${font PizzaDude Bullets:size=14}U${font} Down: ${downspeed enp2s0}${alignr}${downspeedgraph enp2s0 8,60 black black}
+${voffset 4}${font PizzaDude Bullets:size=14}N${font} Upload: ${alignr}${totalup enp2s0}
+${voffset 4}${font PizzaDude Bullets:size=14}T${font} Dowload: ${alignr}${totaldown enp2s0}
+${else}${if_existing /proc/net/route wlp3s0}${alignc 0}${font Capture it:size=12}W i F i
+${font}${alignc}SSID: ${wireless_essid wlp3s0}
+
+Signal: ${wireless_link_qual_perc wlp3s0}% ${alignr}${wireless_link_bar 8,60 wlp3s0}
+
+${font PizzaDude Bullets:size=14}O${font} Up: ${upspeed wlp3s0}${alignr}${upspeedgraph wlp3s0 8,60 black black}
+${voffset 4}${font PizzaDude Bullets:size=14}U${font} Down: ${downspeed wlp3s0}${alignr}${downspeedgraph wlp3s0 8,60 black black}
+
+${voffset 4}${font PizzaDude Bullets:size=14}N${font} Upload: ${alignr}${totalup wlp3s0}
+${voffset 4}${font PizzaDude Bullets:size=14}T${font} Download: ${alignr}${totaldown wlp3s0}
+${endif}
diff --git a/conky/test.conf b/conky/test.conf
new file mode 100644
index 0000000..27152dd
--- /dev/null
+++ b/conky/test.conf
@@ -0,0 +1,42 @@
+conky.config = {
+ alignment = 'top_right',
+ background = false,
+ border_width = 0,
+ cpu_avg_samples = 2,
+ default_color = 'BFDDB2',
+ default_outline_color = 'white',
+ default_shade_color = 'white',
+ double_buffer = true,
+ draw_borders = false,
+ draw_graph_borders = true,
+ draw_outline = false,
+ draw_shades = false,
+ extra_newline = false,
+ font = 'Sarasa Fixed K :size=18',
+ gap_x = 50,
+ gap_y = 50,
+ minimum_height = 5,
+ minimum_width = 5,
+ net_avg_samples = 2,
+ no_buffers = true,
+ out_to_console = false,
+ out_to_ncurses = false,
+ out_to_stderr = false,
+ out_to_x = true,
+ own_window = true,
+ own_window_class = 'Conky',
+ own_window_type = 'desktop',
+ own_window = true,
+ own_window_transparent = true,
+ own_window_argb_visual = true,
+ own_window_type = 'desktop',
+ show_graph_range = false,
+ show_graph_scale = false,
+ stippled_borders = 0,
+ update_interval = 1.0,
+ uppercase = false,
+ use_spacer = 'none',
+ use_xft = true
+}
+conky.text=[[
+]]
diff --git a/dunst/dunstrc b/dunst/dunstrc
new file mode 100644
index 0000000..39296fd
--- /dev/null
+++ b/dunst/dunstrc
@@ -0,0 +1,63 @@
+[global]
+ monitor = 0
+ follow = keyboard
+ geometry = "300x10-8+34"
+ indicate_hidden = yes
+ shrink = true
+ transparency = 6
+ notification_height = 0
+ separator_height = 20
+ padding = 20
+ horizontal_padding = 10
+ frame_width = 1
+ frame_color = "#ffffff"
+ separator_color = auto
+ font = FiraSans
+ markup = full
+ format = "<b>%s</b> %p\n<i>%b</i>"
+ alignment = left
+ show_age_threshold = 60
+ word_wrap = yes
+ ellipsize = middle
+ ignore_newline = no
+ stack_duplicates = true
+ hide_duplicate_count = false
+ show_indicators = yes
+ icon_position = left
+ max_icon_size = 48
+ icon_path = /usr/share/icons/Papirus/16x16/status/:/usr/share/icons/Papirus/16x16/devices/:/usr/share/icons/Papirus/16x16/apps/
+ sticky_history = yes
+ history_length = 20
+ always_run_script = true
+ startup_notification = false
+ browser = /usr/bin/firefox -new-tab
+ verbosity = mesg
+ corner_radius = 0
+ force_xinerama = false
+ mouse_left_click = close_current
+ mouse_middle_click = do_action
+ mouse_right_click = close_all
+
+[shortcuts]
+ close = ctrl+space
+ close_all = ctrl+shift+space
+ history = ctrl+grave
+ context = ctrl+shift+period
+
+[urgency_low]
+timeout = 4
+background = "#2a2f33"
+foreground = "#aadae0"
+frame_color = "#aadae0"
+
+[urgency_normal]
+timeout = 8
+background = "#2a2f33"
+foreground = "#baeff6"
+frame_color = "#baeff6"
+
+[urgency_critical]
+timeout = 0
+background = "#2a2f33"
+foreground = "#ffbaba"
+frame_color = "#ffbaba"
diff --git a/lf/lfrc b/lf/lfrc
new file mode 100644
index 0000000..df6ee39
--- /dev/null
+++ b/lf/lfrc
@@ -0,0 +1,187 @@
+# Basic Settings
+set hidden true
+# set drawbox true
+# set icons false
+set ignorecase true
+
+# Custom Functions
+cmd open ${{
+ case $(file --mime-type "$f" -bL) in
+ text/*|application/json) $EDITOR "$f";;
+ *) xdg-open "$f" ;;
+ esac
+}}
+
+cmd mkdir ${{
+ printf "Directory Name: "
+ read ans
+ mkdir $ans
+}}
+
+cmd mkfile ${{
+ printf "File Name: "
+ read ans
+ $EDITOR $ans
+}}
+
+cmd chmod ${{
+ printf "Mode Bits: "
+ read ans
+
+ for file in "$fx"
+ do
+ chmod $ans $file
+ done
+
+ lf -remote 'send reload'
+}}
+
+cmd sudomkfile ${{
+ printf "File Name: "
+ read ans
+ sudo $EDITOR $ans
+}}
+
+cmd setwallpaper %cp "$f" ~/.config/wallpaper.png && xwallpaper --zoom "$f"
+
+cmd fzf_jump ${{
+ res="$(find . -maxdepth 3 | fzf --reverse --header='Jump to location')"
+ if [ -f "$res" ]; then
+ cmd="select"
+ elif [ -d "$res" ]; then
+ cmd="cd"
+ fi
+ lf -remote "send $id $cmd \"$res\""
+}}
+
+cmd broot_jump ${{
+ f=$(mktemp)
+ res="$(broot --outcmd $f && cat $f | sed 's/cd //')"
+ rm -f "$f"
+ if [ -f "$res" ]; then
+ cmd="select"
+ elif [ -d "$res" ]; then
+ cmd="cd"
+ fi
+ lf -remote "send $id $cmd \"$res\""
+}}
+
+cmd dragon %dragon -a -x $fx
+cmd dragon-stay %dragon -a $fx
+cmd dragon-individual %dragon $fx
+cmd cpdragon %cpdragon
+cmd mvdragon %mvdragon
+cmd dlfile %dlfile
+
+# Archive bindings
+cmd unarchive ${{
+ case "$f" in
+ *.zip) unzip "$f" ;;
+ *.tar.gz) tar -xzvf "$f" ;;
+ *.tar.bz2) tar -xjvf "$f" ;;
+ *.tar) tar -xvf "$f" ;;
+ *) echo "Unsupported format" ;;
+ esac
+}}
+
+cmd zip %zip -r "$f" "$f"
+cmd tar %tar cvf "$f.tar" "$f"
+cmd targz %tar cvzf "$f.tar.gz" "$f"
+cmd tarbz2 %tar cjvf "$f.tar.bz2" "$f"
+
+# Trash cli bindings
+cmd trash ${{
+ files=$(printf "$fx" | tr '\n' ';')
+ while [ "$files" ]; do
+ # extract the substring from start of string up to delimiter.
+ # this is the first "element" of the string.
+ file=${files%%;*}
+
+ trash-put "$(basename "$file")"
+ # if there's only one element left, set `files` to an empty string.
+ # this causes us to exit this `while` loop.
+ # else, we delete the first "element" of the string from files, and move onto the next.
+ if [ "$files" = "$file" ]; then
+ files=''
+ else
+ files="${files#*;}"
+ fi
+ done
+}}
+
+cmd clear_trash %trash-empty
+
+cmd restore_trash ${{
+ trash-restore
+}}
+
+cmd stripspace %stripspace "$f"
+
+# Bindings
+# Remove some defaults
+map m
+map o
+map n
+map "'"
+map '"'
+map d
+map c
+map e
+map f
+
+# File Openers
+map ee $$EDITOR "$f"
+map u $view "$f"
+
+# Archive Mappings
+map az zip
+map at tar
+map ag targz
+map ab targz
+map au unarchive
+
+# Trash Mappings
+map dd trash
+map tc clear_trash
+map tr restore_trash
+
+# Broot Mapping
+map f broot_jump
+
+# Dragon Mapping
+map dr dragon
+map ds dragon-stay
+map di dragon-individual
+map dm mvdragon
+map dc cpdragon
+map dl dlfile
+
+map ss stripspace
+
+# Basic Functions
+map . set hidden!
+map DD delete
+map p paste
+map x cut
+map y copy
+map <enter> open
+map mf mkfile
+map mr sudomkfile
+map md mkdir
+map ms $mkscript
+map ch chmod
+map bg setwallpaper
+map o open_config
+map br $vimv $fx
+map r rename
+map H top
+map L bottom
+map R reload
+map C clear
+map U unselect
+
+
+map gD cd ~/Downloads
+map ge cd ~/Desktop
+
+map \;j cd ~
diff --git a/mpd/mpd.conf b/mpd/mpd.conf
new file mode 100644
index 0000000..884699d
--- /dev/null
+++ b/mpd/mpd.conf
@@ -0,0 +1,31 @@
+# Recommended location for database
+db_file "~/.local/share/mpd/database"
+
+# Logs to systemd journal
+log_file "syslog"
+
+# The music directory is by default the XDG directory, uncomment to amend and choose a different directory
+music_directory "/data/Music/"
+
+# Uncomment to refresh the database whenever files in the music_directory are changed
+auto_update "yes"
+auto_update_depth "1"
+restore_paused "yes"
+
+# Uncomment to enable the functionalities
+playlist_directory "~/.local/share/mpd/playlists"
+pid_file "~/.local/share/mpd/pid"
+state_file "~/.local/share/mpd/state"
+sticker_file "~/.local/share/mpd/sticker.sql"
+
+audio_output {
+ type "fifo"
+ name "my_fifo"
+ path "/tmp/mpd.fifo"
+ format "44100:16:2"
+}
+
+audio_output {
+ type "pulse"
+ name "pulse audio"
+}
diff --git a/mpv/input.conf b/mpv/input.conf
new file mode 100644
index 0000000..a475f10
--- /dev/null
+++ b/mpv/input.conf
@@ -0,0 +1,132 @@
+# vim: syntax=config
+
+
+# Mouse
+
+MOUSE_BTN2 cycle pause
+MOUSE_BTN3 ignore
+MOUSE_BTN4 ignore
+MOUSE_BTN5 ignore
+MOUSE_BTN6 ignore
+
+
+
+# Trackpad
+
+AXIS_UP ignore
+AXIS_DOWN ignore
+AXIS_LEFT ignore
+AXIS_RIGHT ignore
+
+
+
+# Arrow/navigation keys
+
+RIGHT osd-msg-bar seek +5 relative+keyframes
+LEFT osd-msg-bar seek -5 relative+keyframes
+SHIFT+RIGHT osd-msg-bar seek +1 relative+exact
+SHIFT+LEFT osd-msg-bar seek -1 relative+exact
+CTRL+RIGHT frame-step ; show-text "Frame: ${estimated-frame-number} / ${estimated-frame-count}"
+CTRL+LEFT frame-back-step ; show-text "Frame: ${estimated-frame-number} / ${estimated-frame-count}"
+
+UP add volume +2 ; show-text "Volume: ${volume}"
+DOWN add volume -2 ; show-text "Volume: ${volume}"
+SHIFT+UP osd-msg-bar seek +120 relative+keyframes
+SHIFT+DOWN osd-msg-bar seek -120 relative+keyframes
+
+PGUP osd-msg-bar seek +600 relative+keyframes
+PGDWN osd-msg-bar seek -600 relative+keyframes
+
+ALT+RIGHT sub-seek +1 ; show-text "Sub Seek +1"
+ALT+LEFT sub-seek -1 ; show-text "Sub Seek -1"
+
+#ALT+RIGHT add video-pan-x -0.01
+#ALT+LEFT add video-pan-x +0.01
+#ALT+UP add video-pan-y +0.01
+#ALT+DOWN add video-pan-y -0.01
+
+#META+RIGHT add video-zoom +0.05
+#META+LEFT add video-zoom -0.05
+#META+UP add video-zoom +0.05
+#META+DOWN add video-zoom -0.05
+
+
+
+# ` [1] [2] [3] [4] [5] [6] [7] [8] [9] [0] - =
+# ~ [!] @ # $ % ^ & * ( ) _ +
+
+1 add contrast -1 ; show-text "Contrast: ${contrast}"
+2 add contrast +1 ; show-text "Contrast: ${contrast}"
+3 add brightness -1 ; show-text "Brightness: ${brightness}"
+4 add brightness +1 ; show-text "Brightness: ${brightness}"
+5 add gamma -1 ; show-text "Gamma: ${gamma}"
+6 add gamma +1 ; show-text "Gamma: ${gamma}"
+7 add saturation -1 ; show-text "Saturation: ${saturation}"
+8 add saturation +1 ; show-text "Saturation: ${saturation}"
+
+9 add volume -2 ; show-text "Volume: ${volume}"
+0 add volume +2 ; show-text "Volume: ${volume}"
+
+! cycle ontop
+
+# CTRL+1 show-text "Shaders: ${glsl-shaders}"
+# CTRL+2 change-list glsl-shaders append "~/.mpv/shaders/ravu-r3-rgb.hook"
+# CTRL+3 change-list glsl-shaders append "~/.mpv/shaders/FSRCNNX_x2_8-0-4-1.glsl"
+# CTRL+4 change-list glsl-shaders toggle "~/.mpv/shaders/KrigBilateral.glsl"
+# CTRL+5 change-list glsl-shaders toggle "~/.mpv/shaders/SSimSuperRes.glsl"
+# CTRL+6 change-list glsl-shaders toggle "~/.mpv/shaders/SSimDownscaler.glsl"
+# CTRL+7 change-list glsl-shaders toggle "~/.mpv/shaders/FineSharp.glsl"
+# CTRL+8 change-list glsl-shaders toggle "~/.mpv/shaders/adaptive-sharpen.glsl"
+# CTRL+0 set glsl-shaders ""
+
+
+Q quit
+q script-binding auto_save_state/quit-watch-later-conditional
+
+
+
+
+# [esc] [space] [backspace]
+# [tab] [enter]
+
+
+ESC cycle fullscreen
+SPACE cycle pause
+IDEOGRAPHIC_SPACE cycle pause
+TAB cycle mute
+ENTER show-progress
+
+# Numpad
+
+KP0 ignore
+KP1 ignore
+KP2 ignore
+KP3 ignore
+KP4 ignore
+KP5 ignore
+KP6 ignore
+KP7 ignore
+KP8 ignore
+KP9 ignore
+KP_DEC ignore
+KP_ENTER ignore
+
+
+
+# Media Keys
+
+POWER script-binding auto_save_state/quit-watch-later-conditional
+MENU show-progress
+PLAY cycle pause
+PAUSE cycle pause
+PLAYPAUSE cycle pause
+STOP script-binding auto_save_state/quit-watch-later-conditional
+FORWARD osd-msg-bar seek +5 relative keyframes
+REWIND osd-msg-bar seek -5 relative keyframes
+NEXT script-binding betterchapters/chapterplaylist-next #; show-text "${?chapter:Chapter: ${chapter}}"
+PREV script-binding betterchapters/chapterplaylist-prev #; show-text "${?chapter:Chapter: ${chapter}}"
+VOLUME_UP add volume +2 ; show-text "Volume: ${volume}"
+VOLUME_DOWN add volume -2 ; show-text "Volume: ${volume}"
+MUTE cycle mute
+CLOSE_WIN quit
+a script-message cycle-profiles "low-quality;mid-quality;high-quality"
diff --git a/mpv/lua-modules/auto-profiles-functions.lua b/mpv/lua-modules/auto-profiles-functions.lua
new file mode 100644
index 0000000..539a84d
--- /dev/null
+++ b/mpv/lua-modules/auto-profiles-functions.lua
@@ -0,0 +1,122 @@
+local utils = require 'mp.utils'
+local msg = require 'mp.msg'
+
+-- Quality levels
+local HIGH = "High Quality"
+local MID = "Mid Quality"
+local LOW = "Low Quality"
+-- Platform
+local is_linux, is_osx, is_windows = false, false, false
+local exec_cache = {}
+
+
+local function exec(process, force_exec)
+ local key = table.concat(process, " ")
+ if force_exec or exec_cache[key] == nil or exec_cache[key].error then
+ local p_ret = utils.subprocess({args = process, playback_only = false})
+ exec_cache[key] = p_ret
+ if p_ret.error and p_ret.error == "init" then
+ msg.error("executable not found: " .. key)
+ end
+ return p_ret
+ else
+ return exec_cache[key]
+ end
+end
+
+
+local function get_platform()
+ local is_linux = false
+ local is_osx = false
+ local is_windows = type(package) == 'table' and type(package.config) == 'string' and string.sub(package.config, 1, 1) == '\\'
+ if not is_windows then
+ uname = exec({"uname"})
+ is_linux = uname.stdout == "Linux\n"
+ is_osx = uname.stdout == "Darwin\n"
+ end
+ return is_linux, is_osx, is_windows
+end
+
+
+function on_battery()
+ if is_osx then
+ local bat = exec({"/usr/bin/pmset", "-g", "batt"}, true)
+ return string.match(bat.stdout, "Now drawing from 'Battery Power'")
+ elseif is_linux then
+ local res = exec({"/bin/cat", "/sys/class/power_supply/AC0/online"}, true)
+ return res.stdout == "0\n"
+ elseif is_windows then
+ msg.warn("on_battery() not implemented on windows. PRs welcome")
+ end
+ msg.warn("assuming AC power")
+ return false
+end
+
+
+-- This is a crude attempt to figure out if a (beefy) dedicated GPU is present.
+-- Can't identify the actually used GPU but works when we assume that an existing
+-- dedicated GPU can/will be used in case we are drawing power from AC.
+ -- local r = exec({"lshw", "-C", 'display'})
+ -- local r = exec({"nvidia-smi"})
+ -- r.stdout = string.lower(r.stdout)
+ -- return string.find(r.stdout, "amd") ~= nil or string.find(r.stdout, "nvidia") ~= nil
+ -- return string.find(r.stdout, "mpv") ~= nil
+function dedicated_gpu()
+ if is_osx then
+ local r = exec({"system_profiler", "SPDisplaysDataType"})
+ return string.find(r.stdout, "Chipset Model: Radeon") ~= nil or string.find(r.stdout, "Chipset Model: NVIDIA GeForce") ~= nil
+ -- Untested
+ elseif is_linux then
+ local nv = os.getenv("__NV_PRIME_RENDER_OFFLOAD")
+ return nv ~= nil
+ elseif is_windows then
+ msg.warn("dedicated_gpu() not implemented on windows. PRs welcome")
+ end
+ msg.warn("assuming dedicated GPU")
+ return true
+end
+
+
+local function determine_level(width, height, fps)
+
+ if on_battery() then
+ return LOW
+ end
+
+ if dedicated_gpu() then
+ if width > 4096 then
+ return MID
+ end
+ if width > 1920 and fps > 61 then
+ return MID
+ end
+ return HIGH
+ else
+ if width > 1919 then
+ return LOW
+ end
+ if fps > 58 then
+ return LOW
+ end
+ return MID
+ end
+
+ msg.error("could not determine profile")
+ msg.warn("assuming HIGH")
+ return HIGH
+end
+
+
+local function is_level(level)
+ return function(width, height, fps)
+ local l = determine_level(width, height, fps)
+ return l == level
+ end
+end
+
+
+is_high = is_level(HIGH)
+is_mid = is_level(MID)
+is_low = is_level(LOW)
+
+is_linux, is_osx, is_windows = get_platform()
diff --git a/mpv/lua-modules/scroll-list.lua b/mpv/lua-modules/scroll-list.lua
new file mode 100644
index 0000000..0666f5a
--- /dev/null
+++ b/mpv/lua-modules/scroll-list.lua
@@ -0,0 +1,236 @@
+local mp = require 'mp'
+local scroll_list = {
+ global_style = [[]],
+ header_style = [[{\q2\fs35\c&00ccff&}]],
+ list_style = [[{\q2\fs25\c&Hffffff&}]],
+ wrapper_style = [[{\c&00ccff&\fs16}]],
+ cursor_style = [[{\c&00ccff&}]],
+ selected_style = [[{\c&Hfce788&}]],
+
+ cursor = [[➤\h]],
+ indent = [[\h\h\h\h]],
+
+ num_entries = 16,
+ wrap = false,
+ empty_text = "no entries"
+}
+
+--formats strings for ass handling
+--this function is taken from https://github.com/mpv-player/mpv/blob/master/player/lua/console.lua#L110
+function scroll_list.ass_escape(str)
+ str = str:gsub('\\', '\\\239\187\191')
+ str = str:gsub('{', '\\{')
+ str = str:gsub('}', '\\}')
+ -- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of
+ -- consecutive newlines
+ str = str:gsub('\n', '\239\187\191\\N')
+ -- Turn leading spaces into hard spaces to prevent ASS from stripping them
+ str = str:gsub('\\N ', '\\N\\h')
+ str = str:gsub('^ ', '\\h')
+ return str
+end
+--appends the entered text to the overlay
+function scroll_list:append(text)
+ if text == nil then return end
+ self.ass.data = self.ass.data .. text
+ end
+
+--appends a newline character to the osd
+function scroll_list:newline()
+ self.ass.data = self.ass.data .. '\\N'
+end
+
+--re-parses the list into an ass string
+--if the list is closed then it flags an update on the next open
+function scroll_list:update()
+ if self.hidden then self.flag_update = true
+ else self:update_ass() end
+end
+
+--prints the header to the overlay
+function scroll_list:format_header()
+ self:append(self.header_style)
+ self:append(self.header)
+ self:newline()
+end
+
+--formats each line of the list and prints it to the overlay
+function scroll_list:format_line(index, item)
+ self:append(self.list_style)
+
+ if index == self.selected then self:append(self.cursor_style..self.cursor..self.selected_style)
+ else self:append(self.indent) end
+
+ self:append(item.style)
+ self:append(item.ass)
+ self:newline()
+end
+
+--refreshes the ass text using the contents of the list
+function scroll_list:update_ass()
+ self.ass.data = self.global_style
+ self:format_header()
+
+ if #self.list < 1 then
+ self:append(self.empty_text)
+ self.ass:update()
+ return
+ end
+
+ local start = 1
+ local finish = start+self.num_entries-1
+
+ --handling cursor positioning
+ local mid = math.ceil(self.num_entries/2)+1
+ if self.selected+mid > finish then
+ local offset = self.selected - finish + mid
+
+ --if we've overshot the end of the list then undo some of the offset
+ if finish + offset > #self.list then
+ offset = offset - ((finish+offset) - #self.list)
+ end
+
+ start = start + offset
+ finish = finish + offset
+ end
+
+ --making sure that we don't overstep the boundaries
+ if start < 1 then start = 1 end
+ local overflow = finish < #self.list
+ --this is necessary when the number of items in the dir is less than the max
+ if not overflow then finish = #self.list end
+
+ --adding a header to show there are items above in the list
+ if start > 1 then self:append(self.wrapper_style..(start-1)..' item(s) above\\N\\N') end
+
+ for i=start, finish do
+ self:format_line(i, self.list[i])
+ end
+
+ if overflow then self:append('\\N'..self.wrapper_style..#self.list-finish..' item(s) remaining') end
+ self.ass:update()
+end
+
+--moves the selector down the list
+function scroll_list:scroll_down()
+ if self.selected < #self.list then
+ self.selected = self.selected + 1
+ self:update_ass()
+ elseif self.wrap then
+ self.selected = 1
+ self:update_ass()
+ end
+end
+
+--moves the selector up the list
+function scroll_list:scroll_up()
+ if self.selected > 1 then
+ self.selected = self.selected - 1
+ self:update_ass()
+ elseif self.wrap then
+ self.selected = #self.list
+ self:update_ass()
+ end
+end
+
+--adds the forced keybinds
+function scroll_list:add_keybinds()
+ for _,v in ipairs(self.keybinds) do
+ mp.add_forced_key_binding(v[1], 'dynamic/'..self.ass.id..'/'..v[2], v[3], v[4])
+ end
+end
+
+--removes the forced keybinds
+function scroll_list:remove_keybinds()
+ for _,v in ipairs(self.keybinds) do
+ mp.remove_key_binding('dynamic/'..self.ass.id..'/'..v[2])
+ end
+end
+
+--opens the list and sets the hidden flag
+function scroll_list:open_list()
+ self.hidden = false
+ if not self.flag_update then self.ass:update()
+ else self.flag_update = false ; self:update_ass() end
+end
+
+--closes the list and sets the hidden flag
+function scroll_list:close_list()
+ self.hidden = true
+ self.ass:remove()
+end
+
+--modifiable function that opens the list
+function scroll_list:open()
+ self:open_list()
+ self:add_keybinds()
+end
+
+--modifiable function that closes the list
+function scroll_list:close ()
+ self:remove_keybinds()
+ self:close_list()
+end
+
+--toggles the list
+function scroll_list:toggle()
+ if self.hidden then self:open()
+ else self:close() end
+end
+
+--clears the list in-place
+function scroll_list:clear()
+ local i = 1
+ while self.list[i] do
+ self.list[i] = nil
+ i = i + 1
+ end
+end
+
+--added alias for ipairs(list.list) for lua 5.1
+function scroll_list:ipairs()
+ return ipairs(self.list)
+end
+
+--append item to the end of the list
+function scroll_list:insert(item)
+ self.list[#self.list + 1] = item
+end
+
+local metatable = {
+ __index = function(t, key)
+ if scroll_list[key] ~= nil then return scroll_list[key]
+ elseif key == "__current" then return t.list[t.selected]
+ elseif type(key) == "number" then return t.list[key] end
+ end,
+ __newindex = function(t, key, value)
+ if type(key) == "number" then rawset(t.list, key, value)
+ else rawset(t, key, value) end
+ end,
+ __scroll_list = scroll_list,
+ __len = function(t) return #t.list end,
+ __ipairs = function(t) return ipairs(t.list) end
+}
+
+--creates a new list object
+function scroll_list:new()
+ local vars
+ vars = {
+ ass = mp.create_osd_overlay('ass-events'),
+ hidden = true,
+ flag_update = true,
+
+ header = "header \\N ----------------------------------------------",
+ list = {},
+ selected = 1,
+
+ keybinds = {
+ {'DOWN', 'scroll_down', function() vars:scroll_down() end, {repeatable = true}},
+ {'UP', 'scroll_up', function() vars:scroll_up() end, {repeatable = true}},
+ {'ESC', 'close_browser', function() vars:close() end, {}}
+ }
+ }
+ return setmetatable(vars, metatable)
+end
+
+return scroll_list:new()
diff --git a/mpv/lua-modules/user-input-module.lua b/mpv/lua-modules/user-input-module.lua
new file mode 100644
index 0000000..2c25d42
--- /dev/null
+++ b/mpv/lua-modules/user-input-module.lua
@@ -0,0 +1,49 @@
+--[[
+ This is a module designed to interface with mpv-user-input
+ https://github.com/CogentRedTester/mpv-user-input
+
+ Loading this script as a module will return a table with two functions to format
+ requests to get and cancel user-input requests. See the README for details.
+
+ Alternatively, developers can just paste these functions directly into their script,
+ however this is not recommended as there is no guarantee that the formatting of
+ these requests will remain the same for future versions of user-input.
+]]
+
+local mp = require 'mp'
+local mod = {}
+
+local name = mp.get_script_name()
+local counter = 1
+
+-- sends a request to ask the user for input using formatted options provided
+-- creates a script message to recieve the response and call fn
+function mod.get_user_input(fn, options)
+ options = options or {}
+ local response_string = name.."/__user_input_request/"..counter
+ counter = counter + 1
+
+ -- create a callback for user-input to respond to
+ mp.register_script_message(response_string, function(input, err)
+ mp.unregister_script_message(response_string)
+ fn(err == "" and input or nil, err)
+ end)
+
+ -- send the input command
+ mp.commandv("script-message-to", "user_input", "request-user-input",
+ response_string,
+ name .. '/' .. (options.id or ""), -- id code for the request
+ options.request_text or options.text or (name.." is requesting user input:"),
+ options.default_input or "",
+ options.queueable and "1" or "",
+ options.replace and "1" or ""
+ )
+end
+
+-- sends a request to cancel all input requests with the given id
+function mod.cancel_user_input(id)
+ id = name .. '/' .. (id or "")
+ mp.commandv("script-message-to", "user_input", "cancel-user-input", id)
+end
+
+return mod
diff --git a/mpv/mpv.conf b/mpv/mpv.conf
new file mode 100644
index 0000000..0ced36d
--- /dev/null
+++ b/mpv/mpv.conf
@@ -0,0 +1,177 @@
+# vim: syntax=config
+
+
+###########
+# General #
+###########
+
+input-ipc-server=/tmp/mpvsocket # listen for IPC on this socket
+#load-stats-overlay=no # use local stats.lua
+#save-position-on-quit # handled by a script
+
+msg-module # prepend module name to log messages
+msg-color # color log messages on terminal
+term-osd-bar # display a progress bar on the terminal
+use-filedir-conf # look for additional config files in the directory of the opened file
+keep-open # keep the player open when a file's end is reached
+autofit-larger=100%x95% # resize window in case it's larger than W%xH% of the screen
+cursor-autohide-fs-only # don't autohide the cursor in window mode, only fullscreen
+input-media-keys=no # enable/disable OSX media keys
+cursor-autohide=1000 # autohide the curser after 1s
+prefetch-playlist=yes
+force-seekable=yes
+
+screenshot-format=png
+screenshot-png-compression=8
+screenshot-template='~/Desktop/%F (%P) %n'
+
+hls-bitrate=max # use max quality for HLS streams
+
+[default]
+
+
+#########
+# Cache #
+#########
+
+cache=yes
+demuxer-max-bytes=400MiB
+demuxer-max-back-bytes=150MiB
+
+
+#############
+# OSD / OSC #
+#############
+
+osd-level=1 # enable osd and display --osd-status-msg on interaction
+osd-duration=2500 # hide the osd after x ms
+osd-status-msg='${time-pos} / ${duration}${?percent-pos: (${percent-pos}%)}${?frame-drop-count:${!frame-drop-count==0: Dropped: ${frame-drop-count}}}\n${?chapter:Chapter: ${chapter}}'
+
+osd-font='Sarasa Mono K'
+osd-font-size=36
+osd-color='#FFFFFFFF' # ARGB format
+osd-border-color='#FF000000' # ARGB format
+#osd-shadow-offset=1 # pixel width for osd text and progress bar
+# osd-bar-align-y=-1 # progress bar y alignment (-1 top, 0 centered, 1 bottom)
+osd-border-size=2 # size for osd text and progress bar
+# osd-bar-h=2 # height of osd bar as a fractional percentage of your screen height
+# osd-bar-w=100 # width of " " "
+
+
+# Subtitles #
+
+demuxer-mkv-subtitle-preroll=yes # try to show embedded subs when seeking even when no index information is present
+demuxer-mkv-subtitle-preroll-secs=2
+
+sub-auto=fuzzy # external subs don't have to match the file name exactly to autoload
+sub-file-paths-append=ass # search for external subs in these relative subdirectories
+sub-file-paths-append=srt
+sub-file-paths-append=sub
+sub-file-paths-append=subs
+sub-file-paths-append=subtitles
+
+embeddedfonts=yes # use embedded fonts for SSA/ASS subs
+sub-fix-timing=no # do not try to fix gaps (which might make it worse in some cases)
+sub-ass-force-style=Kerning=yes # allows you to override style parameters of ASS scripts
+sub-use-margins
+sub-ass-force-margins
+
+# the following options only apply to subtitles without own styling (i.e. not ASS but e.g. SRT)
+sub-font="Sarasa UI K"
+sub-font-size=40
+sub-color="#FFFFFFFF"
+sub-border-color="#FF000000"
+sub-border-size=2.0
+sub-shadow-offset=1
+sub-shadow-color="#33000000"
+sub-spacing=0.5
+
+
+# Languages #
+
+slang=en,eng # automatically select these subtitles (decreasing priority)
+alang=ja,jp,jpn,en,eng # automatically select these audio tracks (decreasing priority)
+
+
+# Audio #
+
+audio-file-auto=fuzzy # external audio doesn't has to match the file name exactly to autoload
+audio-pitch-correction=yes # automatically insert scaletempo when playing with higher speed
+volume-max=115 # maximum volume in %, everything above 100 results in amplification
+volume=90 # default volume, 100 = unchanged
+
+
+# Video Output #
+
+# Defaults for all profiles
+tscale=oversample # [sharp] oversample <-> linear (triangle) <-> catmull_rom <-> mitchell <-> gaussian <-> bicubic [smooth]
+opengl-early-flush=no
+opengl-pbo=no # "yes" is currently bugged: https://github.com/mpv-player/mpv/issues/4988
+hwdec=no
+
+ytdl-format=bestvideo[height<=?720][fps<=?30][vcodec!=?vp9]+bestaudio/best
+
+[high-quality]
+profile-desc=cond:is_high(get('width', 0), get('height', 0), get('estimated-vf-fps', 0))
+#scale=ewa_hanning
+#scale-radius=3.2383154841662362
+scale=ewa_lanczossharp
+cscale=ewa_lanczossoft
+dscale=mitchell
+scale-antiring=0
+cscale-antiring=0
+dither-depth=auto
+correct-downscaling=yes
+sigmoid-upscaling=yes
+deband=yes
+
+[mid-quality]
+profile-desc=cond:is_mid(get('width', 0), get('height', 0), get('estimated-vf-fps', 0))
+scale=spline36
+cscale=bicubic
+dscale=mitchell
+scale-antiring=1.0
+cscale-antiring=1.0
+dither-depth=auto
+correct-downscaling=yes
+sigmoid-upscaling=yes
+deband=yes
+glsl-shaders-set=""
+
+[low-quality]
+profile-desc=cond:is_low(get('width', 0), get('height', 0), get('estimated-vf-fps', 0))
+scale=bilinear
+cscale=bilinear
+dscale=bilinear
+scale-antiring=0
+cscale-antiring=0
+dither-depth=no
+correct-downscaling=no
+sigmoid-upscaling=no
+deband=no
+glsl-shaders-set=""
+
+[4K-lavc-threads]
+profile-desc=cond:get('width', -math.huge) >= 3840
+vd-lavc-threads=32
+
+[4K-lavc-threads-inverted]
+profile-desc=cond:get('width', math.huge) < 3840
+vd-lavc-threads=0
+
+
+# Protocol Specific Configuration #
+
+[protocol.https]
+cache=yes
+user-agent='Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0'
+
+[protocol.http]
+cache=yes
+user-agent='Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0'
+
+[360p]
+ytdl-format=bestvideo[height<=360][vcodec=vp9]+bestaudio/bestvideo[height<=360]+bestaudio/best[height<=360]/best
+
+[480p]
+ytdl-format=bestvideo[height<=480][vcodec=vp9]+bestaudio/bestvideo[height<=480]+bestaudio/best[height<=480]/best
diff --git a/mpv/scripts/auto-audio-device.lua b/mpv/scripts/auto-audio-device.lua
new file mode 100644
index 0000000..92fcdf8
--- /dev/null
+++ b/mpv/scripts/auto-audio-device.lua
@@ -0,0 +1,36 @@
+local mp = require 'mp'
+
+
+local auto_change = true
+local av_map = {
+ ["default"] = "auto",
+ ["DELL U2312HM"] = "coreaudio/AppleUSBAudioEngine:FiiO:DigiHug USB Audio:1a160000:3", -- FiiO DAC
+ ["SONY TV *00"] = "coreaudio/AppleGFXHDAEngineOutputDP:0:{D94D-8204-01010101}", -- HDMI
+ ["Color LCD"] = "coreaudio/AppleHDAEngineOutput:1B,0,1,1:0", -- Built-in
+}
+
+function set_audio_device(obs_display)
+ if obs_display ~= nil and not auto_change then
+ return
+ end
+
+ local display = obs_display or mp.get_property_native("display-names")
+ if not display or not display[1] then
+ --print("Invalid display return value: " .. tostring(display))
+ return
+ end
+
+ local new_adev = av_map[display[1]] or av_map["default"]
+ local current_adev = mp.get_property("audio-device", av_map["default"])
+ if new_adev ~= current_adev then
+ mp.osd_message("Audio device: " .. new_adev)
+ mp.set_property("audio-device", new_adev)
+ end
+end
+
+mp.observe_property("display-names", "native", function(name, value) set_audio_device(value) end)
+mp.add_key_binding("", "set-audio-device", function() set_audio_device(nil) end)
+mp.add_key_binding("", "toggle-switching", function()
+ auto_change = not auto_change
+ mp.osd_message("Audio device switching: " .. tostring(auto_change))
+end)
diff --git a/mpv/scripts/auto-profiles.lua b/mpv/scripts/auto-profiles.lua
new file mode 100644
index 0000000..32e1809
--- /dev/null
+++ b/mpv/scripts/auto-profiles.lua
@@ -0,0 +1,198 @@
+--[[
+
+Automatically apply profiles based on runtime conditions.
+At least mpv 0.21.0 is required.
+
+This script queries the list of loaded config profiles, and checks the
+"profile-desc" field of each profile. If it starts with "cond:", the script
+parses the string as Lua expression, and evaluates it. If the expression
+returns true, the profile is applied, if it returns false, it is ignored.
+
+Expressions can reference properties by accessing "p". For example, "p.pause"
+would return the current pause status. If the variable name contains any "_"
+characters, they are turned into "-". For example, "playback_time" would
+return the property "playback-time". (Although you can also just write
+p["playback-time"].)
+
+Note that if a property is not available, it will return nil, which can cause
+errors if used in expressions. These are printed and ignored, and the
+expression is considered to be false. You can also write e.g.
+get("playback-time", 0) instead of p.playback_time to default to 0.
+
+Whenever a property referenced by a profile condition changes, the condition
+is re-evaluated. If the return value of the condition changes from false or
+error to true, the profile is applied.
+
+Note that profiles cannot be "unapplied", so you may have to define inverse
+profiles with inverse conditions do undo a profile.
+
+Using profile-desc is just a hack - maybe it will be changed later.
+
+Supported --script-opts:
+
+ auto-profiles: if set to "no", the script disables itself (but will still
+ listen to property notifications etc. - if you set it to
+ "yes" again, it will re-evaluate the current state)
+
+Example profiles:
+
+# the profile names aren't used (except for logging), but must not clash with
+# other profiles
+[test]
+profile-desc=cond:p.playback_time>10
+video-zoom=2
+
+# you would need this to actually "unapply" the "test" profile
+[test-revert]
+profile-desc=cond:p.playback_time<=10
+video-zoom=0
+
+--]]
+
+local lua_modules = mp.find_config_file('lua-modules')
+if lua_modules then
+ package.path = package.path .. ';' .. lua_modules .. '/?.lua'
+end
+
+local f = require 'auto-profiles-functions'
+local utils = require 'mp.utils'
+local msg = require 'mp.msg'
+
+local profiles = {}
+local watched_properties = {} -- indexed by property name (used as a set)
+local cached_properties = {} -- property name -> last known raw value
+local properties_to_profiles = {} -- property name -> set of profiles using it
+local have_dirty_profiles = false -- at least one profile is marked dirty
+
+-- Used during evaluation of the profile condition, and should contain the
+-- profile the condition is evaluated for.
+local current_profile = nil
+
+local function evaluate(profile)
+ msg.verbose("Re-evaluate auto profile " .. profile.name)
+
+ current_profile = profile
+ local status, res = pcall(profile.cond)
+ current_profile = nil
+
+ if not status then
+ -- errors can be "normal", e.g. in case properties are unavailable
+ msg.info("Error evaluating: " .. res)
+ res = false
+ elseif type(res) ~= "boolean" then
+ msg.error("Profile '" .. profile.name .. "' did not return a boolean.")
+ res = false
+ end
+ if res ~= profile.status and res == true then
+ msg.info("Applying profile " .. profile.name)
+ mp.commandv("apply-profile", profile.name)
+ end
+ profile.status = res
+ profile.dirty = false
+end
+
+local function on_property_change(name, val)
+ cached_properties[name] = val
+ -- Mark all profiles reading this property as dirty, so they get re-evaluated
+ -- the next time the script goes back to sleep.
+ local dependent_profiles = properties_to_profiles[name]
+ if dependent_profiles then
+ for profile, _ in pairs(dependent_profiles) do
+ assert(profile.cond) -- must be a profile table
+ profile.dirty = true
+ have_dirty_profiles = true
+ end
+ end
+end
+
+local function on_idle()
+ if mp.get_opt("auto-profiles") == "no" then
+ return
+ end
+
+ -- When events and property notifications stop, re-evaluate all dirty profiles.
+ if have_dirty_profiles then
+ for _, profile in ipairs(profiles) do
+ if profile.dirty then
+ evaluate(profile)
+ end
+ end
+ end
+ have_dirty_profiles = false
+end
+
+mp.register_idle(on_idle)
+
+local evil_meta_magic = {
+ __index = function(table, key)
+ -- interpret everything as property, unless it already exists as
+ -- a non-nil global value
+ local v = _G[key]
+ if type(v) ~= "nil" then
+ return v
+ end
+ -- Lua identifiers can't contain "-", so in order to match with mpv
+ -- property conventions, replace "_" to "-"
+ key = string.gsub(key, "_", "-")
+ -- Normally, we use the cached value only (to reduce CPU usage I guess?)
+ if not watched_properties[key] then
+ watched_properties[key] = true
+ mp.observe_property(key, "native", on_property_change)
+ cached_properties[key] = mp.get_property_native(key)
+ end
+ -- The first time the property is read we need add it to the
+ -- properties_to_profiles table, which will be used to mark the profile
+ -- dirty if a property referenced by it changes.
+ if current_profile then
+ local map = properties_to_profiles[key]
+ if not map then
+ map = {}
+ properties_to_profiles[key] = map
+ end
+ map[current_profile] = true
+ end
+ return cached_properties[key]
+ end,
+}
+
+local evil_magic = {}
+setmetatable(evil_magic, evil_meta_magic)
+
+local function compile_cond(name, s)
+ chunk, err = loadstring("return " .. s, "profile " .. name .. " condition")
+ if not chunk then
+ msg.error("Profile '" .. name .. "' condition: " .. err)
+ return function() return false end
+ end
+ return chunk
+end
+
+for i, v in ipairs(mp.get_property_native("profile-list")) do
+ local desc = v["profile-desc"]
+ if desc and desc:sub(1, 5) == "cond:" then
+ local profile = {
+ name = v.name,
+ cond = compile_cond(v.name, desc:sub(6)),
+ properties = {},
+ status = nil,
+ dirty = true, -- need re-evaluate
+ }
+ profiles[#profiles + 1] = profile
+ have_dirty_profiles = true
+ end
+end
+
+-- these definitions are for use by the condition expressions
+
+p = evil_magic
+
+function get(property_name, default)
+ local val = p[property_name]
+ if val == nil then
+ val = default
+ end
+ return val
+end
+
+-- re-evaluate all profiles immediately
+on_idle()
diff --git a/mpv/scripts/auto-save-state.lua b/mpv/scripts/auto-save-state.lua
new file mode 100644
index 0000000..a4ec3ec
--- /dev/null
+++ b/mpv/scripts/auto-save-state.lua
@@ -0,0 +1,55 @@
+-- Save watch-later conditionally.
+-- a) Always for playlists (so mpv remembers the position within this playlist)
+-- b) Never for files shorter than `min_length` seconds
+-- c) When the current playback position is > `thresh_start` and < `thresh_end`
+
+
+local opts = require 'mp.options'
+local o = {
+ min_length = 600,
+ thresh_end = 180,
+ thresh_start = 60,
+}
+opts.read_options(o)
+
+
+-- Return true when multiple files are being played
+function check_playlist()
+ local pcount, err = mp.get_property_number("playlist-count")
+ if not pcount then
+ print("error: " .. err)
+ pcount = 1
+ end
+
+ return pcount > 1
+end
+
+
+-- Return true when the current playback time is not too close to the start or end
+-- Always return false for short files, no matter the playback time
+function check_time()
+ local duration = mp.get_property_number("duration", 9999)
+ if duration < o.min_length then
+ return false
+ end
+
+ local remaining, err = mp.get_property_number("time-remaining")
+ if not remaining then
+ print("error: " .. err)
+ remaining = -math.huge
+ end
+ local pos, err = mp.get_property_number("time-pos")
+ if not pos then
+ print("error: " .. err)
+ pos = -math.huge
+ end
+
+ return pos > o.thresh_start and remaining > o.thresh_end
+end
+
+
+mp.add_key_binding("q", "quit-watch-later-conditional",
+ function()
+ mp.set_property_bool("options/save-position-on-quit", check_playlist() or check_time())
+ mp.command("quit")
+ end)
diff --git a/mpv/scripts/autodeint.lua b/mpv/scripts/autodeint.lua
new file mode 100644
index 0000000..16f56ea
--- /dev/null
+++ b/mpv/scripts/autodeint.lua
@@ -0,0 +1,158 @@
+-- From: https://github.com/mpv-player/mpv/tree/master/TOOLS/lua
+-- (with slight modifications)
+--
+-- This script uses the lavfi idet filter to automatically insert the
+-- appropriate deinterlacing filter based on a short section of the
+-- currently playing video.
+--
+-- It registers the key-binding ctrl+d, which when pressed, inserts the filters
+-- ``vf=lavfi=idet,pullup,vf=lavfi=idet``. After 4 seconds, it removes these
+-- filters and decides whether the content is progressive, interlaced, or
+-- telecined and the interlacing field dominance.
+--
+-- Based on this information, it may set mpv's ``deinterlace`` property (which
+-- usually inserts the yadif filter), or insert the ``pullup`` filter if the
+-- content is telecined. It also sets mpv's ``field-dominance`` property.
+--
+-- OPTIONS:
+-- The default detection time may be overridden by adding
+--
+-- --script-opts=autodeint.detect_seconds=<number of seconds>
+--
+-- to mpv's arguments. This may be desirable to allow idet more
+-- time to collect data.
+--
+-- To see counts of the various types of frames for each detection phase,
+-- the verbosity can be increased with
+--
+-- --msg-level autodeint=v
+--
+-- This script requires a recent version of ffmpeg for which the idet
+-- filter adds the required metadata.
+
+require "mp.msg"
+
+script_name = mp.get_script_name()
+detect_label = string.format("%s-detect", script_name)
+pullup_label = string.format("%s", script_name)
+ivtc_detect_label = string.format("%s-ivtc-detect", script_name)
+
+-- number of seconds to gather cropdetect data
+detect_seconds = tonumber(mp.get_opt(string.format("%s.detect_seconds", script_name)))
+if not detect_seconds then
+ detect_seconds = 4
+end
+
+function del_filter_if_present(label)
+ -- necessary because mp.command('vf del @label:filter') raises an
+ -- error if the filter doesn't exist
+ local vfs = mp.get_property_native("vf")
+
+ for i,vf in pairs(vfs) do
+ if vf["label"] == label then
+ table.remove(vfs, i)
+ mp.set_property_native("vf", vfs)
+ return true
+ end
+ end
+ return false
+end
+
+function start_detect()
+ -- exit if detection is already in progress
+ if timer then
+ mp.msg.warn("already detecting!")
+ mp.osd_message("autodeint: already detecting!")
+ return
+ end
+
+ mp.set_property("deinterlace","no")
+ del_filter_if_present(pullup_label)
+
+ -- insert the detection filter
+ local cmd = string.format('vf add @%s:lavfi=graph="idet",@%s:pullup,@%s:lavfi=graph="idet"',
+ detect_label, pullup_label, ivtc_detect_label)
+ if not mp.command(cmd) then
+ mp.msg.error("failed to insert detection filters")
+ mp.osd_message("autodeint: failed to insert detection filters")
+ return
+ end
+
+ -- wait to gather data
+ mp.osd_message("autodeint: starting detection")
+ timer = mp.add_timeout(detect_seconds, select_filter)
+end
+
+function stop_detect()
+ del_filter_if_present(detect_label)
+ del_filter_if_present(ivtc_detect_label)
+ timer = nil
+end
+
+progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3, 4
+
+function judge(label)
+ -- get the metadata
+ local result = mp.get_property_native(string.format("vf-metadata/%s", label))
+ -- filter might have been removed by third party
+ if not result or next(result) == nil then
+ return progressive
+ end
+ num_tff = tonumber(result["lavfi.idet.multiple.tff"])
+ num_bff = tonumber(result["lavfi.idet.multiple.bff"])
+ num_progressive = tonumber(result["lavfi.idet.multiple.progressive"])
+ num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"])
+ num_interlaced = num_tff + num_bff
+ num_determined = num_interlaced + num_progressive
+
+ mp.msg.verbose(label .. " progressive = "..num_progressive)
+ mp.msg.verbose(label .. " interlaced-tff = "..num_tff)
+ mp.msg.verbose(label .. " interlaced-bff = "..num_bff)
+ mp.msg.verbose(label .. " undetermined = "..num_undetermined)
+
+ if num_determined < num_undetermined then
+ mp.msg.warn("majority undetermined frames")
+ end
+ if num_progressive > 20*num_interlaced then
+ return progressive
+ elseif num_tff > 10*num_bff then
+ return interlaced_tff
+ elseif num_bff > 10*num_tff then
+ return interlaced_bff
+ else
+ return interlaced
+ end
+end
+
+function select_filter()
+ -- handle the first detection filter results
+ verdict = judge(detect_label)
+ if verdict == progressive then
+ mp.msg.info("progressive: doing nothing")
+ mp.osd_message("autodeint: no deinterlacing required")
+ stop_detect()
+ return
+ elseif verdict == interlaced_tff then
+ mp.set_property("field-dominance", "top")
+ elseif verdict == interlaced_bff then
+ mp.set_property("field-dominance", "bottom")
+ elseif verdict == interlaced then
+ mp.set_property("field-dominance", "auto")
+ end
+
+ -- handle the ivtc detection filter results
+ verdict = judge(ivtc_detect_label)
+ if verdict == progressive then
+ mp.msg.info(string.format("telecinied with %s field dominance: using pullup", mp.get_property("field-dominance")))
+ mp.osd_message("autodeint: using pullup")
+ stop_detect()
+ else
+ mp.msg.info(string.format("interlaced with %s field dominance: setting deinterlace property", mp.get_property("field-dominance")))
+ del_filter_if_present(pullup_label)
+ mp.osd_message(string.format("autodeint: setting deinterlace property (%s)", mp.get_property("field-dominance")))
+ mp.set_property("deinterlace", "yes")
+ stop_detect()
+ end
+end
+
+mp.add_key_binding("ctrl+d", script_name, start_detect)
diff --git a/mpv/scripts/betterchapters.lua b/mpv/scripts/betterchapters.lua
new file mode 100644
index 0000000..4b871c8
--- /dev/null
+++ b/mpv/scripts/betterchapters.lua
@@ -0,0 +1,21 @@
+-- From: https://github.com/mpv-player/mpv/issues/4738#issuecomment-321298846
+
+function chapter_seek(direction)
+ local chapters = mp.get_property_number("chapters")
+ if chapters == nil then chapters = 0 end
+ local chapter = mp.get_property_number("chapter")
+ if chapter == nil then chapter = 0 end
+ if chapter+direction < 0 then
+ mp.command("playlist_prev")
+ mp.commandv("script-message", "osc-playlist")
+ elseif chapter+direction >= chapters then
+ mp.command("playlist_next")
+ mp.commandv("script-message", "osc-playlist")
+ else
+ mp.commandv("add", "chapter", direction)
+ mp.commandv("script-message", "osc-chapterlist")
+ end
+end
+
+mp.add_key_binding(nil, "chapterplaylist-next", function() chapter_seek(1) end)
+mp.add_key_binding(nil, "chapterplaylist-prev", function() chapter_seek(-1) end) \ No newline at end of file
diff --git a/mpv/scripts/blacklist-extensions.lua b/mpv/scripts/blacklist-extensions.lua
new file mode 100644
index 0000000..a8ec638
--- /dev/null
+++ b/mpv/scripts/blacklist-extensions.lua
@@ -0,0 +1,80 @@
+-- From: https://github.com/occivink/mpv-scripts
+
+opts = {
+ blacklist="",
+ whitelist="",
+ remove_files_without_extension = false,
+ oneshot = true,
+}
+(require 'mp.options').read_options(opts)
+local msg = require 'mp.msg'
+
+function split(input)
+ local ret = {}
+ for str in string.gmatch(input, "([^,]+)") do
+ ret[#ret + 1] = str
+ end
+ return ret
+end
+
+opts.blacklist = split(opts.blacklist)
+opts.whitelist = split(opts.whitelist)
+
+local exclude
+if #opts.whitelist > 0 then
+ exclude = function(extension)
+ for _, ext in pairs(opts.whitelist) do
+ if extension == ext then
+ return false
+ end
+ end
+ return true
+ end
+elseif #opts.blacklist > 0 then
+ exclude = function(extension)
+ for _, ext in pairs(opts.blacklist) do
+ if extension == ext then
+ return true
+ end
+ end
+ return false
+ end
+else
+ return
+end
+
+function should_remove(filename)
+ if string.find(filename, "://") then
+ return false
+ end
+ local extension = string.match(filename, "%.([^./]+)$")
+ if not extension and opts.remove_file_without_extension then
+ return true
+ end
+ if extension and exclude(string.lower(extension)) then
+ return true
+ end
+ return false
+end
+
+function process(playlist_count)
+ if playlist_count < 2 then return end
+ if opts.oneshot then
+ mp.unobserve_property(observe)
+ end
+ local playlist = mp.get_property_native("playlist")
+ local removed = 0
+ for i = #playlist, 1, -1 do
+ if should_remove(playlist[i].filename) then
+ mp.commandv("playlist-remove", i-1)
+ removed = removed + 1
+ end
+ end
+ if removed == #playlist then
+ msg.warn("Removed eveything from the playlist")
+ end
+end
+
+function observe(k,v) process(v) end
+
+mp.observe_property("playlist-count", "number", observe)
diff --git a/mpv/scripts/cycle-profiles.lua b/mpv/scripts/cycle-profiles.lua
new file mode 100644
index 0000000..da846c5
--- /dev/null
+++ b/mpv/scripts/cycle-profiles.lua
@@ -0,0 +1,103 @@
+--[[
+ script to cycle profiles with a keybind, accomplished through script messages
+ available at: https://github.com/CogentRedTester/mpv-scripts
+ syntax:
+ script-message cycle-profiles "profile1;profile2;profile3"
+ You must use semicolons to separate the profiles, do not include any spaces that are not part of the profile name.
+ The script will print the profile description to the screen when switching, if there is no profile description, then it just prints the name
+]]--
+
+--change this to change what character separates the profile names
+seperator = ";"
+
+msg = require 'mp.msg'
+
+--splits the profiles string into an array of profile names
+--function taken from: https://stackoverflow.com/questions/1426954/split-string-in-lua/7615129#7615129
+function mysplit (inputstr, sep)
+ if sep == nil then
+ sep = "%s"
+ end
+ local t={}
+ for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
+ table.insert(t, str)
+ end
+ return t
+end
+
+--table of all available profiles and options
+profileList = mp.get_property_native('profile-list')
+
+--keeps track of current profile for every unique cycle
+iterator = {}
+
+--stores descriptions for profiles
+--once requested a description is stored here so it does not need to be found again
+profilesDescs = {}
+
+--if trying to cycle to an unknown profile this function is run to find a description to print
+function findDesc(profile)
+ msg.verbose('unknown profile ' .. profile .. ', searching for description')
+
+ for i = 1, #profileList, 1 do
+ if profileList[i]['name'] == profile then
+ msg.verbose('profile found')
+ local desc = profileList[i]['profile-desc']
+
+ if desc ~= nil then
+ msg.verbose('description found')
+ profilesDescs[profile] = desc
+ else
+ msg.verbose('no description, will use name')
+ profilesDescs[profile] = profile
+ end
+ return
+ end
+ end
+
+ msg.verbose('profile not found')
+ profilesDescs[profile] = "no profile '" .. profile .. "'"
+end
+
+--prints the profile description to the OSD
+--if the profile has not been requested before during the session then it runs findDesc()
+function printProfileDesc(profile)
+ local desc = profilesDescs[profile]
+ if desc == nil then
+ findDesc(profile)
+ desc = profilesDescs[profile]
+ end
+
+ msg.verbose('profile description: ' .. desc)
+ mp.osd_message(desc)
+end
+
+function main(profileStr)
+ --if there is not already an iterator for this cycle then it creates one
+ if iterator[profileStr] == nil then
+ msg.verbose('unknown cycle, creating new iterator')
+ iterator[profileStr] = 1
+ end
+ local i = iterator[profileStr]
+
+ --converts the string into an array of profile names
+ local profiles = mysplit(profileStr, seperator)
+ msg.verbose('cycling ' .. tostring(profiles))
+ msg.verbose("number of profiles: " .. tostring(#profiles))
+
+ --sends the command to apply the profile
+ msg.info("applying profile " .. profiles[i])
+ mp.commandv('apply-profile', profiles[i])
+
+ --prints the profile description to the OSD
+ printProfileDesc(profiles[i])
+
+ --moves the iterator
+ iterator[profileStr] = iterator[profileStr] + 1
+ if iterator[profileStr] > #profiles then
+ msg.verbose('reached end of profiles, wrapping back to start')
+ iterator[profileStr] = 1
+ end
+end
+
+mp.register_script_message('cycle-profiles', main)
diff --git a/mpv/scripts/music-mode.lua b/mpv/scripts/music-mode.lua
new file mode 100644
index 0000000..4c57456
--- /dev/null
+++ b/mpv/scripts/music-mode.lua
@@ -0,0 +1,192 @@
+local mp = require 'mp'
+local msg = require 'mp.msg'
+local opt = require 'mp.options'
+
+--script options, set these in script-opts
+local o = {
+ --change to disable automatic mode switching
+ auto = true,
+
+ --profile to call when valid extension is found
+ profile = "music",
+
+ --runs this profile when in music mode and a non-audio file is loaded
+ --you should essentially put all your defaults that the music profile changed in here
+ undo_profile = "",
+
+ --start playback in music mode. This setting is only applied when the player is initially started,
+ --changing this option during runtime does nothing.
+ --probably only useful if auto is disabled
+ enable = false,
+
+ --the script will also enable the following input section when music mode is enabled
+ --see the mpv manual for details on sections
+ input_section = "music",
+
+ --dispays the metadata of the track on the osd when music mode is on
+ --there is also a script message to enable this seperately
+ show_metadata = false
+}
+
+opt.read_options(o, 'musicmode', function() msg.verbose('options updated') end)
+
+--a music file is one where mpv returns an audio stream or coverart as the first track
+local function is_audio_file()
+ local track_list = mp.get_property_native("track-list")
+
+ local has_audio = false
+ for _, track in ipairs(track_list) do
+ if track.type == "audio" then has_audio = true
+ elseif not track.albumart and (track["demux-fps"] or 2) > 1 then return false end
+ end
+ return has_audio
+end
+
+local metadata = mp.create_osd_overlay('ass-events')
+metadata.hidden = not o.show_metadata
+
+local function update_metadata()
+ metadata.data = mp.get_property_osd('filtered-metadata')
+ metadata:update()
+end
+
+local function enable_metadata()
+ metadata.hidden = false
+ metadata:update()
+end
+
+local function disable_metadata()
+ metadata.hidden = true
+ metadata:remove()
+end
+
+--changes visibility of metadata
+local function show_metadata(command)
+ if command == "on" or command == nil then
+ enable_metadata()
+ elseif command == "off" then
+ disable_metadata()
+ elseif command == "toggle" then
+ if metadata.hidden then
+ enable_metadata()
+ else
+ disable_metadata()
+ end
+ else
+ msg.warn('unknown command "' .. command .. '"')
+ end
+end
+
+--to prevent superfluous loading of profiles the script keeps track of when music mode is enabled
+local musicMode = false
+
+--enables music mode
+local function activate()
+ mp.commandv('apply-profile', o.profile)
+ mp.commandv('enable-section', o.input_section, "allow-vo-dragging+allow-hide-cursor")
+ mp.osd_message('Music Mode enabled')
+
+ if o.show_metadata then
+ show_metadata("on")
+ end
+
+ musicMode = true
+end
+
+--disables music mode
+local function deactivate()
+ mp.commandv('apply-profile', o.undo_profile)
+ mp.commandv('disable-section', o.input_section)
+ mp.osd_message('Music Mode disabled')
+
+ if o.show_metadata then
+ show_metadata('off')
+ end
+
+ musicMode = false
+end
+
+local function main()
+ --if the file is an audio file then the music profile is loaded
+ if is_audio_file() then
+ msg.verbose('audio file, applying profile "' .. o.profile .. '"')
+ if not musicMode then
+ activate()
+ end
+ elseif o.undo_profile ~= "" and musicMode then
+ msg.verbose('video file, applying undo profile "' .. o.undo_profile .. '"')
+ deactivate()
+ end
+end
+
+--sets music mode from script-message
+local function script_message(command)
+ if command == "on" or command == nil then
+ activate()
+ elseif command == "off" then
+ deactivate()
+ elseif command == "toggle" then
+ if musicMode then
+ deactivate()
+ else
+ activate()
+ end
+ else
+ msg.warn('unknown command "' .. command .. '"')
+ end
+end
+
+local function lock()
+ o.auto = false
+ msg.info('Music Mode locked')
+ mp.osd_message('Music Mode locked')
+end
+
+local function unLock()
+ o.auto = true
+ msg.info('Music Mode unlocked')
+ mp.osd_message('Music Mode unlocked')
+end
+
+--toggles lock
+local function lock_script_message(command)
+ if command == "on" or command == nil then
+ lock()
+ elseif command == "off" then
+ unLock()
+ elseif command == "toggle" then
+ if o.auto then
+ lock()
+ else
+ unLock()
+ end
+ else
+ msg.warn('unknown command "' .. command .. '"')
+ end
+end
+
+--runs when the file is loaded, if script is locked it will do nothing
+local function file_loaded()
+ if o.auto then
+ main()
+ end
+end
+
+if o.enable then
+ activate()
+end
+
+--sets music mode
+--accepts arguments: 'on', 'off', 'toggle'
+mp.register_script_message('music-mode', script_message)
+
+--stops the script from switching modes on file loads
+----accepts arguments: 'on', 'off', 'toggle'
+mp.register_script_message('music-mode-lock', lock_script_message)
+
+--shows file metadata on osc
+--accepts arguments: 'on' 'off' 'toggle'
+mp.register_script_message('show-metadata', show_metadata)
+
+mp.add_hook('on_preloaded', 40, file_loaded)
+mp.observe_property('filtered-metadata', 'string', update_metadata)
diff --git a/mpv/scripts/user-input.lua b/mpv/scripts/user-input.lua
new file mode 100644
index 0000000..689e073
--- /dev/null
+++ b/mpv/scripts/user-input.lua
@@ -0,0 +1,664 @@
+local mp = require 'mp'
+local msg = require 'mp.msg'
+local utils = require 'mp.utils'
+local options = require 'mp.options'
+
+-- Default options
+local opts = {
+ -- All drawing is scaled by this value, including the text borders and the
+ -- cursor. Change it if you have a high-DPI display.
+ scale = 1,
+ -- Set the font used for the REPL and the console. This probably doesn't
+ -- have to be a monospaced font.
+ font = "",
+ -- Set the font size used for the REPL and the console. This will be
+ -- multiplied by "scale."
+ font_size = 16,
+}
+
+options.read_options(opts, "user_input")
+
+local queue = {
+ queue = {},
+ active_ids = {}
+}
+local histories = {}
+local request = nil
+
+local line = ''
+
+--[[
+ sends a response to the original script in the form of a json string
+ it is expected that all requests get a response, if the input is nil then err should say why
+ current error codes are:
+ exitted the user closed the input instead of pressing Enter
+ already_queued a request with the specified id was already in the queue
+ replaced the request was replaced with a newer request
+ cancelled a script cancelled the request
+]]--
+local function send_response(send_line, err, override_response)
+ mp.commandv("script-message", override_response or request.response, send_line and line or "", err or "")
+end
+
+
+--[[
+ The below code is a modified implementation of text input from mpv's console.lua:
+ https://github.com/mpv-player/mpv/blob/7ca14d646c7e405f3fb1e44600e2a67fc4607238/player/lua/console.lua
+
+ Modifications:
+ removed support for log messages, sending commands, tab complete, help commands
+ removed update timer
+ Changed esc key to call handle_esc function
+ handle_esc and handle_enter now call the send_response() function
+ all functions that send responses now call queue:pop()
+ made history specific to request ids
+ localised all functions - reordered some to fit
+ keybindings use new names
+]]--
+
+------------------------------START ORIGINAL MPV CODE-----------------------------------
+----------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------
+
+-- Copyright (C) 2019 the mpv developers
+--
+-- Permission to use, copy, modify, and/or distribute this software for any
+-- purpose with or without fee is hereby granted, provided that the above
+-- copyright notice and this permission notice appear in all copies.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+-- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+-- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+local assdraw = require 'mp.assdraw'
+
+local function detect_platform()
+ local o = {}
+ -- Kind of a dumb way of detecting the platform but whatever
+ if mp.get_property_native('options/vo-mmcss-profile', o) ~= o then
+ return 'windows'
+ elseif mp.get_property_native('options/macos-force-dedicated-gpu', o) ~= o then
+ return 'macos'
+ elseif os.getenv('WAYLAND_DISPLAY') then
+ return 'wayland'
+ end
+ return 'x11'
+end
+
+-- Pick a better default font for Windows and macOS
+local platform = detect_platform()
+if platform == 'windows' then
+ opts.font = 'Consolas'
+elseif platform == 'macos' then
+ opts.font = 'Menlo'
+else
+ opts.font = 'monospace'
+end
+
+local repl_active = false
+local insert_mode = false
+local cursor = 1
+local key_bindings = {}
+local global_margin_y = 0
+
+-- Escape a string for verbatim display on the OSD
+local function ass_escape(str)
+ -- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if
+ -- it isn't followed by a recognised character, so add a zero-width
+ -- non-breaking space
+ str = str:gsub('\\', '\\\239\187\191')
+ str = str:gsub('{', '\\{')
+ str = str:gsub('}', '\\}')
+ -- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of
+ -- consecutive newlines
+ str = str:gsub('\n', '\239\187\191\\N')
+ -- Turn leading spaces into hard spaces to prevent ASS from stripping them
+ str = str:gsub('\\N ', '\\N\\h')
+ str = str:gsub('^ ', '\\h')
+ return str
+end
+
+-- Render the REPL and console as an ASS OSD
+local function update()
+ local dpi_scale = mp.get_property_native("display-hidpi-scale", 1.0)
+
+ dpi_scale = dpi_scale * opts.scale
+
+ local screenx, screeny, aspect = mp.get_osd_size()
+ screenx = screenx / dpi_scale
+ screeny = screeny / dpi_scale
+
+ -- Clear the OSD if the REPL is not active
+ if not repl_active then
+ mp.set_osd_ass(screenx, screeny, '')
+ return
+ end
+
+ local ass = assdraw.ass_new()
+ local style = '{\\r' ..
+ '\\1a&H00&\\3a&H00&\\4a&H99&' ..
+ '\\1c&Heeeeee&\\3c&H111111&\\4c&H000000&' ..
+ '\\fn' .. opts.font .. '\\fs' .. opts.font_size ..
+ '\\bord1\\xshad0\\yshad1\\fsp0\\q1}'
+ -- Create the cursor glyph as an ASS drawing. ASS will draw the cursor
+ -- inline with the surrounding text, but it sets the advance to the width
+ -- of the drawing. So the cursor doesn't affect layout too much, make it as
+ -- thin as possible and make it appear to be 1px wide by giving it 0.5px
+ -- horizontal borders.
+ local cheight = opts.font_size * 8
+ local cglyph = '{\\r' ..
+ '\\1a&H44&\\3a&H44&\\4a&H99&' ..
+ '\\1c&Heeeeee&\\3c&Heeeeee&\\4c&H000000&' ..
+ '\\xbord0.5\\ybord0\\xshad0\\yshad1\\p4\\pbo24}' ..
+ 'm 0 0 l 1 0 l 1 ' .. cheight .. ' l 0 ' .. cheight ..
+ '{\\p0}'
+ local before_cur = ass_escape(line:sub(1, cursor - 1))
+ local after_cur = ass_escape(line:sub(cursor))
+
+ ass:new_event()
+ ass:an(1)
+ ass:pos(2, screeny - 2 - global_margin_y * screeny)
+ ass:append(style .. request.text .. '\\N')
+ ass:append('> ' .. before_cur)
+ ass:append(cglyph)
+ ass:append(style .. after_cur)
+
+ -- Redraw the cursor with the REPL text invisible. This will make the
+ -- cursor appear in front of the text.
+ ass:new_event()
+ ass:an(1)
+ ass:pos(2, screeny - 2)
+ ass:append(style .. '{\\alpha&HFF&}> ' .. before_cur)
+ ass:append(cglyph)
+ ass:append(style .. '{\\alpha&HFF&}' .. after_cur)
+
+ mp.set_osd_ass(screenx, screeny, ass.text)
+end
+
+-- Naive helper function to find the next UTF-8 character in 'str' after 'pos'
+-- by skipping continuation bytes. Assumes 'str' contains valid UTF-8.
+local function next_utf8(str, pos)
+ if pos > str:len() then return pos end
+ repeat
+ pos = pos + 1
+ until pos > str:len() or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf
+ return pos
+end
+
+-- As above, but finds the previous UTF-8 charcter in 'str' before 'pos'
+local function prev_utf8(str, pos)
+ if pos <= 1 then return pos end
+ repeat
+ pos = pos - 1
+ until pos <= 1 or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf
+ return pos
+end
+
+-- Insert a character at the current cursor position (any_unicode, Shift+Enter)
+local function handle_char_input(c)
+ if insert_mode then
+ line = line:sub(1, cursor - 1) .. c .. line:sub(next_utf8(line, cursor))
+ else
+ line = line:sub(1, cursor - 1) .. c .. line:sub(cursor)
+ end
+ cursor = cursor + #c
+ update()
+end
+
+-- Remove the character behind the cursor (Backspace)
+local function handle_backspace()
+ if cursor <= 1 then return end
+ local prev = prev_utf8(line, cursor)
+ line = line:sub(1, prev - 1) .. line:sub(cursor)
+ cursor = prev
+ update()
+end
+
+-- Remove the character in front of the cursor (Del)
+local function handle_del()
+ if cursor > line:len() then return end
+ line = line:sub(1, cursor - 1) .. line:sub(next_utf8(line, cursor))
+ update()
+end
+
+-- Toggle insert mode (Ins)
+local function handle_ins()
+ insert_mode = not insert_mode
+end
+
+-- Move the cursor to the next character (Right)
+local function next_char(amount)
+ cursor = next_utf8(line, cursor)
+ update()
+end
+
+-- Move the cursor to the previous character (Left)
+local function prev_char(amount)
+ cursor = prev_utf8(line, cursor)
+ update()
+end
+
+-- Clear the current line (Ctrl+C)
+local function clear()
+ line = ''
+ cursor = 1
+ insert_mode = false
+ request.history.pos = #request.history.list + 1
+ update()
+end
+
+-- Close the REPL if the current line is empty, otherwise do nothing (Ctrl+D)
+local function maybe_exit()
+ if line == '' then
+ send_response(false, "exitted")
+ queue:pop()
+ end
+end
+
+local function handle_esc()
+ send_response(false, "exitted")
+ queue:pop()
+end
+
+-- Run the current command and clear the line (Enter)
+local function handle_enter()
+ if request.history.list[#request.history.list] ~= line and line ~= "" then
+ request.history.list[#request.history.list + 1] = line
+ end
+ send_response(true)
+ queue:pop()
+end
+
+-- Go to the specified position in the command history
+local function go_history(new_pos)
+ local old_pos = request.history.pos
+ request.history.pos = new_pos
+
+ -- Restrict the position to a legal value
+ if request.history.pos > #request.history.list + 1 then
+ request.history.pos = #request.history.list + 1
+ elseif request.history.pos < 1 then
+ request.history.pos = 1
+ end
+
+ -- Do nothing if the history position didn't actually change
+ if request.history.pos == old_pos then
+ return
+ end
+
+ -- If the user was editing a non-history line, save it as the last history
+ -- entry. This makes it much less frustrating to accidentally hit Up/Down
+ -- while editing a line.
+ if old_pos == #request.history.list + 1 and line ~= '' and request.history.list[#request.history.list] ~= line then
+ request.history.list[#request.history.list + 1] = line
+ end
+
+ -- Now show the history line (or a blank line for #history + 1)
+ if request.history.pos <= #request.history.list then
+ line = request.history.list[request.history.pos]
+ else
+ line = ''
+ end
+ cursor = line:len() + 1
+ insert_mode = false
+ update()
+end
+
+-- Go to the specified relative position in the command history (Up, Down)
+local function move_history(amount)
+ go_history(request.history.pos + amount)
+end
+
+-- Go to the first command in the command history (PgUp)
+local function handle_pgup()
+ go_history(1)
+end
+
+-- Stop browsing history and start editing a blank line (PgDown)
+local function handle_pgdown()
+ go_history(#request.history.list + 1)
+end
+
+-- Move to the start of the current word, or if already at the start, the start
+-- of the previous word. (Ctrl+Left)
+local function prev_word()
+ -- This is basically the same as next_word() but backwards, so reverse the
+ -- string in order to do a "backwards" find. This wouldn't be as annoying
+ -- to do if Lua didn't insist on 1-based indexing.
+ cursor = line:len() - select(2, line:reverse():find('%s*[^%s]*', line:len() - cursor + 2)) + 1
+ update()
+end
+
+-- Move to the end of the current word, or if already at the end, the end of
+-- the next word. (Ctrl+Right)
+local function next_word()
+ cursor = select(2, line:find('%s*[^%s]*', cursor)) + 1
+ update()
+end
+
+-- Move the cursor to the beginning of the line (HOME)
+local function go_home()
+ cursor = 1
+ update()
+end
+
+-- Move the cursor to the end of the line (END)
+local function go_end()
+ cursor = line:len() + 1
+ update()
+end
+
+-- Delete from the cursor to the end of the word (Ctrl+W)
+local function del_word()
+ local before_cur = line:sub(1, cursor - 1)
+ local after_cur = line:sub(cursor)
+
+ before_cur = before_cur:gsub('[^%s]+%s*$', '', 1)
+ line = before_cur .. after_cur
+ cursor = before_cur:len() + 1
+ update()
+end
+
+-- Delete from the cursor to the end of the line (Ctrl+K)
+local function del_to_eol()
+ line = line:sub(1, cursor - 1)
+ update()
+end
+
+-- Delete from the cursor back to the start of the line (Ctrl+U)
+local function del_to_start()
+ line = line:sub(cursor)
+ cursor = 1
+ update()
+end
+
+-- Returns a string of UTF-8 text from the clipboard (or the primary selection)
+local function get_clipboard(clip)
+ if platform == 'x11' then
+ local res = utils.subprocess({
+ args = { 'xclip', '-selection', clip and 'clipboard' or 'primary', '-out' },
+ playback_only = false,
+ })
+ if not res.error then
+ return res.stdout
+ end
+ elseif platform == 'wayland' then
+ local res = utils.subprocess({
+ args = { 'wl-paste', clip and '-n' or '-np' },
+ playback_only = false,
+ })
+ if not res.error then
+ return res.stdout
+ end
+ elseif platform == 'windows' then
+ local res = utils.subprocess({
+ args = { 'powershell', '-NoProfile', '-Command', [[& {
+ Trap {
+ Write-Error -ErrorRecord $_
+ Exit 1
+ }
+
+ $clip = ""
+ if (Get-Command "Get-Clipboard" -errorAction SilentlyContinue) {
+ $clip = Get-Clipboard -Raw -Format Text -TextFormatType UnicodeText
+ } else {
+ Add-Type -AssemblyName PresentationCore
+ $clip = [Windows.Clipboard]::GetText()
+ }
+
+ $clip = $clip -Replace "`r",""
+ $u8clip = [System.Text.Encoding]::UTF8.GetBytes($clip)
+ [Console]::OpenStandardOutput().Write($u8clip, 0, $u8clip.Length)
+ }]] },
+ playback_only = false,
+ })
+ if not res.error then
+ return res.stdout
+ end
+ elseif platform == 'macos' then
+ local res = utils.subprocess({
+ args = { 'pbpaste' },
+ playback_only = false,
+ })
+ if not res.error then
+ return res.stdout
+ end
+ end
+ return ''
+end
+
+-- Paste text from the window-system's clipboard. 'clip' determines whether the
+-- clipboard or the primary selection buffer is used (on X11 and Wayland only.)
+local function paste(clip)
+ local text = get_clipboard(clip)
+ local before_cur = line:sub(1, cursor - 1)
+ local after_cur = line:sub(cursor)
+ line = before_cur .. text .. after_cur
+ cursor = cursor + text:len()
+ update()
+end
+
+-- List of input bindings. This is a weird mashup between common GUI text-input
+-- bindings and readline bindings.
+local function get_bindings()
+ local bindings = {
+ { 'esc', handle_esc },
+ { 'enter', handle_enter },
+ { 'kp_enter', handle_enter },
+ { 'shift+enter', function() handle_char_input('\n') end },
+ { 'bs', handle_backspace },
+ { 'shift+bs', handle_backspace },
+ { 'del', handle_del },
+ { 'shift+del', handle_del },
+ { 'ins', handle_ins },
+ { 'shift+ins', function() paste(false) end },
+ { 'mbtn_mid', function() paste(false) end },
+ { 'left', function() prev_char() end },
+ { 'right', function() next_char() end },
+ { 'up', function() move_history(-1) end },
+ { 'wheel_up', function() move_history(-1) end },
+ { 'down', function() move_history(1) end },
+ { 'wheel_down', function() move_history(1) end },
+ { 'wheel_left', function() end },
+ { 'wheel_right', function() end },
+ { 'ctrl+left', prev_word },
+ { 'ctrl+right', next_word },
+ { 'home', go_home },
+ { 'end', go_end },
+ { 'pgup', handle_pgup },
+ { 'pgdwn', handle_pgdown },
+ { 'ctrl+c', clear },
+ { 'ctrl+d', maybe_exit },
+ { 'ctrl+k', del_to_eol },
+ { 'ctrl+u', del_to_start },
+ { 'ctrl+v', function() paste(true) end },
+ { 'meta+v', function() paste(true) end },
+ { 'ctrl+w', del_word },
+ { 'kp_dec', function() handle_char_input('.') end },
+ }
+
+ for i = 0, 9 do
+ bindings[#bindings + 1] =
+ {'kp' .. i, function() handle_char_input('' .. i) end}
+ end
+
+ return bindings
+end
+
+local function text_input(info)
+ if info.key_text and (info.event == "press" or info.event == "down"
+ or info.event == "repeat")
+ then
+ handle_char_input(info.key_text)
+ end
+end
+
+local function define_key_bindings()
+ if #key_bindings > 0 then
+ return
+ end
+ for _, bind in ipairs(get_bindings()) do
+ -- Generate arbitrary name for removing the bindings later.
+ local name = "_userinput_" .. bind[1]
+ key_bindings[#key_bindings + 1] = name
+ mp.add_forced_key_binding(bind[1], name, bind[2], {repeatable = true})
+ end
+ mp.add_forced_key_binding("any_unicode", "_userinput_text", text_input,
+ {repeatable = true, complex = true})
+ key_bindings[#key_bindings + 1] = "_userinput_text"
+end
+
+local function undefine_key_bindings()
+ for _, name in ipairs(key_bindings) do
+ mp.remove_key_binding(name)
+ end
+ key_bindings = {}
+end
+
+-- Set the REPL visibility ("enable", Esc)
+local function set_active(active)
+ if active == repl_active then return end
+ if active then
+ repl_active = true
+ insert_mode = false
+ define_key_bindings()
+ else
+ clear()
+ repl_active = false
+ undefine_key_bindings()
+ collectgarbage()
+ end
+ update()
+end
+
+
+utils.shared_script_property_observe("osc-margins", function(_, val)
+ if val then
+ -- formatted as "%f,%f,%f,%f" with left, right, top, bottom, each
+ -- value being the border size as ratio of the window size (0.0-1.0)
+ local vals = {}
+ for v in string.gmatch(val, "[^,]+") do
+ vals[#vals + 1] = tonumber(v)
+ end
+ global_margin_y = vals[4] -- bottom
+ else
+ global_margin_y = 0
+ end
+ update()
+end)
+
+-- Redraw the REPL when the OSD size changes. This is needed because the
+-- PlayRes of the OSD will need to be adjusted.
+mp.observe_property('osd-width', 'native', update)
+mp.observe_property('osd-height', 'native', update)
+mp.observe_property('display-hidpi-scale', 'native', update)
+
+----------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------
+-------------------------------END ORIGINAL MPV CODE------------------------------------
+
+-- push new request onto the queue
+-- if a request with the same id already exists and the queueable flag is not enabled then
+-- a nil result will be returned to the function
+function queue:push(req)
+ if self.active_ids[req.id] then
+
+ -- replace an existing request with the new one
+ if req.replace then
+ for i = 1, #self.queue do
+ if self.queue[i].id == req.id then
+ send_response(false, "replaced", self.queue[i].response)
+ self.queue[i] = req
+ if i == 1 then request = req ; update() end
+ return
+ end
+ end
+ end
+
+ --cancel the new request if it is not queueable
+ if not req.queueable then send_response(false, "already_queued", req.response) ; return end
+ end
+
+ table.insert(self.queue, req)
+ self.active_ids[req.id] = (self.active_ids[req.id] or 0) + 1
+ if #self.queue == 1 then return self:start_queue() end
+end
+
+-- removes the first item in the queue and either continues or stops the queue
+function queue:pop()
+ self:remove(1)
+ clear()
+
+ if #self.queue < 1 then return self:stop_queue()
+ else return self:continue_queue() end
+end
+
+-- safely removes an item from the queue and updates the set of active requests
+function queue:remove(index)
+ local req = table.remove(self.queue, index)
+ self.active_ids[req.id] = self.active_ids[req.id] ~= 1 and self.active_ids[req.id] - 1 or nil
+end
+
+function queue:start_queue()
+ request = self.queue[1]
+ line = request.default_input
+ set_active(true)
+end
+
+function queue:continue_queue()
+ request = self.queue[1]
+ line = request.default_input
+ update()
+end
+
+function queue:stop_queue()
+ set_active(false)
+end
+
+-- removes all requests with the specified id from the queue
+mp.register_script_message("cancel-user-input", function(id)
+ local i = 2
+ while i <= #queue.queue do
+ if queue.queue[i].id == id then
+ send_response(false, "cancelled", queue.queue[i].response)
+ queue:remove(i)
+ else
+ i = i + 1
+ end
+ end
+
+ if queue.queue[1] and queue.queue[1].id == id then
+ send_response(false, "cancelled")
+ queue:pop()
+ end
+end)
+
+-- script message to recieve input requests, get-user-input.lua acts as an interface to call this script message
+-- requests are recieved as json objects
+mp.register_script_message("request-user-input", function(response, id, request_text, default_input, queueable, replace)
+ local req = {}
+
+ if not response then msg.error("input requests require a response string") ; return end
+ if not id then msg.error("input requests require an id string") ; return end
+ req.response = response
+ req.text = ass_escape(request_text or "")
+ req.default_input = default_input
+ req.id = id or "mpv"
+ req.queueable = (queueable == "1")
+ req.replace = (replace == "1")
+
+ if not histories[id] then histories[id] = {pos = 1, list = {}} end
+ req.history = histories[id]
+
+ queue:push(req)
+end)
+
+--temporary keybind for debugging purposes
+mp.add_key_binding("Ctrl+i", "user-input", function() set_active(true) end)
diff --git a/mpv/scripts/youtube-quality.lua b/mpv/scripts/youtube-quality.lua
new file mode 100644
index 0000000..b587f37
--- /dev/null
+++ b/mpv/scripts/youtube-quality.lua
@@ -0,0 +1,275 @@
+-- youtube-quality.lua
+--
+-- Change youtube video quality on the fly.
+--
+-- Diplays a menu that lets you switch to different ytdl-format settings while
+-- you're in the middle of a video (just like you were using the web player).
+--
+-- Bound to ctrl-f by default.
+
+local mp = require 'mp'
+local utils = require 'mp.utils'
+local msg = require 'mp.msg'
+local assdraw = require 'mp.assdraw'
+
+local opts = {
+ --key bindings
+ toggle_menu_binding = "ctrl+f",
+ up_binding = "UP",
+ down_binding = "DOWN",
+ select_binding = "ENTER",
+
+ --formatting / cursors
+ selected_and_active = "▶ - ",
+ selected_and_inactive = "● - ",
+ unselected_and_active = "▷ - ",
+ unselected_and_inactive = "○ - ",
+
+ --font size scales by window, if false requires larger font and padding sizes
+ scale_playlist_by_window=false,
+
+ --playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua
+ --example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1
+ --read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags
+ --undeclared tags will use default osd settings
+ --these styles will be used for the whole playlist. More specific styling will need to be hacked in
+ --
+ --(a monospaced font is recommended but not required)
+ style_ass_tags = "{\\fnmonospace}",
+
+ --paddings for top left corner
+ text_padding_x = 5,
+ text_padding_y = 5,
+
+ --other
+ menu_timeout = 10,
+
+ --use youtube-dl to fetch a list of available formats (overrides quality_strings)
+ fetch_formats = true,
+
+ --default menu entries
+ quality_strings=[[
+ [
+ {"4320p" : "bestvideo[height<=?4320p]+bestaudio/best"},
+ {"2160p" : "bestvideo[height<=?2160]+bestaudio/best"},
+ {"1440p" : "bestvideo[height<=?1440]+bestaudio/best"},
+ {"1080p" : "bestvideo[height<=?1080]+bestaudio/best"},
+ {"720p" : "bestvideo[height<=?720]+bestaudio/best"},
+ {"480p" : "bestvideo[height<=?480]+bestaudio/best"},
+ {"360p" : "bestvideo[height<=?360]+bestaudio/best"},
+ {"240p" : "bestvideo[height<=?240]+bestaudio/best"},
+ {"144p" : "bestvideo[height<=?144]+bestaudio/best"}
+ ]
+ ]],
+}
+(require 'mp.options').read_options(opts, "youtube-quality")
+opts.quality_strings = utils.parse_json(opts.quality_strings)
+
+local destroyer = nil
+
+
+function show_menu()
+ local selected = 1
+ local active = 0
+ local current_ytdl_format = mp.get_property("ytdl-format")
+ msg.verbose("current ytdl-format: "..current_ytdl_format)
+ local num_options = 0
+ local options = {}
+
+
+ if opts.fetch_formats then
+ options, num_options = download_formats()
+ end
+
+ if next(options) == nil then
+ for i,v in ipairs(opts.quality_strings) do
+ num_options = num_options + 1
+ for k,v2 in pairs(v) do
+ options[i] = {label = k, format=v2}
+ if v2 == current_ytdl_format then
+ active = i
+ selected = active
+ end
+ end
+ end
+ end
+
+ --set the cursor to the currently format
+ for i,v in ipairs(options) do
+ if v.format == current_ytdl_format then
+ active = i
+ selected = active
+ break
+ end
+ end
+
+ function selected_move(amt)
+ selected = selected + amt
+ if selected < 1 then selected = num_options
+ elseif selected > num_options then selected = 1 end
+ timeout:kill()
+ timeout:resume()
+ draw_menu()
+ end
+ function choose_prefix(i)
+ if i == selected and i == active then return opts.selected_and_active
+ elseif i == selected then return opts.selected_and_inactive end
+
+ if i ~= selected and i == active then return opts.unselected_and_active
+ elseif i ~= selected then return opts.unselected_and_inactive end
+ return "> " --shouldn't get here.
+ end
+
+ function draw_menu()
+ local ass = assdraw.ass_new()
+
+ ass:pos(opts.text_padding_x, opts.text_padding_y)
+ ass:append(opts.style_ass_tags)
+
+ for i,v in ipairs(options) do
+ ass:append(choose_prefix(i)..v.label.."\\N")
+ end
+
+ local w, h = mp.get_osd_size()
+ if opts.scale_playlist_by_window then w,h = 0, 0 end
+ mp.set_osd_ass(w, h, ass.text)
+ end
+
+ function destroy()
+ timeout:kill()
+ mp.set_osd_ass(0,0,"")
+ mp.remove_key_binding("move_up")
+ mp.remove_key_binding("move_down")
+ mp.remove_key_binding("select")
+ mp.remove_key_binding("escape")
+ destroyer = nil
+ end
+ timeout = mp.add_periodic_timer(opts.menu_timeout, destroy)
+ destroyer = destroy
+
+ mp.add_forced_key_binding(opts.up_binding, "move_up", function() selected_move(-1) end, {repeatable=true})
+ mp.add_forced_key_binding(opts.down_binding, "move_down", function() selected_move(1) end, {repeatable=true})
+ mp.add_forced_key_binding(opts.select_binding, "select", function()
+ destroy()
+ mp.set_property("ytdl-format", options[selected].format)
+ reload_resume()
+ end)
+ mp.add_forced_key_binding(opts.toggle_menu_binding, "escape", destroy)
+
+ draw_menu()
+ return
+end
+
+local ytdl = {
+ path = "youtube-dl",
+ searched = false,
+ blacklisted = {}
+}
+
+format_cache={}
+function download_formats()
+ local function exec(args)
+ local ret = utils.subprocess({args = args})
+ return ret.status, ret.stdout, ret
+ end
+
+ local function table_size(t)
+ s = 0
+ for i,v in ipairs(t) do
+ s = s+1
+ end
+ return s
+ end
+
+ local url = mp.get_property("path")
+
+ url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix.
+
+ -- don't fetch the format list if we already have it
+ if format_cache[url] ~= nil then
+ local res = format_cache[url]
+ return res, table_size(res)
+ end
+ mp.osd_message("fetching available formats with youtube-dl...", 60)
+
+ if not (ytdl.searched) then
+ local ytdl_mcd = mp.find_config_file("youtube-dl")
+ if not (ytdl_mcd == nil) then
+ msg.verbose("found youtube-dl at: " .. ytdl_mcd)
+ ytdl.path = ytdl_mcd
+ end
+ ytdl.searched = true
+ end
+
+ local command = {ytdl.path, "--no-warnings", "--no-playlist", "-J"}
+ table.insert(command, url)
+ local es, json, result = exec(command)
+
+ if (es < 0) or (json == nil) or (json == "") then
+ mp.osd_message("fetching formats failed...", 1)
+ msg.error("failed to get format list: " .. err)
+ return {}, 0
+ end
+
+ local json, err = utils.parse_json(json)
+
+ if (json == nil) then
+ mp.osd_message("fetching formats failed...", 1)
+ msg.error("failed to parse JSON data: " .. err)
+ return {}, 0
+ end
+
+ res = {}
+ msg.verbose("youtube-dl succeeded!")
+ for i,v in ipairs(json.formats) do
+ if v.vcodec ~= "none" then
+ local fps = v.fps and v.fps.."fps" or ""
+ local resolution = string.format("%sx%s", v.width, v.height)
+ local l = string.format("%-9s %-5s (%-4s / %s)", resolution, fps, v.ext, v.vcodec)
+ local f = string.format("%s+bestaudio/best", v.format_id)
+ table.insert(res, {label=l, format=f, width=v.width })
+ end
+ end
+
+ table.sort(res, function(a, b) return a.width > b.width end)
+
+ mp.osd_message("", 0)
+ format_cache[url] = res
+ return res, table_size(res)
+end
+
+
+-- register script message to show menu
+mp.register_script_message("toggle-quality-menu",
+function()
+ if destroyer ~= nil then
+ destroyer()
+ else
+ show_menu()
+ end
+end)
+
+-- keybind to launch menu
+mp.add_key_binding(opts.toggle_menu_binding, "quality-menu", show_menu)
+
+-- special thanks to reload.lua (https://github.com/4e6/mpv-reload/)
+function reload_resume()
+ local playlist_pos = mp.get_property_number("playlist-pos")
+ local reload_duration = mp.get_property_native("duration")
+ local time_pos = mp.get_property("time-pos")
+
+ mp.set_property_number("playlist-pos", playlist_pos)
+
+ -- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero
+ -- duration property. When reloading VOD, to keep the current time position
+ -- we should provide offset from the start. Stream doesn't have fixed start.
+ -- Decent choice would be to reload stream from it's current 'live' positon.
+ -- That's the reason we don't pass the offset when reloading streams.
+ if reload_duration and reload_duration > 0 then
+ local function seeker()
+ mp.commandv("seek", time_pos, "absolute")
+ mp.unregister_event(seeker)
+ end
+ mp.register_event("file-loaded", seeker)
+ end
+end
diff --git a/mpv/scripts/youtube-serarch.lua b/mpv/scripts/youtube-serarch.lua
new file mode 100644
index 0000000..dfe04c6
--- /dev/null
+++ b/mpv/scripts/youtube-serarch.lua
@@ -0,0 +1,149 @@
+--[[
+ This script allows users to search and open youtube results from within mpv.
+ Available at: https://github.com/CogentRedTester/mpv-scripts
+ Users can open the search page with Y, and use Y again to open a search.
+ Alternatively, Ctrl+y can be used at any time to open a search.
+ Esc can be used to close the page.
+ Enter will open the selected item, Shift+Enter will append the item to the playlist.
+ This script requires that my other scripts `scroll-list` and `user-input` be installed.
+ scroll-list.lua and user-input-module.lua must be in the ~~/script-modules/ directory,
+ while user-input.lua should be loaded by mpv normally.
+ https://github.com/CogentRedTester/mpv-scroll-list
+ https://github.com/CogentRedTester/mpv-user-input
+ This script also requires a youtube API key to be entered.
+ The API key must be passed to the `API_key` script-opt.
+ A personal API key is free and can be created from:
+ https://console.developers.google.com/apis/api/youtube.googleapis.com/
+ The script also requires that curl be in the system path.
+]]--
+
+local mp = require "mp"
+local msg = require "mp.msg"
+local utils = require "mp.utils"
+local opts = require "mp.options"
+
+package.path = mp.command_native({"expand-path", "~~/lua-modules/?.lua;"}) .. package.path
+local ui = require "user-input-module"
+local list = require "scroll-list"
+
+list.header = "Youtube Search Results\\N-----------------------------"
+list.num_entries = 18
+list.list_style = [[{\fs10}\N{\q2\fs25\c&Hffffff&}]]
+
+local o = {
+ API_key = "AIzaSyB3IuyFp8C5SYEgJ0BSGgKZZjfUtuVGl44",
+ num_results = 40
+}
+
+opts.read_options(o)
+
+local ass_escape = list.ass_escape
+
+--taken from: https://gist.github.com/liukun/f9ce7d6d14fa45fe9b924a3eed5c3d99
+local function urlencode(url)
+ if type(url) ~= "string" then return url end
+ url = url:gsub("\n", "\r\n")
+ url = url:gsub("([^%w ])", function (c) string.format("%%%02X", string.byte(c)) end)
+ url = url:gsub(" ", "+")
+ return url
+end
+
+--sends an API request
+local function send_request(type, queries)
+ local url = "https://www.googleapis.com/youtube/v3/"..type
+
+ url = url.."?key="..o.API_key
+
+ for key, value in pairs(queries) do
+ url = url.."&"..key.."="..urlencode(value)
+ end
+
+
+ local request = mp.command_native({
+ name = "subprocess",
+ capture_stdout = true,
+ capture_stderr = true,
+ playback_only = false,
+ args = {"curl", url}
+ })
+
+ local response = utils.parse_json(request.stdout)
+ if request.status ~= 0 then msg.error(request.stderr) ; return nil end
+ return response
+end
+
+local function insert_video(item)
+ list:insert({
+ ass = ("%s {\\c&aaaaaa&}%s"):format(ass_escape(item.snippet.title), ass_escape(item.snippet.channelTitle)),
+ url = "https://www.youtube.com/watch?v="..item.id.videoId
+ })
+end
+
+local function insert_playlist(item)
+ list:insert({
+ ass = ("🖿 %s {\\c&aaaaaa&}%s"):format(ass_escape(item.snippet.title), ass_escape(item.snippet.channelTitle)),
+ url = "https://www.youtube.com/playlist?list="..item.id.playlistId
+ })
+end
+
+local function insert_channel(item)
+ list:insert({
+ ass = ("👤 %s"):format(ass_escape(item.snippet.title)),
+ url = "https://www.youtube.com/channel/"..item.id.channelId
+ })
+end
+
+local function reset_list()
+ list.selected = 1
+ list:clear()
+end
+
+local function search(query)
+ local response = send_request("search", {
+ q = query,
+ part = "id,snippet",
+ maxResults = o.num_results
+ })
+
+ if not response then return end
+ reset_list()
+
+ for _, item in ipairs(response.items) do
+ if item.id.kind == "youtube#video" then
+ insert_video(item)
+ elseif item.id.kind == "youtube#playlist" then
+ insert_playlist(item)
+ elseif item.id.kind == "youtube#channel" then
+ insert_channel(item)
+ end
+ end
+ list.header = "Youtube Search: "..ass_escape(query).."\\N-------------------------------------------------"
+ list:update()
+ list:open()
+end
+
+local function play_result(flag)
+ if not list[list.selected] then return end
+ if flag == "new_window" then mp.commandv("run", "mpv", list[list.selected].url) ; return end
+
+ mp.commandv("loadfile", list[list.selected].url, flag)
+ if flag == "replace" then list:close() end
+end
+
+table.insert(list.keybinds, {"ENTER", "play", function() play_result("replace") end, {}})
+table.insert(list.keybinds, {"Shift+ENTER", "play_append", function() play_result("append-play") end, {}})
+table.insert(list.keybinds, {"Ctrl+ENTER", "play_new_window", function() play_result("new_window") end, {}})
+
+local function open_search_input()
+ ui.get_user_input(function(input)
+ if not input then return end
+ search( input )
+ end)
+end
+
+mp.add_key_binding("Ctrl+y", "yt", open_search_input)
+
+mp.add_key_binding("Y", "youtube-search", function()
+ if not list.hidden then open_search_input()
+ else list:open() end
+end)
diff --git a/ncmpcpp/config b/ncmpcpp/config
new file mode 100644
index 0000000..39ca059
--- /dev/null
+++ b/ncmpcpp/config
@@ -0,0 +1,101 @@
+ncmpcpp_directory = ~/.ncmpcpp
+lyrics_directory = ~/.ncmpcpp/lyrics
+
+mpd_host = "127.0.0.1"
+mpd_port = "6600"
+mpd_connection_timeout = 5
+mpd_crossfade_time = 5
+
+mpd_music_dir = "/data/Music/"
+
+audio_output {
+ type "my_fifo"
+ name "Visualizer feed"
+ path "/tmp/mpd.fifo"
+ format "44100:16:2"
+}
+visualizer_output_name = "my_fifo"
+visualizer_type = "ellipse"
+execute_on_song_change = nowplaying
+
+visualizer_look = "●┃"
+visualizer_in_stereo = "yes"
+
+system_encoding = "utf-8"
+playlist_disable_highlight_delay = "0"
+message_delay_time = 5
+
+now_playing_suffix = $/b
+selected_item_prefix = "* "
+
+browser_sort_mode = name
+browser_sort_format = {%a - }{%t}|{%f} {(%l)}
+song_list_format = "{{%a - %t}|{%f}}{$R%l}"
+song_columns_list_format = "(50)[green]{t|f:Title} (40)[cyan]{ar} (5f)[cyan]{l}"
+# song_columns_list_format = "(50)[cyan]{ar}(50)[green]{t|f:Title}"
+song_status_format = "{$2 $8%a $3: $8%t $3 $6%b}|{$b$2 $8%f}"
+
+progressbar_elapsed_color = cyan
+statusbar_color = green
+statusbar_time_color = cyan
+ playlist_display_mode = "columns"
+
+ browser_display_mode = "columns"
+
+ playlist_disable_highlight_delay = "0"
+
+ playlist_show_remaining_time = "yes"
+
+discard_colors_if_item_is_selected = "no"
+
+incremental_seeking = "yes"
+seek_time = "1"
+
+autocenter_mode = yes
+centered_cursor = yes
+progressbar_look = "━|━"
+# user_interface = "alternative"
+#
+header_visibility = no
+statusbar_visibility = yes
+titles_visibility = no
+header_text_scrolling = yes
+#
+#follow_now_playing_lyrics = no
+fetch_lyrics_for_current_song_in_background = yes
+ask_before_clearing_playlists = yes
+#
+#clock_display_seconds = no
+#
+
+display_volume_level = "no"
+
+display_bitrate = "no"
+search_engine_default_search_mode = 2
+
+external_editor = "/usr/bin/nvim"
+use_console_editor = yes
+
+ follow_now_playing_lyrics = "yes"
+
+ display_screens_numbers_on_start = "yes"
+
+ lyrics_database = "1"
+
+default_place_to_search_in = "database"
+
+lyrics_fetchers = azlyrics, genius, sing365, metrolyrics, justsomelyrics, jahlyrics, plyrics, tekstowo, internet
+
+## Navigation ##
+cyclic_scrolling = "yes"
+jump_to_now_playing_song_at_start = "yes"
+lines_scrolled = "2"
+#fancy_scrolling = "yes"
+
+## Other ##
+regular_expressions = "extended"
+
+# enable_window_title = "no"
+follow_now_playing_lyrics = "yes"
+ignore_leading_the = "yes"
+empty_tag_marker = ""
diff --git a/neofetch/config.conf b/neofetch/config.conf
new file mode 100644
index 0000000..cdba4c6
--- /dev/null
+++ b/neofetch/config.conf
@@ -0,0 +1,864 @@
+# See this wiki page for more info:
+# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
+print_info() {
+ info title
+ info underline
+
+ info "OS" distro
+ info "Host" model
+ info "Kernel" kernel
+ info "Uptime" uptime
+ info "Packages" packages
+ info "Shell" shell
+ info "Resolution" resolution
+ info "DE" de
+ info "WM" wm
+ info "WM Theme" wm_theme
+ info "Theme" theme
+ info "Icons" icons
+ info "Terminal" term
+ info "Terminal Font" term_font
+ info "CPU" cpu
+ info "GPU" gpu
+ info "Memory" memory
+
+ # info "GPU Driver" gpu_driver # Linux/macOS only
+ # info "CPU Usage" cpu_usage
+ # info "Disk" disk
+ # info "Battery" battery
+ # info "Font" font
+ # info "Song" song
+ # [[ "$player" ]] && prin "Music Player" "$player"
+ # info "Local IP" local_ip
+ # info "Public IP" public_ip
+ # info "Users" users
+ # info "Locale" locale # This only works on glibc systems.
+
+ info cols
+}
+
+# Title
+
+
+# Hide/Show Fully qualified domain name.
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --title_fqdn
+title_fqdn="off"
+
+
+# Kernel
+
+
+# Shorten the output of the kernel function.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --kernel_shorthand
+# Supports: Everything except *BSDs (except PacBSD and PC-BSD)
+#
+# Example:
+# on: '4.8.9-1-ARCH'
+# off: 'Linux 4.8.9-1-ARCH'
+kernel_shorthand="on"
+
+
+# Distro
+
+
+# Shorten the output of the distro function
+#
+# Default: 'off'
+# Values: 'on', 'tiny', 'off'
+# Flag: --distro_shorthand
+# Supports: Everything except Windows and Haiku
+distro_shorthand="off"
+
+# Show/Hide OS Architecture.
+# Show 'x86_64', 'x86' and etc in 'Distro:' output.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --os_arch
+#
+# Example:
+# on: 'Arch Linux x86_64'
+# off: 'Arch Linux'
+os_arch="on"
+
+
+# Uptime
+
+
+# Shorten the output of the uptime function
+#
+# Default: 'on'
+# Values: 'on', 'tiny', 'off'
+# Flag: --uptime_shorthand
+#
+# Example:
+# on: '2 days, 10 hours, 3 mins'
+# tiny: '2d 10h 3m'
+# off: '2 days, 10 hours, 3 minutes'
+uptime_shorthand="on"
+
+
+# Memory
+
+
+# Show memory pecentage in output.
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --memory_percent
+#
+# Example:
+# on: '1801MiB / 7881MiB (22%)'
+# off: '1801MiB / 7881MiB'
+memory_percent="off"
+
+# Change memory output unit.
+#
+# Default: 'mib'
+# Values: 'kib', 'mib', 'gib'
+# Flag: --memory_unit
+#
+# Example:
+# kib '1020928KiB / 7117824KiB'
+# mib '1042MiB / 6951MiB'
+# gib: ' 0.98GiB / 6.79GiB'
+memory_unit="mib"
+
+
+# Packages
+
+
+# Show/Hide Package Manager names.
+#
+# Default: 'tiny'
+# Values: 'on', 'tiny' 'off'
+# Flag: --package_managers
+#
+# Example:
+# on: '998 (pacman), 8 (flatpak), 4 (snap)'
+# tiny: '908 (pacman, flatpak, snap)'
+# off: '908'
+package_managers="on"
+
+
+# Shell
+
+
+# Show the path to $SHELL
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --shell_path
+#
+# Example:
+# on: '/bin/bash'
+# off: 'bash'
+shell_path="off"
+
+# Show $SHELL version
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --shell_version
+#
+# Example:
+# on: 'bash 4.4.5'
+# off: 'bash'
+shell_version="on"
+
+
+# CPU
+
+
+# CPU speed type
+#
+# Default: 'bios_limit'
+# Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'.
+# Flag: --speed_type
+# Supports: Linux with 'cpufreq'
+# NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value.
+speed_type="bios_limit"
+
+# CPU speed shorthand
+#
+# Default: 'off'
+# Values: 'on', 'off'.
+# Flag: --speed_shorthand
+# NOTE: This flag is not supported in systems with CPU speed less than 1 GHz
+#
+# Example:
+# on: 'i7-6500U (4) @ 3.1GHz'
+# off: 'i7-6500U (4) @ 3.100GHz'
+speed_shorthand="off"
+
+# Enable/Disable CPU brand in output.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --cpu_brand
+#
+# Example:
+# on: 'Intel i7-6500U'
+# off: 'i7-6500U (4)'
+cpu_brand="on"
+
+# CPU Speed
+# Hide/Show CPU speed.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --cpu_speed
+#
+# Example:
+# on: 'Intel i7-6500U (4) @ 3.1GHz'
+# off: 'Intel i7-6500U (4)'
+cpu_speed="on"
+
+# CPU Cores
+# Display CPU cores in output
+#
+# Default: 'logical'
+# Values: 'logical', 'physical', 'off'
+# Flag: --cpu_cores
+# Support: 'physical' doesn't work on BSD.
+#
+# Example:
+# logical: 'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores)
+# physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores)
+# off: 'Intel i7-6500U @ 3.1GHz'
+cpu_cores="logical"
+
+# CPU Temperature
+# Hide/Show CPU temperature.
+# Note the temperature is added to the regular CPU function.
+#
+# Default: 'off'
+# Values: 'C', 'F', 'off'
+# Flag: --cpu_temp
+# Supports: Linux, BSD
+# NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable
+# coretemp kernel module. This only supports newer Intel processors.
+#
+# Example:
+# C: 'Intel i7-6500U (4) @ 3.1GHz [27.2°C]'
+# F: 'Intel i7-6500U (4) @ 3.1GHz [82.0°F]'
+# off: 'Intel i7-6500U (4) @ 3.1GHz'
+cpu_temp="off"
+
+
+# GPU
+
+
+# Enable/Disable GPU Brand
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --gpu_brand
+#
+# Example:
+# on: 'AMD HD 7950'
+# off: 'HD 7950'
+gpu_brand="on"
+
+# Which GPU to display
+#
+# Default: 'all'
+# Values: 'all', 'dedicated', 'integrated'
+# Flag: --gpu_type
+# Supports: Linux
+#
+# Example:
+# all:
+# GPU1: AMD HD 7950
+# GPU2: Intel Integrated Graphics
+#
+# dedicated:
+# GPU1: AMD HD 7950
+#
+# integrated:
+# GPU1: Intel Integrated Graphics
+gpu_type="all"
+
+
+# Resolution
+
+
+# Display refresh rate next to each monitor
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --refresh_rate
+# Supports: Doesn't work on Windows.
+#
+# Example:
+# on: '1920x1080 @ 60Hz'
+# off: '1920x1080'
+refresh_rate="off"
+
+
+# Gtk Theme / Icons / Font
+
+
+# Shorten output of GTK Theme / Icons / Font
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --gtk_shorthand
+#
+# Example:
+# on: 'Numix, Adwaita'
+# off: 'Numix [GTK2], Adwaita [GTK3]'
+gtk_shorthand="off"
+
+
+# Enable/Disable gtk2 Theme / Icons / Font
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --gtk2
+#
+# Example:
+# on: 'Numix [GTK2], Adwaita [GTK3]'
+# off: 'Adwaita [GTK3]'
+gtk2="on"
+
+# Enable/Disable gtk3 Theme / Icons / Font
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --gtk3
+#
+# Example:
+# on: 'Numix [GTK2], Adwaita [GTK3]'
+# off: 'Numix [GTK2]'
+gtk3="on"
+
+
+# IP Address
+
+
+# Website to ping for the public IP
+#
+# Default: 'http://ident.me'
+# Values: 'url'
+# Flag: --ip_host
+public_ip_host="http://ident.me"
+
+# Public IP timeout.
+#
+# Default: '2'
+# Values: 'int'
+# Flag: --ip_timeout
+public_ip_timeout=2
+
+
+# Desktop Environment
+
+
+# Show Desktop Environment version
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --de_version
+de_version="on"
+
+
+# Disk
+
+
+# Which disks to display.
+# The values can be any /dev/sdXX, mount point or directory.
+# NOTE: By default we only show the disk info for '/'.
+#
+# Default: '/'
+# Values: '/', '/dev/sdXX', '/path/to/drive'.
+# Flag: --disk_show
+#
+# Example:
+# disk_show=('/' '/dev/sdb1'):
+# 'Disk (/): 74G / 118G (66%)'
+# 'Disk (/mnt/Videos): 823G / 893G (93%)'
+#
+# disk_show=('/'):
+# 'Disk (/): 74G / 118G (66%)'
+#
+disk_show=('/')
+
+# Disk subtitle.
+# What to append to the Disk subtitle.
+#
+# Default: 'mount'
+# Values: 'mount', 'name', 'dir', 'none'
+# Flag: --disk_subtitle
+#
+# Example:
+# name: 'Disk (/dev/sda1): 74G / 118G (66%)'
+# 'Disk (/dev/sdb2): 74G / 118G (66%)'
+#
+# mount: 'Disk (/): 74G / 118G (66%)'
+# 'Disk (/mnt/Local Disk): 74G / 118G (66%)'
+# 'Disk (/mnt/Videos): 74G / 118G (66%)'
+#
+# dir: 'Disk (/): 74G / 118G (66%)'
+# 'Disk (Local Disk): 74G / 118G (66%)'
+# 'Disk (Videos): 74G / 118G (66%)'
+#
+# none: 'Disk: 74G / 118G (66%)'
+# 'Disk: 74G / 118G (66%)'
+# 'Disk: 74G / 118G (66%)'
+disk_subtitle="mount"
+
+# Disk percent.
+# Show/Hide disk percent.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --disk_percent
+#
+# Example:
+# on: 'Disk (/): 74G / 118G (66%)'
+# off: 'Disk (/): 74G / 118G'
+disk_percent="on"
+
+
+# Song
+
+
+# Manually specify a music player.
+#
+# Default: 'auto'
+# Values: 'auto', 'player-name'
+# Flag: --music_player
+#
+# Available values for 'player-name':
+#
+# amarok
+# audacious
+# banshee
+# bluemindo
+# clementine
+# cmus
+# deadbeef
+# deepin-music
+# dragon
+# elisa
+# exaile
+# gnome-music
+# gmusicbrowser
+# gogglesmm
+# guayadeque
+# io.elementary.music
+# iTunes
+# juk
+# lollypop
+# mocp
+# mopidy
+# mpd
+# muine
+# netease-cloud-music
+# olivia
+# playerctl
+# pogo
+# pragha
+# qmmp
+# quodlibet
+# rhythmbox
+# sayonara
+# smplayer
+# spotify
+# strawberry
+# tauonmb
+# tomahawk
+# vlc
+# xmms2d
+# xnoise
+# yarock
+music_player="auto"
+
+# Format to display song information.
+#
+# Default: '%artist% - %album% - %title%'
+# Values: '%artist%', '%album%', '%title%'
+# Flag: --song_format
+#
+# Example:
+# default: 'Song: Jet - Get Born - Sgt Major'
+song_format="%artist% - %album% - %title%"
+
+# Print the Artist, Album and Title on separate lines
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --song_shorthand
+#
+# Example:
+# on: 'Artist: The Fratellis'
+# 'Album: Costello Music'
+# 'Song: Chelsea Dagger'
+#
+# off: 'Song: The Fratellis - Costello Music - Chelsea Dagger'
+song_shorthand="off"
+
+# 'mpc' arguments (specify a host, password etc).
+#
+# Default: ''
+# Example: mpc_args=(-h HOST -P PASSWORD)
+mpc_args=()
+
+
+# Text Colors
+
+
+# Text Colors
+#
+# Default: 'distro'
+# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
+# Flag: --colors
+#
+# Each number represents a different part of the text in
+# this order: 'title', '@', 'underline', 'subtitle', 'colon', 'info'
+#
+# Example:
+# colors=(distro) - Text is colored based on Distro colors.
+# colors=(4 6 1 8 8 6) - Text is colored in the order above.
+colors=(distro)
+
+
+# Text Options
+
+
+# Toggle bold text
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --bold
+bold="on"
+
+# Enable/Disable Underline
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --underline
+underline_enabled="on"
+
+# Underline character
+#
+# Default: '-'
+# Values: 'string'
+# Flag: --underline_char
+underline_char="-"
+
+
+# Info Separator
+# Replace the default separator with the specified string.
+#
+# Default: ':'
+# Flag: --separator
+#
+# Example:
+# separator="->": 'Shell-> bash'
+# separator=" =": 'WM = dwm'
+separator=":"
+
+
+# Color Blocks
+
+
+# Color block range
+# The range of colors to print.
+#
+# Default: '0', '15'
+# Values: 'num'
+# Flag: --block_range
+#
+# Example:
+#
+# Display colors 0-7 in the blocks. (8 colors)
+# neofetch --block_range 0 7
+#
+# Display colors 0-15 in the blocks. (16 colors)
+# neofetch --block_range 0 15
+block_range=(0 15)
+
+# Toggle color blocks
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --color_blocks
+color_blocks="on"
+
+# Color block width in spaces
+#
+# Default: '3'
+# Values: 'num'
+# Flag: --block_width
+block_width=3
+
+# Color block height in lines
+#
+# Default: '1'
+# Values: 'num'
+# Flag: --block_height
+block_height=1
+
+# Color Alignment
+#
+# Default: 'auto'
+# Values: 'auto', 'num'
+# Flag: --col_offset
+#
+# Number specifies how far from the left side of the terminal (in spaces) to
+# begin printing the columns, in case you want to e.g. center them under your
+# text.
+# Example:
+# col_offset="auto" - Default behavior of neofetch
+# col_offset=7 - Leave 7 spaces then print the colors
+col_offset="auto"
+
+# Progress Bars
+
+
+# Bar characters
+#
+# Default: '-', '='
+# Values: 'string', 'string'
+# Flag: --bar_char
+#
+# Example:
+# neofetch --bar_char 'elapsed' 'total'
+# neofetch --bar_char '-' '='
+bar_char_elapsed="-"
+bar_char_total="="
+
+# Toggle Bar border
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --bar_border
+bar_border="on"
+
+# Progress bar length in spaces
+# Number of chars long to make the progress bars.
+#
+# Default: '15'
+# Values: 'num'
+# Flag: --bar_length
+bar_length=15
+
+# Progress bar colors
+# When set to distro, uses your distro's logo colors.
+#
+# Default: 'distro', 'distro'
+# Values: 'distro', 'num'
+# Flag: --bar_colors
+#
+# Example:
+# neofetch --bar_colors 3 4
+# neofetch --bar_colors distro 5
+bar_color_elapsed="distro"
+bar_color_total="distro"
+
+
+# Info display
+# Display a bar with the info.
+#
+# Default: 'off'
+# Values: 'bar', 'infobar', 'barinfo', 'off'
+# Flags: --cpu_display
+# --memory_display
+# --battery_display
+# --disk_display
+#
+# Example:
+# bar: '[---=======]'
+# infobar: 'info [---=======]'
+# barinfo: '[---=======] info'
+# off: 'info'
+cpu_display="off"
+memory_display="off"
+battery_display="off"
+disk_display="off"
+
+
+# Backend Settings
+
+
+# Image backend.
+#
+# Default: 'ascii'
+# Values: 'ascii', 'caca', 'chafa', 'jp2a', 'iterm2', 'off',
+# 'pot', 'termpix', 'pixterm', 'tycat', 'w3m', 'kitty'
+# Flag: --backend
+image_backend="ascii"
+
+# Image Source
+#
+# Which image or ascii file to display.
+#
+# Default: 'auto'
+# Values: 'auto', 'ascii', 'wallpaper', '/path/to/img', '/path/to/ascii', '/path/to/dir/'
+# 'command output (neofetch --ascii "$(fortune | cowsay -W 30)")'
+# Flag: --source
+#
+# NOTE: 'auto' will pick the best image source for whatever image backend is used.
+# In ascii mode, distro ascii art will be used and in an image mode, your
+# wallpaper will be used.
+image_source="auto"
+
+
+# Ascii Options
+
+
+# Ascii distro
+# Which distro's ascii art to display.
+#
+# Default: 'auto'
+# Values: 'auto', 'distro_name'
+# Flag: --ascii_distro
+# NOTE: AIX, Alpine, Anarchy, Android, Antergos, antiX, "AOSC OS",
+# "AOSC OS/Retro", Apricity, ArcoLinux, ArchBox, ARCHlabs,
+# ArchStrike, XFerience, ArchMerge, Arch, Artix, Arya, Bedrock,
+# Bitrig, BlackArch, BLAG, BlankOn, BlueLight, bonsai, BSD,
+# BunsenLabs, Calculate, Carbs, CentOS, Chakra, ChaletOS,
+# Chapeau, Chrom*, Cleanjaro, ClearOS, Clear_Linux, Clover,
+# Condres, Container_Linux, CRUX, Cucumber, Debian, Deepin,
+# DesaOS, Devuan, DracOS, DarkOs, DragonFly, Drauger, Elementary,
+# EndeavourOS, Endless, EuroLinux, Exherbo, Fedora, Feren, FreeBSD,
+# FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, Gentoo, Pentoo,
+# gNewSense, GNOME, GNU, GoboLinux, Grombyang, Guix, Haiku, Huayra,
+# Hyperbola, janus, Kali, KaOS, KDE_neon, Kibojoe, Kogaion,
+# Korora, KSLinux, Kubuntu, LEDE, LFS, Linux_Lite,
+# LMDE, Lubuntu, Lunar, macos, Mageia, MagpieOS, Mandriva,
+# Manjaro, Maui, Mer, Minix, LinuxMint, MX_Linux, Namib,
+# Neptune, NetBSD, Netrunner, Nitrux, NixOS, Nurunner,
+# NuTyX, OBRevenge, OpenBSD, openEuler, OpenIndiana, openmamba,
+# OpenMandriva, OpenStage, OpenWrt, osmc, Oracle, OS Elbrus, PacBSD,
+# Parabola, Pardus, Parrot, Parsix, TrueOS, PCLinuxOS, Peppermint,
+# popos, Porteus, PostMarketOS, Proxmox, Puppy, PureOS, Qubes, Radix,
+# Raspbian, Reborn_OS, Redstar, Redcore, Redhat, Refracted_Devuan,
+# Regata, Rosa, sabotage, Sabayon, Sailfish, SalentOS, Scientific,
+# Septor, SereneLinux, SharkLinux, Siduction, Slackware, SliTaz,
+# SmartOS, Solus, Source_Mage, Sparky, Star, SteamOS, SunOS,
+# openSUSE_Leap, openSUSE_Tumbleweed, openSUSE, SwagArch, Tails,
+# Trisquel, Ubuntu-Budgie, Ubuntu-GNOME, Ubuntu-MATE, Ubuntu-Studio,
+# Ubuntu, Venom, Void, Obarun, windows10, Windows7, Xubuntu, Zorin,
+# and IRIX have ascii logos
+# NOTE: Arch, Ubuntu, Redhat, and Dragonfly have 'old' logo variants.
+# Use '{distro name}_old' to use the old logos.
+# NOTE: Ubuntu has flavor variants.
+# Change this to Lubuntu, Kubuntu, Xubuntu, Ubuntu-GNOME,
+# Ubuntu-Studio, Ubuntu-Mate or Ubuntu-Budgie to use the flavors.
+# NOTE: Arcolinux, Dragonfly, Fedora, Alpine, Arch, Ubuntu,
+# CRUX, Debian, Gentoo, FreeBSD, Mac, NixOS, OpenBSD, android,
+# Antrix, CentOS, Cleanjaro, ElementaryOS, GUIX, Hyperbola,
+# Manjaro, MXLinux, NetBSD, Parabola, POP_OS, PureOS,
+# Slackware, SunOS, LinuxLite, OpenSUSE, Raspbian,
+# postmarketOS, and Void have a smaller logo variant.
+# Use '{distro name}_small' to use the small variants.
+ascii_distro="auto"
+
+# Ascii Colors
+#
+# Default: 'distro'
+# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
+# Flag: --ascii_colors
+#
+# Example:
+# ascii_colors=(distro) - Ascii is colored based on Distro colors.
+# ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors.
+ascii_colors=(distro)
+
+# Bold ascii logo
+# Whether or not to bold the ascii logo.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --ascii_bold
+ascii_bold="on"
+
+
+# Image Options
+
+
+# Image loop
+# Setting this to on will make neofetch redraw the image constantly until
+# Ctrl+C is pressed. This fixes display issues in some terminal emulators.
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --loop
+image_loop="off"
+
+# Thumbnail directory
+#
+# Default: '~/.cache/thumbnails/neofetch'
+# Values: 'dir'
+thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch"
+
+# Crop mode
+#
+# Default: 'normal'
+# Values: 'normal', 'fit', 'fill'
+# Flag: --crop_mode
+#
+# See this wiki page to learn about the fit and fill options.
+# https://github.com/dylanaraps/neofetch/wiki/What-is-Waifu-Crop%3F
+crop_mode="normal"
+
+# Crop offset
+# Note: Only affects 'normal' crop mode.
+#
+# Default: 'center'
+# Values: 'northwest', 'north', 'northeast', 'west', 'center'
+# 'east', 'southwest', 'south', 'southeast'
+# Flag: --crop_offset
+crop_offset="center"
+
+# Image size
+# The image is half the terminal width by default.
+#
+# Default: 'auto'
+# Values: 'auto', '00px', '00%', 'none'
+# Flags: --image_size
+# --size
+image_size="auto"
+
+# Gap between image and text
+#
+# Default: '3'
+# Values: 'num', '-num'
+# Flag: --gap
+gap=3
+
+# Image offsets
+# Only works with the w3m backend.
+#
+# Default: '0'
+# Values: 'px'
+# Flags: --xoffset
+# --yoffset
+yoffset=0
+xoffset=0
+
+# Image background color
+# Only works with the w3m backend.
+#
+# Default: ''
+# Values: 'color', 'blue'
+# Flag: --bg_color
+background_color=
+
+
+# Misc Options
+
+# Stdout mode
+# Turn off all colors and disables image backend (ASCII/Image).
+# Useful for piping into another command.
+# Default: 'off'
+# Values: 'on', 'off'
+stdout="off"
diff --git a/picom/picom.conf b/picom/picom.conf
new file mode 100644
index 0000000..6870142
--- /dev/null
+++ b/picom/picom.conf
@@ -0,0 +1,148 @@
+# Animations
+
+transition-length = 250;
+transition-pow-x = 0.3;
+transition-pow-y = 0.3;
+transition-pow-w = 0.3;
+transition-pow-h = 0.3;
+size-transition = true;
+
+## Corners
+
+corner-radius = 5;
+round-borders = 5;
+rounded-corners-exclude = [
+ "window_type = 'dock'",
+ "window_type = 'desktop'",
+ "class_g = 'Plank'"
+];
+
+## Shadows
+
+shadow = true;
+shadow-radius = 10;
+shadow-opacity = 0.25;
+shadow-offset-x = -10;
+shadow-offset-y = -10;
+# shadow-red = 0
+# shadow-green = 0
+# shadow-blue = 0
+shadow-color = "#000000"
+shadow-exclude = [
+ #"name = 'Notification'",
+ "class_g = 'Conky'",
+ #"class_g ?= 'Notify-osd'",
+ "class_g = 'firefox'",
+ #"class_g = 'Rofi'",
+ "class_g = 'Plank'",
+ "_GTK_FRAME_EXTENTS@:c"
+];
+# shadow-exclude-reg = ""
+
+## Fading
+
+fading = true;
+fade-in-step = 0.03;
+fade-out-step = 0.03;
+fade-delta = 7
+fade-exclude = [
+ "class_g *?= \"rofi\""
+]
+no-fading-openclose = false
+no-fading-destroyed-argb = false
+
+## Transparency / Opacity
+
+inactive-opacity = 1.0;
+frame-opacity = 1.0;
+inactive-opacity-override = false;
+active-opacity = 1.0
+inactive-dim = 0.0
+focus-exclude = [
+ "class_g *?= \"rofi\"",
+ "class_g = 'Plank'"
+];
+inactive-dim-fixed = 1.0
+# opacity-rule = []
+
+
+# Background-Blurring
+
+blur: {
+ method = "dual_kawase";
+ strength = 4.0;
+ # deviation = 1.0;
+ # kernel = "11x11gaussian";
+}
+
+# blur-background = true;
+# blur-background-frame = true;
+# blur-kern = "3x3box";
+# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
+# blur-background-fixed = true;
+
+blur-background-exclude = [
+ "window_type = 'desktop'",
+ "window_type = 'utility'",
+ #"window_type = 'notification'",
+ "class_g = 'slop'",
+ #"class_g = 'Polybar'",
+ "class_g = 'Firefox' && argb",
+ "class_g = 'Plank'",
+ "name = 'rofi - Search'",
+ "_GTK_FRAME_EXTENTS@:c"
+];
+# blur-method = "dual_kawase"
+# blur-size = 12
+# blur-deviation = false
+# blur-strength = 5
+# blur-background = false
+# blur-background-frame = false
+# blur-background-fixed = false
+
+# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
+blur-kern = "3x3box";
+
+# General Settings
+
+backend = "glx"; #xrender, glx, xr_glx_hybrid
+vsync = true;
+
+mark-wmwin-focused = true;
+mark-ovredir-focused = true;
+detect-rounded-corners = true;
+detect-client-opacity = true;
+refresh-rate = 0;
+use-ewmh-active-win = true;
+unredir-if-possible = false
+# unredir-if-possible-delay = 0
+# unredir-if-possible-exclude = []
+
+detect-transient = true;
+detect-client-leader = true;
+# resize-damage = 1
+# invert-color-include = []
+# glx-no-stencil = false
+# glx-no-rebind-pixmap = false
+
+use-damage = true;
+xrender-sync-fence = true;
+
+# no-ewmh-fullscreen = false
+# max-brightness = 1.0
+# transparent-clipping = false
+log-level = "warn";
+# log-file = "/path/to/your/log/file"
+
+# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard:
+# "unknown", "desktop", "dock", "toolbar", "menu", "utility",
+# "splash", "dialog", "normal", "dropdown_menu", "popup_menu",
+# "tooltip", "notification", "combo", and "dnd".
+wintypes:
+{
+ tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
+ dock = { shadow = false; }
+ dnd = { shadow = false; }
+ popup_menu = { opacity = 0.95; }
+ dropdown_menu = { opacity = 0.95; }
+};
diff --git a/polybar/colors.ini b/polybar/colors.ini
new file mode 100644
index 0000000..0be6d33
--- /dev/null
+++ b/polybar/colors.ini
@@ -0,0 +1,21 @@
+;; ___ _
+;; / __\___ | | ___ _ __ ___
+;; / / / _ \| |/ _ \| '__/ __|
+;;/ /__| (_) | | (_) | | \__ \
+;;\____/\___/|_|\___/|_| |___/
+
+[colors]
+background = #55000000
+border = #55444444
+background2 = #ff000000
+
+foreground = #ffffff
+foreground2 = #000000
+foreground3 = #bbbbbb
+
+contrast = #8bdfff
+;contrast = #000000
+contrast2 = #ffa676
+contrast3 = #76ffa1
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
diff --git a/polybar/config.ini b/polybar/config.ini
new file mode 100644
index 0000000..5aa12ac
--- /dev/null
+++ b/polybar/config.ini
@@ -0,0 +1,78 @@
+;; ___ _ _
+;; / _ \___ | |_ _| |__ __ _ _ __
+;; / /_)/ _ \| | | | | '_ \ / _` | '__|
+;; / ___/ (_) | | |_| | |_) | (_| | |
+;; \/ \___/|_|\__, |_.__/ \__,_|_|
+;; |___/
+;; https://github.com/b4skyx/dotfiles
+
+
+;-------------------------
+;; Imports
+include-file = ~/.config/polybar/colors.ini
+include-file = ~/.config/polybar/modules.ini
+
+;-------------------------
+[global/wm]
+; margin-top = 5
+; margin-bottom = 5
+
+;-------------------------
+
+[settings]
+screenchange-reload = true
+pseudo-transparency = false
+
+;-------------------------
+
+[bar/main]
+monitor =
+width = 100%
+height = 32
+fixed-center = true
+override-redirect = true
+wm-restack = bspwm
+bottom = false
+
+background = ${colors.background}
+foreground = ${colors.foreground}
+
+line-size = 2
+line-color = #00000000
+
+border-size = 0
+border-bottom-size = 1
+border-color = ${colors.border}
+
+padding-left = 0
+padding-right = 1
+
+font-0 = FiraSans:pixelsize=11;2
+font-1 = Symbols Nerd Font:pixelsize=12;1
+
+modules-left = launcher bspwm xwindow
+modules-center = date time
+modules-right = xkeyboard pulseaudio network battery powercontrol
+
+tray-position = right
+tray-detached = false
+tray-maxsize = 16
+tray-offset-x = 0
+tray-offset-y = 0
+tray-padding = 3
+tray-scale = 1.0
+
+enable-ipc = true
+
+;-------------------------
+
+[bar/secondary]
+
+# Show systray only on first monitor
+
+inherit = bar/main
+
+monitor = DP-1
+tray-position = right
+
+;-------------------------
diff --git a/polybar/launch.sh b/polybar/launch.sh
new file mode 100755
index 0000000..38cf198
--- /dev/null
+++ b/polybar/launch.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+## Add this to your wm startup file.
+
+# Terminate already running bar instances
+killall -q polybar
+
+# Wait until the processes have been shut down
+while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
+
+# Get network Interface
+export DEFAULT_NETWORK_INTERFACE=$(ip route | grep '^default' | awk '{print $5}' | head -n1)
+
+# Load on second monitor if connected
+external_monitor=$(xrandr --query | grep 'DP-1')
+if [[ $external_monitor = DP-1\ connected* ]]; then
+ polybar -c ~/.config/polybar/config.ini secondary &
+fi
+
+## Load bar on primary monitor
+polybar -c ~/.config/polybar/config.ini main &
+
diff --git a/polybar/modules.ini b/polybar/modules.ini
new file mode 100644
index 0000000..0401a5e
--- /dev/null
+++ b/polybar/modules.ini
@@ -0,0 +1,218 @@
+[module/bspwm]
+type = internal/bspwm
+
+ws-icon-0 = 1;1
+ws-icon-1 = 2;2
+ws-icon-2 = 3;3
+ws-icon-3 = 4;4
+ws-icon-4 = 5;5
+ws-icon-5 = 6;6
+ws-icon-6 = 7;7
+ws-icon-7 = 8;8
+ws-icon-8 = 9;9
+
+label-focused = %icon%
+label-focused-foreground = ${colors.foreground2}
+label-focused-background = ${colors.contrast}
+label-focused-padding = 3
+
+label-occupied = %icon%
+label-occupied-foreground = ${colors.foreground3}
+label-occupied-padding = 2
+
+label-urgent = %icon%
+label-urgent-foreground = ${colors.contrast2}
+label-urgent-padding = 2
+
+label-empty =
+label-empty-foreground = ${colors.foreground}
+label-empty-padding = 2
+
+;-------------------------
+
+[module/xwindow]
+type = internal/xwindow
+label = %title:0:100:...%
+label-padding = 4
+label-empty = ~
+label-empty-padding = 4
+label-empty-foreground = ${colors.contrast4}
+format-foreground = ${colors.foreground}
+
+;-------------------------
+
+[module/mpris]
+type = custom/script
+icon = 契
+exec = ~/.config/polybar/scripts/mpris_tail.py --icon-stopped '' --icon-paused '' --icon-playing '' --truncate-text '..' -f '%{A1:playerctl previous:}{icon} %{A} {:artist:t18:{artist}:}{:artist: - :}{:t25:{title}:}'
+tail = true
+format-foreground = ${colors.contrast3}
+format-padding = 2
+label = "%output%"
+click-left = ~/.config/polybar/scripts/mpris_tail.py play-pause &
+click-right = ~/.config/polybar/scripts/mpris_tail.py next &
+
+;-------------------------
+
+[module/date]
+type = internal/date
+interval = 1
+
+time = %A, %b %d
+
+label-padding = 2
+label = %time%
+
+[module/time]
+type = internal/date
+internal = 1
+
+time = %H:%M
+label-padding = 2
+label = %time%
+
+;-------------------------
+
+[module/network]
+type = internal/network
+interface = ${env:DEFAULT_NETWORK_INTERFACE:wlan0}
+
+interval = 3.0
+accumulate-stats = true
+unknown-as-up = true
+
+format-connected = 
+format-connected-padding = 2
+
+format-disconnected = 󱘖
+format-disconnected-padding = 2
+
+;label-connected = "Connected"
+;label-connected-padding = 2
+;label-disconnected = "No signal"
+;label-disconnected-padding = 2
+
+;ramp-signal-0 = 󰢿
+;ramp-signal-1 = 󰢼
+;ramp-signal-2 = 󰢽
+;ramp-signal-3 = 󰢽
+;ramp-signal-4 = 󰢾
+
+;-------------------------
+
+[module/pulseaudio]
+type = internal/pulseaudio
+
+use-ui-max = false
+interval = 5
+
+format-volume = 󰕾 <label-volume>
+format-volume-padding = 2
+
+label-volume = %percentage%%
+label-volume-padding = 1
+
+format-muted = 󰝟 <label-muted>
+label-muted = "Muted"
+label-muted-padding = 1
+format-muted-padding = 2
+
+click-right = tdrop -am -w 1000 -h 650 -x 23% -y 17% -n 2 kitty -e pulsemixer
+
+;-------------------------
+
+[module/battery]
+type = internal/battery
+
+full-at = 99
+
+battery = BAT0
+adapter = ACAD
+
+poll-interval = 2
+time-format = %H:%M
+
+format-charging = <animation-charging>
+format-charging-background = ${colors.dark3}
+format-charging-foreground = ${colors.contrast1}
+format-charging-padding = 2
+
+format-discharging = <ramp-capacity>
+format-discharging-background = ${colors.dark3}
+format-discharging-foreground = ${colors.foreground}
+format-discharging-padding = 2
+
+;label-charging = %percentage%%
+;label-discharging = %percentage%%
+
+label-full =󰁹
+label-full-background = ${colors.dark3}
+label-full-foreground = ${colors.foreground}
+label-full-padding = 2
+
+ramp-capacity-0 = 󰂎
+ramp-capacity-1 = 󰁺
+ramp-capacity-2 = 󰁻
+ramp-capacity-3 = 󰁼
+ramp-capacity-4 = 󰁽
+ramp-capacity-5 = 󰁾
+ramp-capacity-6 = 󰁿
+ramp-capacity-7 = 󰂀
+ramp-capacity-8 = 󰂁
+ramp-capacity-9 = 󰂂
+
+animation-charging-0 = 󰁺
+animation-charging-1 = 󰁻
+animation-charging-2 = 󰁼
+animation-charging-3 = 󰁽
+animation-charging-4 = 󰁾
+animation-charging-5 = 󰁿
+animation-charging-6 = 󰂀
+animation-charging-7 = 󰂁
+animation-charging-8 = 󰂂
+animation-charging-framerate = 750
+
+;-------------------------
+
+[module/xkeyboard]
+type = internal/xkeyboard
+
+; blacklist-0 = num lock
+; blacklist-1 = scroll lock
+; blacklist-2 = caps lock
+
+format = <label-layout> <label-indicator>
+
+format-prefix = "󰌌 "
+
+label-layout = %layout%
+label-layout-padding = 1
+
+blacklist-0 = num lock
+blacklist-1 = scroll lock
+
+format-padding = 2
+label-indicator = %name%
+label-indicator-on-capslock = 
+
+;------------------------
+
+[module/powercontrol]
+type = custom/text
+
+format = ⏻
+format-foreground = ${colors.contrast}
+format-padding = 2
+
+click-left = rofi -show p -modi p:rofi-power-menu -theme iconic -show-icons
+
+;------------------------
+
+[module/launcher]
+type = custom/text
+
+format = 󰘳
+format-foreground = ${colors.contrast}
+format-padding = 4
+
+click-left = rofi -show drun -theme iconic -show-icons
diff --git a/polybar/scripts/micfn b/polybar/scripts/micfn
new file mode 100755
index 0000000..bebe7d6
--- /dev/null
+++ b/polybar/scripts/micfn
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+function helpfn() {
+ echo "micfn, a quick mic toggle script"
+}
+
+active_port=$(pactl list | sed -n '/^Source/,/^$/p' | grep 'Active Port' | cut -d ' ' -f3)
+
+if amixer get Capture | grep "\[off\]" > /dev/null
+then
+ status="OFF"
+else
+ status="ON"
+fi
+
+function toggle() {
+ amixer set Capture toggle > /dev/null
+ if amixer get Capture | grep "\[off\]" > /dev/null
+ then
+ notify-send -t 3000 "$active_port" "Microphone OFF"
+ else
+ notify-send -t 3000 "$active_port" "Microphone ON"
+ fi
+}
+
+if [ "$1" == "-h" -o "$1" == "--help" ]; then
+ helpfn
+ exit 0
+elif [ "$1" == "-t" -o "$1" == "--toggle" ]; then
+ toggle
+ exit 0
+elif [ $# -eq 0 ]; then
+ echo $status
+fi
diff --git a/polybar/scripts/mpris_tail.py b/polybar/scripts/mpris_tail.py
new file mode 100755
index 0000000..9cd4900
--- /dev/null
+++ b/polybar/scripts/mpris_tail.py
@@ -0,0 +1,535 @@
+#!/usr/bin/env python3
+
+import sys
+import dbus
+import os
+from operator import itemgetter
+import argparse
+import re
+from urllib.parse import unquote
+import time
+from dbus.mainloop.glib import DBusGMainLoop
+from gi.repository import GLib
+DBusGMainLoop(set_as_default=True)
+
+
+FORMAT_STRING = '{icon} {artist} - {title}'
+FORMAT_REGEX = re.compile(r'(\{:(?P<tag>.*?)(:(?P<format>[wt])(?P<formatlen>\d+))?:(?P<text>.*?):\})', re.I)
+FORMAT_TAG_REGEX = re.compile(r'(?P<format>[wt])(?P<formatlen>\d+)')
+SAFE_TAG_REGEX = re.compile(r'[{}]')
+
+class PlayerManager:
+ def __init__(self, blacklist = [], connect = True):
+ self.blacklist = blacklist
+ self._connect = connect
+ self._session_bus = dbus.SessionBus()
+ self.players = {}
+
+ self.print_queue = []
+ self.connected = False
+ self.player_states = {}
+
+ self.refreshPlayerList()
+
+ if self._connect:
+ self.connect()
+ loop = GLib.MainLoop()
+ try:
+ loop.run()
+ except KeyboardInterrupt:
+ print("interrupt received, stopping…")
+
+ def connect(self):
+ self._session_bus.add_signal_receiver(self.onOwnerChangedName, 'NameOwnerChanged')
+ self._session_bus.add_signal_receiver(self.onChangedProperties, 'PropertiesChanged',
+ path = '/org/mpris/MediaPlayer2',
+ sender_keyword='sender')
+
+ def onChangedProperties(self, interface, properties, signature, sender = None):
+ if sender in self.players:
+ player = self.players[sender]
+ # If we know this player, but haven't been able to set up a signal handler
+ if 'properties_changed' not in player._signals:
+ # Then trigger the signal handler manually
+ player.onPropertiesChanged(interface, properties, signature)
+ else:
+ # If we don't know this player, get its name and add it
+ bus_name = self.getBusNameFromOwner(sender)
+ if bus_name is None:
+ return
+ self.addPlayer(bus_name, sender)
+ player = self.players[sender]
+ player.onPropertiesChanged(interface, properties, signature)
+
+ def onOwnerChangedName(self, bus_name, old_owner, new_owner):
+ if self.busNameIsAPlayer(bus_name):
+ if new_owner and not old_owner:
+ self.addPlayer(bus_name, new_owner)
+ elif old_owner and not new_owner:
+ self.removePlayer(old_owner)
+ else:
+ self.changePlayerOwner(bus_name, old_owner, new_owner)
+
+ def getBusNameFromOwner(self, owner):
+ player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ]
+ for player_bus_name in player_bus_names:
+ player_bus_owner = self._session_bus.get_name_owner(player_bus_name)
+ if owner == player_bus_owner:
+ return player_bus_name
+
+ def busNameIsAPlayer(self, bus_name):
+ return bus_name.startswith('org.mpris.MediaPlayer2') and bus_name.split('.')[3] not in self.blacklist
+
+ def refreshPlayerList(self):
+ player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ]
+ for player_bus_name in player_bus_names:
+ self.addPlayer(player_bus_name)
+ if self.connected != True:
+ self.connected = True
+ self.printQueue()
+
+ def addPlayer(self, bus_name, owner = None):
+ player = Player(self._session_bus, bus_name, owner = owner, connect = self._connect, _print = self.print)
+ self.players[player.owner] = player
+
+ def removePlayer(self, owner):
+ if owner in self.players:
+ self.players[owner].disconnect()
+ del self.players[owner]
+ # If there are no more players, clear the output
+ if len(self.players) == 0:
+ _printFlush(ICON_NONE)
+ # Else, print the output of the next active player
+ else:
+ players = self.getSortedPlayerOwnerList()
+ if len(players) > 0:
+ self.players[players[0]].printStatus()
+
+ def changePlayerOwner(self, bus_name, old_owner, new_owner):
+ player = Player(self._session_bus, bus_name, owner = new_owner, connect = self._connect, _print = self.print)
+ self.players[new_owner] = player
+ del self.players[old_owner]
+
+ # Get a list of player owners sorted by current status and age
+ def getSortedPlayerOwnerList(self):
+ players = [
+ {
+ 'number': int(owner.split('.')[-1]),
+ 'status': 2 if player.status == 'playing' else 1 if player.status == 'paused' else 0,
+ 'owner': owner
+ }
+ for owner, player in self.players.items()
+ ]
+ return [ info['owner'] for info in reversed(sorted(players, key=itemgetter('status', 'number'))) ]
+
+ # Get latest player that's currently playing
+ def getCurrentPlayer(self):
+ playing_players = [
+ player_owner for player_owner in self.getSortedPlayerOwnerList()
+ if
+ self.players[player_owner].status == 'playing' or
+ self.players[player_owner].status == 'paused'
+ ]
+ return self.players[playing_players[0]] if playing_players else None
+
+ def print(self, status, player):
+ self.player_states[player.bus_name] = status
+
+ if self.connected:
+ current_player = self.getCurrentPlayer()
+ if current_player != None:
+ _printFlush(self.player_states[current_player.bus_name])
+ else:
+ _printFlush(ICON_STOPPED)
+ else:
+ self.print_queue.append([status, player])
+
+ def printQueue(self):
+ for args in self.print_queue:
+ self.print(args[0], args[1])
+ self.print_queue.clear()
+
+
+class Player:
+ def __init__(self, session_bus, bus_name, owner = None, connect = True, _print = None):
+ self._session_bus = session_bus
+ self.bus_name = bus_name
+ self._disconnecting = False
+ self.__print = _print
+
+ self.metadata = {
+ 'artist' : '',
+ 'album' : '',
+ 'title' : '',
+ 'track' : 0
+ }
+
+ self._rate = 1.
+ self._positionAtLastUpdate = 0.
+ self._timeAtLastUpdate = time.time()
+ self._positionTimerRunning = False
+
+ self._metadata = None
+ self.status = 'stopped'
+ self.icon = ICON_NONE
+ self.icon_reversed = ICON_PLAYING
+ if owner is not None:
+ self.owner = owner
+ else:
+ self.owner = self._session_bus.get_name_owner(bus_name)
+ self._obj = self._session_bus.get_object(self.bus_name, '/org/mpris/MediaPlayer2')
+ self._properties_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Properties')
+ self._introspect_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Introspectable')
+ self._media_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2')
+ self._player_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2.Player')
+ self._introspect = self._introspect_interface.get_dbus_method('Introspect', dbus_interface=None)
+ self._getProperty = self._properties_interface.get_dbus_method('Get', dbus_interface=None)
+ self._playerPlay = self._player_interface.get_dbus_method('Play', dbus_interface=None)
+ self._playerPause = self._player_interface.get_dbus_method('Pause', dbus_interface=None)
+ self._playerPlayPause = self._player_interface.get_dbus_method('PlayPause', dbus_interface=None)
+ self._playerStop = self._player_interface.get_dbus_method('Stop', dbus_interface=None)
+ self._playerPrevious = self._player_interface.get_dbus_method('Previous', dbus_interface=None)
+ self._playerNext = self._player_interface.get_dbus_method('Next', dbus_interface=None)
+ self._playerRaise = self._media_interface.get_dbus_method('Raise', dbus_interface=None)
+ self._signals = {}
+
+ self.refreshPosition()
+ self.refreshStatus()
+ self.refreshMetadata()
+
+ if connect:
+ self.printStatus()
+ self.connect()
+
+ def play(self):
+ self._playerPlay()
+ def pause(self):
+ self._playerPause()
+ def playpause(self):
+ self._playerPlayPause()
+ def stop(self):
+ self._playerStop()
+ def previous(self):
+ self._playerPrevious()
+ def next(self):
+ self._playerNext()
+ def raisePlayer(self):
+ self._playerRaise()
+
+ def connect(self):
+ if self._disconnecting is not True:
+ introspect_xml = self._introspect(self.bus_name, '/')
+ if 'TrackMetadataChanged' in introspect_xml:
+ self._signals['track_metadata_changed'] = self._session_bus.add_signal_receiver(self.onMetadataChanged, 'TrackMetadataChanged', self.bus_name)
+ self._signals['seeked'] = self._player_interface.connect_to_signal('Seeked', self.onSeeked)
+ self._signals['properties_changed'] = self._properties_interface.connect_to_signal('PropertiesChanged', self.onPropertiesChanged)
+
+ def disconnect(self):
+ self._disconnecting = True
+ for signal_name, signal_handler in list(self._signals.items()):
+ signal_handler.remove()
+ del self._signals[signal_name]
+
+ def refreshStatus(self):
+ # Some clients (VLC) will momentarily create a new player before removing it again
+ # so we can't be sure the interface still exists
+ try:
+ self.status = str(self._getProperty('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')).lower()
+ self.updateIcon()
+ self.checkPositionTimer()
+ except dbus.exceptions.DBusException:
+ self.disconnect()
+
+ def refreshMetadata(self):
+ # Some clients (VLC) will momentarily create a new player before removing it again
+ # so we can't be sure the interface still exists
+ try:
+ self._metadata = self._getProperty('org.mpris.MediaPlayer2.Player', 'Metadata')
+ self._parseMetadata()
+ except dbus.exceptions.DBusException:
+ self.disconnect()
+
+ def updateIcon(self):
+ self.icon = (
+ ICON_PLAYING if self.status == 'playing' else
+ ICON_PAUSED if self.status == 'paused' else
+ ICON_STOPPED if self.status == 'stopped' else
+ ICON_NONE
+ )
+ self.icon_reversed = (
+ ICON_PAUSED if self.status == 'playing' else
+ ICON_PLAYING
+ )
+
+ def _print(self, status):
+ self.__print(status, self)
+
+ def _parseMetadata(self):
+ if self._metadata != None:
+ # Obtain properties from _metadata
+ _artist = _getProperty(self._metadata, 'xesam:artist', [''])
+ _album = _getProperty(self._metadata, 'xesam:album', '')
+ _title = _getProperty(self._metadata, 'xesam:title', '')
+ _track = _getProperty(self._metadata, 'xesam:trackNumber', '')
+ _genre = _getProperty(self._metadata, 'xesam:genre', [''])
+ _disc = _getProperty(self._metadata, 'xesam:discNumber', '')
+ _length = _getProperty(self._metadata, 'xesam:length', 0) or _getProperty(self._metadata, 'mpris:length', 0)
+ _length_int = _length if type(_length) is int else int(float(_length))
+ _date = _getProperty(self._metadata, 'xesam:contentCreated', '')
+ _year = _date[0:4] if len(_date) else ''
+ _url = _getProperty(self._metadata, 'xesam:url', '')
+ _cover = _getProperty(self._metadata, 'xesam:artUrl', '') or _getProperty(self._metadata, 'mpris:artUrl', '')
+ _duration = _getDuration(_length_int)
+ # Update metadata
+ self.metadata['artist'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_artist))
+ self.metadata['album'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_album))
+ self.metadata['title'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_title))
+ self.metadata['track'] = _track
+ self.metadata['genre'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_genre))
+ self.metadata['disc'] = _disc
+ self.metadata['date'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _date)
+ self.metadata['year'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _year)
+ self.metadata['url'] = _url
+ self.metadata['filename'] = os.path.basename(_url)
+ self.metadata['length'] = _length_int
+ self.metadata['cover'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_cover))
+ self.metadata['duration'] = _duration
+
+ def onMetadataChanged(self, track_id, metadata):
+ self.refreshMetadata()
+ self.printStatus()
+
+ def onPropertiesChanged(self, interface, properties, signature):
+ updated = False
+ if dbus.String('Metadata') in properties:
+ _metadata = properties[dbus.String('Metadata')]
+ if _metadata != self._metadata:
+ self._metadata = _metadata
+ self._parseMetadata()
+ updated = True
+ if dbus.String('PlaybackStatus') in properties:
+ status = str(properties[dbus.String('PlaybackStatus')]).lower()
+ if status != self.status:
+ self.status = status
+ self.checkPositionTimer()
+ self.updateIcon()
+ updated = True
+ if dbus.String('Rate') in properties and dbus.String('PlaybackStatus') not in properties:
+ self.refreshStatus()
+ if NEEDS_POSITION and dbus.String('Rate') in properties:
+ rate = properties[dbus.String('Rate')]
+ if rate != self._rate:
+ self._rate = rate
+ self.refreshPosition()
+
+ if updated:
+ self.refreshPosition()
+ self.printStatus()
+
+ def checkPositionTimer(self):
+ if NEEDS_POSITION and self.status == 'playing' and not self._positionTimerRunning:
+ self._positionTimerRunning = True
+ GLib.timeout_add_seconds(1, self._positionTimer)
+
+ def onSeeked(self, position):
+ self.refreshPosition()
+ self.printStatus()
+
+ def _positionTimer(self):
+ self.printStatus()
+ self._positionTimerRunning = self.status == 'playing'
+ return self._positionTimerRunning
+
+ def refreshPosition(self):
+ try:
+ time_us = self._getProperty('org.mpris.MediaPlayer2.Player', 'Position')
+ except dbus.exceptions.DBusException:
+ time_us = 0
+
+ self._timeAtLastUpdate = time.time()
+ self._positionAtLastUpdate = time_us / 1000000
+
+ def _getPosition(self):
+ if self.status == 'playing':
+ return self._positionAtLastUpdate + self._rate * (time.time() - self._timeAtLastUpdate)
+ else:
+ return self._positionAtLastUpdate
+
+ def _statusReplace(self, match, metadata):
+ tag = match.group('tag')
+ format = match.group('format')
+ formatlen = match.group('formatlen')
+ text = match.group('text')
+ tag_found = False
+ reversed_tag = False
+
+ if tag.startswith('-'):
+ tag = tag[1:]
+ reversed_tag = True
+
+ if format is None:
+ tag_is_format_match = re.match(FORMAT_TAG_REGEX, tag)
+ if tag_is_format_match:
+ format = tag_is_format_match.group('format')
+ formatlen = tag_is_format_match.group('formatlen')
+ tag_found = True
+ if format is not None:
+ text = text.format_map(CleanSafeDict(**metadata))
+ if format == 'w':
+ formatlen = int(formatlen)
+ text = text[:formatlen]
+ elif format == 't':
+ formatlen = int(formatlen)
+ if len(text) > formatlen:
+ text = text[:max(formatlen - len(TRUNCATE_STRING), 0)] + TRUNCATE_STRING
+ if tag_found is False and tag in metadata and len(metadata[tag]):
+ tag_found = True
+
+ if reversed_tag:
+ tag_found = not tag_found
+
+ if tag_found:
+ return text
+ else:
+ return ''
+
+ def printStatus(self):
+ if self.status in [ 'playing', 'paused' ]:
+ metadata = { **self.metadata, 'icon': self.icon, 'icon-reversed': self.icon_reversed }
+ if NEEDS_POSITION:
+ metadata['position'] = time.strftime("%M:%S", time.gmtime(self._getPosition()))
+ # replace metadata tags in text
+ text = re.sub(FORMAT_REGEX, lambda match: self._statusReplace(match, metadata), FORMAT_STRING)
+ # restore polybar tag formatting and replace any remaining metadata tags after that
+ try:
+ text = re.sub(r'􏿿p􏿿(.*?)􏿿p􏿿(.*?)􏿿p􏿿(.*?)􏿿p􏿿', r'%{\1}\2%{\3}', text.format_map(CleanSafeDict(**metadata)))
+ except:
+ print("Invalid format string")
+ self._print(text)
+ else:
+ self._print(ICON_STOPPED)
+
+
+def _dbusValueToPython(value):
+ if isinstance(value, dbus.Dictionary):
+ return {_dbusValueToPython(key): _dbusValueToPython(value) for key, value in value.items()}
+ elif isinstance(value, dbus.Array):
+ return [ _dbusValueToPython(item) for item in value ]
+ elif isinstance(value, dbus.Boolean):
+ return int(value) == 1
+ elif (
+ isinstance(value, dbus.Byte) or
+ isinstance(value, dbus.Int16) or
+ isinstance(value, dbus.UInt16) or
+ isinstance(value, dbus.Int32) or
+ isinstance(value, dbus.UInt32) or
+ isinstance(value, dbus.Int64) or
+ isinstance(value, dbus.UInt64)
+ ):
+ return int(value)
+ elif isinstance(value, dbus.Double):
+ return float(value)
+ elif (
+ isinstance(value, dbus.ObjectPath) or
+ isinstance(value, dbus.Signature) or
+ isinstance(value, dbus.String)
+ ):
+ return unquote(str(value))
+
+def _getProperty(properties, property, default = None):
+ value = default
+ if not isinstance(property, dbus.String):
+ property = dbus.String(property)
+ if property in properties:
+ value = properties[property]
+ return _dbusValueToPython(value)
+ else:
+ return value
+
+def _getDuration(t: int):
+ seconds = t / 1000000
+ return time.strftime("%M:%S", time.gmtime(seconds))
+
+def _metadataGetFirstItem(_value):
+ if type(_value) is list:
+ # Returns the string representation of the first item on _value if it has at least one item.
+ # Returns an empty string if _value is empty.
+ return str(_value[0]) if len(_value) else ''
+ else:
+ # If _value isn't a list just return the string representation of _value.
+ return str(_value)
+
+class CleanSafeDict(dict):
+ def __missing__(self, key):
+ return '{{{}}}'.format(key)
+
+
+"""
+Seems to assure print() actually prints when no terminal is connected
+"""
+
+_last_status = ''
+def _printFlush(status, **kwargs):
+ global _last_status
+ if status != _last_status:
+ print(status, **kwargs)
+ sys.stdout.flush()
+ _last_status = status
+
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument('command', help="send the given command to the active player",
+ choices=[ 'play', 'pause', 'play-pause', 'stop', 'previous', 'next', 'status', 'list', 'current', 'metadata', 'raise' ],
+ default=None,
+ nargs='?')
+parser.add_argument('-b', '--blacklist', help="ignore a player by it's bus name. Can be be given multiple times (e.g. -b vlc -b audacious)",
+ action='append',
+ metavar="BUS_NAME",
+ default=[])
+parser.add_argument('-f', '--format', default='{icon} {:artist:{artist} - :}{:title:{title}:}{:-title:{filename}:}')
+parser.add_argument('--truncate-text', default='…')
+parser.add_argument('--icon-playing', default='⏵')
+parser.add_argument('--icon-paused', default='⏸')
+parser.add_argument('--icon-stopped', default='⏹')
+parser.add_argument('--icon-none', default='')
+args = parser.parse_args()
+
+FORMAT_STRING = re.sub(r'%\{(.*?)\}(.*?)%\{(.*?)\}', r'􏿿p􏿿\1􏿿p􏿿\2􏿿p􏿿\3􏿿p􏿿', args.format)
+NEEDS_POSITION = "{position}" in FORMAT_STRING
+
+TRUNCATE_STRING = args.truncate_text
+ICON_PLAYING = args.icon_playing
+ICON_PAUSED = args.icon_paused
+ICON_STOPPED = args.icon_stopped
+ICON_NONE = args.icon_none
+
+if args.command is None:
+ PlayerManager(blacklist = args.blacklist)
+else:
+ player_manager = PlayerManager(blacklist = args.blacklist, connect = False)
+ current_player = player_manager.getCurrentPlayer()
+ if args.command == 'play' and current_player:
+ current_player.play()
+ elif args.command == 'pause' and current_player:
+ current_player.pause()
+ elif args.command == 'play-pause' and current_player:
+ current_player.playpause()
+ elif args.command == 'stop' and current_player:
+ current_player.stop()
+ elif args.command == 'previous' and current_player:
+ current_player.previous()
+ elif args.command == 'next' and current_player:
+ current_player.next()
+ elif args.command == 'status' and current_player:
+ current_player.printStatus()
+ elif args.command == 'list':
+ print("\n".join(sorted([
+ "{} : {}".format(player.bus_name.split('.')[3], player.status)
+ for player in player_manager.players.values() ])))
+ elif args.command == 'current' and current_player:
+ print("{} : {}".format(current_player.bus_name.split('.')[3], current_player.status))
+ elif args.command == 'metadata' and current_player:
+ print(_dbusValueToPython(current_player._metadata))
+ elif args.command == 'raise' and current_player:
+ current_player.raisePlayer()
diff --git a/redshift.conf b/redshift.conf
new file mode 100644
index 0000000..587d209
--- /dev/null
+++ b/redshift.conf
@@ -0,0 +1,14 @@
+[redshift]
+; Set the day and night screen temperatures
+temp-day=6500
+temp-night=3700
+; enabling smooth transition
+transition=1
+adjustment-method=randr
+; Now specify the location manually
+location-provider=manual
+[manual]
+; use the Internet to get your latitudes and longitudes
+; below is the latitude and longitude for Delhi
+lat=28.38
+lon=77.12
diff --git a/rofi/colors.rasi b/rofi/colors.rasi
new file mode 100644
index 0000000..48b4a9c
--- /dev/null
+++ b/rofi/colors.rasi
@@ -0,0 +1,13 @@
+* {
+ /* Theme Colors */
+ bg: #101010;
+ bg2: #4e4949;
+
+ fg: #cccccc;
+ fg2: #ebdada;
+
+ border: #202020;
+ border2: #615a5a;
+
+ transparent: #00000000;
+}
diff --git a/rofi/config.rasi b/rofi/config.rasi
new file mode 100644
index 0000000..c45acb9
--- /dev/null
+++ b/rofi/config.rasi
@@ -0,0 +1 @@
+@import "simple"
diff --git a/rofi/iconic.rasi b/rofi/iconic.rasi
new file mode 100644
index 0000000..a2c8388
--- /dev/null
+++ b/rofi/iconic.rasi
@@ -0,0 +1,119 @@
+configuration {
+ display-drun: "";
+ display-run: "";
+ display-window: "";
+ drun-display-format: "{name}";
+ icon-theme: "Papirus";
+ fixed-num-lines: true;
+ font: "FiraSans Regular 14";
+}
+
+@import "colors"
+
+window {
+ width: 20em;
+ spacing: 0;
+ transparency: "real";
+ background-color: @bg;
+ padding: 0em;
+ border: 0;
+ border-color: @transparent;
+ border-radius: 2;
+}
+
+mainbox {
+ background-color: @transparent;
+}
+
+inputbar {
+ background-color: @bg;
+ text-color: @fg;
+ border-color: @border;
+ children: [prompt, entry];
+ padding: 0;
+ border: 0;
+ margin: 0 0 0em 0;
+ border-radius: 2;
+}
+
+prompt {
+ background-color: inherit;
+ text-color: @fg;
+ padding: 1em 0.75em;
+ border-radius: 2;
+}
+
+entry {
+ background-color: inherit;
+ text-color: @fg;
+ placeholder: "Search...";
+ padding: 1em 0 1em 0;
+ width: 10%;
+ horizontal-align: 0.013;
+ vertical-align: 0;
+ border: 0;
+ border-radius: 2;
+}
+
+listview {
+ background-color: @transparent;
+ text-color: @fg;
+ cycle: false;
+ dynamic: true;
+ border: 0;
+ border-radius: 2;
+ layout: vertical;
+ spacing: 0.1em;
+ lines: 6;
+ columns: 1;
+}
+
+element {
+ background-color: @bg;
+ text-color: @fg;
+ border: 0;
+ border-radius: 0;
+ orientation: horizontal;
+}
+
+element-icon {
+ background-color: @transparent;
+ border: 0;
+ border-radius: 0;
+ size: 28px;
+ padding: 0.25em 0.5em;
+ horizontal-align: 0.5;
+ vertical-align: 0.5;
+}
+
+element-text {
+ background-color: @transparent;
+ text-color: @fg;
+ text-size: 6;
+ border: 0;
+ border-radius: 0;
+ padding: 0.2em 0.2em 0.2em 0;
+ horizontal-align: 0;
+ vertical-align: 0.5;
+}
+
+element selected {
+ background-color: @bg2;
+ text-color: @fg2;
+ border-color: @bg2;
+ border: 1;
+ border-radius: 0;
+}
+
+element-text selected {
+ background-color: @bg2;
+ text-color: @fg2;
+ border-color: @bg2;
+ border: 0;
+}
+element-icon selected {
+ background-color: @bg2;
+ text-color: @fg2;
+ border-color: @bg2;
+ border: 0;
+}
diff --git a/rofi/simple.rasi b/rofi/simple.rasi
new file mode 100644
index 0000000..584d93f
--- /dev/null
+++ b/rofi/simple.rasi
@@ -0,0 +1,90 @@
+configuration {
+ display-drun: "";
+ display-run: "";
+ display-window: "缾";
+ icon-theme: "Flatery";
+ fixed-num-lines: true;
+ font: "Sarasa UI K 12";
+}
+
+@import "colors"
+
+window {
+ width: 30em;
+ spacing: 0;
+ transparency: "real";
+ background-color: @bg;
+ border: 3;
+ border-color: @bg2;
+ border-radius: 0;
+}
+
+inputbar {
+ background-color: @bg;
+ text-color: @fg;
+ border-color: @bg2;
+ children: [prompt, entry];
+ border: 0;
+}
+
+prompt {
+ background-color: @bg;
+ text-color: @fg;
+ padding: 0.5em 0.5em 0.5em 0.5em;
+ border: 0;
+}
+
+entry {
+ background-color: @bg;
+ text-color: @fg;
+ placeholder: "";
+ padding: 0.5em 0 0.5em 0;
+ border: 0;
+}
+
+listview {
+ background-color: @bg;
+ cycle: false;
+ dynamic: true;
+ padding: 0 0 0 0;
+ border: 0;
+ lines: 8;
+ columns: 1;
+ children: [element];
+}
+
+scrollbar {
+ handle-width: 0;
+}
+
+mainbox {
+ background-color: @bg;
+ border: 0;
+}
+
+element {
+ background-color: @bg;
+ text-color: @fg;
+ padding: 0px;
+ border: 0;
+}
+
+element selected {
+ background-color: @bg2;
+ text-color: @fg;
+ border: 0;
+}
+
+element-text {
+ background-color: @bg;
+ text-color: @fg;
+ border: 0;
+ padding: 0.2em 0.2em 0.2em 0.2em;
+}
+
+element-text selected {
+ background-color: @bg2;
+ text-color: @fg;
+ border: 0;
+ padding: 0.2em 0.2em 0.2em 0.2em;
+}
diff --git a/sxhkd/sxhkdrc b/sxhkd/sxhkdrc
new file mode 100644
index 0000000..f1f9a2a
--- /dev/null
+++ b/sxhkd/sxhkdrc
@@ -0,0 +1,229 @@
+#######################
+# Program Keybindings #
+#######################
+
+# Spawn Terminal of a certain geometry
+super + Return
+ alacritty
+
+# Rofi
+super + d
+ rofi -show drun -theme iconic -show-icons
+
+# rofi-emoji script
+super + j
+ rofi-emoji
+
+# Screenshot
+Print
+ maim -s ~/Pictures/Screenshots/$(date +%Y-%m-%d_%H-%M-%S).png
+
+shift + Print
+ maim --window $(xdotool getactivewindow) ~/Pictures/Screenshots/$(date +%Y-%m-%d_%H-%M-%S).png
+
+#####################
+# BSPWM Keybindings #
+#####################
+
+#----~ Init ~----#
+
+# make sxhkd reload its configuration files:
+super + Escape
+ pkill -USR1 -x sxhkd
+
+# Toggle compositor
+super + shift + c
+ picom_toggle
+
+# Toggle glava
+super + shift + m
+ pkill -USR1 -x glava || glava --desktop > /dev/null &
+
+# Reload Polybar
+super + shift + Escape
+ ~/.config/polybar/launch.sh
+
+# quit/restart bspwm
+super + alt + {q,r}
+ bspc {quit,wm -r}
+
+# Quit all ~ return to login
+super + alt + x
+ kill -9 -1
+
+# close and kill windows
+super + {_,shift + }q
+ bspc node -{c,k}
+
+#----~ Workspace Switching ~----#
+
+# Switch Active Workspaces
+alt + {Tab, shift + Tab}
+ bspc {desktop next.occupied -f, desktop prev.occupied -f}
+
+# focus the last node/desktop
+super + {grave,Tab}
+ bspc {node,desktop} -f last
+
+#----~ Workspace Management ~----#
+
+# alternate between the tiled and monocle layout
+super + m
+ bspc desktop -l next
+super + f
+ bspc node -t \~fullscreen
+
+# swap the current node and the biggest local node
+super + g
+ bspc node -s biggest.local
+
+# set the node flags
+super + ctrl + {m,l,s,p}
+ bspc node -g {marked,locked,sticky,private}
+
+# Toggle between floating and tiling
+super + u
+ bspc node focused.tiled -t floating || bspc node focused.floating -t tiled
+
+# Toggle between pseudo-tiling and tiling
+super + i
+ bspc node focused.tiled -t pseudo_tiled || bspc node -t tiled
+
+# Mark node as hidden/unhide all
+super + {_, shift} + h
+ {bspc node --flag hidden=on, bspunhide}
+
+# Hide all on current desktop
+super + ctrl + h
+ bsphide
+
+# Rotate layout by 90 degrees
+super + shift + r
+ bspc node @/ -R 90
+
+#send node to next/previous window
+super + {_, shift} + k
+ bspc node -d {next, prev} -f
+
+#----~ Focus Settings ~----#
+
+# focus the node in the given direction
+super + {Left, Down, Up, Right}
+ bspc node -f {west,south,north,east}
+
+# focus the node for the given path jump
+super + shift + {p,b}
+ bspc node -f @{parent,brother}
+
+# focus the next/previous node in the current desktop
+super + {_,shift + }n
+ bspc node -f {next,prev}.local.!hidden.window
+
+# focus the next/previous desktop in the current monitor
+super + bracket{left,right}
+ bspc desktop -f {prev,next}.local
+
+# focus or send to the given desktop
+super + {_,shift + }{1-9}
+ bspc {desktop -f,node -d} '{1-9}'
+
+# Switch places with the direction window or create an empty node
+super + shift + {Left, Down, Up, Right}
+ bspwm_move {west,south,north,east}
+
+# Show or hide marked nodes
+super + semicolon
+ bspc_marked_hidden
+
+#----~ Preselection ~----#
+
+# preselect the direction
+super + ctrl + {Left, Down, Up, Right}
+ bspc node -p {west,south,north,east}
+
+# preselect the ratio
+super + ctrl + {1-9}
+ bspc node -o 0.{1-9}
+
+# cancel the preselection for the focused node
+super + ctrl + space
+ bspc node -p cancel
+
+# cancel the preselection for the focused desktop
+super + ctrl + shift + space
+ bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel
+
+#----~ Movement/Resizing ~----#
+
+# Move current window to a pre-selected space or an empty node
+super + y
+ bspwm_fill
+
+# Resize
+super + alt + {Left, Down, Up, Right}
+ bspc node -z {left -20 0 || bspc node -z right -20 0, \
+ bottom 0 20 || bspc node -z top 0 20, \
+ top 0 -20 || bspc node -z bottom 0 -20, \
+ right 20 0 || bspc node -z left 20 0}
+
+#----~ BSPWM tabs using Suckless tabbetd ~----#
+
+# At given direction: join two windows into a new tabbed or add window to an existing tabbed
+super + t; {Left,Down,Up,Right}
+ tabc.sh $(bspc query -N -n {west,south,north,east}) add $(bspc query -N -n focused)
+
+# Remove current tab from tabbed
+super + t; r
+ tabc.sh $(bspc query -N -n focused) remove
+
+
+
+###################################
+########### System Keys ###########
+###################################
+
+#Volume Control
+XF86AudioLowerVolume
+ pamixer -u && pamixer -d 5
+XF86AudioRaiseVolume
+ pamixer -u && pamixer -i 5
+XF86AudioMute
+ pamixer -t
+
+#Brightness control
+XF86MonBrightnessDown
+ brightness -dec 5
+XF86MonBrightnessUp
+ brightness -inc 5
+
+## Lcok screen
+super + shift + l
+ lock.sh
+
+## Personal password manager
+super + p
+ dpass
+
+## Music Controls
+super + {less, greater, question}
+ playerctl {previous, next, play-pause}
+
+## Mic Toggle
+super + apostrophe
+ micfn --toggle
+
+## Open Applications
+
+## Tdrop, a drop down terminal to act like a scratchpad. Check scripts
+
+# Spawn a term with tmux
+super + shift + Return
+ st -g 90x24 -e "tmux"
+
+# General app shortcuts
+super + o; {w, p, r}
+ {firefox, pavucontrol, tdrop_c -n 3 -p 'bspc rule -a St -o state=floating' st -e lf}
+
+# Ncmpcpp
+super + alt + m
+ tdrop_c -n 2 -p 'bspc rule -a St -o state=floating' st -e ncmpcpp