commit 982f56d950166153d0a5f5c88b27f25fa40b4df4 Author: Niktia Bykov Date: Mon Jan 1 15:42:39 2024 +0500 initial diff --git a/.config/alacritty b/.config/alacritty new file mode 160000 index 0000000..114fb5f --- /dev/null +++ b/.config/alacritty @@ -0,0 +1 @@ +Subproject commit 114fb5fb32e76243d8b1fae3985b17d8129755db diff --git a/.config/awesome/rc.lua b/.config/awesome/rc.lua new file mode 100644 index 0000000..1b7b08d --- /dev/null +++ b/.config/awesome/rc.lua @@ -0,0 +1,464 @@ +-- If LuaRocks is installed, make sure that packages installed through it are +-- found (e.g. lgi). If LuaRocks is not installed, do nothing. +pcall(require, "luarocks.loader") + +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") +require("awful.autofocus") +-- Widget and layout library +local wibox = require("wibox") +-- Theme handling library +local beautiful = require("beautiful") +-- Notification library +local naughty = require("naughty") +local hotkeys_popup = require("awful.hotkeys_popup") +-- Enable hotkeys help widget for VIM and other apps +-- when client with a matching name is opened: +require("awful.hotkeys_popup.keys") + +-- {{{ Error handling +-- Check if awesome encountered an error during startup and fell back to +-- another config (This code will only ever execute for the fallback config) +if awesome.startup_errors then + naughty.notify({ + preset = naughty.config.presets.critical, + title = "Oops, there were errors during startup!", + text = awesome.startup_errors, + }) +end + +-- Handle runtime errors after startup +do + local in_error = false + awesome.connect_signal("debug::error", function(err) + -- Make sure we don't go into an endless error loop + if in_error then + return + end + in_error = true + + naughty.notify({ + preset = naughty.config.presets.critical, + title = "Oops, an error happened!", + text = tostring(err), + }) + in_error = false + end) +end +-- }}} + +-- {{{ Variable definitions +-- Themes define colours, icons, font and wallpapers. +beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua") + +-- This is used later as the default terminal and editor to run. +browser = "librewolf" +terminal = "alacritty" +editor = os.getenv("nvim") or "nvim" +editor_cmd = terminal .. " -e " .. editor + +modkey = "Mod4" + +awful.layout.layouts = { + awful.layout.suit.tile, +} + +local taglist_buttons = gears.table.join( + awful.button({}, 1, function(t) + t:view_only() + end), + awful.button({ modkey }, 1, function(t) + if client.focus then + client.focus:move_to_tag(t) + end + end), + awful.button({}, 3, awful.tag.viewtoggle), + awful.button({ modkey }, 3, function(t) + if client.focus then + client.focus:toggle_tag(t) + end + end), + awful.button({}, 4, function(t) + awful.tag.viewnext(t.screen) + end), + awful.button({}, 5, function(t) + awful.tag.viewprev(t.screen) + end) +) + +local tasklist_buttons = gears.table.join( + awful.button({}, 1, function(c) + if c == client.focus then + c.minimized = true + else + c:emit_signal("request::activate", "tasklist", { raise = true }) + end + end), + awful.button({}, 3, function() + awful.menu.client_list({ theme = { width = 250 } }) + end), + awful.button({}, 4, function() + awful.client.focus.byidx(1) + end), + awful.button({}, 5, function() + awful.client.focus.byidx(-1) + end) +) + +local function set_wallpaper(s) + -- Wallpaper + if beautiful.wallpaper then + local wallpaper = beautiful.wallpaper + -- If wallpaper is a function, call it with the screen + if type(wallpaper) == "function" then + wallpaper = wallpaper(s) + end + gears.wallpaper.maximized(wallpaper, s, true) + end +end + +-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution) +screen.connect_signal("property::geometry", set_wallpaper) + +awful.screen.connect_for_each_screen(function(s) + awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1]) +end) + +-- {{{ Mouse bindings +root.buttons(gears.table.join( + -- awful.button({}, 3, function() + -- mymainmenu:toggle() + -- end), + awful.button({}, 4, awful.tag.viewnext), + awful.button({}, 5, awful.tag.viewprev) +)) +-- }}} + +-- {{{ Key bindings +globalkeys = gears.table.join( + awful.key({ modkey }, "s", hotkeys_popup.show_help, { description = "show help", group = "awesome" }), + -- awful.key({ modkey }, "Left", awful.tag.viewprev, { description = "view previous", group = "tag" }), + -- awful.key({ modkey }, "Right", awful.tag.viewnext, { description = "view next", group = "tag" }), + awful.key({ modkey }, "Escape", awful.tag.history.restore, { description = "go back", group = "tag" }), + awful.key({ modkey }, "l", function() + awful.client.focus.byidx(1) + end, { description = "focus next by index", group = "client" }), + awful.key({ modkey }, "h", function() + awful.client.focus.byidx(-1) + end, { description = "focus previous by index", group = "client" }), + awful.key({ modkey }, "w", function() + mymainmenu:show() + end, { description = "show main menu", group = "awesome" }), + + -- Layout manipulation + awful.key({ modkey, "Shift" }, "h", function() + awful.client.swap.byidx(1) + end, { description = "swap with next client by index", group = "client" }), + awful.key({ modkey, "Shift" }, "l", function() + awful.client.swap.byidx(-1) + end, { description = "swap with previous client by index", group = "client" }), + awful.key({ modkey }, "k", function() + awful.screen.focus_relative(1) + end, { description = "focus the next screen", group = "screen" }), + awful.key({ modkey }, "j", function() + awful.screen.focus_relative(-1) + end, { description = "focus the previous screen", group = "screen" }), + awful.key({ modkey }, "u", awful.client.urgent.jumpto, { description = "jump to urgent client", group = "client" }), + awful.key({ modkey }, "Tab", function() + awful.client.focus.history.previous() + if client.focus then + client.focus:raise() + end + end, { description = "go back", group = "client" }), + + -- Standard program + awful.key({ modkey, "Shift" }, "r", awesome.restart, { description = "reload awesome", group = "awesome" }), + awful.key({ modkey, "Shift" }, "e", awesome.quit, { description = "quit awesome", group = "awesome" }), + awful.key({ modkey }, "y", function() + awful.tag.incmwfact(0.05) + end, { description = "increase master width factor", group = "layout" }), + awful.key({ modkey }, "o", function() + awful.tag.incmwfact(-0.05) + end, { description = "decrease master width factor", group = "layout" }), + + -- launch dmenu + awful.key({ modkey }, "d", function() + awful.util.spawn("dmenu_run") + end, { description = "dmenu", group = "launcher" }), + + -- launch browser + awful.key({ modkey }, "b", function() + awful.util.spawn(browser) + end, { description = "launch browser", group = "launcher" }), + + -- launch terminal + awful.key({ modkey }, "Return", function() + awful.spawn(terminal) + end, { description = "open a terminal", group = "launcher" }), + + -- launch ncmpcpp + awful.key({ modkey }, "m", function() + awful.spawn.with_shell(terminal .. " -e ncmpcpp") + end, { description = "open ncmpcpp", group = "launcher" }), + + -- music player daemon controls + awful.key({}, "XF86AudioPlay", function() + awful.spawn("playerctl play-pause") + end, { description = "toggle play", group = "launcher" }), + awful.key({}, "XF86AudioPause", function() + awful.spawn.with_shell("playerctl play-pause") + end, { description = "toggle play", group = "launcher" }), + awful.key({}, "XF86AudioNext", function() + awful.spawn.with_shell("playerctl next") + end, { description = "next", group = "launcher" }), + awful.key({}, "XF86AudioPrev", function() + awful.spawn.with_shell("playerctl previous") + end, { description = "previous", group = "launcher" }), + awful.key({ modkey, "Shift" }, "bracketleft", function() + awful.spawn.with_shell("playerctl -p mpd volume 0.05-") + end, { description = "decrease volume", group = "launcher" }), + awful.key({ modkey, "Shift" }, "bracketright", function() + awful.spawn.with_shell("playerctl -p mpd volume 0.05+") + end, { description = "increase volume", group = "launcher" }), + -- media hotkeys + awful.key({}, "XF86AudioRaiseVolume", function() + awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ +10%") + end, { description = "raise volume", group = "launcher" }), + awful.key({}, "XF86AudioLowerVolume", function() + awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ -10%") + end, { description = "lower volume", group = "launcher" }), + awful.key({}, "XF86AudioMute", function() + awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") + end, { description = "toggle mute", group = "launcher" }), + + -- toggle picom + awful.key({ modkey }, "c", function() + awful.spawn.with_shell("~/.config/awesome/scripts/toggle_picom.sh") + end, { description = "toggle picom", group = "launcher" }), + + -- make screenshot + awful.key({ modkey }, "Print", function() + awful.spawn.with_shell("flameshot gui") + end, { description = "flameshot", group = "launcher" }), + + -- logout + awful.key({ modkey, "Shift" }, "BackSpace", function() + awful.spawn.with_shell("$HOME/.config/awesome/scripts/logout_script.sh") + end, { description = "logout", group = "launcher" }) +) + +clientkeys = gears.table.join( + awful.key({ modkey }, "f", function(c) + c.fullscreen = not c.fullscreen + c:raise() + end, { description = "toggle fullscreen", group = "client" }), + awful.key({ modkey, "Shift" }, "q", function(c) + c:kill() + end, { description = "close", group = "client" }), + awful.key( + { modkey, "Shift" }, + "space", + awful.client.floating.toggle, + { description = "toggle floating", group = "client" } + ), + awful.key({ modkey }, "space", function(c) + c:swap(awful.client.getmaster()) + end, { description = "move to master", group = "client" }), + awful.key({ modkey }, "p", function(c) + c:move_to_screen() + end, { description = "move to screen", group = "client" }), + awful.key({ modkey }, "t", function(c) + c.ontop = not c.ontop + end, { description = "toggle keep on top", group = "client" }) +) + +-- Bind all key numbers to tags. +-- Be careful: we use keycodes to make it work on any keyboard layout. +-- This should map on the top row of your keyboard, usually 1 to 9. +for i = 1, 9 do + globalkeys = gears.table.join( + globalkeys, + -- View tag only. + awful.key({ modkey }, "#" .. i + 9, function() + local screen = awful.screen.focused() + local tag = screen.tags[i] + if tag then + tag:view_only() + end + end, { description = "view tag #" .. i, group = "tag" }), + -- Toggle tag display. + awful.key({ modkey, "Control" }, "#" .. i + 9, function() + local screen = awful.screen.focused() + local tag = screen.tags[i] + if tag then + awful.tag.viewtoggle(tag) + end + end, { description = "toggle tag #" .. i, group = "tag" }), + -- Move client to tag. + awful.key({ modkey, "Shift" }, "#" .. i + 9, function() + if client.focus then + local tag = client.focus.screen.tags[i] + if tag then + client.focus:move_to_tag(tag) + end + end + end, { description = "move focused client to tag #" .. i, group = "tag" }), + -- Toggle tag on focused client. + awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, function() + if client.focus then + local tag = client.focus.screen.tags[i] + if tag then + client.focus:toggle_tag(tag) + end + end + end, { description = "toggle focused client on tag #" .. i, group = "tag" }) + ) +end + +clientbuttons = gears.table.join( + awful.button({}, 1, function(c) + c:emit_signal("request::activate", "mouse_click", { raise = true }) + end), + awful.button({ modkey }, 1, function(c) + c:emit_signal("request::activate", "mouse_click", { raise = true }) + awful.mouse.client.move(c) + end), + awful.button({ modkey }, 3, function(c) + c:emit_signal("request::activate", "mouse_click", { raise = true }) + awful.mouse.client.resize(c) + end) +) + +-- Set keys +root.keys(globalkeys) +-- }}} + +-- {{{ Rules +-- Rules to apply to new clients (through the "manage" signal). +awful.rules.rules = { + -- All clients will match this rule. + { + rule = {}, + properties = { + border_width = beautiful.border_width, + border_color = beautiful.border_normal, + focus = awful.client.focus.filter, + raise = true, + keys = clientkeys, + buttons = clientbuttons, + screen = awful.screen.preferred, + placement = awful.placement.no_overlap + awful.placement.no_offscreen, + }, + }, + { + rule = { instance = "polybar" }, + properties = { border_width = false, focusable = false, below = true }, + }, + + -- Floating clients. + { + rule_any = { + instance = { + "DTA", -- Firefox addon DownThemAll. + "copyq", -- Includes session name in class. + "pinentry", + }, + class = { + "Arandr", + "Blueman-manager", + "Gpick", + "Kruler", + "MessageWin", -- kalarm. + "Sxiv", + "Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size. + "Wpa_gui", + "veromix", + "xtightvncviewer", + }, + -- Note that the name property shown in xprop might be set slightly after creation of the client + -- and the name shown there might not match defined rules here. + name = { + "Event Tester", -- xev. + }, + role = { + "AlarmWindow", -- Thunderbird's calendar. + "ConfigManager", -- Thunderbird's about:config. + "pop-up", -- e.g. Google Chrome's (detached) Developer Tools. + }, + }, + properties = { floating = true }, + }, + + -- Add titlebars to normal clients and dialogs + { rule_any = { type = { "normal", "dialog" } }, properties = { titlebars_enabled = false } }, +} +-- }}} + +-- {{{ Signals +-- Signal function to execute when a new client appears. +client.connect_signal("manage", function(c) + -- Set the windows at the slave, + -- i.e. put it at the end of others instead of setting it master. + -- if not awesome.startup then awful.client.setslave(c) end + + if awesome.startup and not c.size_hints.user_position and not c.size_hints.program_position then + -- Prevent clients from being unreachable after screen count changes. + awful.placement.no_offscreen(c) + end +end) + +-- Enable sloppy focus, so that focus follows mouse. +client.connect_signal("mouse::enter", function(c) + c:emit_signal("request::activate", "mouse_enter", { raise = false }) +end) + +client.connect_signal("focus", function(c) + c.border_color = beautiful.border_focus +end) +client.connect_signal("unfocus", function(c) + c.border_color = beautiful.border_normal +end) + +-- Gaps +beautiful.useless_gap = 10 + +client.connect_signal("property::minimized", function(c) + c.minimized = false +end) + +-- client.connect_signal("property::maximized", function(c) +-- c.shape = function(cr, w, h) +-- gears.shape.rounded_rect(cr, w, h, 0) +-- end +-- end) + +-- rounded borders +client.connect_signal("manage", function(c) + if c.instance ~= "polybar" then + c.shape = function(cr, w, h) + gears.shape.rounded_rect(cr, w, h, 0) + end + end +end) + +-- !!! somehow this breaks fullscreen !!! +-- floating on top always +-- client.connect_signal("property::floating", function(c) +-- if c.floating then +-- c.ontop = true +-- else +-- c.ontop = false +-- end +-- end) + +-- Autostart +-- awful.spawn.with_shell("picom") +awful.spawn.with_shell("$HOME/.config/polybar/launch_polybar.sh") +awful.spawn.with_shell("~/.fehbg") +awful.spawn.with_shell("xinput set-prop 13 298 0, -1") +awful.spawn.with_shell("amixer -c 0 set Front unmute") +-- awful.spawn.with_shell("mpDris2") +-- awful.spawn.with_shell("dex -ae i3") + +naughty.config.defaults.icon_size = 32 diff --git a/.config/awesome/scripts/logout_script.sh b/.config/awesome/scripts/logout_script.sh new file mode 100755 index 0000000..0115ae4 --- /dev/null +++ b/.config/awesome/scripts/logout_script.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# a simple dmenu session script +# +### + +DMENU='dmenu -i' +choice=$(echo -e "logout\nshutdown\nreboot\nsuspend\nhibernate" | $DMENU) + +case "$choice" in + shutdown) shutdown -h now & ;; + reboot) shutdown -r now & ;; + suspend) systemctl suspend & ;; + hibernate) systemctl hibernate & ;; +esac diff --git a/.config/awesome/scripts/toggle_picom.sh b/.config/awesome/scripts/toggle_picom.sh new file mode 100755 index 0000000..f095f0b --- /dev/null +++ b/.config/awesome/scripts/toggle_picom.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +pgrep picom>/dev/null && + killall picom &>/dev/null || + setsid picom --config ~/.config/picom/picom.conf & >/dev/null diff --git a/.config/dunst/dunstrc b/.config/dunst/dunstrc new file mode 100644 index 0000000..3aaaa84 --- /dev/null +++ b/.config/dunst/dunstrc @@ -0,0 +1,17 @@ +[global] +format = "%s\n%b" + +icon_path = "~/.local/share/icons/" +icon_theme = WhiteSur +max_icon_size = 64 +enable_recursive_icon_lookup = true + +origin = top-right +offset = 22x22 +frame_width = 2 +frame_color = "#b4befe" +separator_color= frame +font = "Input Mono" +corner_radius = 7 +background = "#11111B" +foreground = "#CDD6F4" diff --git a/.config/hypr/hyprland.conf b/.config/hypr/hyprland.conf new file mode 100644 index 0000000..8946256 --- /dev/null +++ b/.config/hypr/hyprland.conf @@ -0,0 +1,223 @@ +source=~/.config/hypr/mocha.conf + +exec-once = copyq --start-server + +exec-once=waybar +exec-once=hyprpaper +exec-once=dunst + +exec-once=xrandr --output DP-2 --primary + +exec-once = hyprpm reload -n + +monitor=DP-2,2560x1440@144,1920x0,1,vrr,2 +monitor=HDMI-A-1,1920x1080@60,0x360,1 + +# For all categories, see https://wiki.hyprland.org/Configuring/Variables/ +input { + kb_layout = us,ru + kb_variant = + kb_model = + kb_options = grp:alt_shift_toggle, caps:escape + kb_rules = + + accel_profile = + + follow_mouse = 1 + mouse_refocus = true + + repeat_rate = 35 + repeat_delay = 500 + + sensitivity = 0 # -1.0 - 1.0, 0 means no modification. + force_no_accel = true +} + +general { + gaps_in = 8 + gaps_out = 20 + border_size = 2 + + sensitivity = 1 + + col.active_border = rgba(05a4c4ee) + col.inactive_border = rgba(595959aa) + + layout = master +} + +decoration { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + + # rounding = 10 + rounding = 2 + drop_shadow = no + shadow_range = 4 + shadow_render_power = 3 + col.shadow = rgba(1a1a1aee) + inactive_opacity = 0.90 + active_opacity = 0.90 + + blur { + enabled = yes + size = 8 + } + +} + +animations { + enabled = false + + # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more + + bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + + animation = windows, 1, 4, myBezier, popin 70% + animation = windowsOut, 1, 4, default, popin 80% + animation = border, 0, 10, default + animation = borderangle, 0, 8, default + animation = fade, 0, 7, default + animation = workspaces, 0, 6, default +} + +dwindle { + # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more + pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below + preserve_split = yes # you probably want this +} + +master { + # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more + new_is_master = true + new_on_top = true + mfact = 0.5 +} + +gestures { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + workspace_swipe = off +} + +misc { + vrr = 2 + disable_hyprland_logo = true + no_direct_scanout = false +} + +# Example windowrule v1 +# windowrule = float, ^(kitty)$ +# Example windowrule v2 +# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ +# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more + + +# See https://wiki.hyprland.org/Configuring/Keywords/ for more +$mainMod = SUPER +$terminal = alacritty +# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more +# +bind = $mainMod_SHIFT, E, exit +bind = $mainMod_SHIFT, Q, killactive, +bind = $mainMod_SHIFT, SPACE, togglefloating, + +bind = $mainMod, D, exec, tofi-drun --drun-launch=true + +# Apps binds +bind = $mainMod, RETURN, exec, $terminal +bind = $mainMod, M, exec, $terminal -e ncmpcpp +bind = $mainMod, B, exec, librewolf + +# screenshot area +bind = $mainMod_SHIFT, S, exec, grim -g "$(slurp)" - | wl-copy + +# powermenu +bind = $mainMod_SHIFT, BackSpace, exec, ~/.config/tofi/powermenu.sh + +# bind = $mainMod, P, pseudo, # dwindle +# bind = $mainMod, J, togglesplit, # dwindle + +# Move focus with mainMod + arrow keys +# bind = $mainMod, L, movefocus, l +# bind = $mainMod, H, movefocus, r +# bind = $mainMod, up, movefocus, u +# bind = $mainMod, down, movefocus, d +# +bind = $mainMod, L, layoutmsg, cyclenext +bind = $mainMod, H, layoutmsg, cycleprev + +bind = $mainMod, J, focusmonitor, -1 +bind = $mainMod, K, focusmonitor, +1 + +bind = $mainMod, Y, splitratio, +0.1 +bind = $mainMod, O, splitratio, -0.1 + +bind = $mainMod, P, movewindow, mon:-1 +# bind = $mainMod, H, cycleprev +# +# bind = $mainMod, Y, master, mfact + 10 + +bind = $mainMod, SPACE, layoutmsg, swapwithmaster + +bind = $mainMod, F, fullscreen, swapwithmaster + + +# volume controls +bind = ,XF86AudioPlay, exec, playerctl play-pause +bind = ,XF86AudioPause, exec, playerctl play-pause +bind = ,XF86AudioNext, exec, playerctl next +bind = ,XF86AudioPrev, exec, playerctl previous + +bind = $mainMod_SHIFT, bracketleft, exec, playerctl -p mpd volume 0.05- +bind = $mainMod_SHIFT, bracketright, exec, playerctl -p mpd volume 0.05+ + +bind = $mainMod, PAGE_UP, pass, ^(discord)$ +# bind = $mainMod, PAGE_UP, pass, ^(discord-screenaudio)$ + +bind = ,XF86AudioRaiseVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ +5% +bind = ,XF86AudioLowerVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ -5% +bind = ,XF86AudioMute, exec, pactl set-sink-mute @DEFAULT_SINK@ toggle + +bind = ,XF86MonBrightnessDown, exec, ddcutil -d 2 setvcp 10 - 5 +bind = ,XF86MonBrightnessUp, exec, ddcutil -d 2 setvcp 10 + 5 + +exec-once=sleep 2; amixer -c 0 set Front unmute +exec-once=sleep 2; amixer -c 1 set Front unmute + +# exec-once=hyprctl plugin load $HOME/.config/hypr/split-monitor-workspaces.so + +plugin { + split-monitor-workspaces { + count = 10 + } +} + +# Switch workspaces with mainMod + [0-9] +bind = $mainMod, 1, split-workspace, 1 +bind = $mainMod, 2, split-workspace, 2 +bind = $mainMod, 3, split-workspace, 3 +bind = $mainMod, 4, split-workspace, 4 +bind = $mainMod, 5, split-workspace, 5 +bind = $mainMod, 6, split-workspace, 6 +bind = $mainMod, 7, split-workspace, 7 +bind = $mainMod, 8, split-workspace, 8 +bind = $mainMod, 9, split-workspace, 9 + +# Move active window to a workspace with mainMod + SHIFT + [0-9] +bind = $mainMod SHIFT, 1, split-movetoworkspacesilent, 1 +bind = $mainMod SHIFT, 2, split-movetoworkspacesilent, 2 +bind = $mainMod SHIFT, 3, split-movetoworkspacesilent, 3 +bind = $mainMod SHIFT, 4, split-movetoworkspacesilent, 4 +bind = $mainMod SHIFT, 5, split-movetoworkspacesilent, 5 +bind = $mainMod SHIFT, 6, split-movetoworkspacesilent, 6 +bind = $mainMod SHIFT, 7, split-movetoworkspacesilent, 7 +bind = $mainMod SHIFT, 8, split-movetoworkspacesilent, 8 +bind = $mainMod SHIFT, 9, split-movetoworkspacesilent, 9 + + +# Scroll through existing workspaces with mainMod + scroll +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 + +# Move/resize windows with mainMod + LMB/RMB and dragging +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow diff --git a/.config/hypr/hyprpaper.conf b/.config/hypr/hyprpaper.conf new file mode 100644 index 0000000..42c8e72 --- /dev/null +++ b/.config/hypr/hyprpaper.conf @@ -0,0 +1,4 @@ +preload = ~/Pictures/wallpapers/wallhaven-o5w96p_2560x1440.png + +wallpaper = HDMI-A-1,~/Pictures/wallpapers/wallhaven-o5w96p_2560x1440.png +wallpaper = DP-2,~/Pictures/wallpapers/wallhaven-o5w96p_2560x1440.png diff --git a/.config/hypr/mocha.conf b/.config/hypr/mocha.conf new file mode 100644 index 0000000..1463565 --- /dev/null +++ b/.config/hypr/mocha.conf @@ -0,0 +1,61 @@ +$rosewaterAlpha = f5e0dc +$flamingoAlpha = f2cdcd +$pinkAlpha = f5c2e7 +$mauveAlpha = cba6f7 +$redAlpha = f38ba8 +$maroonAlpha = eba0ac +$peachAlpha = fab387 +$yellowAlpha = f9e2af +$greenAlpha = a6e3a1 +$tealAlpha = 94e2d5 +$skyAlpha = 89dceb +$sapphireAlpha = 74c7ec +$blueAlpha = 89b4fa +$lavenderAlpha = b4befe + +$textAlpha = cdd6f4 +$subtext1Alpha = bac2de +$subtext0Alpha = a6adc8 + +$overlay2Alpha = 9399b2 +$overlay1Alpha = 7f849c +$overlay0Alpha = 6c7086 + +$surface2Alpha = 585b70 +$surface1Alpha = 45475a +$surface0Alpha = 313244 + +$baseAlpha = 1e1e2e +$mantleAlpha = 181825 +$crustAlpha = 11111b + +$rosewater = 0xfff5e0dc +$flamingo = 0xfff2cdcd +$pink = 0xfff5c2e7 +$mauve = 0xffcba6f7 +$red = 0xfff38ba8 +$maroon = 0xffeba0ac +$peach = 0xfffab387 +$yellow = 0xfff9e2af +$green = 0xffa6e3a1 +$teal = 0xff94e2d5 +$sky = 0xff89dceb +$sapphire = 0xff74c7ec +$blue = 0xff89b4fa +$lavender = 0xffb4befe + +$text = 0xffcdd6f4 +$subtext1 = 0xffbac2de +$subtext0 = 0xffa6adc8 + +$overlay2 = 0xff9399b2 +$overlay1 = 0xff7f849c +$overlay0 = 0xff6c7086 + +$surface2 = 0xff585b70 +$surface1 = 0xff45475a +$surface0 = 0xff313244 + +$base = 0xff1e1e2e +$mantle = 0xff181825 +$crust = 0xff11111b diff --git a/.config/lazygit/config.yml b/.config/lazygit/config.yml new file mode 100644 index 0000000..e69de29 diff --git a/.config/lazygit/state.yml b/.config/lazygit/state.yml new file mode 100644 index 0000000..f153ede --- /dev/null +++ b/.config/lazygit/state.yml @@ -0,0 +1,15 @@ +lastupdatecheck: 0 +recentrepos: +- /home/nikita/Code/job_hunter +- /home/nikita/Code/maxim_test +- /home/nikita/Code/coworking/backend +- /home/nikita/Code/rlt_test +- /home/nikita/Code/coworking/admin_frontend +- /home/nikita/Code/bur_test_full/BurTest +- /home/nikita/Code/bur_test_full/bur_test +- /home/nikita/Code/itteams +- /home/nikita/.config/nvim +startuppopupversion: 5 +customcommandshistory: [] +hidecommandlog: true +ignorewhitespaceindiffview: false diff --git a/.config/mpd/database b/.config/mpd/database new file mode 100644 index 0000000..2a29a02 Binary files /dev/null and b/.config/mpd/database differ diff --git a/.config/mpd/mpd.conf b/.config/mpd/mpd.conf new file mode 100644 index 0000000..ae3cc21 --- /dev/null +++ b/.config/mpd/mpd.conf @@ -0,0 +1,446 @@ +# An example configuration file for MPD. +# Read the user manual for documentation: http://www.musicpd.org/doc/user/ + + +# Files and directories ####################################################### +# +# This setting controls the top directory which MPD will search to discover the +# available audio files and add them to the daemon's online database. This +# setting defaults to the XDG directory, otherwise the music directory will be +# be disabled and audio files will only be accepted over ipc socket (using +# file:// protocol) or streaming files over an accepted protocol. +# +music_directory "~/Music" +# +# This setting sets the MPD internal playlist directory. The purpose of this +# directory is storage for playlists created by MPD. The server will use +# playlist files not created by the server but only if they are in the MPD +# format. This setting defaults to playlist saving being disabled. +# +playlist_directory "~/.config/mpd/playlists" +# +# This setting sets the location of the MPD database. This file is used to +# load the database at server start up and store the database while the +# server is not up. This setting defaults to disabled which will allow +# MPD to accept files over ipc socket (using file:// protocol) or streaming +# files over an accepted protocol. +# +db_file "~/.config/mpd/database" + +# These settings are the locations for the daemon log files for the daemon. +# +# The special value "syslog" makes MPD use the local syslog daemon. This +# setting defaults to logging to syslog. +# +# If you use systemd, do not configure a log_file. With systemd, MPD +# defaults to the systemd journal, which is fine. +# +#log_file "~/.mpd/log" + +# This setting sets the location of the file which stores the process ID +# for use of mpd --kill and some init scripts. This setting is disabled by +# default and the pid file will not be stored. +# +# If you use systemd, do not configure a pid_file. +# +#pid_file "~/.config/mpd/pid" + +# This setting sets the location of the file which contains information about +# most variables to get MPD back into the same general shape it was in before +# it was brought down. This setting is disabled by default and the server +# state will be reset on server start up. +# +state_file "~/.config/mpd/state" +# +# The location of the sticker database. This is a database which +# manages dynamic information attached to songs. +# +sticker_file "~/.config/mpd/sticker.sql" +# +############################################################################### + + +# General music daemon options ################################################ +# +# This setting specifies the user that MPD will run as. MPD should never run as +# root and you may use this setting to make MPD change its user ID after +# initialization. This setting is disabled by default and MPD is run as the +# current user. +# +#user "nobody" +# +# This setting specifies the group that MPD will run as. If not specified +# primary group of user specified with "user" setting will be used (if set). +# This is useful if MPD needs to be a member of group such as "audio" to +# have permission to use sound card. +# +#group "nogroup" +# +# This setting sets the address for the daemon to listen on. Careful attention +# should be paid if this is assigned to anything other than the default, any. +# This setting can deny access to control of the daemon. Not effective if +# systemd socket activation is in use. +# +# For network +#bind_to_address "any" +# +# And for Unix Socket +#bind_to_address "~/.mpd/socket" +# +# This setting is the TCP port that is desired for the daemon to get assigned +# to. +# +#port "6600" +# +# Suppress all messages below the given threshold. Use "verbose" for +# troubleshooting. Available setting arguments are "notice", "info", "verbose", +# "warning" and "error". +# +#log_level "notice" +# +# Setting "restore_paused" to "yes" puts MPD into pause mode instead +# of starting playback after startup. +# +#restore_paused "no" +# +# This setting enables MPD to create playlists in a format usable by other +# music players. +# +#save_absolute_paths_in_playlists "no" +# +# This setting defines a list of tag types that will be extracted during the +# audio file discovery process. The complete list of possible values can be +# found in the user manual. +#metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc" +# +# This example just enables the "comment" tag without disabling all +# the other supported tags: +#metadata_to_use "+comment" +# +# This setting enables automatic update of MPD's database when files in +# music_directory are changed. +# +auto_update "yes" +# +# Limit the depth of the directories being watched, 0 means only watch +# the music directory itself. There is no limit by default. +# +#auto_update_depth "3" +# +############################################################################### + + +# Symbolic link behavior ###################################################### +# +# If this setting is set to "yes", MPD will discover audio files by following +# symbolic links outside of the configured music_directory. +# +#follow_outside_symlinks "yes" +# +# If this setting is set to "yes", MPD will discover audio files by following +# symbolic links inside of the configured music_directory. +# +#follow_inside_symlinks "yes" +# +############################################################################### + + +# Zeroconf / Avahi Service Discovery ########################################## +# +# If this setting is set to "yes", service information will be published with +# Zeroconf / Avahi. +# +#zeroconf_enabled "yes" +# +# The argument to this setting will be the Zeroconf / Avahi unique name for +# this MPD server on the network. %h will be replaced with the hostname. +# +#zeroconf_name "Music Player @ %h" +# +############################################################################### + + +# Permissions ################################################################# +# +# If this setting is set, MPD will require password authorization. The password +# setting can be specified multiple times for different password profiles. +# +#password "password@read,add,control,admin" +# +# This setting specifies the permissions a user has who has not yet logged in. +# +#default_permissions "read,add,control,admin" +# +############################################################################### + + +# Database ####################################################################### +# +# An example of a database section instead of the old 'db_file' setting. +# It enables mounting other storages into the music directory. +# +#database { +# plugin "simple" +# path "~/.local/share/mpd/db +# cache_directory "~/.local/share/mpd/cache" +#} +# +# An example of database config for a satellite setup +# +#music_directory "nfs://fileserver.local/srv/mp3" +#database { +# plugin "proxy" +# host "other.mpd.host" +# port "6600" +#} + +# Input ####################################################################### +# +input { + plugin "curl" +# proxy "proxy.isp.com:8080" +# proxy_user "user" +# proxy_password "password" +} + +# +############################################################################### + +# Audio Output ################################################################ +# +# MPD supports various audio output types, as well as playing through multiple +# audio outputs at the same time, through multiple audio_output settings +# blocks. Setting this block is optional, though the server will only attempt +# autodetection for one sound card. +# +# An example of an ALSA output: +# +#audio_output { +# type "alsa" +# name "My ALSA Device" +## device "hw:0,0" # optional +## mixer_type "hardware" # optional +## mixer_device "default" # optional +## mixer_control "PCM" # optional +## mixer_index "0" # optional +#} +# +# An example of an OSS output: +# +#audio_output { +# type "oss" +# name "My OSS Device" +## device "/dev/dsp" # optional +## mixer_type "hardware" # optional +## mixer_device "/dev/mixer" # optional +## mixer_control "PCM" # optional +#} +# +# An example of a shout output (for streaming to Icecast): +# +#audio_output { +# type "shout" +# encoder "vorbis" # optional +# name "My Shout Stream" +# host "localhost" +# port "8000" +# mount "/mpd.ogg" +# password "hackme" +# quality "5.0" +# bitrate "128" +# format "44100:16:1" +## protocol "icecast2" # optional +## user "source" # optional +## description "My Stream Description" # optional +## url "http://example.com" # optional +## genre "jazz" # optional +## public "no" # optional +## timeout "2" # optional +## mixer_type "software" # optional +#} +# +# An example of a recorder output: +# +#audio_output { +# type "recorder" +# name "My recorder" +# encoder "vorbis" # optional, vorbis or lame +# path "/var/lib/mpd/recorder/mpd.ogg" +## quality "5.0" # do not define if bitrate is defined +# bitrate "128" # do not define if quality is defined +# format "44100:16:1" +#} +# +# An example of a httpd output (built-in HTTP streaming server): +# +#audio_output { +# type "httpd" +# name "My HTTP Stream" +# encoder "vorbis" # optional, vorbis or lame +# port "8000" +# bind_to_address "0.0.0.0" # optional, IPv4 or IPv6 +## quality "5.0" # do not define if bitrate is defined +# bitrate "128" # do not define if quality is defined +# format "44100:16:1" +# max_clients "0" # optional 0=no limit +#} +# +# An example of a pulseaudio output (streaming to a remote pulseaudio server) +# + +#audio_output { +# type "pulse" +# name "pulse audio" +#} + +audio_output { + type "pipewire" + name "PipeWire Sound Server" +} + +# +# An example of a winmm output (Windows multimedia API). +# +#audio_output { +# type "winmm" +# name "My WinMM output" +## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional +# or +## device "0" # optional +## mixer_type "hardware" # optional +#} +# +# An example of a wasapi output (Windows multimedia API). +# +#audio_output { +# type "wasapi" +# name "My WASAPI output" +## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional +# or +## device "0" # optional +## Exclusive mode blocks all other audio source, and get best audio quality without resampling. +## exclusive "no" # optional +## Enumerate all devices in log. +## enumerate "no" # optional +#} +# +# An example of an openal output. +# +#audio_output { +# type "openal" +# name "My OpenAL output" +## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional +#} +# +# An example of an sndio output. +# +#audio_output { +# type "sndio" +# name "sndio output" +# mixer_type "hardware" +#} +# +# An example of an OS X output: +# +#audio_output { +# type "osx" +# name "My OS X Device" +## device "Built-in Output" # optional +## channel_map "-1,-1,0,1" # optional +#} +# +## Example "pipe" output: +# +#audio_output { +# type "pipe" +# name "my pipe" +# command "aplay -f cd 2>/dev/null" +## Or if you're want to use AudioCompress +# command "AudioCompress -m | aplay -f cd 2>/dev/null" +## Or to send raw PCM stream through PCM: +# command "nc example.org 8765" +# format "44100:16:2" +#} +# +## An example of a null output (for no audio output): +# +#audio_output { +# type "null" +# name "My Null Output" +# mixer_type "none" # optional +#} +# + +audio_output { + type "fifo" + name "my_fifo" + path "/tmp/mpd.fifo" + format "44100:16:2" +} + + + +############################################################################### + + +# Normalization automatic volume adjustments ################################## +# +# This setting specifies the type of ReplayGain to use. This setting can have +# the argument "off", "album", "track" or "auto". "auto" is a special mode that +# chooses between "track" and "album" depending on the current state of +# random playback. If random playback is enabled then "track" mode is used. +# See for +# more details about ReplayGain. +# This setting is off by default. +# +#replaygain "album" +# +# This setting sets the pre-amp used for files that have ReplayGain tags. By +# default this setting is disabled. +# +#replaygain_preamp "0" +# +# This setting sets the pre-amp used for files that do NOT have ReplayGain tags. +# By default this setting is disabled. +# +#replaygain_missing_preamp "0" +# +# This setting enables or disables ReplayGain limiting. +# MPD calculates actual amplification based on the ReplayGain tags +# and replaygain_preamp / replaygain_missing_preamp setting. +# If replaygain_limit is enabled MPD will never amplify audio signal +# above its original level. If replaygain_limit is disabled such amplification +# might occur. By default this setting is enabled. +# +#replaygain_limit "yes" +# +# This setting enables on-the-fly normalization volume adjustment. This will +# result in the volume of all playing audio to be adjusted so the output has +# equal "loudness". This setting is disabled by default. +# +#volume_normalization "no" +# +############################################################################### + +# Character Encoding ########################################################## +# +# If file or directory names do not display correctly for your locale then you +# may need to modify this setting. +# +#filesystem_charset "UTF-8" +# +############################################################################### + +playlist_plugin { + name "m3u" + enabled "true" +} + +playlist_plugin { + name "extm3u" + enabled "true" + as_directory "yes" +} + + +restore_paused "yes" diff --git a/.config/mpd/playlists/play.m3u b/.config/mpd/playlists/play.m3u new file mode 100644 index 0000000..fc482cc --- /dev/null +++ b/.config/mpd/playlists/play.m3u @@ -0,0 +1,297 @@ +#EXTM3U +#EXTINF:92,mymusic - 10. Claw Finger - Akira Yamaoka (Silent Hill Soundtrack) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=189&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTg5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.EBF6etEYfMcbR0Pdi3q9XvcRo7JLf5rnnDmT7FkgO7s +#EXTINF:333,mymusic - A Moment_s Peace +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=197&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTk3JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.q8zxYFyi29SKfnXQI8c6OzOitvLdfSDHoCNqA2QRnHE +#EXTINF:140,mymusic - Akira Yamaoka Never Forgive Me, Never Forget Me +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=101&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTAxJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.5NbWbOgwyffIwNroqc3uOADrg_PVYykr3k3CdHlwiZA +#EXTINF:298,mymusic - Angelo Badalamenti Twin Peaks Theme ( Instrumental) 1990 +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=75&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NzUmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.nReR3K9oDjBgdwn-jlxYTq1nnTn4lLqWGVmKLYiP1HI +#EXTINF:116,Berserk soundtrack - Behelit +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=134&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTM0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.pQ89FzPQSbgA_bE_8MzaKh8MMGcqeO4Fs_CVHpiFBZk +#EXTINF:216,Berserk soundtrack - 4 Gatsu +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=109&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTA5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.JnjEGdDQvI0PHI7V9TxC1Z82NlSYR6JH4v4_PRWH-g8 +#EXTINF:439,mymusic - Boy Harsher — Pain +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=21&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjEmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.4_WIanWn4KTq0e87bztSjMlMxXe04d912Jhtn-U20NE +#EXTINF:242,mymusic - CC - KEPT +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=25&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjUmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.EWOpWl3qIYYyP2vdUcovbNiN7V2I79eSm0a4dRJ8qKE +#EXTINF:221,mymusic - Chernikovskaya Hata - Nochnoe Randevu +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=62&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NjImc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.GornkB4kDwWFJInsgedalOYdOMy8kS2du0S01BCIofo +#EXTINF:189,mymusic - Chloroform +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=51&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NTEmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.CmGR8pEsBL3H0CNU6BoeUJX0I-1MyqlATfjAyEOi5NQ +#EXTINF:35,mymusic - city_station +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=196&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTk2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ._3qipdp2JwdLqsgQ8DO4adYP0GabJ74y2ydDQxfD4jg +#EXTINF:209,mymusic - CRIM3S - BREED +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=24&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjQmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.uU-kiei7a44YK-zXFVrcTdY1Q1quVVBX4t2RdqRYu3E +#EXTINF:148,mymusic - CRIM3S - lost +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=145&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTQ1JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.RTlZGsYr-7-XopYsAzbQG_nLzEZaqVQGFnmAhYD6S4Y +#EXTINF:201,mymusic - CRIM3S - still goin (OFFICIAL) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=40&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NDAmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.PVh8_35cUc5EDmFy5if0MDVlBU4Vq5GZGGrl_O_4NRQ +#EXTINF:166,mymusic - CRIM3S - stress (OFFICIAL) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=190&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTkwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.e9-ygAab8kt78a0HsCWh8kUF6o2SrNPs69oIdU4g55Q +#EXTINF:188,mymusic - CRYSTAL CASTLES - CHAR --official +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=32&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MzImc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.DiRahuRQNy6bO3ZIKp7XrhqrW6olMTjODSDYWEOtZgA +#EXTINF:197,mymusic - Crystal Castles - Concrete +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=142&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTQyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.XrkFRC_28LxWjRIHNzQzx3eWQDgbrZs6lBI_rISOWOU +#EXTINF:174,mymusic - Crystal Castles - Crimewave (Radio Edit) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=64&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NjQmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.A5d-GjP00--fxXzVHELZ9TzeA9Y6sR2odyJ8S1u2Wsg +#EXTINF:294,mymusic - Crystal Castles - Deicide (2015) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=94&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTQmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.eqEYjVUO0YS2uRoyOHV8Vlg6buL9BJDBONAOqayRG1g +#EXTINF:251,mymusic - Crystal Castles - Empathy +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=218&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjE4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.N5g91uRiiCEqsy6-tPLWd2NyyKnxT6Z-6xD6l3DqELU +#EXTINF:152,mymusic - Crystal Castles - Femen +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=129&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTI5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.yk7Ze1WJs_D0_lHdyGEub_x6cxdkguwz4dClyUCcIPA +#EXTINF:168,mymusic - Crystal Castles - Frail +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=56&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NTYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.XUeU2jmV3Mp4-33BwK5HBZqS7dn_PPZJdFpR83JOFGM +#EXTINF:175,mymusic - Crystal Castles - Good Time +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=178&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTc4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.ngzJBkVe9Z81onoraYW8uURCM2dKQGx--zG9C9mmW6Q +#EXTINF:285,mymusic - Crystal Castles - Intimate +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=212&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjEyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.32v3OHWg_iR6Cyq2j1M6271YF79FAHz9vmlSuk1e7qY +#EXTINF:192,mymusic - Crystal Castles - Kerosene +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=176&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTc2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.dITX2F_laay-CObMMvlYQxJ6jZpa2FQudqmNI-aq_r8 +#EXTINF:254,mymusic - crystal castles - leni +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=20&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjAmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.bXFzSULI5LIBCc__lgA-6OsNVVCHUnLTxXiNC7IPCA0 +#EXTINF:366,mymusic - Crystal Castles - Magic Spells +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=119&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTE5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.i5tvJAGP7weVU4uHfIDz8t1Ldz94jdKpMMD96_iK9Rk +#EXTINF:223,mymusic - Crystal Castles - Pap Smear +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=48&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NDgmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.P4v9CfXYXiilQUt8QoVly8I9_jKjJrndNwT7owT3s0Y +#EXTINF:207,mymusic - Crystal Castles - Sad Eyes +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=29&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Mjkmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.4lEpDIP9hitBsn_g_ntJ1dNhB4dZDAnH0ZAJ5IdraNw +#EXTINF:242,mymusic - Crystal Castles - Suffocation +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=112&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTEyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.IihicjI3K_7s4-FFUBDBNypPd-heswQQ2VahijIojtU +#EXTINF:150,mymusic - crystal castles - transgender (sped up_nightcore) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=222&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjIyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.tuINja0ByyKwBbxjCveN2Si9jTMdDoTXKHMihzmXaAY +#EXTINF:184,mymusic - Crystal Castles - Transgender +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=116&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTE2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.w-UEcxUzXqh00bw-Br09uw_wMrcw1z8b4yFfSIC3_wQ +#EXTINF:186,mymusic - Crystal Castles - Untrust Us +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=93&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTMmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.uy7sWcxPLatlxtb7xJAEWniN8axtt6sRZML0fOwmt0k +#EXTINF:243,mymusic - Crystal Castles - Vanished +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=139&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTM5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.WUVWJXmt40q4Z-BcDCa09ZXxCerX1rDvB7DG8AALaZ4 +#EXTINF:308,mymusic - Crystal Castles - Vietnam +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=124&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTI0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.T24h95SGAgA_CG0PX4dLSfvpB1ZKarBGC75SKvY5tTA +#EXTINF:429,mymusic - Daft Punk - Around the World (Official Audio) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=209&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjA5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.Mr35-G4dCU2OajlGWmBM0mvf-MCmEVI-uWdt-LM8Q6E +#EXTINF:328,mymusic - Daft Punk - Da Funk (Official Audio) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=85&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9ODUmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.GodWiIUABrGpBFHvnGK1LlPiYp3DnQmdPjM-FufwUCA +#EXTINF:240,mymusic - Daft Punk - Face to Face (Official Audio) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=19&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTkmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.QQWP-evn46ZKfWcacFfB2uQAUddmbUTnS7xU0Pb90Eo +#EXTINF:226,mymusic - Daft Punk - Harder, Better, Faster, Stronger (Official Audio) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=66&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NjYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.re8fzSr6PX2uBWvYIeDbSmZeI0SET5I5c3lG-PNnR1w +#EXTINF:321,mymusic - Daft Punk - One More Time (Official Video) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=161&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTYxJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.t8YBmenQ9-VbR0BU99hg7g9eopQuwXI7wOIPrSfkywY +#EXTINF:196,mymusic - Daft Punk - Robot Rock (Official Video) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=14&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTQmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.2r0m0tWSSqZUk33rpcZWmfDH7--5wOHobDWc9-mCD6U +#EXTINF:228,mymusic - Daft Punk - Something About Us (Official Video) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=68&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Njgmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.BEzEYBoiu-1qbs8oAA2wYYnGSlu6TbFFFG1-pniZQ8U +#EXTINF:133,mymusic - Daft Punk - Something About US Love (Theme from Interstella 5555) HD +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=47&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NDcmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.qb5DgJMiXPaOAg3QQ4ZC68sC6AEeYwqz9rpjAe_gMUQ +#EXTINF:600,mymusic - Daft Punk - Too Long (Official Audio) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=80&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9ODAmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.Szu_PTF3_ctuQM8FjRlm-K059xFI8AS37CP4UzUFNPE +#EXTINF:357,mymusic - Daft Punk - Veridis Quo (Music Video) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=198&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTk4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.CAjz2bUfuv6wZM9vFAq5RFgHC8zyjmtLkHlzqrUK8sM +#EXTINF:227,mymusic - Daft Punk - Voyager (Official Audio) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=73&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NzMmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.QaCM3JY2dwvTYaTPa-ohjtkL_0XG6IogyEVCFjS263E +#EXTINF:162,mymusic - Daisuke - El Huervo +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=78&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Nzgmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.39l6tTmjPxs2ZRfR7im-VN3Qsf55e6tXoLB1eH68R8o +#EXTINF:198,mymusic - dark beach - pastel ghost (sped up) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=181&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTgxJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.z_S2TJYyCOsNKF5_HvbbVth6elf4T-Gi4ZfJLYtPzw8 +#EXTINF:127,mymusic - Death Note Ost 1 - 17 Taikutsu +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=159&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTU5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.Wo1K22FkcyU86eo_Mp5q-sa4eQ7RfalpY0gUNzNiKdo +#EXTINF:128,mymusic - Death Note OST I - Tokusou Kira Han +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=90&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTAmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.GSD1BNwUOWsmTt48fZ-0qLa05VBaY0ek3nDjwPIs2sw +#EXTINF:193,mymusic - Death Note OST- 07- Solitude (孤独 Kodoku) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=54&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NTQmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.7N8ENvu68M4FzJ5yksW9FwZ4KdnvLhtgoQRdasUcJkU +#EXTINF:205,mymusic - Deathbrain - how to sleep +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=226&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjI2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.XJddK9rcSy7H_RV93JNuB0NV65-JHxSGaWuzsf0J6-Q +#EXTINF:279,mymusic - Decade Dance (Game Mix) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=177&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTc3JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.rx1OfYuzy43QKdnUk9i69rVOtN6_yDCdQE4rBDLh8I0 +#EXTINF:234,mymusic - Eagle Eyed Tiger - Stasis +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=169&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTY5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.ixLvIvzJRTTgTKlKEWxzefQXaMxjePs7-ODRBFHuJQU +#EXTINF:261,mymusic - El Tigr3 - Huntress +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=33&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MzMmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.IlIsuAZbskLZlP1hs7g004f7zcjMZXLfJReyjXy_lF4 +#EXTINF:301,mymusic - El Tigr3 - Infanticide +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=74&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NzQmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.mSlFuKylr7Ocm9rPpG5Jet96rcWBvV6kRM-zPEO-o0c +#EXTINF:209,mymusic - Enth +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=50&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NTAmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.Qk4u4o-g3Zehl-7yssWhsQQQsX-jVLXftLdlU15az4Y +#EXTINF:242,mymusic - forces +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=143&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTQzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.VJxjziyUgcug9-phjmhpcPV-fmN1ypq-vWc5OWQQv4g +#EXTINF:317,mymusic - Goreshit - Fine Night +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=158&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTU4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.oHGV8AnRtRbrHBqkglZbpj11DcuMaA4L6aCIp3PhTnA +#EXTINF:383,mymusic - Goreshit - o'er the flood +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=225&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjI1JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.-RdgIRREHtbhf1Zvv2vK6lyAt3cmkL5kYli4vH3riA0 +#EXTINF:271,mymusic - Grimes - 4ÆM (Audio) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=30&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MzAmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9._mpLM4JRA0VyT-gMqbxBXcfGeW1Emn9BRdUCnIfS5j8 +#EXTINF:249,mymusic - Highway Superstar - Maximum Performance +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=192&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTkyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.OHH83nrQ-tywZhXUFRAb7zzNTbMNqxhUl66rLDog8wY +#EXTINF:213,mymusic - HOME - Resonance +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=217&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjE3JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.VvyGEJhtlmXVaK49dSPTpZSeXax_yCo-lyLvavOdjhQ +#EXTINF:193,mymusic - Hotline Miami 2 - _Remorse_ [Nightclub Version] +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=150&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTUwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.XJz6FxYHINIZHBNQCknT8rOrcMtAZvIbWlAkoIWbIP0 +#EXTINF:499,mymusic - Hotline Miami 2_ Wrong Number Soundtrack - Delay +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=37&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Mzcmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.QEQh6jO1_l7zYh9eS5-P_Fuvq78b4CnU9_HJhOJDEAc +#EXTINF:281,mymusic - Hotline Miami 2_ Wrong Number Soundtrack - She Swallowed Burning Coals +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=168&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTY4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.JSAjSU49FTqIE-CH-z5uM9tJVeP0EJSw1qdayuWuZ-0 +#EXTINF:293,mymusic - iamthekidyouknowwhatimean – Run +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=58&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NTgmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.4hd3CjcURFnh_XLS3e2ImpctDZF84FcUvh58eoYPVOU +#EXTINF:106,mymusic - Insulin +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=36&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MzYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.R-izAsz9jBkqR4HD5f_QbkmOPTd_T862LSqbpmxuWwU +#EXTINF:148,mymusic - Kaito Shoma - GAZ +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=184&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTg0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.kJ8_D6weDOd5fh7lGq3NyYqPOqUjcpgby5cyvlMkLiI +#EXTINF:158,mymusic - Kaito Shoma - Hotline +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=193&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTkzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.pS4MIy3FbAsPFfbfRj3UJ0zo6M1anyZ7ZdQw7KYkD98 +#EXTINF:235,mymusic - keygen (feat. sewerslvt) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=233&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjMzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.CFR-SSdzG5Jgv1RT2Vu-dkIt5BO_enQJ6iDbWN7uY5M +#EXTINF:181,mymusic - Killer Queen (Remastered 2011) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=136&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTM2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.45D4LbbjIy6L9DzZY5zbQ1274Z7qj0jdLK2-09ZqihM +#EXTINF:382,mymusic - KINO - Spokoynaya Noch_ (Calm Night) Спокойная ночь +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=229&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjI5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.w1gQ316fXi741vLJ919Lr1H1XJQAYPQSjK1ZK_WSztM +#EXTINF:-1,mymusic - l no nakama +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=13&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTMmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.dVHttHuvgBnw4KmEqcKgxkbD5C1mcbwZozBydDgzzZs +#EXTINF:173,mymusic - L_s Theme - Death Note [Piano Tutorial] (Synthesia) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=160&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTYwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.dW3dn0T8mZCG3BxxGUdORvHyPTmBJOTI4Z2pkFVKdKA +#EXTINF:174,mymusic - l s theme b 5191430769908670513 +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=115&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTE1JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.q3uYexg3E7z6FtrMrtEI-ffdFPsQIN8QazSsxQQ1Klo +#EXTINF:133,mymusic - Lil Peep - Suck my blood (Music Video) (Lyrics) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=170&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTcwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.T5AeRPRRtfaNkPyA0l77dCgAiLbRlMX0Q_UgWH5qYa4 +#EXTINF:237,mymusic - Lil Peep -- 16 Lines (Official Video) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=106&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTA2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.19AgjeXvQ3MITHG_rg7S4Bu9714REAMKy0OPl5IfQK0 +#EXTINF:510,mymusic - Lolibox +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=100&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTAwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.Uh9f6T1wYSuuWoNagB7LRClcgkht1pTzXjSOCs3dLC4 +#EXTINF:156,mymusic - Ls Ideology +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=79&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Nzkmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.Ejp0arsC9WltBKQBH62O68k-xToPywy43UUYYx3JNYw +#EXTINF:288,mymusic - Luciferians +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=57&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NTcmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.-M1Mj4V1l1gLl5VVA92RJ-kwwFD0qDcZo3lPL8lsw10 +#EXTINF:570,mymusic - M.O.O.N - Alicia (Single Version) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=76&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NzYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.Lh8KiiyqsmoHafBYDK1cKFKjpJ5YPrxO7vsDlOMt4ks +#EXTINF:302,mymusic - M.O.O.N - Dust (Synthwave) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=26&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.vI88EgXqEniViQUOUaL6OFcgRMbsL-7MToV5eN0TYiQ +#EXTINF:236,mymusic - M.O.O.N - Medium Cool +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=98&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTgmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.dlYZxoGsZO8jmkKWvTYTY3oph-Oup6OL-pfvOdt4CuY +#EXTINF:289,mymusic - M.O.O.N. - _Crystals_ [Hotline Miami Soundtrack] +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=191&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTkxJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.fc2yIh0oY2ibzVmBrOx5VMeYGJGi8wiqMcROcfRbAa0 +#EXTINF:290,mymusic - M.O.O.N. - _Hydrogen_ [Hotline Miami Soundtrack] +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=167&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTY3JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.j3FXcg2A83ciWM2vHrXG6YP22w_flxlx-K-ZVdG8I8U +#EXTINF:271,mymusic - M.O.O.N. - _Paris_ [Hotline Miami Soundtrack] +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=165&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTY1JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.Y5CTheDrTti7J4q0E3HwQtDY9lwTFp7IYuRvbZoeH-M +#EXTINF:251,mymusic - M_O_O_N - Certainty +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=173&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTczJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.GJ6GFVE8pJb0i0h2FyDwwvPU7Uc5faFdTsM4RYc8blo +#EXTINF:225,mymusic - M_O_O_N - Warehouse (ft. GLASS TEETH) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=140&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTQwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ._El33L5H9TN_acnaq8C9EXa_jAry0ujfj9s6z6kToBk +#EXTINF:199,mymusic - Majula +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=203&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjAzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.65KlmEtGH_UeIlw3pMrrSDWXkHK5XI_C38acQsmnILw +#EXTINF:250,mymusic - Mello's Theme A SLOWED+REVERB +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=41&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NDEmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.FSW9HoXlJPfkX0gdCQjt4YcEAq5ujvsxnLUGeKOp6O0 +#EXTINF:271,mymusic - Miami (Original Mix) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=89&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9ODkmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.7VBYiYe2kDEbOttSUCj4NnSFhvJGc_W9lFqYkmyXyRg +#EXTINF:400,mymusic - Nameless Song +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=102&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTAyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.EmGJQvfAUuJtcDqKgTrx7ivCag7Rl9VuDjCMH0ZLcJA +#EXTINF:182,mymusic - Near's Theme (A) - Death Note +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=141&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTQxJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.sTSPtDHrNTUqoF8DuF3Ew1gmehjMuqE4sgkU-_q8WTc +#EXTINF:220,mymusic - Oldsong +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=35&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MzUmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.NENBQgiJvkRnFu6iGdVV70BpHZDc_c7dxhthllpKrT8 +#EXTINF:247,mymusic - Ornament +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=154&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTU0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.EdSmuGIc6Vhx0X8zGfs9DF1wZJhoN8qrBsm6DKHSJNY +#EXTINF:206,mymusic - Pastel Ghost - Embrace +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=163&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTYzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.vRAxV7S01H_xyb1TO8co2GbQBiW3LeReTJrmO-cxDqU +#EXTINF:243,mymusic - Pastel Ghost - Pulse +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=9&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OSZzdWZmaXg9Lm1wMyIsImV4cCI6MTY1NzgwNTM3MH0.X--bCOYR4Pr_EaODNRFwCzdmThgi4KmKhS_EhfmBZzw +#EXTINF:248,mymusic - PASTEL GHOST ___ CLOUDS「official video」 +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=211&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjExJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.XOjw-t-3qttMT-f6Q8-8ROdUtoJH1zvWy-zqOxRBjEI +#EXTINF:183,mymusic - Peaceful Waters (From _The Elder Scrolls III_ Morrowind Original_) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=128&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTI4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.GAHWSzYJNoikS4xS3KK6TLyyAYQD_6zDtvUpoL_LTCA +#EXTINF:97,mymusic - Pianissimo Epilogue +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=202&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjAyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.G1ay8HgvEVkm-eHi9qiSUqY1FirZorcaoBdesql43Qg +#EXTINF:175,mymusic - Prey +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=199&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTk5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.YBko0m9tErCkKGNBADE2v8VYb_YQRAaOwr43D8B6izA +#EXTINF:286,mymusic - Queen - Scandal (Official Video) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=206&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjA2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.zG38sZorqk7nbSWG90gSvjmXuLGDU8n2Jb1S5Ytx7xI +#EXTINF:259,mymusic - Quixotic - Dust To Dust +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=118&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTE4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.mfjzO1lJdBJX4L8TBC17JvX0KdnmKRlCUmP0irF6y20 +#EXTINF:370,mymusic - Quixotic - Palms (Official Music Video) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=195&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTk1JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.QgP0z5Yn7sJq3iTqLjr9Q8JdBLJdOeYnp_72nN-bxjg +#EXTINF:214,mymusic - Reasoning +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=3&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MyZzdWZmaXg9Lm1wMyIsImV4cCI6MTY1NzgwNTM3MH0.ZJDC9dMUREIqdgYyI86z1qFcVQsIHWLIOPXd5fs12Lo +#EXTINF:321,mymusic - River of Life +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=137&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTM3JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.31CgAZOoICDkV-gJkOV-momM-XgX-tIU1qBpMHSahZY +#EXTINF:294,mymusic - Sewerslvt - Cyberia lyr1 +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=127&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTI3JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.We-R5eImumNXenxPiVmq6g30GyYOzB1Zusas89JZpv4 +#EXTINF:347,mymusic - Sewerslvt - Ecifircas +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=91&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTEmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.wGhA1it-8lwnYpwu76SaRskzs3hUtRMMdHUGZy2ECUE +#EXTINF:246,mymusic - Sewerslvt - Euphoric Filth (Cheru's Theme) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=95&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTUmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.0X8RbzRju_QzTtM_3_IGvDQa5lRh8E7IX3I-iwjeDDQ +#EXTINF:439,mymusic - Sewerslvt - her +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=46&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NDYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.T3UMulHPNAkzK1mJteu308xgYq2QhGIx4292ht2FJgo +#EXTINF:291,mymusic - Sewerslvt - Hopelessness +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=103&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTAzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.DST29hwxt8P4B0WYacCa-U4_ThIUeHkkg38ar3cnHsQ +#EXTINF:353,mymusic - Sewerslvt - I Really Like You pt1 +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=153&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTUzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.7BAY3y5agRbgnjHsYH7dGf9AaetX2F3mS6gKKY_A2mE +#EXTINF:162,mymusic - Sewerslvt - inlove +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=194&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTk0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.q3nciMsVbI3oJiK-SX7NDGQnDb3RMbry-Mg68FD5OEc +#EXTINF:305,mymusic - Sewerslvt - inpeace +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=84&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9ODQmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.sqyJ0ItE9s8xTdSO6okbFlm0a0x6wcUH1b9CpMinW2w +#EXTINF:363,mymusic - Sewerslvt - Oni +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=133&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTMzJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.ZOPO_RU9Eb_MFe6N6Xz4LDjjM3JKkehLsG4cANWm6QQ +#EXTINF:492,mymusic - Sewerslvt - Slowdeath +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=182&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTgyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.LEAjdbsUBnlkHaVmJafw5ET3VBeGFGBulUnXKKy4yZg +#EXTINF:491,mymusic - Sewerslvt - The Grilled Fish's Ballad +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=12&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTImc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.c_3WOM5Qi3buIAMtXWjMofBRheX6YHCgdU5Zm4kkauA +#EXTINF:302,mymusic - Shadow Lady +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=5&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NSZzdWZmaXg9Lm1wMyIsImV4cCI6MTY1NzgwNTM3MH0.5hWgePso0QhZLsulm73WdS7pM7wqujl2WZ9rIfTnTjs +#EXTINF:175,mymusic - Silent Hill - Not Tomorrow (Long Version) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=125&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTI1JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.kMLdrTMfWxA9fx5drqmCN9EVIZPzO4t2iWdnU1dMwAY +#EXTINF:177,mymusic - Silent Hill 2 - White Noiz (Remix) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=87&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9ODcmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.NovW7ZdLscJcGALmnFSLBuiZJZ4xePNiHPDooXHRVI8 +#EXTINF:136,mymusic - Silent Hill 2 OST - Fermata In Mistic Air +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=108&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTA4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.bxNTHc9KZBGKVCZ34i3vq1NFdPyFKMmnTP1ah7aS0FY +#EXTINF:124,mymusic - Silent Hill 2 OST - Heaven's Night +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=45&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NDUmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.y5JnMdZ8LwxbwJK5q-SkZa56BCOXibPkCy2TrgMJDPA +#EXTINF:170,mymusic - Silent Hill 2 OST - Null Moon +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=130&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTMwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.Dns3fmTY_PuxyVIkTHN23olfeyqcK8KjHG1sTzrAZw0 +#EXTINF:237,mymusic - Silent Hill Ost Tears Of +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=114&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTE0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.X0FdveYiVFlgLe39ivxJdSzPiyYd3POisOBxWx4LsUI +#EXTINF:344,mymusic - Squids +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=96&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.eJSvbwLG1gQC8_W5DbpYZ_uRFcaMnPVHObrAGPgTnRk +#EXTINF:227,mymusic - STRAPLOCKED - Active Aggression _ Magnatron III _ +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=180&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTgwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.nY9iYnMm5uA0HgQFr8pjy9xAUZlD_Upp2NB9EtVRTDs +#EXTINF:97,mymusic - The Day Of Night +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=171&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTcxJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.HVP1MkZLMczMrIi3_8yZaB8MLEKDdwUj03z6D0yTvG0 +#EXTINF:225,mymusic - Their Kindness Is Charade +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=67&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Njcmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.0TYgkBrJWeP0NiOIOwruDQGEG6enuR5kBHbMhmy_L48 +#EXTINF:118,mymusic - To the top - Scattle _ Hotline Miami Bonus OST +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=92&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9OTImc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.rf7-Up8qVZq9Q2BYFWiB-EK0by9t8fQH373_mmYA-aA +#EXTINF:248,mymusic - VHS Dreams - Nightdrive +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=104&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTA0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.n9JSaJ04VZyjOoVHUbTzGz9628cyCbLunQ7_gqbMVDk +#EXTINF:214,mymusic - Voyager (Original Mix) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=27&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Mjcmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.Lb1xmOAq79vae7QgLLWaV4JQXVInhhea8HAfNkHfypM +#EXTINF:119,mymusic - Xleepy +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=28&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9Mjgmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.Z050r3WpZP89-hiZjsLNAr0g_PxiN-uqcDqf-eeuM5I +#EXTINF:233,mymusic - Zero Strike (feat. D-Noise) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=7&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NyZzdWZmaXg9Lm1wMyIsImV4cCI6MTY1NzgwNTM3MH0.781LBv_LlpPzX2L24Ph4ipuZH1fb62QVElR4et6mm_c +#EXTINF:343,mymusic - Альянс - На заре (1987) Стерео HD Премьера клипа!!! +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=155&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTU1JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.4rKQUB5q7N25SeAJzaOuxmZTLJjjE6reJ1twQxdDb28 +#EXTINF:130,mymusic - Бери шинель (Like a Rolling Stone) +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=156&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTU2JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.mgGceO-6Wn1pvLZDse-fJGesOkelXq2fA8eG9RyWP_Y +#EXTINF:277,mymusic - Виктор Цой - Пачка Сигарет +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=49&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NDkmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.i9auT7Mk0XoErjj4cZXOrLgf-kDmF4pbGb8G5R_8NeE +#EXTINF:195,mymusic - Гражданская Оборона - Беспонтовый пирожок +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=227&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjI3JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.yIgekXNZshk3ps03v_wf0ICkHgYwab1H01EMv7U__9Q +#EXTINF:159,mymusic - Егор Летов - Моя оборона +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=200&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjAwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.UXq7d3zX2Zsz2R_tffdjjclsPEqcQij07C8x9-zcSXI +#EXTINF:160,mymusic - Егор Летов - Мёртвые +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=65&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NjUmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.jIqWYgoO46st5e6AGntsX68xbwmcfmb6W176INUuH2M +#EXTINF:174,mymusic - Егор Летов - Насрать на моё лицо +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=230&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjMwJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.hkDezprEwkMPg00Zu1qGl1lVucZodYirX7yzuzq5pug +#EXTINF:144,mymusic - Егор Летов - Отряд не заметил потери бойца +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=232&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjMyJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.G1YvZD6TNw7Mk5EpdorutrwYlQrKgUxWYRimQuiGapA +#EXTINF:132,mymusic - Егор Летов - Харакири +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=188&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTg4JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.7RFQbV03kW8TLYZHU45pIzvLu1kCXO_zKucfr-9_qKc +#EXTINF:184,mymusic - КИНО - Виктор Цой - Последний Герой +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=231&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MjMxJnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.KMVhA-2Iw9A-Ui0qkmRRyqCLMq8CnU5QscUdu2GFHV0 +#EXTINF:196,mymusic - Летов Егор- Всё идёт по плану. +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=86&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9ODYmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.OGN5QUphj7CZaKYTotoLujkLCbUVw6ZYcbWjldnqtXI +#EXTINF:189,mymusic - Непонятная песенка +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=11&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTEmc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.BXP-pduHDgs5nJchWE8nvC4tj1HeY83crObS9jJq-7A +#EXTINF:138,mymusic - Солдатами не рождаются +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=174&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTc0JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1MzcwfQ.ADCK1q8TTu09ons1cVF7ojYO5152_PurpJkI2e63BHQ +#EXTINF:160,mymusic - Философская песня о пуле +https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=52&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9NTImc3VmZml4PS5tcDMiLCJleHAiOjE2NTc4MDUzNzB9.P2xyr1iyruQkMfEsWcpiRpHSWm5V8Vrtkv1TOhMhyS0 diff --git a/.config/mpd/state b/.config/mpd/state new file mode 100644 index 0000000..5744203 --- /dev/null +++ b/.config/mpd/state @@ -0,0 +1,55 @@ +sw_volume: 15 +audio_device_state:1:PipeWire Sound Server +audio_device_state:1:my_fifo +state: pause +current: 31 +time: 245.329000 +random: 1 +repeat: 1 +single: 0 +consume: 0 +crossfade: 5 +mixrampdb: 0.000000 +mixrampdelay: -1.000000 +playlist_begin +0:local_songs/sewerslvt/2019 - Drowning In The Sewer/02. Cyberia lyr1.mp3 +1:local_songs/sewerslvt/2019 - Drowning In The Sewer/03. Luciferians.mp3 +2:local_songs/sewerslvt/2019 - Drowning In The Sewer/04. Squids.mp3 +3:local_songs/sewerslvt/2019 - Drowning In The Sewer/05. Hopelessness.mp3 +4:local_songs/sewerslvt/2019 - Drowning In The Sewer/10. Junko Loves You.mp3 +5:local_songs/sewerslvt/2019 - Drowning In The Sewer/11. Lolibox.mp3 +6:local_songs/sewerslvt/2020 - Draining Love Story/02. Newlove.mp3 +7:local_songs/sewerslvt/2020 - Draining Love Story/03. Yandere Complex.mp3 +8:local_songs/sewerslvt/2020 - Draining Love Story/04. Ecifircas.mp3 +9:local_songs/sewerslvt/2020 - Draining Love Story/05. Lexapro Delirium.mp3 +10:local_songs/sewerslvt/2020 - Draining Love Story/08. Mr. Kill Myself.mp3 +11:local_songs/sewerslvt/2020 - Draining Love Story/09. Down The Drain (feat. Nurtheon).mp3 +12:local_songs/sewerslvt/2020 - Draining Love Story/10. Slowdeath.mp3 +13:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/01. My Fvcked Up Head.mp3 +14:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/02. I Break My Heart & Yours.mp3 +15:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/03. Looming.Sorrow.Descent.mp3 +16:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/04. I Bleed.mp3 +17:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/05. Restlessness.mp3 +18:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/06. Existing Everywhere.mp3 +19:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/07. Car Accident.mp3 +20:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/08. Purple Hearts In Her Eyes.mp3 +21:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/10. Ecocide Suite.mp3 +22:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/11. Antidepressant.mp3 +23:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/12. Never Existed.mp3 +24:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/13. Blooming Iridescent Flower.mp3 +25:local_songs/sewerslvt/2021 - Skitzofrenia Simulation/14. With You Forever.mp3 +26:local_songs/sewerslvt/2021 - we had good times together, don't forget that/01. dissociating.mp3 +27:local_songs/sewerslvt/2021 - we had good times together, don't forget that/02. self destruction worldwide broadcast.mp3 +28:local_songs/sewerslvt/2021 - we had good times together, don't forget that/03. all the joy in life was gone once you left.mp3 +29:local_songs/sewerslvt/2021 - we had good times together, don't forget that/04. the last thing she sent me.mp3 +30:local_songs/sewerslvt/2021 - we had good times together, don't forget that/05. light at the end of the tunnel.mp3 +31:local_songs/sewerslvt/2021 - we had good times together, don't forget that/06. ultradespair.mp3 +32:local_songs/sewerslvt/2021 - we had good times together, don't forget that/07. borderline.mp3 +33:local_songs/sewerslvt/2021 - we had good times together, don't forget that/08. whatever.mp3 +34:local_songs/sewerslvt/2021 - we had good times together, don't forget that/09. blissful overdose.mp3 +35:local_songs/sewerslvt/2021 - we had good times together, don't forget that/10. inertia status.mp3 +36:local_songs/sewerslvt/2021 - we had good times together, don't forget that/11. die alone.mp3 +37:local_songs/sewerslvt/2021 - we had good times together, don't forget that/12. sick, twisted, demented.mp3 +38:local_songs/sewerslvt/2021 - we had good times together, don't forget that/13. her.mp3 +39:local_songs/sewerslvt/2021 - we had good times together, don't forget that/14. goodbye.mp3 +playlist_end diff --git a/.config/mpd/sticker.sql b/.config/mpd/sticker.sql new file mode 100644 index 0000000..72ce590 Binary files /dev/null and b/.config/mpd/sticker.sql differ diff --git a/.config/mpv/encoding.rst b/.config/mpv/encoding.rst new file mode 100644 index 0000000..ee46cec --- /dev/null +++ b/.config/mpv/encoding.rst @@ -0,0 +1,155 @@ +General usage +============= + +:: + + mpv infile -o outfile [-of outfileformat] [-ofopts formatoptions] [-orawts] \ + [(any other mpv options)] \ + -ovc outvideocodec [-ovcopts outvideocodecoptions] \ + -oac outaudiocodec [-oacopts outaudiocodecoptions] + +Help for these options is provided if giving help as parameter, as in:: + + mpv -ovc help + +The suboptions of these generally are identical to ffmpeg's (as option parsing +is simply delegated to ffmpeg). The option -ocopyts enables copying timestamps +from the source as-is, instead of fixing them to match audio playback time +(note: this doesn't work with all output container formats); -orawts even turns +off discontinuity fixing. + +Note that if neither -ofps nor -oautofps is specified, VFR encoding is assumed +and the time base is 24000fps. -oautofps sets -ofps to a guessed fps number +from the input video. Note that not all codecs and not all formats support VFR +encoding, and some which do have bugs when a target bitrate is specified - use +-ofps or -oautofps to force CFR encoding in these cases. + +Of course, the options can be stored in a profile, like this .config/mpv/mpv.conf +section:: + + [myencprofile] + vf-add = scale=480:-2 + ovc = libx264 + ovcopts-add = preset=medium + ovcopts-add = tune=fastdecode + ovcopts-add = crf=23 + ovcopts-add = maxrate=1500k + ovcopts-add = bufsize=1000k + ovcopts-add = rc_init_occupancy=900k + ovcopts-add = refs=2 + ovcopts-add = profile=baseline + oac = aac + oacopts-add = b=96k + +It's also possible to define default encoding options by putting them into +the section named ``[encoding]``. (This behavior changed after mpv 0.3.x. In +mpv 0.3.x, config options in the default section / no section were applied +to encoding. This is not the case anymore.) + +One can then encode using this profile using the command:: + + mpv infile -o outfile.mp4 -profile myencprofile + +Some example profiles are provided in a file +etc/encoding-profiles.conf; as for this, see below. + + +Encoding examples +================= + +These are some examples of encoding targets this code has been used and tested +for. + +Typical MPEG-4 Part 2 ("ASP", "DivX") encoding, AVI container:: + + mpv infile -o outfile.avi \ + --vf=fps=25 \ + -ovc mpeg4 -ovcopts qscale=4 \ + -oac libmp3lame -oacopts ab=128k + +Note: AVI does not support variable frame rate, so the fps filter must be used. +The frame rate should ideally match the input (25 for PAL, 24000/1001 or +30000/1001 for NTSC) + +Typical MPEG-4 Part 10 ("AVC", "H.264") encoding, Matroska (MKV) container:: + + mpv infile -o outfile.mkv \ + -ovc libx264 -ovcopts preset=medium,crf=23,profile=baseline \ + -oac libvorbis -oacopts qscale=3 + +Typical MPEG-4 Part 10 ("AVC", "H.264") encoding, MPEG-4 (MP4) container:: + + mpv infile -o outfile.mp4 \ + -ovc libx264 -ovcopts preset=medium,crf=23,profile=baseline \ + -oac aac -oacopts ab=128k + +Typical VP8 encoding, WebM (restricted Matroska) container:: + + mpv infile -o outfile.mkv \ + -of webm \ + -ovc libvpx -ovcopts qmin=6,b=1000000k \ + -oac libvorbis -oacopts qscale=3 + + +Device targets +============== + +As the options for various devices can get complex, profiles can be used. + +An example profile file for encoding is provided in +etc/encoding-profiles.conf in the source tree. This file is installed and loaded +by default. If you want to modify it, you can replace and it with your own copy +by doing:: + + mkdir -p ~/.mpv + cp /etc/mpv/encoding-profiles.conf ~/.mpv/encoding-profiles.conf + +Keep in mind that the default profile is the playback one. If you want to add +options that apply only in encoding mode, put them into a ``[encoding]`` +section. + +Refer to the top of that file for more comments - in a nutshell, the following +options are added by it:: + + -profile enc-to-dvdpal DVD-Video PAL, use dvdauthor -v pal+4:3 -a ac3+en + -profile enc-to-dvdntsc DVD-Video NTSC, use dvdauthor -v ntsc+4:3 -a ac3+en + -profile enc-to-bb-9000 MP4 for Blackberry Bold 9000 + -profile enc-to-nok-6300 3GP for Nokia 6300 + -profile enc-to-psp MP4 for PlayStation Portable + -profile enc-to-iphone MP4 for iPhone + -profile enc-to-iphone-4 MP4 for iPhone 4 (double res) + -profile enc-to-iphone-5 MP4 for iPhone 5 (even larger res) + +You can encode using these with a command line like:: + + mpv infile -o outfile.mp4 -profile enc-to-bb-9000 + +Of course, you are free to override options set by these profiles by specifying +them after the -profile option. + + +What works +========== + +* Encoding at variable frame rate (default) +* Encoding at constant frame rate using --vf=fps=RATE +* 2-pass encoding (specify flags=+pass1 in the first pass's -ovcopts, specify + flags=+pass2 in the second pass) +* Hardcoding subtitles using vobsub, ass or srt subtitle rendering (just + configure mpv for the subtitles as usual) +* Hardcoding any other mpv OSD (e.g. time codes, using -osdlevel 3 and -vf + expand=::::1) +* Encoding directly from a DVD, network stream, webcam, or any other source + mpv supports +* Using x264 presets/tunings/profiles (by using profile=, tune=, preset= in the + -ovcopts) +* Deinterlacing/Inverse Telecine with any of mpv's filters for that +* Audio file converting: mpv -o outfile.mp3 infile.flac -no-video -oac + libmp3lame -oacopts ab=320k + +What does not work yet +====================== + +* 3-pass encoding (ensuring constant total size and bitrate constraints while + having VBR audio; mencoder calls this "frameno") +* Direct stream copy diff --git a/.config/mpv/input.conf b/.config/mpv/input.conf new file mode 100644 index 0000000..76c246a --- /dev/null +++ b/.config/mpv/input.conf @@ -0,0 +1,179 @@ +# mpv keybindings +# +# Location of user-defined bindings: ~/.config/mpv/input.conf +# +# Lines starting with # are comments. Use SHARP to assign the # key. +# Copy this file and uncomment and edit the bindings you want to change. +# +# List of commands and further details: DOCS/man/input.rst +# List of special keys: --input-keylist +# Keybindings testing mode: mpv --input-test --force-window --idle +# +# Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore'). +# +# Strings need to be quoted and escaped: +# KEY show-text "This is a single backslash: \\ and a quote: \" !" +# +# You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with +# the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal). +# +# The default keybindings are hardcoded into the mpv binary. +# You can disable them completely with: --no-input-default-bindings + +# Developer note: +# On compilation, this file is baked into the mpv binary, and all lines are +# uncommented (unless '#' is followed by a space) - thus this file defines the +# default key bindings. + +# If this is enabled, treat all the following bindings as default. +#default-bindings start + +#MBTN_LEFT ignore # don't do anything +#MBTN_LEFT_DBL cycle fullscreen # toggle fullscreen +#MBTN_RIGHT cycle pause # toggle pause/playback mode +#MBTN_BACK playlist-prev # skip to the previous file +#MBTN_FORWARD playlist-next # skip to the next file + +# Mouse wheels, touchpad or other input devices that have axes +# if the input devices supports precise scrolling it will also scale the +# numeric value accordingly +#WHEEL_UP seek 10 # seek 10 seconds forward +#WHEEL_DOWN seek -10 # seek 10 seconds backward +#WHEEL_LEFT add volume -2 +#WHEEL_RIGHT add volume 2 + +## Seek units are in seconds, but note that these are limited by keyframes +#RIGHT seek 5 # seek 5 seconds forward +#LEFT seek -5 # seek 5 seconds backward +#UP seek 60 # seek 1 minute forward +#DOWN seek -60 # seek 1 minute backward +# Do smaller, always exact (non-keyframe-limited), seeks with shift. +# Don't show them on the OSD (no-osd). +#Shift+RIGHT no-osd seek 1 exact # seek exactly 1 second forward +#Shift+LEFT no-osd seek -1 exact # seek exactly 1 second backward +#Shift+UP no-osd seek 5 exact # seek exactly 5 seconds forward +#Shift+DOWN no-osd seek -5 exact # seek exactly 5 seconds backward +#Ctrl+LEFT no-osd sub-seek -1 # seek to the previous subtitle +#Ctrl+RIGHT no-osd sub-seek 1 # seek to the next subtitle +#Ctrl+Shift+LEFT sub-step -1 # change subtitle timing such that the previous subtitle is displayed +#Ctrl+Shift+RIGHT sub-step 1 # change subtitle timing such that the next subtitle is displayed +#Alt+left add video-pan-x 0.1 # move the video right +#Alt+right add video-pan-x -0.1 # move the video left +#Alt+up add video-pan-y 0.1 # move the video down +#Alt+down add video-pan-y -0.1 # move the video up +#Alt++ add video-zoom 0.1 # zoom in +#Alt+- add video-zoom -0.1 # zoom out +#Alt+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 # reset zoom and pan settings +#PGUP add chapter 1 # seek to the next chapter +#PGDWN add chapter -1 # seek to the previous chapter +#Shift+PGUP seek 600 # seek 10 minutes forward +#Shift+PGDWN seek -600 # seek 10 minutes backward +#[ multiply speed 1/1.1 # decrease the playback speed +#] multiply speed 1.1 # increase the playback speed +#{ multiply speed 0.5 # halve the playback speed +#} multiply speed 2.0 # double the playback speed +#BS set speed 1.0 # reset the speed to normal +#Shift+BS revert-seek # undo the previous (or marked) seek +#Shift+Ctrl+BS revert-seek mark # mark the position for revert-seek +#q quit +#Q quit-watch-later # exit and remember the playback position +#q {encode} quit 4 +#ESC set fullscreen no # leave fullscreen +#ESC {encode} quit 4 +#p cycle pause # toggle pause/playback mode +#. frame-step # advance one frame and pause +#, frame-back-step # go back by one frame and pause +#SPACE cycle pause # toggle pause/playback mode +#> playlist-next # skip to the next file +#ENTER playlist-next # skip to the next file +#< playlist-prev # skip to the previous file +#O no-osd cycle-values osd-level 3 1 # toggle displaying the OSD on user interaction or always +#o show-progress # show playback progress +#P show-progress # show playback progress +#i script-binding stats/display-stats # display information and statistics +#I script-binding stats/display-stats-toggle # toggle displaying information and statistics +#` script-binding console/enable # open the console +#z add sub-delay -0.1 # shift subtitles 100 ms earlier +#Z add sub-delay +0.1 # delay subtitles by 100 ms +#x add sub-delay +0.1 # delay subtitles by 100 ms +#ctrl++ add audio-delay 0.100 # change audio/video sync by delaying the audio +#ctrl+- add audio-delay -0.100 # change audio/video sync by shifting the audio earlier +#Shift+g add sub-scale +0.1 # increase the subtitle font size +#Shift+f add sub-scale -0.1 # decrease the subtitle font size +#9 add volume -2 +#/ add volume -2 +#0 add volume 2 +#* add volume 2 +#m cycle mute # toggle mute +#1 add contrast -1 +#2 add contrast 1 +#3 add brightness -1 +#4 add brightness 1 +#5 add gamma -1 +#6 add gamma 1 +#7 add saturation -1 +#8 add saturation 1 +#Alt+0 set current-window-scale 0.5 # halve the window size +#Alt+1 set current-window-scale 1.0 # reset the window size +#Alt+2 set current-window-scale 2.0 # double the window size +#d cycle deinterlace # toggle the deinterlacing filter +#r add sub-pos -1 # move subtitles up +#R add sub-pos +1 # move subtitles down +#t add sub-pos +1 # move subtitles down +#v cycle sub-visibility # hide or show the subtitles +#Alt+v cycle secondary-sub-visibility # hide or show the secondary subtitles +#V cycle sub-ass-vsfilter-aspect-compat # toggle stretching SSA/ASS subtitles with anamorphic videos to match the historical renderer +#u cycle-values sub-ass-override "force" "no" # toggle overriding SSA/ASS subtitle styles with the normal styles +#j cycle sub # switch subtitle track +#J cycle sub down # switch subtitle track backwards +#SHARP cycle audio # switch audio track +#_ cycle video # switch video track +#T cycle ontop # toggle placing the video on top of other windows +#f cycle fullscreen # toggle fullscreen +#s screenshot # take a screenshot of the video in its original resolution with subtitles +#S screenshot video # take a screenshot of the video in its original resolution without subtitles +#Ctrl+s screenshot window # take a screenshot of the window with OSD and subtitles +#Alt+s screenshot each-frame # automatically screenshot every frame; issue this command again to stop taking screenshots +#w add panscan -0.1 # decrease panscan +#W add panscan +0.1 # shrink black bars by cropping the video +#e add panscan +0.1 # shrink black bars by cropping the video +#A cycle-values video-aspect-override "16:9" "4:3" "2.35:1" "-1" # cycle the video aspect ratio ("-1" is the container aspect) +#POWER quit +#PLAY cycle pause # toggle pause/playback mode +#PAUSE cycle pause # toggle pause/playback mode +#PLAYPAUSE cycle pause # toggle pause/playback mode +#PLAYONLY set pause no # unpause +#PAUSEONLY set pause yes # pause +#STOP quit +#FORWARD seek 60 # seek 1 minute forward +#REWIND seek -60 # seek 1 minute backward +#NEXT playlist-next # skip to the next file +#PREV playlist-prev # skip to the previous file +#VOLUME_UP add volume 2 +#VOLUME_DOWN add volume -2 +#MUTE cycle mute # toggle mute +#CLOSE_WIN quit +#CLOSE_WIN {encode} quit 4 +#ctrl+w quit +#E cycle edition # switch edition +#l ab-loop # set/clear A-B loop points +#L cycle-values loop-file "inf" "no" # toggle infinite looping +#ctrl+c quit 4 +#DEL script-binding osc/visibility # cycle OSC visibility between never, auto (mouse-move) and always +#ctrl+h cycle-values hwdec "auto" "no" # toggle hardware decoding +#F8 show-text ${playlist} # show the playlist +#F9 show-text ${track-list} # show the list of video, audio and sub tracks + +# +# Legacy bindings (may or may not be removed in the future) +# +#! add chapter -1 # seek to the previous chapter +#@ add chapter 1 # seek to the next chapter + +# +# Not assigned by default +# (not an exhaustive list of unbound commands) +# + +# ? cycle sub-forced-only # toggle DVD forced subs +# ? stop # stop playback (quit or enter idle mode) diff --git a/.config/mpv/mplayer-input.conf b/.config/mpv/mplayer-input.conf new file mode 100644 index 0000000..2d23e47 --- /dev/null +++ b/.config/mpv/mplayer-input.conf @@ -0,0 +1,93 @@ +## +## MPlayer-style key bindings +## +## Save it as ~/.config/mpv/input.conf to use it. +## +## Generally, it's recommended to use this as reference-only. +## + +RIGHT seek +10 +LEFT seek -10 +DOWN seek -60 +UP seek +60 +PGUP seek 600 +PGDWN seek -600 +m cycle mute +SHARP cycle audio # switch audio streams ++ add audio-delay 0.100 += add audio-delay 0.100 +- add audio-delay -0.100 +[ multiply speed 0.9091 # scale playback speed +] multiply speed 1.1 +{ multiply speed 0.5 +} multiply speed 2.0 +BS set speed 1.0 # reset speed to normal +q quit +ESC quit +ENTER playlist-next force # skip to next file +p cycle pause +. frame-step # advance one frame and pause +SPACE cycle pause +HOME set playlist-pos 0 # not the same as MPlayer +#END pt_up_step -1 +> playlist-next # skip to next file +< playlist-prev # previous +#INS alt_src_step 1 +#DEL alt_src_step -1 +o osd +I show-text "${filename}" # display filename in osd +P show-progress +z add sub-delay -0.1 # subtract 100 ms delay from subs +x add sub-delay +0.1 # add +9 add volume -1 +/ add volume -1 +0 add volume 1 +* add volume 1 +1 add contrast -1 +2 add contrast 1 +3 add brightness -1 +4 add brightness 1 +5 add hue -1 +6 add hue 1 +7 add saturation -1 +8 add saturation 1 +( add balance -0.1 # adjust audio balance in favor of left +) add balance +0.1 # right +d cycle framedrop +D cycle deinterlace # toggle deinterlacer (auto-inserted filter) +r add sub-pos -1 # move subtitles up +t add sub-pos +1 # down +#? sub-step +1 # immediately display next subtitle +#? sub-step -1 # previous +#? add sub-scale +0.1 # increase subtitle font size +#? add sub-scale -0.1 # decrease subtitle font size +f cycle fullscreen +T cycle ontop # toggle video window ontop of other windows +w add panscan -0.1 # zoom out with -panscan 0 -fs +e add panscan +0.1 # in +c cycle stream-capture # save (and append) file/stream to stream.dump with -capture +s screenshot # take a screenshot (if you want PNG, use "--screenshot-format=png") +S screenshot - each-frame # S will take a png screenshot of every frame + +h cycle tv-channel 1 +l cycle tv-channel -1 +n cycle tv-norm +#b tv_step_chanlist + +#? add chapter -1 # skip to previous dvd chapter +#? add chapter +1 # next + +## +## Advanced seek +## Uncomment the following lines to be able to seek to n% of the media with +## the Fx keys. +## +#F1 seek 10 absolute-percent +#F2 seek 20 absolute-percent +#F3 seek 30 absolute-percent +#F4 seek 40 absolute-percent +#F5 seek 50 absolute-percent +#F6 seek 60 absolute-percent +#F7 seek 70 absolute-percent +#F8 seek 80 absolute-percent +#F9 seek 90 absolute-percent diff --git a/.config/mpv/mpv.conf b/.config/mpv/mpv.conf new file mode 100644 index 0000000..3434c39 --- /dev/null +++ b/.config/mpv/mpv.conf @@ -0,0 +1,144 @@ +# +# Example mpv configuration file +# +# Warning: +# +# The commented example options usually do _not_ set the default values. Call +# mpv with --list-options to see the default values for most options. There is +# no builtin or example mpv.conf with all the defaults. +# +# +# Configuration files are read system-wide from /usr/local/etc/mpv.conf +# and per-user from ~/.config/mpv/mpv.conf, where per-user settings override +# system-wide settings, all of which are overridden by the command line. +# +# Configuration file settings and the command line options use the same +# underlying mechanisms. Most options can be put into the configuration file +# by dropping the preceding '--'. See the man page for a complete list of +# options. +# +# Lines starting with '#' are comments and are ignored. +# +# See the CONFIGURATION FILES section in the man page +# for a detailed description of the syntax. +# +# Profiles should be placed at the bottom of the configuration file to ensure +# that settings wanted as defaults are not restricted to specific profiles. + +################## +# video settings # +################## + +# Start in fullscreen mode by default. +#fs=yes + +# force starting with centered window +#geometry=50%:50% + +# don't allow a new window to have a size larger than 90% of the screen size +#autofit-larger=90%x90% + +# Do not close the window on exit. +#keep-open=yes + +# Do not wait with showing the video window until it has loaded. (This will +# resize the window once video is loaded. Also always shows a window with +# audio.) +#force-window=immediate + +# Disable the On Screen Controller (OSC). +#osc=no + +# Keep the player window on top of all other windows. +#ontop=yes + +# Specify high quality video rendering preset (for --vo=gpu only) +# Can cause performance problems with some drivers and GPUs. +#profile=gpu-hq + +# Force video to lock on the display's refresh rate, and change video and audio +# speed to some degree to ensure synchronous playback - can cause problems +# with some drivers and desktop environments. +#video-sync=display-resample + +# Enable hardware decoding if available. Often, this does not work with all +# video outputs, but should work well with default settings on most systems. +# If performance or energy usage is an issue, forcing the vdpau or vaapi VOs +# may or may not help. +#hwdec=auto + +################## +# audio settings # +################## + +# Specify default audio device. You can list devices with: --audio-device=help +# The option takes the device string (the stuff between the '...'). +#audio-device=alsa/default + +# Do not filter audio to keep pitch when changing playback speed. +#audio-pitch-correction=no + +# Output 5.1 audio natively, and upmix/downmix audio with a different format. +#audio-channels=5.1 +# Disable any automatic remix, _if_ the audio output accepts the audio format. +# of the currently played file. See caveats mentioned in the manpage. +# (The default is "auto-safe", see manpage.) +#audio-channels=auto + +################## +# other settings # +################## + +#--volume=30 + +# Pretend to be a web browser. Might fix playback with some streaming sites, +# but also will break with shoutcast streams. +#user-agent="Mozilla/5.0" + +# cache settings +# +# Use a large seekable RAM cache even for local input. +#cache=yes +# +# Use extra large RAM cache (needs cache=yes to make it useful). +#demuxer-max-bytes=500M +#demuxer-max-back-bytes=100M +# +# Disable the behavior that the player will pause if the cache goes below a +# certain fill size. +#cache-pause=no +# +# Store cache payload on the hard disk instead of in RAM. (This may negatively +# impact performance unless used for slow input such as network.) +#cache-dir=~/.cache/ +#cache-on-disk=yes + +# Display English subtitles if available. +#slang=en + +# Play Finnish audio if available, fall back to English otherwise. +#alang=fi,en + +# Change subtitle encoding. For Arabic subtitles use 'cp1256'. +# If the file seems to be valid UTF-8, prefer UTF-8. +# (You can add '+' in front of the codepage to force it.) +#sub-codepage=cp1256 + +# You can also include other configuration files. +#include=/path/to/the/file/you/want/to/include + +############ +# Profiles # +############ + +# The options declared as part of profiles override global default settings, +# but only take effect when the profile is active. + +# The following profile can be enabled on the command line with: --profile=eye-cancer + +#[eye-cancer] +#sharpen=5 + +--sub-auto=all + +--sub-file-paths=sub:subtitles diff --git a/.config/mpv/restore-old-bindings.conf b/.config/mpv/restore-old-bindings.conf new file mode 100644 index 0000000..662a699 --- /dev/null +++ b/.config/mpv/restore-old-bindings.conf @@ -0,0 +1,61 @@ + +# This file contains all bindings that were removed after a certain release. +# If you want MPlayer bindings, use mplayer-input.conf + +# Pick the bindings you want back and add them to your own input.conf. Append +# this file to your input.conf if you want them all back: +# +# cat restore-old-bindings.conf >> ~/.config/mpv/input.conf +# +# Older installations use ~/.mpv/input.conf instead. + +# changed in mpv 0.27.0 (macOS and Wayland only) + +# WHEEL_UP seek 10 +# WHEEL_DOWN seek -10 +# WHEEL_LEFT seek 5 +# WHEEL_RIGHT seek -5 + +# changed in mpv 0.26.0 + +h cycle tv-channel -1 # previous channel +k cycle tv-channel +1 # next channel +H cycle dvb-channel-name -1 # previous channel +K cycle dvb-channel-name +1 # next channel + +I show-text "${filename}" # display filename in osd + +# changed in mpv 0.24.0 + +L cycle-values loop "inf" "no" + +# changed in mpv 0.10.0 + +O osd +D cycle deinterlace +d cycle framedrop + +# changed in mpv 0.7.0 + +ENTER playlist-next force + +# changed in mpv 0.6.0 + +ESC quit + +# changed in mpv 0.5.0 + +PGUP seek 600 +PGDWN seek -600 +RIGHT seek 10 +LEFT seek -10 ++ add audio-delay 0.100 +- add audio-delay -0.100 +( add balance -0.1 +) add balance 0.1 +F cycle sub-forced-only +TAB cycle program +A cycle angle +U stop +o osd +I show-text "${filename}" diff --git a/.config/mpv/tech-overview.txt b/.config/mpv/tech-overview.txt new file mode 100644 index 0000000..4bb06ff --- /dev/null +++ b/.config/mpv/tech-overview.txt @@ -0,0 +1,657 @@ +This file intends to give a big picture overview of how mpv is structured. + +player/*.c: + Essentially makes up the player applications, including the main() function + and the playback loop. + + Generally, it accesses all other subsystems, initializes them, and pushes + data between them during playback. + + The structure is as follows (as of commit e13c05366557cb): + * main(): + * basic initializations (e.g. init_libav() and more) + * pre-parse command line (verbosity level, config file locations) + * load config files (parse_cfgfiles()) + * parse command line, add files from the command line to playlist + (m_config_parse_mp_command_line()) + * check help options etc. (call handle_help_options()), possibly exit + * call mp_play_files() function that works down the playlist: + * run idle loop (idle_loop()), until there are files in the + playlist or an exit command was given (only if --idle it set) + * actually load and play a file in play_current_file(): + * run all the dozens of functions to load the file and + initialize playback + * run a small loop that does normal playback, until the file is + done or a command terminates playback + (on each iteration, run_playloop() is called, which is rather + big and complicated - it decodes some audio and video on + each frame, waits for input, etc.) + * uninitialize playback + * determine next entry on the playlist to play + * loop, or exit if no next file or quit is requested + (see enum stop_play_reason) + * call mp_destroy() + * run_playloop(): + * calls fill_audio_out_buffers() + This checks whether new audio needs to be decoded, and pushes it + to the AO. + * calls write_video() + Decode new video, and push it to the VO. + * determines whether playback of the current file has ended + * determines when to start playback after seeks + * and calls a whole lot of other stuff + (Really, this function does everything.) + + Things worth saying about the playback core: + - most state is in MPContext (core.h), which is not available to the + subsystems (and should not be made available) + - the currently played tracks are in mpctx->current_tracks, and decoder + state in track.dec/d_sub + - the other subsystems rarely call back into the frontend, and the frontend + polls them instead (probably a good thing) + - one exceptions are wakeup callbacks, which notify a "higher" component + of a changed situation in a subsystem + + I like to call the player/*.c files the "frontend". + +ta.h & ta.c: + Hierarchical memory manager inspired by talloc from Samba. It's like a + malloc() with more features. Most importantly, each talloc allocation can + have a parent, and if the parent is free'd, all children will be free'd as + well. The parent is an arbitrary talloc allocation. It's either set by the + allocation call by passing a talloc parent, usually as first argument to the + allocation function. It can also be set or reset later by other calls (at + least talloc_steal()). A talloc allocation that is used as parent is often + called a talloc context. + + One very useful feature of talloc is fast tracking of memory leaks. ("Fast" + as in it doesn't require valgrind.) You can enable it by setting the + MPV_LEAK_REPORT environment variable to "1": + export MPV_LEAK_REPORT=1 + Or permanently by building with --enable-ta-leak-report. + This will list all unfree'd allocations on exit. + + Documentation can be found here: + http://git.samba.org/?p=samba.git;a=blob;f=lib/talloc/talloc.h;hb=HEAD + + For some reason, we're still using API-compatible wrappers instead of TA + directly. The talloc wrapper has only a subset of the functionality, and + in particular the wrappers abort() on memory allocation failure. + + Note: unlike tcmalloc, jemalloc, etc., talloc() is not actually a malloc + replacement. It works on top of system malloc and provides additional + features that are supposed to make memory management easier. + +player/command.c: + This contains the implementation for client API commands and properties. + Properties are essentially dynamic variables changed by certain commands. + This is basically responsible for all user commands, like initiating + seeking, switching tracks, etc. It calls into other player/*.c files, + where most of the work is done, but also calls other parts of mpv. + +player/core.h: + Data structures and function prototypes for most of player/*.c. They are + usually not accessed by other parts of mpv for the sake of modularization. + +player/client.c: + This implements the client API (libmpv/client.h). For the most part, this + just calls into other parts of the player. This also manages a ringbuffer + of events from player to clients. + +options/options.h, options/options.c + options.h contains the global option struct MPOpts. The option declarations + (option names, types, and MPOpts offsets for the option parser) are in + options.c. Most default values for options and MPOpts are in + mp_default_opts at the end of options.c. + + MPOpts is unfortunately quite monolithic, but is being incrementally broken + up into sub-structs. Many components have their own sub-option structs + separate from MPOpts. New options should be bound to the component that uses + them. Add a new option table/struct if needed. + + The global MPOpts still contains the sub-structs as fields, which serves to + link them to the option parser. For example, an entry like this may be + typical: + + {"", OPT_SUBSTRUCT(demux_opts, demux_conf)}, + + This directs the option access code to include all options in demux_conf + into the global option list, with no prefix (""), and as part of the + MPOpts.demux_opts field. The MPOpts.demux_opts field is actually not + accessed anywhere, and instead demux.c does this: + + struct m_config_cache *opts_cache = + m_config_cache_alloc(demuxer, global, &demux_conf); + struct demux_opts *opts = opts_cache->opts; + + ... to get a copy of its options. + + See m_config.h (below) how to access options. + + The actual option parser is spread over m_option.c, m_config.c, and + parse_commandline.c, and uses the option table in options.c. + +options/m_config.h & m_config.c: + Code for querying and managing options. This (unfortunately) contains both + declarations for the "legacy-ish" global m_config struct, and ways to access + options in a threads-safe way anywhere, like m_config_cache_alloc(). + + m_config_cache_alloc() lets anyone read, observe, and write options in any + thread. The only state it needs is struct mpv_global, which is an opaque + type that can be passed "down" the component hierarchy. For safety reasons, + you should not pass down any pointers to option structs (like MPOpts), but + instead pass down mpv_global, and use m_config_cache_alloc() (or similar) + to get a synchronized copy of the options. + +input/input.c: + This translates keyboard input coming from VOs and other sources (such + as remote control devices like Apple IR or client API commands) to the + key bindings listed in the user's (or the builtin) input.conf and turns + them into items of type struct mp_cmd. These commands are queued, and read + by playloop.c. They get pushed with run_command() to command.c. + + Note that keyboard input and commands used by the client API are the same. + The client API only uses the command parser though, and has its own queue + of input commands somewhere else. + +common/msg.h: + All terminal output must go through mp_msg(). + +stream/*: + File input is implemented here. stream.h/.c provides a simple stream based + interface (like reading a number of bytes at a given offset). mpv can + also play from http streams and such, which is implemented here. + + E.g. if mpv sees "http://something" on the command line, it will pick + stream_lavf.c based on the prefix, and pass the rest of the filename to it. + + Some stream inputs are quite special: stream_dvd.c turns DVDs into mpeg + streams (DVDs are actually a bunch of vob files etc. on a filesystem), + stream_tv.c provides TV input including channel switching. + + Some stream inputs are just there to invoke special demuxers, like + stream_mf.c. (Basically to make the prefix "mf://" do something special.) + +demux/: + Demuxers split data streams into audio/video/sub streams, which in turn + are split in packets. Packets (see demux_packet.h) are mostly byte chunks + tagged with a playback time (PTS). These packets are passed to the decoders. + + Most demuxers have been removed from this fork, and the only important and + "actual" demuxers left are demux_mkv.c and demux_lavf.c (uses libavformat). + There are some pseudo demuxers like demux_cue.c. + + The main interface is in demux.h. The stream headers are in stheader.h. + There is a stream header for each audio/video/sub stream, and each of them + holds codec information about the stream and other information. + + demux.c is a bit big, the main reason being that it contains the demuxer + cache, which is implemented as a list of packets. The cache is complex + because it support seeking, multiple ranges, prefetching, and so on. + +video/: + This contains several things related to audio/video decoding, as well as + video filters. + + mp_image.h and img_format.h define how mpv stores decoded video frames + internally. + +video/decode/: + vd_*.c are video decoders. (There's only vd_lavc.c left.) dec_video.c + handles most of connecting the frontend with the actual decoder. + +video/filter/: + vf_*.c and vf.c form the video filter chain. They are fed by the video + decoder, and output the filtered images to the VOs though vf_vo.c. By + default, no video filters (except vf_vo) are used. vf_scale is automatically + inserted if the video output can't handle the video format used by the + decoder. + +video/out/: + Video output. They also create GUI windows and handle user input. In most + cases, the windowing code is shared among VOs, like x11_common.c for X11 and + w32_common.c for Windows. The VOs stand between frontend and windowing code. + vo_gpu can pick a windowing system at runtime, e.g. the same binary can + provide both X11 and Cocoa support on OSX. + + VOs can be reconfigured at runtime. A vo_reconfig() call can change the video + resolution and format, without destroying the window. + + vo_gpu should be taken as reference. + +audio/: + format.h/format.c define the uncompressed audio formats. (As well as some + compressed formats used for spdif.) + +audio/decode/: + ad_*.c and dec_audio.c handle audio decoding. ad_lavc.c is the + decoder using ffmpeg. ad_spdif.c is not really a decoder, but is used for + compressed audio passthrough. + +audio/filter/: + Audio filter chain. af_lavrresample is inserted if any form of conversion + between audio formats is needed. + +audio/out/: + Audio outputs. + + Unlike VOs, AOs can't be reconfigured on a format change. On audio format + changes, the AO will simply be closed and re-opened. + + There are wrappers to support for two types of audio APIs: push.c and + pull.c. ao.c calls into one of these. They contain generic code to deal + with the data flow these APIs impose. + + Note that mpv synchronizes the video to the audio. That's the reason + why buggy audio drivers can have a bad influence on playback quality. + +sub/: + Contains subtitle and OSD rendering. + + osd.c/.h is actually the OSD code. It queries dec_sub.c to retrieve + decoded/rendered subtitles. osd_libass.c is the actual implementation of + the OSD text renderer (which uses libass, and takes care of all the tricky + fontconfig/freetype API usage and text layouting). + + The VOs call osd.c to render OSD and subtitle (via e.g. osd_draw()). osd.c + in turn asks dec_sub.c for subtitle overlay bitmaps, which relays the + request to one of the sd_*.c subtitle decoders/renderers. + + Subtitle loading is in demux/. The MPlayer subreader.c is mostly gone - parts + of it survive in demux_subreader.c. It's used as last fallback, or to handle + some text subtitle types on Libav. It should go away eventually. Normally, + subtitles are loaded via demux_lavf.c. + + The subtitles are passed to dec_sub.c and the subtitle decoders in sd_*.c + as they are demuxed. All text subtitles are rendered by sd_ass.c. If text + subtitles are not in the ASS format, the libavcodec subtitle converters are + used (lavc_conv.c). + + Text subtitles can be preloaded, in which case they are read fully as soon + as the subtitle is selected. In this case, they are effectively stored in + sd_ass.c's internal state. + +etc/: + The file input.conf is actually integrated into the mpv binary by the + build system. It contains the default keybindings. + +Best practices and Concepts within mpv +====================================== + +General contribution etc. +------------------------- + +See: DOCS/contribute.md + +Error checking +-------------- + +If an error is relevant, it should be handled. If it's interesting, log the +error. However, mpv often keeps errors silent and reports failures somewhat +coarsely by propagating them upwards the caller chain. This is OK, as long as +the errors are not very interesting, or would require a developer to debug it +anyway (in which case using a debugger would be more convenient, and the +developer would need to add temporary debug printfs to get extremely detailed +information which would not be appropriate during normal operation). + +Basically, keep a balance on error reporting. But always check them, unless you +have a good argument not to. + +Memory allocation errors (OOM) are a special class of errors. Normally such +allocation failures are not handled "properly". Instead, abort() is called. +(New code should use MP_HANDLE_OOM() for this.) This is done out of laziness and +for convenience, and due to the fact that MPlayer/mplayer2 never handled it +correctly. (MPlayer varied between handling it correctly, trying to do so but +failing, and just not caring, while mplayer2 started using abort() for it.) + +This is justifiable in a number of ways. Error handling paths are notoriously +untested and buggy, so merely having them won't make your program more reliable. +Having these error handling paths also complicates non-error code, due to the +need to roll back state at any point after a memory allocation. + +Take any larger body of code, that is supposed to handle OOM, and test whether +the error paths actually work, for example by overriding malloc with a version +that randomly fails. You will find bugs quickly, and often they will be very +annoying to fix (if you can even reproduce them). + +In addition, a clear indication that something went wrong may be missing. On +error your program may exhibit "degraded" behavior by design. Consider a video +encoder dropping frames somewhere in the middle of a video due to temporary +allocation failures, instead of just exiting with an errors. In other cases, it +may open conceptual security holes. Failing fast may be better. + +mpv uses GPU APIs, which may be break on allocation errors (because driver +authors will have the same issues as described here), or don't even have a real +concept for dealing with OOM (OpenGL). + +libmpv is often used by GUIs, which I predict always break if OOM happens. + +Last but not least, OSes like Linux use "overcommit", which basically means that +your program may crash any time OOM happens, even if it doesn't use malloc() at +all! + +But still, don't just assume malloc() always succeeds. Use MP_HANDLE_OOM(). The +ta* APIs do this for you. The reason for this is that dereferencing a NULL +pointer can have security relevant consequences if large offsets are involved. +Also, a clear error message is better than a random segfault. + +Some big memory allocations are checked anyway. For example, all code must +assume that allocating video frames or packets can fail. (The above example +of dropping video frames during encoding is entirely possible in mpv.) + +Undefined behavior +------------------ + +Undefined behavior (UB) is a concept in the C language. C is famous for being a +language that makes it almost impossible to write working code, because +undefined behavior is so easily triggered, compilers will happily abuse it to +generate "faster" code, debugging tools will shout at you, and sometimes it +even means your code doesn't work. + +There is a lot of literature on this topic. Read it. + +(In C's defense, UB exists in other languages too, but since they're not used +for low level infrastructure, and/or these languages are at times not rigorously +defined, simply nobody cares. However, the C standard committee is still guilty +for not addressing this. I'll admit that I can't even tell from the standard's +gibberish whether some specific behavior is UB or not. It's written like tax +law.) + +In mpv, we generally try to avoid undefined behavior. For one, we want portable +and reliable operation. But more importantly, we want clean output from +debugging tools, in order to find real bugs more quickly and effectively. + +Avoid the "works in practice" argument. Once debugging tools come into play, or +simply when "in practice" stops being true, this will all get back to you in a +bad way. + +Global state, library safety +---------------------------- + +Mutable global state is when code uses global variables that are not read-only. +This must be avoided in mpv. Always use context structs that the caller of +your code needs to allocate, and whose pointers are passed to your functions. + +Library safety means that your code (or library) can be used by a library +without causing conflicts with other library users in the same process. To any +piece of code, a "safe" library's API can simply be used, without having to +worry about other API users that may be around somewhere. + +Libraries are often not library safe, because they they use global mutable state +or other "global" resources. Typical examples include use of signals, simple +global variables (like hsearch() in libc), or internal caches not protected by +locks. + +A surprisingly high number of libraries are not library safe because they need +global initialization. Typically they provide an API function, which +"initializes" the library, and which must be called before calling any other +API functions. Often, you are to provide global configuration parameters, which +can change the behavior of the library. If two libraries A and B use library C, +but A and B initialize C with different parameters, something "bad" may happen. +In addition, these global initialization functions are often not thread-safe. So +if A and B try to initialize C at the same time (from different threads and +without knowing about each other), it may cause undefined behavior. (libcurl is +a good example of both of these issues. FFmpeg and some TLS libraries used to be +affected, but improved.) + +This is so bad because library A and B from the previous example most likely +have no way to cooperate, because they're from different authors and have no +business knowing each others. They'd need a library D, which wraps library C +in a safe way. Unfortunately, typically something worse happens: libraries get +"infected" by the unsafeness of its sub-libraries, and export a global init API +just to initialize the sub-libraries. In the previous example, libraries A and B +would export global init APIs just to init library C, even though the rest of +A/B are clean and library safe. (Again, libcurl is an example of this, if you +subtract other historic anti-features.) + +The main problem with library safety is that its lack propagates to all +libraries using the library. + +We require libmpv to be library safe. This is not really possible, because some +libraries are not library safe (FFmpeg, Xlib, partially ALSA). However, for +ideological reasons, there is no global init API, and best effort is made to try +to avoid problems. + +libmpv has some features that are not library safe, but which are disabled by +default (such as terminal usage aka stdout, or JSON IPC blocking SIGPIPE for +internal convenience). + +A notable, very disgustingly library unsafe behavior of libmpv is calling +abort() on some memory allocation failure. See error checking section. + +Logging +------- + +All logging and terminal output in mpv goes through the functions and macros +provided in common/msg.h. This is in part for library safety, and in part to +make sure users can silence all output, or to redirect the output elsewhere, +like a log file or the internal console.lua script. + +Locking +------- + +See generally available literature. In mpv, we use pthread for this. + +Always keep locking clean. Don't skip locking just because it will work "in +practice". (See undefined behavior section.) If your use case is simple, you may +use C11 atomics (osdep/atomic.h for partial C99 support), but most likely you +will only hurt yourself and others. + +Always make clear which fields in a struct are protected by which lock. If a +field is immutable, or simply not thread-safe (e.g. state for a single worker +thread), document it as well. + +Internal mpv APIs are assumed to be not thread-safe by default. If they have +special guarantees (such as being usable by more than one thread at a time), +these should be explicitly documented. + +All internal mpv APIs must be free of global state. Even if a component is not +thread-safe, multiple threads can use _different_ instances of it without any +locking. + +On a side note, recursive locks may seem convenient at first, but introduce +additional problems with condition variables and locking hierarchies. They +should be avoided. + +Locking hierarchy +----------------- + +A simple way to avoid deadlocks with classic locking is to define a locking +hierarchy or lock order. If all threads acquire locks in the same order, no +deadlocks will happen. + +For example, a "leaf" lock is a lock that is below all other locks in the +hierarchy. You can acquire it any time, as long as you don't acquire other +locks while holding it. + +Unfortunately, C has no way to declare or check the lock order, so you should at +least document it. + +In addition, try to avoid exposing locks to the outside. Making the declaration +of a lock private to a specific .c file (and _not_ exporting accessors or +lock/unlock functions that manipulate the lock) is a good idea. Your component's +API may acquire internal locks, but should release them when returning. Keeping +the entire locking in a single file makes it easy to check it. + +Avoiding callback hell +---------------------- + +mpv code is separated in components, like the "frontend" (i.e. MPContext mpctx), +VOs, AOs, demuxers, and more. The frontend usually calls "down" the usage +hierarchy: mpctx almost on top, then things like vo/ao, and utility code on the +very bottom. + +"Callback hell" is when when components call both up and down the hierarchy, +which for example leads to accidentally recursion, reentrancy problems, or +locking nightmares. This is avoided by (mostly) calling only down the hierarchy. +Basically the call graph forms a DAG. The other direction is handled by event +queues, wakeup callbacks, and similar mechanisms. + +Typically, a component provides an API, and does not know anything about its +user. The API user (component higher in the hierarchy) polls the state of the +lower component when needed. + +This also enforces some level of modularization, and with some luck the locking +hierarchy. (Basically, locks of lower components automatically become leaf +locks.) Another positive effect is simpler memory management. + +(Also see e.g.: http://250bpm.com/blog:24) + +Wakeup callbacks +---------------- + +This is a common concept in mpv. Even the public API uses it. It's used when an +API has internal threads (or otherwise triggers asynchronous events), but the +component call hierarchy needs to be kept. The wakeup callback is the only +exception to the call hierarchy, and always calls up. + +For example, vo spawns a thread that the API user (the mpv frontend) does not +need to know about. vo simply provides a single-threaded API (or that looks like +one). This API needs a way to notify the API user of new events. But the vo +event producer is on the vo thread - it can't simply invoke a callback back into +the API user, because then the API user has to deal with locking, despite not +using threads. In addition, this will probably cause problems like mentioned in +the "callback hell" section, especially lock order issues. + +The solution is the wakeup callback. It merely unblocks the API user from +waiting, and the API user then uses the normal vo API to examine whether or +which state changed. As a concept, it documents what a wakeup callback is +allowed to do and what not, to avoid the aforementioned problems. + +Generally, you are not allowed to call any API from the wakeup callback. You +just do whatever is needed to unblock your thread. For example, if it's waiting +on a mutex/condition variable, acquire the mutex, set a change flag, signal +the condition variable, unlock, return. (This mutex must not be held when +calling the API. It must be a leaf lock.) + +Restricting the wakeup callback like this sidesteps any reentrancy issues and +other complexities. The API implementation can simply hold internal (and +non-recursive) locks while invoking the wakeup callback. + +The API user still needs to deal with locking (probably), but there's only the +need to implement a single "receiver", that can handle the entire API of the +used component. (Or multiple APIs - MPContext for example has only 1 wakeup +callback that handles all AOs, VOs, input, demuxers, and more. It simple re-runs +the playloop.) + +You could get something more advanced by turning this into a message queue. The +API would append a message to the queue, and the API user can read it. But then +you still need a way to "wakeup" the API user (unless you force the API user +to block on your API, which will make things inconvenient for the API user). You +also need to worry about what happens if the message queue overruns (you either +lose messages or have unbounded memory usage). In the mpv public API, the +distinction between message queue and wakeup callback is sort of blurry, because +it does provide a message queue, but an additional wakeup callback, so API +users are not required to call mpv_wait_event() with a high timeout. + +mpv itself prefers using wakeup callbacks over a generic event queue, because +most times an event queue is not needed (or complicates things), and it is +better to do it manually. + +(You could still abstract the API user side of wakeup callback handling, and +avoid reimplementing it all the time. Although mp_dispatch_queue already +provides mechanisms for this.) + +Condition variables +------------------- + +They're used whenever a thread needs to wait for something, without nonsense +like sleep calls or busy waiting. mpv uses the standard pthread API for this. +There's a lot of literature on it. Read it. + +For initial understanding, it may be helpful to know that condition variables +are not variables that signal a condition. pthread_cond_t does not have any +state per-se. Maybe pthread_cond_t would better be named pthread_interrupt_t, +because its sole purpose is to interrupt a thread waiting via pthread_cond_wait() +(or similar). The "something" in "waiting for something" can be called +predicate (to avoid confusing it with "condition"). Consult literature for the +proper terms. + +The very short version is... + +Shared declarations: + + pthread_mutex_t lock; + pthread_cond_t cond_var; + struct something state_var; // protected by lock, changes signaled by cond_var + +Waiter thread: + + pthread_mutex_lock(&lock); + + // Wait for a change in state_var. We want to wait until predicate_fulfilled() + // returns true. + // Must be a loop for 2 reasons: + // 1. cond_var may be associated with other conditions too + // 2. pthread_cond_wait() can have sporadic wakeups + while (!predicate_fulfilled(&state_var)) { + // This unlocks, waits for cond_var to be signaled, and then locks again. + // The _whole_ point of cond_var is that unlocking and waiting for the + // signal happens atomically. + pthread_cond_wait(&cond_var, &lock); + } + + // Here you may react to the state change. The state cannot change + // asynchronously as long as you still hold the lock (and didn't release + // and reacquire it). + // ... + + pthread_mutex_unlock(&lock); + +Signaler thread: + + pthread_mutex_lock(&lock); + + // Something changed. Update the shared variable with the new state. + update_state(&state_var); + + // Notify that something changed. This will wake up the waiter thread if + // it's blocked in pthread_cond_wait(). If not, nothing happens. + pthread_cond_broadcast(&cond_var); + + // Fun fact: good implementations wake up the waiter only when the lock is + // released, to reduce kernel scheduling overhead. + pthread_mutex_unlock(&lock); + +Some basic rules: + 1. Always access your state under proper locking + 2. Always check your predicate before every call to pthread_cond_wait() + (And don't call pthread_cond_wait() if the predicate is fulfilled.) + 3. Always call pthread_cond_wait() in a loop + (And only if your predicate failed without releasing the lock..) + 4. Always call pthread_cond_broadcast()/_signal() inside of its associated + lock + +mpv sometimes violates rule 3, and leaves "retrying" (i.e. looping) to the +caller. + +Common pitfalls: + - Thinking that pthread_cond_t is some kind of semaphore, or holds any + application state or the user predicate (it _only_ wakes up threads + that are at the same time blocking on pthread_cond_wait() and friends, + nothing else) + - Changing the predicate, but not updating all pthread_cond_broadcast()/ + _signal() calls correctly + - Forgetting that pthread_cond_wait() unlocks the lock (other threads can + and must acquire the lock) + - Holding multiple nested locks while trying to wait (=> deadlock, violates + the lock order anyway) + - Waiting for a predicate correctly, but unlocking/relocking before acting + on it (unlocking allows arbitrary state changes) + - Confusing which lock/condition var. is used to manage a bit of state + +Generally available literature probably has better examples and explanations. + +Using condition variables the proper way is generally preferred over using more +messy variants of them. (Just saying because on win32, "SetEvent" exists, and +it's inferior to condition variables. Try to avoid the win32 primitives, even if +you're dealing with Windows-only code.) + +Threads +------- + +Threading should be conservatively used. Normally, mpv code pretends to be +single-threaded, and provides thread-unsafe APIs. Threads are used coarsely, +and if you can avoid messing with threads, you should. For example, VOs and AOs +do not need to deal with threads normally, even though they run on separate +threads. The glue code "isolates" them from any threading issues. diff --git a/.config/mpv/watch_later/CACAA34377FFD1DEE065BD79830BED0A b/.config/mpv/watch_later/CACAA34377FFD1DEE065BD79830BED0A new file mode 100644 index 0000000..48c657f --- /dev/null +++ b/.config/mpv/watch_later/CACAA34377FFD1DEE065BD79830BED0A @@ -0,0 +1,4 @@ +start=7562.692000 +volume=52.000000 +aid=4 +sid=1 diff --git a/.config/ncmpcpp/config b/.config/ncmpcpp/config new file mode 100644 index 0000000..d950de7 --- /dev/null +++ b/.config/ncmpcpp/config @@ -0,0 +1,598 @@ +############################################################## +## This is an example configuration file. Copy it to ## +## $XDG_CONFIG_HOME/ncmpcpp/config or $HOME/.ncmpcpp/config ## +## and set up your preferences. ## +############################################################## +# +##### directories ###### +## +## Directory for storing ncmpcpp related files. Changing it is useful if you +## want to store everything somewhere else and provide command line setting for +## alternative location to config file which defines that while launching +## ncmpcpp. +## +# +ncmpcpp_directory = ~/.config/ncmpcpp +# +## +## Directory for storing downloaded lyrics. It defaults to ~/.lyrics since other +## MPD clients (eg. ncmpc) also use that location. +## +# +#lyrics_directory = ~/.lyrics +# +##### connection settings ##### +# +#mpd_host = localhost +# +#mpd_port = 6600 +# +#mpd_connection_timeout = 5 +# +## Needed for tag editor and file operations to work. +## +#mpd_music_dir = ~/music +# +#mpd_crossfade_time = 5 +# +# Exclude pattern for random song action +# http://www.boost.org/doc/libs/1_46_1/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html +#random_exclude_pattern = "^(temp|midi_songs).*" +# +##### music visualizer ##### +## +## In order to make music visualizer work with MPD you need to use the fifo +## output. Its format parameter has to be set to 44100:16:1 for mono +## visualization or 44100:16:2 for stereo visualization. As an example here is +## the relevant section for mpd.conf: +## +## audio_output { +## type "fifo" +## name "Visualizer feed" +## path "/tmp/mpd.fifo" +## format "44100:16:2" +## } +## +## If the visualization on occasion diverges from the audio output, please set +## 'buffer_time' parameter of your audio output in mpd.conf to '100000' (100ms) +## or less to prevent that from happening. +## +## Note: If you're using Mopidy, an address of a udpsink gstreamer's output is +## also accepted. For example, the following section in mopidy.conf: +## +## [audio] +## output = tee name=t ! queue ! autoaudiosink t. +## ! queue ! audio/x-raw,rate=44100,channels=2,format=S16LE +## ! udpsink host=localhost port=5555 +## +## will make localhost:5555 available as a source of data for the stereo +## visualizer. +## +# +visualizer_data_source = /tmp/mpd.fifo +# +## +## Note: Below parameter is needed for ncmpcpp to determine which output +## provides data for visualizer and reset it at the beginning of visualization +## to synchronize with audio. +## +# +visualizer_output_name = Visualizer feed +# +## +## If you set format to 44100:16:2, make it 'yes'. +## +visualizer_in_stereo = yes +# +## +## Note: set below to >=10 only if you have synchronization issues with +## visualization and audio. +## +# +visualizer_sync_interval = 0 +# +## +## Note: To enable spectrum frequency visualization you need to compile ncmpcpp +## with fftw3 support. +## +# +## Available values: spectrum, wave, wave_filled, ellipse. +## +visualizer_type = spectrum +# +visualizer_fps = 144 +# +visualizer_autoscale = yes +# +visualizer_look = ●▮ +# +#visualizer_color = blue, cyan, green, yellow, magenta, red +# +## Alternative subset of 256 colors for terminals that support it. +## +#visualizer_color = 47, 83, 119, 155, 191, 227, 221, 215, 209, 203, 197, 161 +# +## +## Note: The next few visualization options apply to the spectrum visualizer. +## +# +## Use unicode block characters for a smoother, more continuous look. +## This will override the visualizer_look option. With transparent terminals +## and visualizer_in_stereo set, artifacts may be visible on the bottom half of +## the visualization. +# +visualizer_spectrum_smooth_look = yes +# +## A value between 1 and 5 inclusive. Specifying a larger value makes the +## visualizer look at a larger slice of time, which results in less jumpy +## visualizer output. +# +visualizer_spectrum_dft_size = 1 +# +#visualizer_spectrum_gain = 10 +# +## Left-most frequency of visualizer in Hz, must be less than HZ MAX +# +#visualizer_spectrum_hz_min = 20 +# +## Right-most frequency of visualizer in Hz, must be greater than HZ MIN +# +#visualizer_spectrum_hz_max = 20000 +# +##### system encoding ##### +## +## ncmpcpp should detect your charset encoding but if it failed to do so, you +## can specify charset encoding you are using here. +## +## Note: You can see whether your ncmpcpp build supports charset detection by +## checking output of `ncmpcpp --version`. +## +## Note: Since MPD uses UTF-8 by default, setting this option makes sense only +## if your encoding is different. +## +# +#system_encoding = "" +# +##### delays ##### +# +## Time of inactivity (in seconds) after playlist highlighting will be disabled +## (0 = always on). +## +#playlist_disable_highlight_delay = 5 +# +## Defines how long messages are supposed to be visible. +## +#message_delay_time = 5 +# +##### song format ##### +## +## For a song format you can use: +## +## %l - length +## %f - filename +## %D - directory +## %a - artist +## %A - album artist +## %t - title +## %b - album +## %y - date +## %n - track number (01/12 -> 01) +## %N - full track info (01/12 -> 01/12) +## %g - genre +## %c - composer +## %p - performer +## %d - disc +## %C - comment +## %P - priority +## $R - begin right alignment +## +## If you want to make sure that a part of the format is displayed only when +## certain tags are present, you can archieve it by grouping them with brackets, +## e.g. '{%a - %t}' will be evaluated to 'ARTIST - TITLE' if both tags are +## present or '' otherwise. It is also possible to define a list of +## alternatives by providing several groups and separating them with '|', +## e.g. '{%t}|{%f}' will be evaluated to 'TITLE' or 'FILENAME' if the former is +## not present. +## +## Note: If you want to set limit on maximal length of a tag, just put the +## appropriate number between % and character that defines tag type, e.g. to +## make album take max. 20 terminal cells, use '%20b'. +## +## In addition, formats support markers used for text attributes. They are +## followed by character '$'. After that you can put: +## +## - 0 - default window color (discards all other colors) +## - 1 - black +## - 2 - red +## - 3 - green +## - 4 - yellow +## - 5 - blue +## - 6 - magenta +## - 7 - cyan +## - 8 - white +## - 9 - end of current color +## - b - bold text +## - u - underline text +## - r - reverse colors +## - a - use alternative character set +## +## If you don't want to use a non-color attribute anymore, just put it again, +## but this time insert character '/' between '$' and attribute character, +## e.g. {$b%t$/b}|{$r%f$/r} will display bolded title tag or filename with +## reversed colors. +## +## If you want to use 256 colors and/or background colors in formats (the naming +## scheme is described below in section about color definitions), it can be done +## with the syntax $(COLOR), e.g. to set the artist tag to one of the +## non-standard colors and make it have yellow background, you need to write +## $(197_yellow)%a$(end). Note that for standard colors this is interchangable +## with attributes listed above. +## +## Note: colors can be nested. +## +# +song_list_format = {%a - }{%t}|{$8%f$9}$R{$3%l$9} +# +#song_status_format = {{%a{ "%b"{ (%y)}} - }{%t}}|{%f} +# +#song_library_format = {%n - }{%t}|{%f} +# +#alternative_header_first_line_format = $b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b +# +#alternative_header_second_line_format = {{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D} +# +#current_item_prefix = $(yellow)$r +# +#current_item_suffix = $/r$(end) +# +#current_item_inactive_column_prefix = $(white)$r +# +#current_item_inactive_column_suffix = $/r$(end) +# +#now_playing_prefix = $b +# +#now_playing_suffix = $/b +# +#browser_playlist_prefix = "$2playlist$9 " +# +#selected_item_prefix = $6 +# +#selected_item_suffix = $9 +# +#modified_item_prefix = $3> $9 +# +## +## Note: attributes are not supported for the following variables. +## +#song_window_title_format = {%a - }{%t}|{%f} +## +## Note: Below variables are used for sorting songs in browser. The sort mode +## determines how songs are sorted, and can be used in combination with a sort +## format to specify a custom sorting format. Available values for +## browser_sort_mode are "type", "name", "mtime", "format" and "none". +## +# +#browser_sort_mode = type +# +#browser_sort_format = {%a - }{%t}|{%f} {%l} +# +##### columns settings ##### +## +## syntax of song columns list format is "column column etc." +## +## - syntax for each column is: +## +## (width of the column)[color of the column]{displayed tag} +## +## Note: Width is by default in %, if you want a column to have fixed size, add +## 'f' after the value, e.g. (10)[white]{a} will be the column that take 10% of +## screen (so the real width will depend on actual screen size), whereas +## (10f)[white]{a} will take 10 terminal cells, no matter how wide the screen +## is. +## +## - color is optional (if you want the default one, leave the field empty). +## +## Note: You can give a column additional attributes by putting appropriate +## character after displayed tag character. Available attributes are: +## +## - r - column will be right aligned +## - E - if tag is empty, empty tag marker won't be displayed +## +## You can also: +## +## - give a column custom name by putting it after attributes, separated with +## character ':', e.g. {lr:Length} gives you right aligned column of lengths +## named "Length". +## +## - define sequence of tags, that have to be displayed in case predecessor is +## empty in a way similar to the one in classic song format, i.e. using '|' +## character, e.g. {a|c|p:Owner} creates column named "Owner" that tries to +## display artist tag and then composer and performer if previous ones are not +## available. +## +# +#song_columns_list_format = (20)[]{a} (6f)[green]{NE} (50)[white]{t|f:Title} (20)[cyan]{b} (7f)[magenta]{l} +# +##### various settings ##### +# +## +## Note: Custom command that will be executed each time song changes. Useful for +## notifications etc. +## +#execute_on_song_change = "" +# +## +## Note: Custom command that will be executed each time player state +## changes. The environment variable MPD_PLAYER_STATE is set to the current +## state (either unknown, play, pause, or stop) for its duration. +## +# +#execute_on_player_state_change = "" +# +#playlist_show_mpd_host = no +# +#playlist_show_remaining_time = no +# +#playlist_shorten_total_times = no +# +#playlist_separate_albums = no +# +## +## Note: Possible display modes: classic, columns. +## +#playlist_display_mode = columns +# +#browser_display_mode = classic +# +#search_engine_display_mode = classic +# +#playlist_editor_display_mode = classic +# +#discard_colors_if_item_is_selected = yes +# +#show_duplicate_tags = yes +# +#incremental_seeking = yes +# +#seek_time = 1 +# +#volume_change_step = 2 +# +#autocenter_mode = no +# +#centered_cursor = no +# +## +## Note: You can specify third character which will be used to build 'empty' +## part of progressbar. +## +#progressbar_look = => +# +## Available values: database, playlist. +## +#default_place_to_search_in = database +# +## Available values: classic, alternative. +## +#user_interface = classic +# +#data_fetching_delay = yes +# +## Available values: artist, album_artist, date, genre, composer, performer. +## +#media_library_primary_tag = artist +# +#media_library_albums_split_by_date = yes +# +#media_library_hide_album_dates = no +# +## Available values: wrapped, normal. +## +#default_find_mode = wrapped +# +#default_tag_editor_pattern = %n - %t +# +#header_visibility = yes +# +#statusbar_visibility = yes +# +## Show the "Connected to ..." message on startup +#connected_message_on_startup = yes +# +#titles_visibility = yes +# +#header_text_scrolling = yes +# +#cyclic_scrolling = no +# +#lyrics_fetchers = azlyrics, genius, musixmatch, sing365, metrolyrics, justsomelyrics, jahlyrics, plyrics, tekstowo, zeneszoveg, internet +# +#follow_now_playing_lyrics = no +# +#fetch_lyrics_for_current_song_in_background = no +# +#store_lyrics_in_song_dir = no +# +#generate_win32_compatible_filenames = yes +# +#allow_for_physical_item_deletion = no +# +## +## Note: If you set this variable, ncmpcpp will try to get info from last.fm in +## language you set and if it fails, it will fall back to english. Otherwise it +## will use english the first time. +## +## Note: Language has to be expressed as an ISO 639 alpha-2 code. +## +#lastfm_preferred_language = en +# +#space_add_mode = add_remove +# +#show_hidden_files_in_local_browser = no +# +## +## How shall screen switcher work? +## +## - "previous" - switch between the current and previous screen. +## - "screen1,...,screenN" - switch between given sequence of screens. +## +## Screens available for use: help, playlist, browser, search_engine, +## media_library, playlist_editor, tag_editor, outputs, visualizer, clock, +## lyrics, last_fm. +## +#screen_switcher_mode = playlist, browser +# +## +## Note: You can define startup screen by choosing screen from the list above. +## +#startup_screen = playlist +# +## +## Note: You can define startup slave screen by choosing screen from the list +## above or an empty value for no slave screen. +## +#startup_slave_screen = "" +# +#startup_slave_screen_focus = no +# +## +## Default width of locked screen (in %). Acceptable values are from 20 to 80. +## +# +#locked_screen_width_part = 50 +# +#ask_for_locked_screen_width_part = yes +# +#jump_to_now_playing_song_at_start = yes +# +#ask_before_clearing_playlists = yes +# +#clock_display_seconds = no +# +#display_volume_level = yes +# +#display_bitrate = no +# +#display_remaining_time = no +# +## Available values: none, basic, extended, perl. +## +#regular_expressions = perl +# +## +## Note: if below is enabled, ncmpcpp will ignore leading "The" word while +## sorting items in browser, tags in media library, etc. +## +#ignore_leading_the = no +# +## +## Note: if below is enabled, ncmpcpp will ignore diacritics while searching and +## filtering lists. This takes an effect only if boost was compiled with ICU +## support. +## +#ignore_diacritics = no +# +#block_search_constraints_change_if_items_found = yes +# +#mouse_support = yes +# +#mouse_list_scroll_whole_page = no +# +#lines_scrolled = 5 +# +#empty_tag_marker = +# +#tags_separator = " | " +# +#tag_editor_extended_numeration = no +# +#media_library_sort_by_mtime = no +# +#enable_window_title = yes +# +## +## Note: You can choose default search mode for search engine. Available modes +## are: +## +## - 1 - use mpd built-in searching (no regexes, pattern matching) +## +## - 2 - use ncmpcpp searching (pattern matching with support for regexes, but +## if your mpd is on a remote machine, downloading big database to process +## it can take a while +## +## - 3 - match only exact values (this mode uses mpd function for searching in +## database and local one for searching in current playlist) +## +# +#search_engine_default_search_mode = 1 +# +#external_editor = nano +# +## Note: set to yes if external editor is a console application. +## +#use_console_editor = yes +# +##### colors definitions ##### +## +## It is possible to set a background color by setting a color value +## "_", e.g. red_black will set foregound color to red +## and background color to black. +## +## In addition, for terminals that support 256 colors it is possible to set one +## of them by using a number in range [1, 256] instead of color name, +## e.g. numerical value corresponding to red_black is 2_1. To find out if the +## terminal supports 256 colors, run ncmpcpp and check out the bottom of the +## help screen for list of available colors and their numerical values. +## +## What is more, there are two special values for the background color: +## "transparent" and "current". The first one explicitly sets the background to +## be transparent, while the second one allows you to preserve current +## background color and change only the foreground one. It's used implicitly +## when background color is not specified. +## +## Moreover, it is possible to attach format information to selected color +## variables by appending to their end a colon followed by one or more format +## flags, e.g. black:b or red:ur. The following variables support this syntax: +## visualizer_color, color1, color2, empty_tag_color, volume_color, +## state_line_color, state_flags_color, progressbar_color, +## progressbar_elapsed_color, player_state_color, statusbar_time_color, +## alternative_ui_separator_color. +## +## Note: due to technical limitations of older ncurses version, if 256 colors +## are used there is a possibility that you'll be able to use only colors with +## transparent background. +# +#colors_enabled = yes +# +#empty_tag_color = cyan +# +#header_window_color = default +# +#volume_color = default +# +#state_line_color = default +# +#state_flags_color = default:b +# +#main_window_color = yellow +# +#color1 = white +# +#color2 = green +# +#progressbar_color = black:b +# +#progressbar_elapsed_color = green:b +# +#statusbar_color = default +# +#statusbar_time_color = default:b +# +#player_state_color = default:b +# +#alternative_ui_separator_color = black:b +# +#window_border_color = green +# +#active_window_border = red +# diff --git a/.config/ncmpcpp/error.log b/.config/ncmpcpp/error.log new file mode 100644 index 0000000..7e0f7ef --- /dev/null +++ b/.config/ncmpcpp/error.log @@ -0,0 +1,2 @@ +TagLib: Could not open file /home/nikita/music/https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=189&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTg5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1Njg3fQ.9BXm5D0zRPktJQy4koGBTJPxbjN2JGr8OXBnCyFikmU +TagLib: Could not open file /home/nikita/music/https://airsonic.woopwoopserver.com:443/ext/stream?player=5&id=189&suffix=.mp3&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXRoIjoiL2V4dC9zdHJlYW0_cGxheWVyPTUmaWQ9MTg5JnN1ZmZpeD0ubXAzIiwiZXhwIjoxNjU3ODA1Njg3fQ.9BXm5D0zRPktJQy4koGBTJPxbjN2JGr8OXBnCyFikmU diff --git a/.config/newsboat b/.config/newsboat new file mode 160000 index 0000000..819f320 --- /dev/null +++ b/.config/newsboat @@ -0,0 +1 @@ +Subproject commit 819f320eefcca1914f03952458445673bec2a1a7 diff --git a/.config/nvim/.gitignore b/.config/nvim/.gitignore new file mode 100644 index 0000000..d7ad043 --- /dev/null +++ b/.config/nvim/.gitignore @@ -0,0 +1 @@ +plugin/ diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua new file mode 100644 index 0000000..0c02612 --- /dev/null +++ b/.config/nvim/init.lua @@ -0,0 +1,27 @@ +require("user.plugins") +require("user.themes.kanagawa") +require("user.options") +require("user.keymaps") +require("user.cmp") +require("user.lsp") +require("user.treesitter") +require("user.blank_indent_highlight") +require("user.autopairs") +require("user.telescope") +require("user.lsp_format") +require("user.bufferline") +require("user.null_ls") +require("user.nvim_scrollbar") +require("user.onedark_config") +require("user.gitsigns") +require("user.lualine") +require("user.dap.dap") +require("user.dap.dapui") +require("user.neotree") +-- require("user.colorschemes.tokyo_night") +-- require("user.nvim_tree") +-- require("user.heirline") + +vim.cmd("colorscheme kanagawa") + +-- vim.cmd([[highlight IndentBlanklineContextChar guifg=#757575]]) diff --git a/.config/nvim/lua/user/autopairs.lua b/.config/nvim/lua/user/autopairs.lua new file mode 100644 index 0000000..577e571 --- /dev/null +++ b/.config/nvim/lua/user/autopairs.lua @@ -0,0 +1,33 @@ +-- Setup nvim-cmp. +local status_ok, npairs = pcall(require, "nvim-autopairs") +if not status_ok then + return +end + +npairs.setup { + check_ts = true, + ts_config = { + lua = { "string", "source" }, + javascript = { "string", "template_string" }, + java = false, + }, + disable_filetype = { "TelescopePrompt", "spectre_panel" }, + fast_wrap = { + map = "", + chars = { "{", "[", "(", '"', "'" }, + pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], "%s+", ""), + offset = 0, -- Offset from pattern match + end_key = "$", + keys = "qwertyuiopzxcvbnmasdfghjkl", + check_comma = true, + highlight = "PmenuSel", + highlight_grey = "LineNr", + }, +} + +local cmp_autopairs = require "nvim-autopairs.completion.cmp" +local cmp_status_ok, cmp = pcall(require, "cmp") +if not cmp_status_ok then + return +end +cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done { map_char = { tex = "" } }) diff --git a/.config/nvim/lua/user/blank_indent_highlight.lua b/.config/nvim/lua/user/blank_indent_highlight.lua new file mode 100644 index 0000000..5cbcdfe --- /dev/null +++ b/.config/nvim/lua/user/blank_indent_highlight.lua @@ -0,0 +1,7 @@ +require("ibl").setup({ + scope = { + enabled = true, + show_start = false, + show_end = false, + }, +}) diff --git a/.config/nvim/lua/user/bufferline.lua b/.config/nvim/lua/user/bufferline.lua new file mode 100644 index 0000000..838efdb --- /dev/null +++ b/.config/nvim/lua/user/bufferline.lua @@ -0,0 +1,20 @@ +local status_ok, bufferline = pcall(require, "bufferline") +if not status_ok then + return +end +bufferline.setup({ + options = { + offsets = { + { filetype = "NvimTree", text = "", padding = 1 }, + { filetype = "neo-tree", text = "", padding = 1 }, + { filetype = "Outline", text = "", padding = 1 }, + }, + buffer_close_icon = "", + modified_icon = "", + close_icon = "", + max_name_length = 14, + max_prefix_length = 13, + tab_size = 20, + separator_style = "thin", + }, +}) diff --git a/.config/nvim/lua/user/cmp.lua b/.config/nvim/lua/user/cmp.lua new file mode 100644 index 0000000..a9e7048 --- /dev/null +++ b/.config/nvim/lua/user/cmp.lua @@ -0,0 +1,131 @@ +local cmp_status_ok, cmp = pcall(require, "cmp") +if not cmp_status_ok then + return +end + +local snip_status_ok, luasnip = pcall(require, "luasnip") +if not snip_status_ok then + return +end + +require("luasnip/loaders/from_vscode").lazy_load() + +local check_backspace = function() + local col = vim.fn.col "." - 1 + return col == 0 or vim.fn.getline("."):sub(col, col):match "%s" +end + +--   פּ ﯟ   some other good icons +local kind_icons = { + Text = "", + Method = "m", + Function = "", + Constructor = "", + Field = "", + Variable = "", + Class = "", + Interface = "", + Module = "", + Property = "", + Unit = "", + Value = "", + Enum = "", + Keyword = "", + Snippet = "", + Color = "", + File = "", + Reference = "", + Folder = "", + EnumMember = "", + Constant = "", + Struct = "", + Event = "", + Operator = "", + TypeParameter = "", +} +-- find more here: https://www.nerdfonts.com/cheat-sheet + +cmp.setup { + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) -- For `luasnip` users. + end, + }, + mapping = { + [""] = cmp.mapping.select_prev_item(), + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping(cmp.mapping.scroll_docs(-1), { "i", "c" }), + [""] = cmp.mapping(cmp.mapping.scroll_docs(1), { "i", "c" }), + [""] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }), + [""] = cmp.config.disable, -- Specify `cmp.config.disable` if you want to remove the default `` mapping. + [""] = cmp.mapping { + i = cmp.mapping.abort(), + c = cmp.mapping.close(), + }, + -- Accept currently selected item. If none selected, `select` first item. + -- Set `select` to `false` to only confirm explicitly selected items. + [""] = cmp.mapping.confirm { select = true }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + -- elseif luasnip.expandable() then + -- luasnip.expand() + -- elseif luasnip.expand_or_jumpable() then + -- luasnip.expand_or_jump() + -- elseif check_backspace() then + -- fallback() + else + fallback() + end + end, { + "i", + "s", + }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { + "i", + "s", + }), + }, + formatting = { + fields = { "kind", "abbr", "menu" }, + format = function(entry, vim_item) + -- Kind icons + vim_item.kind = string.format("%s", kind_icons[vim_item.kind]) + -- vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) -- This concatonates the icons with the name of the item kind + vim_item.menu = ({ + nvim_lsp = "[LSP]", + luasnip = "[Snippet]", + buffer = "[Buffer]", + path = "[Path]", + })[entry.source.name] + return vim_item + end, + }, + sources = { + { name = "nvim_lsp" }, + { name = "luasnip" }, + { name = "buffer" }, + { name = "path" }, + }, + confirm_opts = { + behavior = cmp.ConfirmBehavior.Replace, + select = false, + }, + window = { + documentation = { + border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, + }, + }, + experimental = { + ghost_text = false, + native_menu = false, + }, +} diff --git a/.config/nvim/lua/user/colorschemes/tokyo_night.lua b/.config/nvim/lua/user/colorschemes/tokyo_night.lua new file mode 100644 index 0000000..f6afac5 --- /dev/null +++ b/.config/nvim/lua/user/colorschemes/tokyo_night.lua @@ -0,0 +1 @@ +vim.g.tokyonight_style = "night" diff --git a/.config/nvim/lua/user/dap/dap.lua b/.config/nvim/lua/user/dap/dap.lua new file mode 100644 index 0000000..d40edf2 --- /dev/null +++ b/.config/nvim/lua/user/dap/dap.lua @@ -0,0 +1,45 @@ +local dap_status_ok, dap = pcall(require, "dap") +if not dap_status_ok then + return +end + +local dapui_status_ok, dapui = pcall(require, "dapui") +if not dapui_status_ok then + return +end + +dap.adapters.coreclr = { + type = 'executable', + command = '/usr/local/netcoredbg', + args = {'--interpreter=vscode'} +} + +dap.configurations.cs = { + { + type = "coreclr", + name = "launch - netcoredbg", + request = "launch", + program = function() + return vim.fn.input('Path to dll', vim.fn.getcwd() .. '/bin/Debug/', 'file') + end, + }, +} + +vim.keymap.set('n', 'dr', dap.continue) +vim.keymap.set('n', 'dj', dap.step_into) +vim.keymap.set('n', 'dl', dap.step_over) +vim.keymap.set('n', 'dk', dap.step_out) +vim.keymap.set('n', 'db', dap.toggle_breakpoint) +vim.keymap.set('n', 'ds', dap.terminate) + + +--Autostart ui when debugging +dap.listeners.after.event_initialized["dapui_config"] = function() + dapui.open() +end +dap.listeners.before.event_terminated["dapui_config"] = function() + dapui.close() +end +dap.listeners.before.event_exited["dapui_config"] = function() + dapui.close() +end diff --git a/.config/nvim/lua/user/dap/dapui.lua b/.config/nvim/lua/user/dap/dapui.lua new file mode 100644 index 0000000..2d2e610 --- /dev/null +++ b/.config/nvim/lua/user/dap/dapui.lua @@ -0,0 +1,6 @@ +local dapui_status_ok, dapui = pcall(require, "dapui") +if not dapui_status_ok then + return +end + +dapui.setup() diff --git a/.config/nvim/lua/user/gitsigns.lua b/.config/nvim/lua/user/gitsigns.lua new file mode 100644 index 0000000..f1e8524 --- /dev/null +++ b/.config/nvim/lua/user/gitsigns.lua @@ -0,0 +1,42 @@ +require('gitsigns').setup { + signs = { + add = { hl = 'GitSignsAdd' , text = '│', numhl='GitSignsAddNr' , linehl='GitSignsAddLn' }, + change = { hl = 'GitSignsChange', text = '│', numhl='GitSignsChangeNr', linehl='GitSignsChangeLn' }, + delete = { hl = 'GitSignsDelete', text = '_', numhl='GitSignsDeleteNr', linehl='GitSignsDeleteLn' }, + topdelete = { hl = 'GitSignsDelete', text = '‾', numhl='GitSignsDeleteNr', linehl='GitSignsDeleteLn' }, + changedelete = { hl = 'GitSignsChange', text = '~', numhl='GitSignsChangeNr', linehl='GitSignsChangeLn' }, + untracked = { hl = 'GitSignsAdd' , text = '┆', numhl='GitSignsAddNr' , linehl='GitSignsAddLn' }, + }, + signcolumn = true, -- Toggle with `:Gitsigns toggle_signs` + numhl = false, -- Toggle with `:Gitsigns toggle_numhl` + linehl = false, -- Toggle with `:Gitsigns toggle_linehl` + word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff` + watch_gitdir = { + interval = 1000, + follow_files = true + }, + attach_to_untracked = true, + current_line_blame = false, -- Toggle with `:Gitsigns toggle_current_line_blame` + current_line_blame_opts = { + virt_text = true, + virt_text_pos = 'eol', -- 'eol' | 'overlay' | 'right_align' + delay = 1000, + ignore_whitespace = false, + }, + current_line_blame_formatter = ', - ', + sign_priority = 6, + update_debounce = 100, + status_formatter = nil, -- Use default + max_file_length = 40000, -- Disable if file is longer than this (in lines) + preview_config = { + -- Options passed to nvim_open_win + border = 'single', + style = 'minimal', + relative = 'cursor', + row = 0, + col = 1 + }, + yadm = { + enable = false + }, +} diff --git a/.config/nvim/lua/user/heirline.lua b/.config/nvim/lua/user/heirline.lua new file mode 100644 index 0000000..e3cfb93 --- /dev/null +++ b/.config/nvim/lua/user/heirline.lua @@ -0,0 +1,58 @@ + +local Git = { + condition = conditions.is_git_repo, + + init = function(self) + self.status_dict = vim.b.gitsigns_status_dict + self.has_changes = self.status_dict.added ~= 0 or self.status_dict.removed ~= 0 or self.status_dict.changed ~= 0 + end, + + hl = { fg = "orange" }, + + { -- git branch name + provider = function(self) + return " " .. self.status_dict.head + end, + hl = { bold = true }, + }, + -- You could handle delimiters, icons and counts similar to Diagnostics + { + condition = function(self) + return self.has_changes + end, + provider = "(", + }, + { + provider = function(self) + local count = self.status_dict.added or 0 + return count > 0 and ("+" .. count) + end, + hl = { fg = "git_add" }, + }, + { + provider = function(self) + local count = self.status_dict.removed or 0 + return count > 0 and ("-" .. count) + end, + hl = { fg = "git_del" }, + }, + { + provider = function(self) + local count = self.status_dict.changed or 0 + return count > 0 and ("~" .. count) + end, + hl = { fg = "git_change" }, + }, + { + condition = function(self) + return self.has_changes + end, + provider = ")", + }, +} + +local statusline = { Git } +local winbar = {} +local tabline = {} + +require("heirline").setup(statusline, winbar, tabline) diff --git a/.config/nvim/lua/user/keymaps.lua b/.config/nvim/lua/user/keymaps.lua new file mode 100644 index 0000000..5feb71a --- /dev/null +++ b/.config/nvim/lua/user/keymaps.lua @@ -0,0 +1,59 @@ +local opts = { noremap = true, silent = true } + +local term_opts = { silent = true } + +local keymap = vim.api.nvim_set_keymap + +keymap("", "", "", opts) + +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +--window navigation +keymap("n", "", "h", opts) +keymap("n", "", "j", opts) +keymap("n", "", "k", opts) +keymap("n", "", "l", opts) + +-- Resize with arrows +keymap("n", "", ":resize +2", opts) +keymap("n", "", ":resize -2", opts) +keymap("n", "", ":vertical resize -2", opts) +keymap("n", "", ":vertical resize +2", opts) + +--move text up and down +keymap("v", "", ":m .+1==", opts) +keymap("v", "", ":m .-2==", opts) +keymap("v", "p", '"_dP', opts) + +keymap("v", "<", "", ">gv", opts) + +--center when moving with ctrl-u, ctrl-d +keymap("n", "", "zz", opts) +keymap("n", "", "zz", opts) + +keymap("x", "J", ":move '>+1gv-gv", opts) +keymap("x", "K", ":move '<-2gv-gv", opts) +keymap("x", "", ":move '>+1gv-gv", opts) +keymap("x", "", ":move '<-2gv-gv", opts) + +-- Navigate buffers +keymap("n", "", ":bnext", opts) +keymap("n", "", ":bprevious", opts) + +--Close buffer +keymap("n", "", ":bd | bp ", opts) + +--Format document +keymap("n", "F", ":lua vim.lsp.buf.format() ", opts) + +keymap("n", "ff", + "lua require'telescope.builtin'.find_files(require('telescope.themes').get_dropdown({ previewer = false }))", + opts) +keymap("n", "fw", + "lua require'telescope.builtin'.live_grep()", + opts) + + +keymap("n", "e", ":Neotree toggle ", opts) diff --git a/.config/nvim/lua/user/lsp/handlers.lua b/.config/nvim/lua/user/lsp/handlers.lua new file mode 100644 index 0000000..96efc8c --- /dev/null +++ b/.config/nvim/lua/user/lsp/handlers.lua @@ -0,0 +1,62 @@ +local M = {} + +-- TODO: backfill this to template +M.setup = function() + local signs = { + { name = "DiagnosticSignError", text = "" }, + { name = "DiagnosticSignWarn", text = "" }, + { name = "DiagnosticSignHint", text = "" }, + { name = "DiagnosticSignInfo", text = "" }, + } + + for _, sign in ipairs(signs) do + vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = "" }) + end + + local config = { + -- disable virtual text + -- virtual_text = false, + -- show signs + signs = { + active = signs, + }, + update_in_insert = true, + underline = true, + severity_sort = true, + float = { + focusable = false, + style = "minimal", + border = "rounded", + source = "always", + header = "", + prefix = "", + }, + } + + vim.diagnostic.config(config) + + vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { + border = "rounded", + width = 60, + }) + + vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { + border = "rounded", + width = 60, + }) +end + +-- local function lsp_highlight_document(client) +-- -- Set autocommands conditional on server_capabilities +-- local status_ok, illuminate = pcall(require, "illuminate") +-- if not status_ok then +-- return +-- end +-- illuminate.on_attach(client) +-- end + +-- M.on_attach = function(client, bufnr) +-- lsp_highlight_document(client) +-- end + +return M diff --git a/.config/nvim/lua/user/lsp/init.lua b/.config/nvim/lua/user/lsp/init.lua new file mode 100644 index 0000000..6d81a1c --- /dev/null +++ b/.config/nvim/lua/user/lsp/init.lua @@ -0,0 +1,44 @@ +local status_ok, mason = pcall(require, "mason") +if not status_ok then + return +end + +local status_ok, mason_lspconfig = pcall(require, "mason-lspconfig") +if not status_ok then + return +end + +local status_ok, lspconfig = pcall(require, "lspconfig") +if not status_ok then + return +end + +mason.setup() +mason_lspconfig.setup() + +local opts = { noremap = true, silent = true } + +vim.api.nvim_set_keymap("n", "gD", "lua vim.lsp.buf.declaration()", opts) +vim.api.nvim_set_keymap("n", "gd", "lua vim.lsp.buf.definition()", opts) +vim.api.nvim_set_keymap("n", "K", "lua vim.lsp.buf.hover()", opts) +vim.api.nvim_set_keymap("n", "gi", "lua vim.lsp.buf.implementation()", opts) +vim.api.nvim_set_keymap("n", "", "lua vim.lsp.buf.signature_help()", opts) +vim.api.nvim_set_keymap("n", "grr", "lua vim.lsp.buf.rename()", opts) +vim.api.nvim_set_keymap("n", "gr", "lua vim.lsp.buf.references()", opts) +vim.api.nvim_set_keymap("n", "ca", "lua vim.lsp.buf.code_action()", opts) +-- vim.api.nvim_buf_set_keymap("n", "f", "lua vim.diagnostic.open_float()", opts) +vim.api.nvim_set_keymap("n", "[d", 'lua vim.diagnostic.goto_prev({ border = "rounded" })', opts) +vim.api.nvim_set_keymap( + "n", + "gl", + 'lua vim.diagnostic.open_float({ border = "rounded" })', + opts +) +vim.api.nvim_set_keymap("n", "]d", 'lua vim.diagnostic.goto_next({ border = "rounded" })', opts) +vim.api.nvim_set_keymap("n", "q", "lua vim.diagnostic.setloclist()", opts) + +vim.cmd([[ command! Format execute 'lua vim.lsp.buf.format{async=true}' ]]) + +require("user.lsp.mason_lsp_config") + +require("user.lsp.handlers").setup() diff --git a/.config/nvim/lua/user/lsp/mason_lsp_config.lua b/.config/nvim/lua/user/lsp/mason_lsp_config.lua new file mode 100644 index 0000000..995deea --- /dev/null +++ b/.config/nvim/lua/user/lsp/mason_lsp_config.lua @@ -0,0 +1,52 @@ +local mason_lspconfig = require("mason-lspconfig") + +mason_lspconfig.setup_handlers({ + -- The first entry (without a key) will be the default handler + -- and will be called for each installed server that doesn't have + -- a dedicated handler. + ["omnisharp"] = function() + require("lspconfig")["omnisharp"].setup({ + on_attach = function(client, bufnr) + if client.name == "omnisharp" then + client.server_capabilities.semanticTokensProvider = nil + end + end, + }) + end, + ["pylsp"] = function() + require("lspconfig")["pylsp"].setup({ + settings = { + pylsp = { + plugins = { + pycodestyle = { + ignore = { "E501", "E231", "W503" }, + maxLineLength = 100, + }, + }, + }, + }, + }) + end, + ["rust_analyzer"] = function() + require("lspconfig")["rust_analyzer"].setup({ + settings = { + ["rust-analyzer"] = { + cargo = { + allFeatures = true, + }, + }, + }, + }) + end, + function(server_name) -- default handler (optional) + require("lspconfig")[server_name].setup({}) + end, + -- ["omnisharp"] = function() + -- require("omnisharp").setup({}) + -- end, + -- Next, you can provide a dedicated handler for specific servers. + -- For example, a handler override for the `rust_analyzer`: + -- ["rust_analyzer"] = function() + -- require("rust-tools").setup({}) + -- end, +}) diff --git a/.config/nvim/lua/user/lsp/settings/jsonls.lua b/.config/nvim/lua/user/lsp/settings/jsonls.lua new file mode 100644 index 0000000..8ee9544 --- /dev/null +++ b/.config/nvim/lua/user/lsp/settings/jsonls.lua @@ -0,0 +1,182 @@ +local schemas = { + { + description = "TypeScript compiler configuration file", + fileMatch = { + "tsconfig.json", + "tsconfig.*.json", + }, + url = "https://json.schemastore.org/tsconfig.json", + }, + { + description = "Lerna config", + fileMatch = { "lerna.json" }, + url = "https://json.schemastore.org/lerna.json", + }, + { + description = "Babel configuration", + fileMatch = { + ".babelrc.json", + ".babelrc", + "babel.config.json", + }, + url = "https://json.schemastore.org/babelrc.json", + }, + { + description = "ESLint config", + fileMatch = { + ".eslintrc.json", + ".eslintrc", + }, + url = "https://json.schemastore.org/eslintrc.json", + }, + { + description = "Bucklescript config", + fileMatch = { "bsconfig.json" }, + url = "https://raw.githubusercontent.com/rescript-lang/rescript-compiler/8.2.0/docs/docson/build-schema.json", + }, + { + description = "Prettier config", + fileMatch = { + ".prettierrc", + ".prettierrc.json", + "prettier.config.json", + }, + url = "https://json.schemastore.org/prettierrc", + }, + { + description = "Vercel Now config", + fileMatch = { "now.json" }, + url = "https://json.schemastore.org/now", + }, + { + description = "Stylelint config", + fileMatch = { + ".stylelintrc", + ".stylelintrc.json", + "stylelint.config.json", + }, + url = "https://json.schemastore.org/stylelintrc", + }, + { + description = "A JSON schema for the ASP.NET LaunchSettings.json files", + fileMatch = { "launchsettings.json" }, + url = "https://json.schemastore.org/launchsettings.json", + }, + { + description = "Schema for CMake Presets", + fileMatch = { + "CMakePresets.json", + "CMakeUserPresets.json", + }, + url = "https://raw.githubusercontent.com/Kitware/CMake/master/Help/manual/presets/schema.json", + }, + { + description = "Configuration file as an alternative for configuring your repository in the settings page.", + fileMatch = { + ".codeclimate.json", + }, + url = "https://json.schemastore.org/codeclimate.json", + }, + { + description = "LLVM compilation database", + fileMatch = { + "compile_commands.json", + }, + url = "https://json.schemastore.org/compile-commands.json", + }, + { + description = "Config file for Command Task Runner", + fileMatch = { + "commands.json", + }, + url = "https://json.schemastore.org/commands.json", + }, + { + description = "AWS CloudFormation provides a common language for you to describe and provision all the infrastructure resources in your cloud environment.", + fileMatch = { + "*.cf.json", + "cloudformation.json", + }, + url = "https://raw.githubusercontent.com/awslabs/goformation/v5.2.9/schema/cloudformation.schema.json", + }, + { + description = "The AWS Serverless Application Model (AWS SAM, previously known as Project Flourish) extends AWS CloudFormation to provide a simplified way of defining the Amazon API Gateway APIs, AWS Lambda functions, and Amazon DynamoDB tables needed by your serverless application.", + fileMatch = { + "serverless.template", + "*.sam.json", + "sam.json", + }, + url = "https://raw.githubusercontent.com/awslabs/goformation/v5.2.9/schema/sam.schema.json", + }, + { + description = "Json schema for properties json file for a GitHub Workflow template", + fileMatch = { + ".github/workflow-templates/**.properties.json", + }, + url = "https://json.schemastore.org/github-workflow-template-properties.json", + }, + { + description = "golangci-lint configuration file", + fileMatch = { + ".golangci.toml", + ".golangci.json", + }, + url = "https://json.schemastore.org/golangci-lint.json", + }, + { + description = "JSON schema for the JSON Feed format", + fileMatch = { + "feed.json", + }, + url = "https://json.schemastore.org/feed.json", + versions = { + ["1"] = "https://json.schemastore.org/feed-1.json", + ["1.1"] = "https://json.schemastore.org/feed.json", + }, + }, + { + description = "Packer template JSON configuration", + fileMatch = { + "packer.json", + }, + url = "https://json.schemastore.org/packer.json", + }, + { + description = "NPM configuration file", + fileMatch = { + "package.json", + }, + url = "https://json.schemastore.org/package.json", + }, + { + description = "JSON schema for Visual Studio component configuration files", + fileMatch = { + "*.vsconfig", + }, + url = "https://json.schemastore.org/vsconfig.json", + }, + { + description = "Resume json", + fileMatch = { "resume.json" }, + url = "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json", + }, +} + +local opts = { + settings = { + json = { + schemas = schemas, + }, + }, + setup = { + commands = { + Format = { + function() + vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 }) + end, + }, + }, + }, +} + +return opts diff --git a/.config/nvim/lua/user/lsp/settings/lua_ls.lua b/.config/nvim/lua/user/lsp/settings/lua_ls.lua new file mode 100644 index 0000000..0ac454a --- /dev/null +++ b/.config/nvim/lua/user/lsp/settings/lua_ls.lua @@ -0,0 +1,16 @@ +return { + settings = { + + Lua = { + diagnostics = { + globals = { "vim" }, + }, + workspace = { + library = { + [vim.fn.expand("$VIMRUNTIME/lua")] = true, + [vim.fn.stdpath("config") .. "/lua"] = true, + }, + }, + }, + }, +} diff --git a/.config/nvim/lua/user/lsp/settings/omnisharp.lua b/.config/nvim/lua/user/lsp/settings/omnisharp.lua new file mode 100644 index 0000000..e69de29 diff --git a/.config/nvim/lua/user/lsp/settings/pyright.lua b/.config/nvim/lua/user/lsp/settings/pyright.lua new file mode 100644 index 0000000..49223b0 --- /dev/null +++ b/.config/nvim/lua/user/lsp/settings/pyright.lua @@ -0,0 +1,12 @@ +return { + settings = { + + python = { + analysis = { + typeCheckingMode = "off", + diagnosticMode = "workspace", + autoSearchPaths = true, + }, + }, + }, +} diff --git a/.config/nvim/lua/user/lsp_format.lua b/.config/nvim/lua/user/lsp_format.lua new file mode 100644 index 0000000..c213507 --- /dev/null +++ b/.config/nvim/lua/user/lsp_format.lua @@ -0,0 +1,7 @@ +require("lsp-format").setup {} + +local on_attach = function(client) + require "lsp-format".on_attach(client) +end + +require "lspconfig".gopls.setup { on_attach = on_attach } diff --git a/.config/nvim/lua/user/lualine.lua b/.config/nvim/lua/user/lualine.lua new file mode 100644 index 0000000..bbe6cf9 --- /dev/null +++ b/.config/nvim/lua/user/lualine.lua @@ -0,0 +1,40 @@ +require('lualine').setup { + options = { + icons_enabled = true, + theme = 'kanagawa', + component_separators = { left = '', right = ''}, + section_separators = { left = '', right = ''}, + disabled_filetypes = { + statusline = {}, + winbar = {}, + }, + ignore_focus = {}, + always_divide_middle = true, + globalstatus = true, + refresh = { + statusline = 1000, + tabline = 1000, + winbar = 1000, + } + }, + sections = { + lualine_a = {'mode'}, + lualine_b = {'branch', 'diff', 'diagnostics'}, + lualine_c = {'filename'}, + lualine_x = {'encoding', 'fileformat', 'filetype'}, + lualine_y = {'progress'}, + lualine_z = {'location'} + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {} + }, + tabline = {}, + winbar = {}, + inactive_winbar = {}, + extensions = {} +} diff --git a/.config/nvim/lua/user/neotree.lua b/.config/nvim/lua/user/neotree.lua new file mode 100644 index 0000000..ad81d8f --- /dev/null +++ b/.config/nvim/lua/user/neotree.lua @@ -0,0 +1,73 @@ +-- vim.fn.sign_define("DiagnosticSignError", { text = " ", texthl = "DiagnosticSignError" }) +-- vim.fn.sign_define("DiagnosticSignWarn", { text = " ", texthl = "DiagnosticSignWarn" }) +-- vim.fn.sign_define("DiagnosticSignInfo", { text = " ", texthl = "DiagnosticSignInfo" }) +-- vim.fn.sign_define("DiagnosticSignHint", { text = "", texthl = "DiagnosticSignHint" }) + +require("neo-tree").setup({ + enable_diagnostics = false, + enable_git_status = true, + default_component_configs = { + icon = { + folder_empty = "󰜌", + folder_empty_open = "󰜌", + }, + git_status = { + symbols = { + -- Change type + added = "", -- or "✚", but this is redundant info if you use git_status_colors on the name + modified = "", -- or "", but this is redundant info if you use git_status_colors on the name + deleted = "✖", -- this can only be used in the git_status source + renamed = "", -- this can only be used in the git_status source + -- Status type + untracked = "", + ignored = "", + unstaged = "", + staged = "", + conflict = "", + }, + }, + }, + document_symbols = { + kinds = { + File = { icon = "󰈙", hl = "Tag" }, + Namespace = { icon = "󰌗", hl = "Include" }, + Package = { icon = "󰏖", hl = "Label" }, + Class = { icon = "󰌗", hl = "Include" }, + Property = { icon = "󰆧", hl = "@property" }, + Enum = { icon = "󰒻", hl = "@number" }, + Function = { icon = "󰊕", hl = "Function" }, + String = { icon = "󰀬", hl = "String" }, + Number = { icon = "󰎠", hl = "Number" }, + Array = { icon = "󰅪", hl = "Type" }, + Object = { icon = "󰅩", hl = "Type" }, + Key = { icon = "󰌋", hl = "" }, + Struct = { icon = "󰌗", hl = "Type" }, + Operator = { icon = "󰆕", hl = "Operator" }, + TypeParameter = { icon = "󰊄", hl = "Type" }, + StaticMethod = { icon = "󰠄 ", hl = "Function" }, + }, + }, + git_status = { + symbols = { + -- Change type + added = "", -- or "✚", but this is redundant info if you use git_status_colors on the name + modified = "", -- or "", but this is redundant info if you use git_status_colors on the name + deleted = "✖", -- this can only be used in the git_status source + renamed = "", -- this can only be used in the git_status source + -- Status type + untracked = "", + ignored = "", + unstaged = "", + staged = "", + conflict = "", + }, + }, + -- Add this section only if you've configured source selector. + source_selector = { + sources = { + { source = "filesystem", display_name = " 󰉓 Files " }, + { source = "git_status", display_name = " 󰊢 Git " }, + }, + }, + -- Other options ... +}) diff --git a/.config/nvim/lua/user/null_ls.lua b/.config/nvim/lua/user/null_ls.lua new file mode 100644 index 0000000..a02197d --- /dev/null +++ b/.config/nvim/lua/user/null_ls.lua @@ -0,0 +1,20 @@ +local null_ls_status_ok, null_ls = pcall(require, "null-ls") +if not null_ls_status_ok then + return +end + +-- https://github.com/jose-elias-alvarez/null-ls.nvim/tree/main/lua/null-ls/builtins/formatting +local formatting = null_ls.builtins.formatting +-- https://github.com/jose-elias-alvarez/null-ls.nvim/tree/main/lua/null-ls/builtins/diagnostics +local diagnostics = null_ls.builtins.diagnostics + +null_ls.setup({ + debug = false, + sources = { + formatting.prettier.with({ extra_args = { "--no-semi", "--single-quote", "--jsx-single-quote" } }), + formatting.black.with({ extra_args = { "--fast" } }), + formatting.isort, + formatting.stylua, + -- diagnostics.flake8 + }, +}) diff --git a/.config/nvim/lua/user/nvim_scrollbar.lua b/.config/nvim/lua/user/nvim_scrollbar.lua new file mode 100644 index 0000000..534039b --- /dev/null +++ b/.config/nvim/lua/user/nvim_scrollbar.lua @@ -0,0 +1,6 @@ +local null_ls_status_ok, null_ls = pcall(require, "scrollbar") +if not null_ls_status_ok then + return +end + +null_ls.setup() diff --git a/.config/nvim/lua/user/nvim_tree.lua b/.config/nvim/lua/user/nvim_tree.lua new file mode 100644 index 0000000..636ac18 --- /dev/null +++ b/.config/nvim/lua/user/nvim_tree.lua @@ -0,0 +1,24 @@ +-- examples for your init.lua + +-- empty setup using defaults + +-- OR setup with some options +require("nvim-tree").setup({ + sort_by = "case_sensitive", + view = { + adaptive_size = false, + width = 22, + height = 22, + mappings = { + list = { + { key = "u", action = "dir_up" }, + }, + }, + }, + renderer = { + group_empty = true, + }, + filters = { + dotfiles = true, + }, +}) diff --git a/.config/nvim/lua/user/onedark_config.lua b/.config/nvim/lua/user/onedark_config.lua new file mode 100644 index 0000000..b88bd53 --- /dev/null +++ b/.config/nvim/lua/user/onedark_config.lua @@ -0,0 +1,8 @@ +require("onedark").setup({ + style = "darker", + transparent = true, + highlights = { + NvimTreeWinSeparator = {fg ='#aaaaa'} + } +}) +require("onedark").load() diff --git a/.config/nvim/lua/user/options.lua b/.config/nvim/lua/user/options.lua new file mode 100644 index 0000000..b4fda6b --- /dev/null +++ b/.config/nvim/lua/user/options.lua @@ -0,0 +1,25 @@ +vim.opt.backup = false +vim.opt.cmdheight = 1 +vim.opt.completeopt = { "menuone", "noselect" } +vim.opt.fileencoding = "utf-8" +vim.opt.ignorecase = true +vim.opt.showtabline = 2 +vim.opt.smartindent = true +vim.opt.smartcase = true +vim.opt.splitright = true +vim.opt.number = true +vim.opt.relativenumber = true +vim.opt.termguicolors = true +vim.opt.tabstop = 2 +vim.opt.shiftwidth = 2 +vim.opt.updatetime = 300 +vim.opt.ttimeoutlen = 5 + +vim.api.nvim_create_autocmd("FileType", { + pattern = "cs", + command = "setlocal shiftwidth=4 tabstop=4" +}) + +vim.cmd "au VimEnter * silent! !xmodmap -e 'clear Lock' -e 'keycode 0x42 = Escape'" +vim.cmd "au VimLeave * silent! !xmodmap -e 'clear Lock' -e 'keycode 0x42 = Caps_Lock'" +vim.cmd [[autocmd BufWritePre lua vim.lsp.buf.format()]] diff --git a/.config/nvim/lua/user/plugins.lua b/.config/nvim/lua/user/plugins.lua new file mode 100644 index 0000000..05bc5f3 --- /dev/null +++ b/.config/nvim/lua/user/plugins.lua @@ -0,0 +1,140 @@ +local fn = vim.fn + +-- Automatically install packer +local install_path = fn.stdpath("data") .. "/site/pack/packer/start/packer.nvim" +if fn.empty(fn.glob(install_path)) > 0 then + PACKER_BOOTSTRAP = fn.system({ + "git", + "clone", + "--depth", + "1", + "https://github.com/wbthomason/packer.nvim", + install_path, + }) + print("Installing packer close and reopen Neovim...") + vim.cmd([[packadd packer.nvim]]) +end + +-- Autocommand that reloads neovim whenever you save the plugins.lua file +vim.cmd([[ + augroup packer_user_config + autocmd! + autocmd BufWritePost plugins.lua source | PackerSync + augroup end +]]) + +-- Use a protected call so we don't error out on first use +local status_ok, packer = pcall(require, "packer") +if not status_ok then + return +end + +-- Have packer use a popup window +packer.init({ + display = { + open_fn = function() + return require("packer.util").float({ border = "rounded" }) + end, + }, +}) + +-- Install your plugins here +return packer.startup(function(use) + -- My plugins here + use("wbthomason/packer.nvim") -- Have packer manage itself + use("nvim-lua/popup.nvim") -- An implementation of the Popup API from vim in Neovim + use("nvim-lua/plenary.nvim") -- Useful lua functions used ny lots of plugins + --colorschemes + use("navarasu/onedark.nvim") + use("morhetz/gruvbox") + use("Mofiqul/dracula.nvim") + use("folke/tokyonight.nvim") + -- use("lunarvim/colorschemes") + + use("windwp/nvim-autopairs") + + use("hrsh7th/nvim-cmp") -- The completion plugin + use("hrsh7th/cmp-buffer") -- buffer completions + use("hrsh7th/cmp-path") -- path completions + use("hrsh7th/cmp-cmdline") -- cmdline completions + use("saadparwaiz1/cmp_luasnip") -- snippet completions + use("hrsh7th/cmp-nvim-lsp") + + -- snippets + use("L3MON4D3/LuaSnip") --snippet engine + use("rafamadriz/friendly-snippets") -- a bunch of snippets to use + use({ "dsznajder/vscode-es7-javascript-react-snippets", run = "yarn install --frozen-lockfile && yarn compile" }) + + -- LSP + use("williamboman/mason.nvim") -- simple to use language server installer + use("williamboman/mason-lspconfig.nvim") + use("neovim/nvim-lspconfig") -- enable LSP + -- use("williamboman/nvim-lsp-installer") -- simple to use language server installer + use("nvim-treesitter/nvim-treesitter-refactor") + + -- file explorer + vim.cmd([[ let g:neo_tree_remove_legacy_commands = 1 ]]) + use { + "nvim-neo-tree/neo-tree.nvim", + branch = "v2.x", + requires = { + "nvim-lua/plenary.nvim", + "nvim-tree/nvim-web-devicons", -- not strictly required, but recommended + "MunifTanjim/nui.nvim", + } + } + + use({ + "kyazdani42/nvim-tree.lua", + requires = { + "kyazdani42/nvim-web-devicons", -- optional, for file icons + }, + tag = "nightly", -- optional, updated every week. (see issue #1193) + }) + + use({ "akinsho/bufferline.nvim", tag = "v2.*", requires = "kyazdani42/nvim-web-devicons" }) + + use({ + "nvim-treesitter/nvim-treesitter", + run = ":TSUpdate", + }) + + use({ + "nvimtools/none-ls.nvim", + }) + + use("lukas-reineke/lsp-format.nvim") + use("Vimjas/vim-python-pep8-indent") + + --telescope + use("nvim-telescope/telescope.nvim") + use("nvim-telescope/telescope-media-files.nvim") + + --comment out + use("tpope/vim-commentary") + use("lukas-reineke/indent-blankline.nvim") + use("windwp/nvim-ts-autotag") + + use("sickill/vim-monokai") + use("rebelot/kanagawa.nvim") + + --scrollbar + use("petertriho/nvim-scrollbar") + + --heirline statusbar + use("rebelot/heirline.nvim") + + --heirline statusbar + use("lewis6991/gitsigns.nvim") + + --debugging + use("mfussenegger/nvim-dap") + use("rcarriga/nvim-dap-ui") + + use("nvim-lualine/lualine.nvim") + -- Automatically set up your configuration after cloning packer.nvim + -- Put this at the end after all plugins + if PACKER_BOOTSTRAP then + require("packer").sync() + end +end) diff --git a/.config/nvim/lua/user/telescope.lua b/.config/nvim/lua/user/telescope.lua new file mode 100644 index 0000000..e13b658 --- /dev/null +++ b/.config/nvim/lua/user/telescope.lua @@ -0,0 +1,104 @@ +local status_ok, telescope = pcall(require, "telescope") +if not status_ok then + return +end + +telescope.load_extension('media_files') + +local actions = require "telescope.actions" + +telescope.setup { + defaults = { + file_ignore_patterns = { "node_modules", "venv" }, + prompt_prefix = " ", + selection_caret = " ", + path_display = { "smart" }, + + mappings = { + i = { + [""] = actions.cycle_history_next, + [""] = actions.cycle_history_prev, + + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + + [""] = actions.close, + + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + + [""] = actions.select_default, + [""] = actions.select_horizontal, + [""] = actions.select_vertical, + [""] = actions.select_tab, + + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_down, + + [""] = actions.results_scrolling_up, + [""] = actions.results_scrolling_down, + + [""] = actions.toggle_selection + actions.move_selection_worse, + [""] = actions.toggle_selection + actions.move_selection_better, + [""] = actions.send_to_qflist + actions.open_qflist, + [""] = actions.send_selected_to_qflist + actions.open_qflist, + [""] = actions.complete_tag, + [""] = actions.which_key, -- keys from pressing + }, + + n = { + [""] = actions.close, + [""] = actions.select_default, + [""] = actions.select_horizontal, + [""] = actions.select_vertical, + [""] = actions.select_tab, + + [""] = actions.toggle_selection + actions.move_selection_worse, + [""] = actions.toggle_selection + actions.move_selection_better, + [""] = actions.send_to_qflist + actions.open_qflist, + [""] = actions.send_selected_to_qflist + actions.open_qflist, + + ["j"] = actions.move_selection_next, + ["k"] = actions.move_selection_previous, + ["H"] = actions.move_to_top, + ["M"] = actions.move_to_middle, + ["L"] = actions.move_to_bottom, + + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + ["gg"] = actions.move_to_top, + ["G"] = actions.move_to_bottom, + + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_down, + + [""] = actions.results_scrolling_up, + [""] = actions.results_scrolling_down, + + ["?"] = actions.which_key, + }, + }, + }, + pickers = { + -- Default configuration for builtin pickers goes here: + -- picker_name = { + -- picker_config_key = value, + -- ... + -- } + -- Now the picker_config_key will be applied every time you call this + -- builtin picker + }, + extensions = { + media_files = { + -- filetypes whitelist + -- defaults to {"png", "jpg", "mp4", "webm", "pdf"} + filetypes = { "png", "webp", "jpg", "jpeg" }, + find_cmd = "rg" -- find command (defaults to `fd`) + } + -- Your extension configuration goes here: + -- extension_name = { + -- extension_config_key = value, + -- } + -- please take a look at the readme of the extension you want to configure + }, +} diff --git a/.config/nvim/lua/user/themes/kanagawa.lua b/.config/nvim/lua/user/themes/kanagawa.lua new file mode 100644 index 0000000..809becb --- /dev/null +++ b/.config/nvim/lua/user/themes/kanagawa.lua @@ -0,0 +1,24 @@ +require("kanagawa").setup({ + compile = false, -- enable compiling the colorscheme + undercurl = true, -- enable undercurls + commentStyle = { italic = true }, + functionStyle = {}, + keywordStyle = { italic = true }, + statementStyle = { bold = true }, + typeStyle = {}, + transparent = true, -- do not set background color + dimInactive = false, -- dim inactive window `:h hl-NormalNC` + terminalColors = true, -- define vim.g.terminal_color_{0,17} + colors = { + -- add/modify theme and palette colors + palette = {}, + theme = { wave = {}, lotus = {}, dragon = {}, all = {} }, + }, + overrides = function(colors) -- add/modify highlights + return {} + end, + theme = "wave", -- Load "wave" theme when 'background' option is not set + background = { -- map the value of 'background' option to a theme + dark = "wave", -- try "dragon" ! + }, +}) diff --git a/.config/nvim/lua/user/treesitter.lua b/.config/nvim/lua/user/treesitter.lua new file mode 100644 index 0000000..3edaf1b --- /dev/null +++ b/.config/nvim/lua/user/treesitter.lua @@ -0,0 +1,34 @@ +local status_ok, configs = pcall(require, "nvim-treesitter.configs") +if not status_ok then + return +end + +configs.setup({ + ensure_installed = {"python", "rust", "javascript"}, -- one of "all" or a list of languages + ignore_install = { "phpdoc", "comment", "rst" }, -- List of parsers to ignore installing + highlight = { + additional_vim_regex_highlighting = false, + enable = true, -- false will disable the whole extension + disable = { "css" }, -- list of language that will be disabled + }, + autopairs = { + enable = true, + }, + indent = { enable = true, disable = { "python", "css" } }, + autotag = { + enable = true, + }, + refactor = { + highlight_definitions = { + enable = false, + -- Set to false if you have an `updatetime` of ~100. + clear_on_cursor_move = true, + }, + smart_rename = { + enable = false, + keymaps = { + smart_rename = "grr", + }, + }, + }, +}) diff --git a/.config/waybar/config b/.config/waybar/config new file mode 100644 index 0000000..c7fe829 --- /dev/null +++ b/.config/waybar/config @@ -0,0 +1,182 @@ +{ + "layer": "top", // Waybar at top layer + "position": "bottom", // Waybar position (top|bottom|left|right) + "margin-bottom": 0, + "margin-left": 0, + "margin-right": 0, + "height": 10, // Waybar height (to be removed for auto height) + // "width": 1280, // Waybar width + "spacing": 10, // Gaps between modules (4px) + // Choose the order of the modules + "modules-left": [ + "hyprland/workspaces", + ], + "modules-center": ["mpd"], + "modules-right": [ + "hyprland/language", + "pulseaudio", + "cpu", + "memory", + "custom/weather", + "clock", + ], + "hyprland/language": { + "format": "{}", + "format-en": "en", + "format-ru": "ru", + "keyboard-name": "keychron-keychron-q1-keyboard" +}, + // Modules configuration + "custom/weather": { + "exec": "$HOME/.config/waybar/weather-plugin.sh", + "interval": 600, + "signal": "8", + }, + "hyprland/workspaces": { + "format": "{name}", + "tooltip": false, + "on-click": "activate", + "sort-by-number": true, + "all-outputs": true, + "disable-scroll": true, + "show-special": true, + "format-icons": { + "active": "", + "default": "" + } + }, + "keyboard-state": { + "numlock": true, + "capslock": true, + "format": "{name} {icon}", + "format-icons": { + "locked": "", + "unlocked": "" + } + }, + "mpd": { + "on-click": "mpc toggle", + "tooltip": false, + "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {title}", + "format-disconnected": "Disconnected ", + "format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ", + "unknown-tag": "N/A", + "interval": 2, + "consume-icons": { + "on": " " + }, + "random-icons": { + "off": " ", + "on": " " + }, + "repeat-icons": { + "on": " " + }, + "single-icons": { + "on": "1 " + }, + "state-icons": { + "paused": "", + "playing": "" + }, + "max-length": 40, + "tooltip-format": "MPD (connected)", + "tooltip-format-disconnected": "MPD (disconnected)", + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "", + "deactivated": "" + } + }, + "tray": { + // "icon-size": 21, + "spacing": 10 + }, + "clock": { + // "timezone": "America/New_York", + "format": "{:%a, %b %d %H:%M}", + "tooltip-format": "{:%Y %B}\n{calendar}", + "format-alt": "{:%Y-%m-%d}" + }, + "cpu": { + "format": "{usage}% ", + "tooltip": false + }, + "memory": { + "format": "{}% " + }, + "temperature": { + // "thermal-zone": 2, + // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input", + "critical-threshold": 80, + // "format-critical": "{temperatureC}°C {icon}", + "format": "{temperatureC}°C {icon}", + "format-icons": ["", "", ""] + }, + "backlight": { + // "device": "acpi_video1", + "format": "{percent}% {icon}", + "format-icons": ["", "", "", "", "", "", "", "", ""] + }, + "battery": { + "states": { + // "good": 95, + "warning": 30, + "critical": 15 + }, + "format": "{capacity}% {icon}", + "format-charging": "{capacity}% ", + "format-plugged": "{capacity}% ", + "format-alt": "{time} {icon}", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": ["", "", "", "", ""] + }, + "battery#bat2": { + "bat": "BAT2" + }, + "network": { + // "interface": "wlp2*", // (Optional) To force the use of this interface + "format-wifi": "{essid} ({signalStrength}%) ", + "format-ethernet": "{ipaddr}/{cidr} ", + "tooltip-format": "{ifname} via {gwaddr} ", + "format-linked": "{ifname} (No IP) ", + "format-disconnected": "Disconnected ⚠", + "format-alt": "{ifname}: {ipaddr}/{cidr}" + }, + "pulseaudio": { + "tooltip": false, + // "scroll-step": 1, // %, can be a float + //"format": "{volume}% {icon} {format_source}", + "format": "{volume}% {icon}", + "format-bluetooth": "{volume}% {icon} {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": "󰟎", + "format-source": "{volume}% ", + "format-source-muted": "", + "format-icons": { + "headphone": "󰋋", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pavucontrol" + }, + "custom/media": { + "format": "{icon} {}", + "return-type": "json", + "max-length": 40, + "format-icons": { + "spotify": "", + "default": "🎜" + }, + "escape": true, + "exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null" // Script in resources folder + // "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name + } +} diff --git a/.config/waybar/style.css b/.config/waybar/style.css new file mode 100644 index 0000000..a3e3d28 --- /dev/null +++ b/.config/waybar/style.css @@ -0,0 +1,48 @@ +*, body{ + margin: 0; + padding: 0; + border: none; + border-radius: 0; + font-family: 'Input Mono', 'Symbols Nerd Font Mono'; + font-size: 13px; + min-height: 1.5em; +} + +window#waybar { + background: rgba(0, 0, 0, 0.87); + margin: 0; +} + + +#workspaces button { + margin: 0; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; + border-bottom: 2px solid #05a4c4; + border-radius: 0; +} + +#workspaces button.active { + border-bottom: 2px solid white; + border-radius: 0; +} + +#clock, +#backlight, +#pulseaudio, +#bluetooth, +#network, +#battery, +#mpd, +#cpu, +#memory, +#custom-weather, +#language { + border-bottom: 2px solid #05a4c4; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} diff --git a/.config/waybar/weather-plugin.sh b/.config/waybar/weather-plugin.sh new file mode 100755 index 0000000..ade97b1 --- /dev/null +++ b/.config/waybar/weather-plugin.sh @@ -0,0 +1,288 @@ +#!/bin/bash + +# SETTINGS vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +# API settings ________________________________________________________________ + +APIKEY=`cat $HOME/.owm-key` +CITY_NAME='Tyumen' +COUNTRY_CODE='RUS' +# Desired output language +LANG="en" +# UNITS can be "metric", "imperial" or "kelvin". Set KNOTS to "yes" if you +# want the wind in knots: + +# | temperature | wind +# ----------------------------------- +# metric | Celsius | km/h +# imperial | Fahrenheit | miles/hour +# kelvin | Kelvin | km/h + +UNITS="metric" + +# Color Settings ______________________________________________________________ + +COLOR_CLOUD="#606060" +COLOR_THUNDER="#d3b987" +COLOR_LIGHT_RAIN="#73cef4" +COLOR_HEAVY_RAIN="#b3deef" +COLOR_SNOW="#FFFFFF" +COLOR_FOG="#606060" +COLOR_TORNADO="#d3b987" +COLOR_SUN="#ffc24b" +COLOR_MOON="#FFFFFF" +COLOR_ERR="#f43753" +COLOR_WIND="#73cef4" +COLOR_COLD="#b3deef" +COLOR_HOT="#f43753" +COLOR_NORMAL_TEMP="#FFFFFF" + +# Leave "" if you want the default polybar color +COLOR_TEXT="" +# Polybar settings ____________________________________________________________ + +# Font for the weather icons +WEATHER_FONT_CODE=4 + +# Font for the thermometer icon +TEMP_FONT_CODE=2 + +# Wind settings _______________________________________________________________ + +# Display info about the wind or not. yes/no +DISPLAY_WIND="yes" + +# Display in knots. yes/no +KNOTS="no" + +# How many decimals after the floating point +DECIMALS=0 + +# Min. wind force required to display wind info (it depends on what +# measurement unit you have set: knots, m/s or mph). Set to 0 if you always +# want to display wind info. It's ignored if DISPLAY_WIND is false. + +MIN_WIND=0 + +# Display the numeric wind force or not. If not, only the wind icon will +# appear. yes/no + +DISPLAY_FORCE="yes" + +# Display the wind unit if wind force is displayed. yes/no +DISPLAY_WIND_UNIT="yes" + +# Thermometer settings ________________________________________________________ + +# When the thermometer icon turns red +HOT_TEMP=25 + +# When the thermometer icon turns blue +COLD_TEMP=0 + +# Other settings ______________________________________________________________ + +# Display the weather description. yes/no +DISPLAY_LABEL="yes" + +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +if [ "$COLOR_TEXT" != "" ]; then + COLOR_TEXT_BEGIN="%{F$COLOR_TEXT}" + COLOR_TEXT_END="%{F-}" +fi + +RESPONSE="" +ERROR=0 +ERR_MSG="" +if [ $UNITS = "kelvin" ]; then + UNIT_URL="" +else + UNIT_URL="&units=$UNITS" +fi +URL="api.openweathermap.org/data/2.5/weather?appid=$APIKEY$UNIT_URL&lang=$LANG&q=$CITY_NAME,$COUNTRY_CODE" + +function getData { + ERROR=0 + # For logging purposes + # echo " " >> "$HOME/.weather.log" + # echo `date`" ################################" >> "$HOME/.weather.log" + RESPONSE=`curl -s $URL` + if [ "$1" = "-d" ]; then + echo $RESPONSE + echo "" + fi + CODE="$?" + # echo "Response: $RESPONSE" >> "$HOME/.weather.log" + RESPONSECODE=0 + if [ $CODE -eq 0 ]; then + RESPONSECODE=`echo $RESPONSE | jq .cod` + fi + if [ $CODE -ne 0 ] || [ $RESPONSECODE -ne 200 ]; then + if [ $CODE -ne 0 ]; then + ERR_MSG="curl Error $CODE" + # echo "curl Error $CODE" >> "$HOME/.weather.log" + else + ERR_MSG="Conn. Err. $RESPONSECODE" + # echo "API Error $RESPONSECODE" >> "$HOME/.weather.log" + fi + ERROR=1 + # else + # echo "$RESPONSE" > "$HOME/.weather-last" + # echo `date +%s` >> "$HOME/.weather-last" + fi +} +function setIcons { + if [ $WID -le 232 ]; then + #Thunderstorm + ICON_COLOR=$COLOR_THUNDER + if [ $DATE -ge $SUNRISE -a $DATE -le $SUNSET ]; then + ICON="" + else + ICON="" + fi + elif [ $WID -le 311 ]; then + #Light drizzle + ICON_COLOR=$COLOR_LIGHT_RAIN + if [ $DATE -ge $SUNRISE -a $DATE -le $SUNSET ]; then + ICON="" + else + ICON="" + fi + elif [ $WID -le 321 ]; then + #Heavy drizzle + ICON_COLOR=$COLOR_HEAVY_RAIN + if [ $DATE -ge $SUNRISE -a $DATE -le $SUNSET ]; then + ICON="" + else + ICON="" + fi + elif [ $WID -le 531 ]; then + #Rain + ICON_COLOR=$COLOR_HEAVY_RAIN + if [ $DATE -ge $SUNRISE -a $DATE -le $SUNSET ]; then + ICON="" + else + ICON="" + fi + elif [ $WID -le 622 ]; then + #Snow + ICON_COLOR=$COLOR_SNOW + ICON="" + elif [ $WID -le 771 ]; then + #Fog + ICON_COLOR=$COLOR_FOG + ICON="" + elif [ $WID -eq 781 ]; then + #Tornado + ICON_COLOR=$COLOR_TORNADO + ICON="" + elif [ $WID -eq 800 ]; then + #Clear sky + if [ $DATE -ge $SUNRISE -a $DATE -le $SUNSET ]; then + ICON_COLOR=$COLOR_SUN + ICON="" + else + ICON_COLOR=$COLOR_MOON + ICON="" + fi + elif [ $WID -eq 801 ]; then + # Few clouds + if [ $DATE -ge $SUNRISE -a $DATE -le $SUNSET ]; then + ICON_COLOR=$COLOR_SUN + ICON="" + else + ICON_COLOR=$COLOR_MOON + ICON="" + fi + elif [ $WID -le 804 ]; then + # Overcast + ICON_COLOR=$COLOR_CLOUD + ICON="" + else + ICON_COLOR=$COLOR_ERR + ICON="" + fi + WIND="" + WINDFORCE=`echo "$RESPONSE" | jq .wind.speed` + if [ $KNOTS = "yes" ]; then + case $UNITS in + "imperial") + # The division by one is necessary because scale works only for divisions. bc is stupid. + WINDFORCE=`echo "scale=$DECIMALS;$WINDFORCE * 0.8689762419 / 1" | bc` + ;; + *) + WINDFORCE=`echo "scale=$DECIMALS;$WINDFORCE * 1.943844 / 1" | bc` + ;; + esac + else + if [ $UNITS != "imperial" ]; then + # Conversion from m/s to km/h + WINDFORCE=`echo "scale=$DECIMALS;$WINDFORCE * 3.6 / 1" | bc` + else + WINDFORCE=`echo "scale=$DECIMALS;$WINDFORCE / 1" | bc` + fi + fi + if [ "$DISPLAY_WIND" = "yes" ] && [ `echo "$WINDFORCE >= $MIN_WIND" |bc -l` -eq 1 ]; then + WIND="" + if [ $DISPLAY_FORCE = "yes" ]; then + WIND="$WIND $COLOR_TEXT_BEGIN$WINDFORCE$COLOR_TEXT_END" + if [ $DISPLAY_WIND_UNIT = "yes" ]; then + if [ $KNOTS = "yes" ]; then + WIND="$WIND ${COLOR_TEXT_BEGIN}kn$COLOR_TEXT_END" + elif [ $UNITS = "imperial" ]; then + WIND="$WIND ${COLOR_TEXT_BEGIN}mph$COLOR_TEXT_END" + else + WIND="$WIND ${COLOR_TEXT_BEGIN}km/h$COLOR_TEXT_END" + fi + fi + fi + WIND="$WIND |" + fi + if [ "$UNITS" = "metric" ]; then + TEMP_ICON="糖" + elif [ "$UNITS" = "imperial" ]; then + TEMP_ICON="宅" + else + TEMP_ICON="洞" + fi + + TEMP=`echo "$TEMP" | cut -d "." -f 1` + + if [ "$TEMP" -le $COLD_TEMP ]; then + TEMP=" $COLOR_TEXT_BEGIN$TEMP$TEMP_ICON$COLOR_TEXT_END" + elif [ `echo "$TEMP >= $HOT_TEMP" | bc` -eq 1 ]; then + TEMP=" $COLOR_TEXT_BEGIN$TEMP$TEMP_ICON$COLOR_TEXT_END" + else + TEMP=" $COLOR_TEXT_BEGIN$TEMP$TEMP_ICON$COLOR_TEXT_END" + fi +} + +function outputCompact { + OUTPUT="$WIND $ICON $ERR_MSG$COLOR_TEXT_BEGIN$DESCRIPTION$COLOR_TEXT_END| $TEMP" + # echo "Output: $OUTPUT" >> "$HOME/.weather.log" + echo "$OUTPUT" +} + +getData $1 +if [ $ERROR -eq 0 ]; then + MAIN=`echo $RESPONSE | jq .weather[0].main` + WID=`echo $RESPONSE | jq .weather[0].id` + DESC=`echo $RESPONSE | jq .weather[0].description` + SUNRISE=`echo $RESPONSE | jq .sys.sunrise` + SUNSET=`echo $RESPONSE | jq .sys.sunset` + DATE=`date +%s` + WIND="" + TEMP=`echo $RESPONSE | jq .main.temp` + if [ $DISPLAY_LABEL = "yes" ]; then + DESCRIPTION=`echo "$RESPONSE" | jq .weather[0].description | tr -d '"' | sed 's/.*/\L&/; s/[a-z]*/\u&/g'`" " + else + DESCRIPTION="" + fi + PRESSURE=`echo $RESPONSE | jq .main.pressure` + HUMIDITY=`echo $RESPONSE | jq .main.humidity` + setIcons + outputCompact +else + echo " " +fi diff --git a/.zshrc b/.zshrc new file mode 100644 index 0000000..11f0381 --- /dev/null +++ b/.zshrc @@ -0,0 +1,109 @@ +# If you come from bash you might have to change your $PATH. +# export PATH=$HOME/bin:/usr/local/bin:$PATH + +# Path to your oh-my-zsh installation. +export ZSH="$HOME/.oh-my-zsh" + +# Set name of the theme to load --- if set to "random", it will +# load a random theme each time oh-my-zsh is loaded, in which case, +# to know which specific one was loaded, run: echo $RANDOM_THEME +# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes +ZSH_THEME="simple" + +# Set list of themes to pick from when loading at random +# Setting this variable when ZSH_THEME=random will cause zsh to load +# a theme from this variable instead of looking in $ZSH/themes/ +# If set to an empty array, this variable will have no effect. +# ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" ) + +# Uncomment the following line to use case-sensitive completion. +# CASE_SENSITIVE="true" + +# Uncomment the following line to use hyphen-insensitive completion. +# Case-sensitive completion must be off. _ and - will be interchangeable. +# HYPHEN_INSENSITIVE="true" + +# Uncomment one of the following lines to change the auto-update behavior +# zstyle ':omz:update' mode disabled # disable automatic updates +# zstyle ':omz:update' mode auto # update automatically without asking +# zstyle ':omz:update' mode reminder # just remind me to update when it's time + +# Uncomment the following line to change how often to auto-update (in days). +# zstyle ':omz:update' frequency 13 + +# Uncomment the following line if pasting URLs and other text is messed up. +# DISABLE_MAGIC_FUNCTIONS="true" + +# Uncomment the following line to disable colors in ls. +# DISABLE_LS_COLORS="true" + +# Uncomment the following line to disable auto-setting terminal title. +# DISABLE_AUTO_TITLE="true" + +# Uncomment the following line to enable command auto-correction. +# ENABLE_CORRECTION="true" + +# Uncomment the following line to display red dots whilst waiting for completion. +# You can also set it to another string to have that shown instead of the default red dots. +# e.g. COMPLETION_WAITING_DOTS="%F{yellow}waiting...%f" +# Caution: this setting can cause issues with multiline prompts in zsh < 5.7.1 (see #5765) +# COMPLETION_WAITING_DOTS="true" + +# Uncomment the following line if you want to disable marking untracked files +# under VCS as dirty. This makes repository status check for large repositories +# much, much faster. +# DISABLE_UNTRACKED_FILES_DIRTY="true" + +# Uncomment the following line if you want to change the command execution time +# stamp shown in the history command output. +# You can set one of the optional three formats: +# "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd" +# or set a custom format using the strftime function format specifications, +# see 'man strftime' for details. +# HIST_STAMPS="mm/dd/yyyy" + +# Would you like to use another custom folder than $ZSH/custom? +# ZSH_CUSTOM=/path/to/new-custom-folder + +# Which plugins would you like to load? +# Standard plugins can be found in $ZSH/plugins/ +# Custom plugins may be added to $ZSH_CUSTOM/plugins/ +# Example format: plugins=(rails git textmate ruby lighthouse) +# Add wisely, as too many plugins slow down shell startup. +plugins=(git zsh-autosuggestions jsontools vi-mode zsh-syntax-highlighting sudo) + +source $ZSH/oh-my-zsh.sh + +# User configuration + +# export MANPATH="/usr/local/man:$MANPATH" + +# You may need to manually set your language environment +# export LANG=en_US.UTF-8 + +# Preferred editor for local and remote sessions +# if [[ -n $SSH_CONNECTION ]]; then +# export EDITOR='vim' +# else +# export EDITOR='mvim' +# fi + +# Compilation flags +# export ARCHFLAGS="-arch x86_64" + +# Set personal aliases, overriding those provided by oh-my-zsh libs, +# plugins, and themes. Aliases can be placed here, though oh-my-zsh +# users are encouraged to define aliases within the ZSH_CUSTOM folder. +# For a full list of active aliases, run `alias`. +# +# Example aliases +# alias zshconfig="mate ~/.zshrc" +# alias ohmyzsh="mate ~/.oh-my-zsh" +alias vim="nvim" +alias config="/usr/bin/git --git-dir=$HOME/dotfiles/ --work-tree=$HOME" + +export PATH=/home/nikita/.local/bin:$PATH +export WLR_NO_HARDWARE_CURSORS=1 +export EDITOR=/usr/bin/nvim +export SUDO_EDITOR=/usr/bin/nvim +export UPDATE_ZSH_DAYS=7