diff --git a/dots/.bin/restore-passwddb b/dots/.bin/restore-passwddb deleted file mode 100755 index 0c99639..0000000 --- a/dots/.bin/restore-passwddb +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -# Backup existing password databases and -# database keys (using date in filename date -u -# +%Y-%m-%d_%H-%M-%S) - -RCLONE_REMOTE="proton-drive" - -for f in "$HOME/doc"/*.{kdbx,kdbx.key}; do - [ -e "$f" ] || continue - echo "Backing up $f to $f-$(date -u +%Y-%m-%d_%H-%M-%S)" - cp "$f" "$f-$(date -u +%Y-%m-%d_%H-%M-%S)" -done - -echo "Restoring KeePassXC databases and database keys" -rclone copyto \ - "$RCLONE_REMOTE:doc"/ "$HOME/doc/" \ - --progress \ - --include "/*.{kdbx,kdbx.key}" diff --git a/dots/.bin/save-passwddb b/dots/.bin/save-passwddb deleted file mode 100755 index a442ac3..0000000 --- a/dots/.bin/save-passwddb +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env bash - -# Save (encrypted) password database to cloud storage -# -# Usage: -# save-passwddb - Save databases to cloud -# save-passwddb init - Restore databases from cloud (with single backup archive) - -RCLONE_REMOTE="proton" -SOURCE_DIR="$HOME/doc" -TARGET_DIR="$RCLONE_REMOTE:doc" -BACKUP_DIR="$HOME/doc/bak" - -function save_databases() { - if [ 0 -lt "$(ls $SOURCE_DIR/*.kdbx 2>/dev/null | wc -w)" ]; then - echo "[save] Saving KeePassXC databases and database keys" - rclone copy "$SOURCE_DIR" "$TARGET_DIR" \ - --include "/*.{kdbx,kdbx.key}" \ - --progress - echo "[save] Done" - else - echo "[save] No password database found, restore with:" - echo "" - echo " $0 init" - exit 1 - fi -} - -function backup_existing() { - mkdir -p "$BACKUP_DIR" - local timestamp=$(date +%Y%m%d-%H%M%S) - local backup_file="$BACKUP_DIR/passwddb_backup_${timestamp}.tar.gz" - - echo "[backup] Creating backup archive: ${backup_file}" - tar -czf "$backup_file" -C "$SOURCE_DIR" $(find "$SOURCE_DIR" -maxdepth 1 -type f \( -name "*.kdbx" -o -name "*.kdbx.key" \) -printf "%f ") - echo "[backup] Backup complete" -} - -function restore_databases() { - echo "[init] Checking for existing files..." - - local existing_files=$(find "$SOURCE_DIR" -maxdepth 1 -type f \( -name "*.kdbx" -o -name "*.kdbx.key" \) -print) - - if [ -n "$existing_files" ]; then - echo "[init] Found existing database files:" - echo "$existing_files" | while read -r file; do - echo " - $file" - done - read -p "[init] Create backup archive of existing files? [y/N] " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - backup_existing - fi - fi - - echo "[init] Restoring KeePassXC databases and database keys" - mkdir -p "$SOURCE_DIR" - rclone copy "$TARGET_DIR" "$SOURCE_DIR" \ - --include "*.{kdbx,kdbx.key}" \ - --progress - echo "[init] Done" -} - -case "$1" in - ""|save) - save_databases - ;; - init) - restore_databases - ;; - *) - echo "Usage: $0 [init|save]" - exit 1 - ;; -esac diff --git a/dots/.config/Code/User/keybindings.json b/dots/.config/Code/User/keybindings.json deleted file mode 100644 index b3ae49c..0000000 --- a/dots/.config/Code/User/keybindings.json +++ /dev/null @@ -1 +0,0 @@ -[{ "key": "ctrl+b", "command": "workbench.action.toggleSidebarVisibility" }] diff --git a/dots/.config/Code/User/settings.json b/dots/.config/Code/User/settings.json deleted file mode 100644 index 723cacc..0000000 --- a/dots/.config/Code/User/settings.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - /* view */ - "workbench.statusBar.visible": true, - "workbench.activityBar.visible": false, - "breadcrumbs.enabled": false, - "editor.minimap.enabled": false, - "window.menuBarVisibility": "hidden", - "workbench.editor.showTabs": false, - "workbench.editor.showIcons": false, - - /* font */ - "editor.fontSize": 20, - "editor.fontLigatures": true, - "editor.fontFamily": "Iosevka", - "terminal.integrated.fontSize": 20, - - /* editor */ - "editor.lineNumbers": "relative", - "editor.glyphMargin": false, - "terminal.integrated.allowMnemonics": false, - "workbench.colorCustomizations": { - "editorGroup.emptyBackground": "#0c0c0c", - "scrollbar.shadow": "#000", - "widget.shadow": "#000", - "editorWidget.background": "#0c0c0c", - "editor.background": "#0c0c0c", - "sideBar.background": "#0c0c0c", - "editorGroupHeader.noTabsBackground": "#0c0c0c", - "scrollbarSlider.background": "#222", - "scrollbarSlider.activeBackground": "#222", - "scrollbarSlider.hoverBackground": "#333", - "statusBar.noFolderBackground": "#0c0c0c", - "statusBar.border": "#0c0c0c", - "statusBar.background": "#0c0c0c", - "statusBar.foreground": "#555" - }, - - "editor.tokenColorCustomizations": { - "comments": "#555", - "functions": "#aaa", - "numbers": "#fff", - "strings": "#fff", - "types": "#aaa", - "variables": "#aaa", - "keywords": "#aaa" - }, - - /* vim keybindings */ - "vim.incsearch": true, - "vim.hlsearch": true, - "vim.leader": "", - "vim.normalModeKeyBindingsNonRecursive": [ - /* quick quit */ - { - "before": ["", "q"], - "commands": [":q"] - }, - { - "before": ["", "w"], - "commands": [":w"] - }, - { - "before": ["", "Q"], - "commands": [":q!"] - }, - { - "before": ["", "W"], - "commands": [":w!"] - }, - /* split */ - { - "before": ["", "s", "s"], - "commands": [":sp"] - }, - { - "before": ["", "s", "v"], - "commands": [":vs"] - }, - /* clear search highlight */ - { - "before": ["", ""], - "commands": [":nohl"] - } - ], - - "vim.insertModeKeyBindings": [ - /* quick exit insert */ - { - "before": ["j", "j"], - "after": [""] - } - ], - - "vim.handleKeys": { - "": false, - "": false - }, - - /* eslint & prettier */ - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true - }, - - "editor.codeActionsOnSave": { - "source.fixAll": true - }, - - "workbench.colorTheme": "Absolute Black", - "window.zoomLevel": 1, - "javascript.updateImportsOnFileMove.enabled": "always" -} diff --git a/dots/.config/feh/keys b/dots/.config/feh/keys deleted file mode 100644 index 9d06ac1..0000000 --- a/dots/.config/feh/keys +++ /dev/null @@ -1,12 +0,0 @@ -prev_img h -next_img l -scroll_left L -scroll_right H -scroll_up J -scroll_down K -zoom_in j -zoom_out k -zoom_fit z -zoom_default = -mirror bar -close q Q diff --git a/dots/.config/feh/themes b/dots/.config/feh/themes deleted file mode 100644 index 1b26433..0000000 --- a/dots/.config/feh/themes +++ /dev/null @@ -1,3 +0,0 @@ -feh \ --B black \ ---auto-zoom diff --git a/dots/.config/flameshot/flameshot.ini b/dots/.config/flameshot/flameshot.ini deleted file mode 100644 index e9f778c..0000000 --- a/dots/.config/flameshot/flameshot.ini +++ /dev/null @@ -1,36 +0,0 @@ -[General] -checkForUpdates=false -disabledTrayIcon=true -uiColor=#cccccc -fontFamily=Inter -drawColor=#ffffff -savePath=/home/h/doc/clips -copyPathAfterSave=true -saveLastRegion=true -saveAsFileExtension=png -userColors=picker, #800000, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ffffff, #000000 - -[Shortcuts] -TYPE_ARROW=a -TYPE_CIRCLE=o -TYPE_CIRCLECOUNT=Shift+o -TYPE_COMMIT_CURRENT_TOOL=Ctrl+Return -TYPE_COPY=y -TYPE_DELETE_CURRENT_TOOL= -TYPE_DRAWER=l -TYPE_EXIT=q -TYPE_IMAGEUPLOADER= -TYPE_MARKER=m -TYPE_MOVESELECTION=Ctrl+M -TYPE_MOVE_DOWN=j -TYPE_MOVE_LEFT=h -TYPE_MOVE_RIGHT=l -TYPE_MOVE_UP=k -TYPE_OPEN_APP=o -TYPE_PENCIL=d -TYPE_PIN=Enter -TYPE_PIXELATE=p -TYPE_RECTANGLE=r -TYPE_REDO=Ctrl+r -TYPE_RESIZE_DOWN=Shift+j -TYPE_RESIZE_LEFT=Shift+h diff --git a/dots/.config/gh/config.yml b/dots/.config/gh/config.yml deleted file mode 100644 index 7f71cff..0000000 --- a/dots/.config/gh/config.yml +++ /dev/null @@ -1,16 +0,0 @@ -git_protocol: ssh -prompt: enabled -aliases: - co: pr checkout - c: repo clone - f: repo fork - rc: repo create - rv: repo view - re: repo edit - rm: repo remove - rn: repo rename - lr: repo list - li: issue list - al: alias - al-: alias delete -version: "1" diff --git a/dots/.config/gtk-3.0/settings.ini b/dots/.config/gtk-3.0/settings.ini deleted file mode 100644 index e2a9a83..0000000 --- a/dots/.config/gtk-3.0/settings.ini +++ /dev/null @@ -1,5 +0,0 @@ -[Settings] -gtk-font-name=Inter 12 -gtk-application-prefer-dark-theme=true -gtk-icon-theme-name=Adwaita -gtk-theme-name=Adwaita diff --git a/dots/.config/ipython/profile_default/ipython_config.py b/dots/.config/ipython/profile_default/ipython_config.py deleted file mode 100644 index 2e83af8..0000000 --- a/dots/.config/ipython/profile_default/ipython_config.py +++ /dev/null @@ -1,1315 +0,0 @@ -# Configuration file for ipython. - -c = get_config() #noqa - -#------------------------------------------------------------------------------ -# InteractiveShellApp(Configurable) configuration -#------------------------------------------------------------------------------ -## A Mixin for applications that start InteractiveShell instances. -# -# Provides configurables for loading extensions and executing files -# as part of configuring a Shell environment. -# -# The following methods should be called by the :meth:`initialize` method -# of the subclass: -# -# - :meth:`init_path` -# - :meth:`init_shell` (to be implemented by the subclass) -# - :meth:`init_gui_pylab` -# - :meth:`init_extensions` -# - :meth:`init_code` - -## Execute the given command string. -# Default: '' -# c.InteractiveShellApp.code_to_run = '' - -## Run the file referenced by the PYTHONSTARTUP environment -# variable at IPython startup. -# Default: True -# c.InteractiveShellApp.exec_PYTHONSTARTUP = True - -## List of files to run at IPython startup. -# Default: [] -# c.InteractiveShellApp.exec_files = [] - -## lines of code to run at IPython startup. -# Default: [] -# c.InteractiveShellApp.exec_lines = [] - -## A list of dotted module names of IPython extensions to load. -# Default: [] -# c.InteractiveShellApp.extensions = [] - -## Dotted module name(s) of one or more IPython extensions to load. -# -# For specifying extra extensions to load on the command-line. -# -# .. versionadded:: 7.10 -# Default: [] -# c.InteractiveShellApp.extra_extensions = [] - -## A file to be run -# Default: '' -# c.InteractiveShellApp.file_to_run = '' - -## Enable GUI event loop integration with any of ('asyncio', 'glut', 'gtk', -# 'gtk2', 'gtk3', 'gtk4', 'osx', 'pyglet', 'qt', 'qt5', 'qt6', 'tk', 'wx', -# 'gtk2', 'qt4'). -# Choices: any of ['asyncio', 'glut', 'gtk', 'gtk2', 'gtk3', 'gtk4', 'osx', 'pyglet', 'qt', 'qt5', 'qt6', 'tk', 'wx', 'gtk2', 'qt4'] (case-insensitive) or None -# Default: None -# c.InteractiveShellApp.gui = None - -## Should variables loaded at startup (by startup files, exec_lines, etc.) -# be hidden from tools like %who? -# Default: True -# c.InteractiveShellApp.hide_initial_ns = True - -## If True, IPython will not add the current working directory to sys.path. -# When False, the current working directory is added to sys.path, allowing imports -# of modules defined in the current directory. -# Default: False -# c.InteractiveShellApp.ignore_cwd = False - -## Configure matplotlib for interactive use with -# the default matplotlib backend. -# Choices: any of ['auto', 'agg', 'gtk', 'gtk3', 'gtk4', 'inline', 'ipympl', 'nbagg', 'notebook', 'osx', 'pdf', 'ps', 'qt', 'qt4', 'qt5', 'qt6', 'svg', 'tk', 'webagg', 'widget', 'wx'] (case-insensitive) or None -# Default: None -# c.InteractiveShellApp.matplotlib = None - -## Run the module as a script. -# Default: '' -# c.InteractiveShellApp.module_to_run = '' - -## Pre-load matplotlib and numpy for interactive use, -# selecting a particular matplotlib backend and loop integration. -# Choices: any of ['auto', 'agg', 'gtk', 'gtk3', 'gtk4', 'inline', 'ipympl', 'nbagg', 'notebook', 'osx', 'pdf', 'ps', 'qt', 'qt4', 'qt5', 'qt6', 'svg', 'tk', 'webagg', 'widget', 'wx'] (case-insensitive) or None -# Default: None -# c.InteractiveShellApp.pylab = None - -## If true, IPython will populate the user namespace with numpy, pylab, etc. -# and an ``import *`` is done from numpy and pylab, when using pylab mode. -# -# When False, pylab mode should not import any names into the user -# namespace. -# Default: True -# c.InteractiveShellApp.pylab_import_all = True - -## Reraise exceptions encountered loading IPython extensions? -# Default: False -# c.InteractiveShellApp.reraise_ipython_extension_failures = False - -#------------------------------------------------------------------------------ -# Application(SingletonConfigurable) configuration -#------------------------------------------------------------------------------ -## This is an application. - -## The date format used by logging formatters for %(asctime)s -# Default: '%Y-%m-%d %H:%M:%S' -# c.Application.log_datefmt = '%Y-%m-%d %H:%M:%S' - -## The Logging format template -# Default: '[%(name)s]%(highlevel)s %(message)s' -# c.Application.log_format = '[%(name)s]%(highlevel)s %(message)s' - -## Set the log level by value or name. -# Choices: any of [0, 10, 20, 30, 40, 50, 'DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL'] -# Default: 30 -# c.Application.log_level = 30 - -## Configure additional log handlers. -# -# The default stderr logs handler is configured by the log_level, log_datefmt -# and log_format settings. -# -# This configuration can be used to configure additional handlers (e.g. to -# output the log to a file) or for finer control over the default handlers. -# -# If provided this should be a logging configuration dictionary, for more -# information see: -# https://docs.python.org/3/library/logging.config.html#logging-config- -# dictschema -# -# This dictionary is merged with the base logging configuration which defines -# the following: -# -# * A logging formatter intended for interactive use called -# ``console``. -# * A logging handler that writes to stderr called -# ``console`` which uses the formatter ``console``. -# * A logger with the name of this application set to ``DEBUG`` -# level. -# -# This example adds a new handler that writes to a file: -# -# .. code-block:: python -# -# c.Application.logging_config = { -# 'handlers': { -# 'file': { -# 'class': 'logging.FileHandler', -# 'level': 'DEBUG', -# 'filename': '', -# } -# }, -# 'loggers': { -# '': { -# 'level': 'DEBUG', -# # NOTE: if you don't list the default "console" -# # handler here then it will be disabled -# 'handlers': ['console', 'file'], -# }, -# } -# } -# Default: {} -# c.Application.logging_config = {} - -## Instead of starting the Application, dump configuration to stdout -# Default: False -# c.Application.show_config = False - -## Instead of starting the Application, dump configuration to stdout (as JSON) -# Default: False -# c.Application.show_config_json = False - -#------------------------------------------------------------------------------ -# BaseIPythonApplication(Application) configuration -#------------------------------------------------------------------------------ -# Default: False -# c.BaseIPythonApplication.add_ipython_dir_to_sys_path = False - -## Whether to create profile dir if it doesn't exist -# Default: False -# c.BaseIPythonApplication.auto_create = False - -## Whether to install the default config files into the profile dir. -# If a new profile is being created, and IPython contains config files for that -# profile, then they will be staged into the new directory. Otherwise, -# default config files will be automatically generated. -# Default: False -# c.BaseIPythonApplication.copy_config_files = False - -## Path to an extra config file to load. -# -# If specified, load this config file in addition to any other IPython -# config. -# Default: '' -# c.BaseIPythonApplication.extra_config_file = '' - -## The name of the IPython directory. This directory is used for logging -# configuration (through profiles), history storage, etc. The default is usually -# $HOME/.ipython. This option can also be specified through the environment -# variable IPYTHONDIR. -# Default: '' -# c.BaseIPythonApplication.ipython_dir = '' - -## The date format used by logging formatters for %(asctime)s -# See also: Application.log_datefmt -# c.BaseIPythonApplication.log_datefmt = '%Y-%m-%d %H:%M:%S' - -## The Logging format template -# See also: Application.log_format -# c.BaseIPythonApplication.log_format = '[%(name)s]%(highlevel)s %(message)s' - -## Set the log level by value or name. -# See also: Application.log_level -# c.BaseIPythonApplication.log_level = 30 - -## -# See also: Application.logging_config -# c.BaseIPythonApplication.logging_config = {} - -## Whether to overwrite existing config files when copying -# Default: False -# c.BaseIPythonApplication.overwrite = False - -## The IPython profile to use. -# Default: 'default' -# c.BaseIPythonApplication.profile = 'default' - -## Instead of starting the Application, dump configuration to stdout -# See also: Application.show_config -# c.BaseIPythonApplication.show_config = False - -## Instead of starting the Application, dump configuration to stdout (as JSON) -# See also: Application.show_config_json -# c.BaseIPythonApplication.show_config_json = False - -## Create a massive crash report when IPython encounters what may be an -# internal error. The default is to append a short message to the -# usual traceback -# Default: False -# c.BaseIPythonApplication.verbose_crash = False - -#------------------------------------------------------------------------------ -# TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp) configuration -#------------------------------------------------------------------------------ -# See also: BaseIPythonApplication.add_ipython_dir_to_sys_path -# c.TerminalIPythonApp.add_ipython_dir_to_sys_path = False - -## Execute the given command string. -# See also: InteractiveShellApp.code_to_run -# c.TerminalIPythonApp.code_to_run = '' - -## Whether to install the default config files into the profile dir. -# See also: BaseIPythonApplication.copy_config_files -# c.TerminalIPythonApp.copy_config_files = False - -## Whether to display a banner upon starting IPython. -# Default: True -# c.TerminalIPythonApp.display_banner = True - -## Run the file referenced by the PYTHONSTARTUP environment -# See also: InteractiveShellApp.exec_PYTHONSTARTUP -# c.TerminalIPythonApp.exec_PYTHONSTARTUP = True - -## List of files to run at IPython startup. -# See also: InteractiveShellApp.exec_files -# c.TerminalIPythonApp.exec_files = [] - -## lines of code to run at IPython startup. -# See also: InteractiveShellApp.exec_lines -# c.TerminalIPythonApp.exec_lines = [] - -## A list of dotted module names of IPython extensions to load. -# See also: InteractiveShellApp.extensions -# c.TerminalIPythonApp.extensions = [] - -## Path to an extra config file to load. -# See also: BaseIPythonApplication.extra_config_file -# c.TerminalIPythonApp.extra_config_file = '' - -## -# See also: InteractiveShellApp.extra_extensions -# c.TerminalIPythonApp.extra_extensions = [] - -## A file to be run -# See also: InteractiveShellApp.file_to_run -# c.TerminalIPythonApp.file_to_run = '' - -## If a command or file is given via the command-line, -# e.g. 'ipython foo.py', start an interactive shell after executing the -# file or command. -# Default: False -# c.TerminalIPythonApp.force_interact = False - -## Enable GUI event loop integration with any of ('asyncio', 'glut', 'gtk', -# 'gtk2', 'gtk3', 'gtk4', 'osx', 'pyglet', 'qt', 'qt5', 'qt6', 'tk', 'wx', -# 'gtk2', 'qt4'). -# See also: InteractiveShellApp.gui -# c.TerminalIPythonApp.gui = None - -## Should variables loaded at startup (by startup files, exec_lines, etc.) -# See also: InteractiveShellApp.hide_initial_ns -# c.TerminalIPythonApp.hide_initial_ns = True - -## If True, IPython will not add the current working directory to sys.path. -# See also: InteractiveShellApp.ignore_cwd -# c.TerminalIPythonApp.ignore_cwd = False - -## Class to use to instantiate the TerminalInteractiveShell object. Useful for -# custom Frontends -# Default: 'IPython.terminal.interactiveshell.TerminalInteractiveShell' -# c.TerminalIPythonApp.interactive_shell_class = 'IPython.terminal.interactiveshell.TerminalInteractiveShell' - -## -# See also: BaseIPythonApplication.ipython_dir -# c.TerminalIPythonApp.ipython_dir = '' - -## The date format used by logging formatters for %(asctime)s -# See also: Application.log_datefmt -# c.TerminalIPythonApp.log_datefmt = '%Y-%m-%d %H:%M:%S' - -## The Logging format template -# See also: Application.log_format -# c.TerminalIPythonApp.log_format = '[%(name)s]%(highlevel)s %(message)s' - -## Set the log level by value or name. -# See also: Application.log_level -# c.TerminalIPythonApp.log_level = 30 - -## -# See also: Application.logging_config -# c.TerminalIPythonApp.logging_config = {} - -## Configure matplotlib for interactive use with -# See also: InteractiveShellApp.matplotlib -# c.TerminalIPythonApp.matplotlib = None - -## Run the module as a script. -# See also: InteractiveShellApp.module_to_run -# c.TerminalIPythonApp.module_to_run = '' - -## Whether to overwrite existing config files when copying -# See also: BaseIPythonApplication.overwrite -# c.TerminalIPythonApp.overwrite = False - -## The IPython profile to use. -# See also: BaseIPythonApplication.profile -# c.TerminalIPythonApp.profile = 'default' - -## Pre-load matplotlib and numpy for interactive use, -# See also: InteractiveShellApp.pylab -# c.TerminalIPythonApp.pylab = None - -## If true, IPython will populate the user namespace with numpy, pylab, etc. -# See also: InteractiveShellApp.pylab_import_all -# c.TerminalIPythonApp.pylab_import_all = True - -## Start IPython quickly by skipping the loading of config files. -# Default: False -# c.TerminalIPythonApp.quick = False - -## Reraise exceptions encountered loading IPython extensions? -# See also: InteractiveShellApp.reraise_ipython_extension_failures -# c.TerminalIPythonApp.reraise_ipython_extension_failures = False - -## Instead of starting the Application, dump configuration to stdout -# See also: Application.show_config -# c.TerminalIPythonApp.show_config = False - -## Instead of starting the Application, dump configuration to stdout (as JSON) -# See also: Application.show_config_json -# c.TerminalIPythonApp.show_config_json = False - -## Create a massive crash report when IPython encounters what may be an -# See also: BaseIPythonApplication.verbose_crash -# c.TerminalIPythonApp.verbose_crash = False - -#------------------------------------------------------------------------------ -# InteractiveShell(SingletonConfigurable) configuration -#------------------------------------------------------------------------------ -## An enhanced, interactive shell for Python. - -## 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying which -# nodes should be run interactively (displaying output from expressions). -# Choices: any of ['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'] -# Default: 'last_expr' -# c.InteractiveShell.ast_node_interactivity = 'last_expr' - -## A list of ast.NodeTransformer subclass instances, which will be applied to -# user input before code is run. -# Default: [] -# c.InteractiveShell.ast_transformers = [] - -## Automatically run await statement in the top level repl. -# Default: True -# c.InteractiveShell.autoawait = True - -## Make IPython automatically call any callable object even if you didn't type -# explicit parentheses. For example, 'str 43' becomes 'str(43)' automatically. -# The value can be '0' to disable the feature, '1' for 'smart' autocall, where -# it is not applied if there are no more arguments on the line, and '2' for -# 'full' autocall, where all callable objects are automatically called (even if -# no arguments are present). -# Choices: any of [0, 1, 2] -# Default: 0 -# c.InteractiveShell.autocall = 0 - -## Autoindent IPython code entered interactively. -# Default: True -# c.InteractiveShell.autoindent = True - -## Enable magic commands to be called without the leading %. -# Default: True -# c.InteractiveShell.automagic = True - -## The part of the banner to be printed before the profile -# Default: "Python 3.11.3 (main, Apr 5 2023, 15:52:25) [GCC 12.2.1 20230201]\nType 'copyright', 'credits' or 'license' for more information\nIPython 8.13.2 -- An enhanced Interactive Python. Type '?' for help.\n" -# c.InteractiveShell.banner1 = "Python 3.11.3 (main, Apr 5 2023, 15:52:25) [GCC 12.2.1 20230201]\nType 'copyright', 'credits' or 'license' for more information\nIPython 8.13.2 -- An enhanced Interactive Python. Type '?' for help.\n" - -## The part of the banner to be printed after the profile -# Default: '' -# c.InteractiveShell.banner2 = '' - -## Set the size of the output cache. The default is 1000, you can change it -# permanently in your config file. Setting it to 0 completely disables the -# caching system, and the minimum value accepted is 3 (if you provide a value -# less than 3, it is reset to 0 and a warning is issued). This limit is defined -# because otherwise you'll spend more time re-flushing a too small cache than -# working -# Default: 1000 -# c.InteractiveShell.cache_size = 1000 - -## Use colors for displaying information about objects. Because this information -# is passed through a pager (like 'less'), and some pagers get confused with -# color codes, this capability can be turned off. -# Default: True -# c.InteractiveShell.color_info = True - -## Set the color scheme (NoColor, Neutral, Linux, or LightBG). -# Choices: any of ['Neutral', 'NoColor', 'LightBG', 'Linux'] (case-insensitive) -# Default: 'Neutral' -# c.InteractiveShell.colors = 'Neutral' - -# Default: False -# c.InteractiveShell.debug = False - -## Don't call post-execute functions that have failed in the past. -# Default: False -# c.InteractiveShell.disable_failing_post_execute = False - -## If True, anything that would be passed to the pager -# will be displayed as regular output instead. -# Default: False -# c.InteractiveShell.display_page = False - -## (Provisional API) enables html representation in mime bundles sent to pagers. -# Default: False -# c.InteractiveShell.enable_html_pager = False - -## Total length of command history -# Default: 10000 -# c.InteractiveShell.history_length = 10000 - -## The number of saved history entries to be loaded into the history buffer at -# startup. -# Default: 1000 -# c.InteractiveShell.history_load_length = 1000 - -## Class to use to instantiate the shell inspector -# Default: 'IPython.core.oinspect.Inspector' -# c.InteractiveShell.inspector_class = 'IPython.core.oinspect.Inspector' - -# Default: '' -# c.InteractiveShell.ipython_dir = '' - -## Start logging to the given file in append mode. Use `logfile` to specify a log -# file to **overwrite** logs to. -# Default: '' -# c.InteractiveShell.logappend = '' - -## The name of the logfile to use. -# Default: '' -# c.InteractiveShell.logfile = '' - -## Start logging to the default log file in overwrite mode. Use `logappend` to -# specify a log file to **append** logs to. -# Default: False -# c.InteractiveShell.logstart = False - -## Select the loop runner that will be used to execute top-level asynchronous -# code -# Default: 'IPython.core.interactiveshell._asyncio_runner' -# c.InteractiveShell.loop_runner = 'IPython.core.interactiveshell._asyncio_runner' - -# Choices: any of [0, 1, 2] -# Default: 0 -# c.InteractiveShell.object_info_string_level = 0 - -## Automatically call the pdb debugger after every exception. -# Default: False -# c.InteractiveShell.pdb = False - -# Default: False -# c.InteractiveShell.quiet = False - -# Default: '\n' -# c.InteractiveShell.separate_in = '\n' - -# Default: '' -# c.InteractiveShell.separate_out = '' - -# Default: '' -# c.InteractiveShell.separate_out2 = '' - -## Show rewritten input, e.g. for autocall. -# Default: True -# c.InteractiveShell.show_rewritten_input = True - -## Enables rich html representation of docstrings. (This requires the docrepr -# module). -# Default: False -# c.InteractiveShell.sphinxify_docstring = False - -## Warn if running in a virtual environment with no IPython installed (so IPython -# from the global environment is used). -# Default: True -# c.InteractiveShell.warn_venv = True - -# Default: True -# c.InteractiveShell.wildcards_case_sensitive = True - -## Switch modes for the IPython exception handlers. -# Choices: any of ['Context', 'Plain', 'Verbose', 'Minimal'] (case-insensitive) -# Default: 'Context' -# c.InteractiveShell.xmode = 'Context' - -#------------------------------------------------------------------------------ -# TerminalInteractiveShell(InteractiveShell) configuration -#------------------------------------------------------------------------------ -## -# See also: InteractiveShell.ast_node_interactivity -# c.TerminalInteractiveShell.ast_node_interactivity = 'last_expr' - -## -# See also: InteractiveShell.ast_transformers -# c.TerminalInteractiveShell.ast_transformers = [] - -## Automatically add/delete closing bracket or quote when opening bracket or -# quote is entered/deleted. Brackets: (), [], {} Quotes: '', "" -# Default: False -# c.TerminalInteractiveShell.auto_match = False - -## -# See also: InteractiveShell.autoawait -# c.TerminalInteractiveShell.autoawait = True - -## -# See also: InteractiveShell.autocall -# c.TerminalInteractiveShell.autocall = 0 - -## Autoformatter to reformat Terminal code. Can be `'black'`, `'yapf'` or `None` -# Default: None -# c.TerminalInteractiveShell.autoformatter = None - -## -# See also: InteractiveShell.autoindent -# c.TerminalInteractiveShell.autoindent = True - -## -# See also: InteractiveShell.automagic -# c.TerminalInteractiveShell.automagic = True - -## Specifies from which source automatic suggestions are provided. Can be set to -# ``'NavigableAutoSuggestFromHistory'`` (:kbd:`up` and :kbd:`down` swap -# suggestions), ``'AutoSuggestFromHistory'``, or ``None`` to disable automatic -# suggestions. Default is `'NavigableAutoSuggestFromHistory`'. -# Default: 'NavigableAutoSuggestFromHistory' -# c.TerminalInteractiveShell.autosuggestions_provider = 'NavigableAutoSuggestFromHistory' - -## The part of the banner to be printed before the profile -# See also: InteractiveShell.banner1 -# c.TerminalInteractiveShell.banner1 = "Python 3.11.3 (main, Apr 5 2023, 15:52:25) [GCC 12.2.1 20230201]\nType 'copyright', 'credits' or 'license' for more information\nIPython 8.13.2 -- An enhanced Interactive Python. Type '?' for help.\n" - -## The part of the banner to be printed after the profile -# See also: InteractiveShell.banner2 -# c.TerminalInteractiveShell.banner2 = '' - -## -# See also: InteractiveShell.cache_size -# c.TerminalInteractiveShell.cache_size = 1000 - -## -# See also: InteractiveShell.color_info -# c.TerminalInteractiveShell.color_info = True - -## Set the color scheme (NoColor, Neutral, Linux, or LightBG). -# See also: InteractiveShell.colors -# c.TerminalInteractiveShell.colors = 'Neutral' - -## Set to confirm when you try to exit IPython with an EOF (Control-D in Unix, -# Control-Z/Enter in Windows). By typing 'exit' or 'quit', you can force a -# direct exit without any confirmation. -# Default: True -# c.TerminalInteractiveShell.confirm_exit = True - -# See also: InteractiveShell.debug -# c.TerminalInteractiveShell.debug = False - -## File in which to store and read history -# Default: '~/.pdbhistory' -# c.TerminalInteractiveShell.debugger_history_file = '~/.pdbhistory' - -## Don't call post-execute functions that have failed in the past. -# See also: InteractiveShell.disable_failing_post_execute -# c.TerminalInteractiveShell.disable_failing_post_execute = False - -## Options for displaying tab completions, 'column', 'multicolumn', and -# 'readlinelike'. These options are for `prompt_toolkit`, see `prompt_toolkit` -# documentation for more information. -# Choices: any of ['column', 'multicolumn', 'readlinelike'] -# Default: 'multicolumn' -# c.TerminalInteractiveShell.display_completions = 'multicolumn' - -## If True, anything that would be passed to the pager -# See also: InteractiveShell.display_page -# c.TerminalInteractiveShell.display_page = False - -## Shortcut style to use at the prompt. 'vi' or 'emacs'. -# Default: 'emacs' -c.TerminalInteractiveShell.editing_mode = 'vi' - -## Set the editor used by IPython (default to $EDITOR/vi/notepad). -# Default: 'vim' -# c.TerminalInteractiveShell.editor = 'vim' - -## Add shortcuts from 'emacs' insert mode to 'vi' insert mode. -# Default: True -c.TerminalInteractiveShell.emacs_bindings_in_vi_insert_mode = False - -## Allows to enable/disable the prompt toolkit history search -# Default: True -# c.TerminalInteractiveShell.enable_history_search = True - -## -# See also: InteractiveShell.enable_html_pager -# c.TerminalInteractiveShell.enable_html_pager = False - -## Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. This is -# in addition to the F2 binding, which is always enabled. -# Default: False -# c.TerminalInteractiveShell.extra_open_editor_shortcuts = False - -## Provide an alternative handler to be called when the user presses Return. This -# is an advanced option intended for debugging, which may be changed or removed -# in later releases. -# Default: None -# c.TerminalInteractiveShell.handle_return = None - -## Highlight matching brackets. -# Default: True -# c.TerminalInteractiveShell.highlight_matching_brackets = True - -## The name or class of a Pygments style to use for syntax -# highlighting. To see available styles, run `pygmentize -L styles`. -# Default: traitlets.Undefined -# c.TerminalInteractiveShell.highlighting_style = traitlets.Undefined - -## Override highlighting format for specific tokens -# Default: {} -# c.TerminalInteractiveShell.highlighting_style_overrides = {} - -## Total length of command history -# See also: InteractiveShell.history_length -# c.TerminalInteractiveShell.history_length = 10000 - -## -# See also: InteractiveShell.history_load_length -# c.TerminalInteractiveShell.history_load_length = 1000 - -## Class to use to instantiate the shell inspector -# See also: InteractiveShell.inspector_class -# c.TerminalInteractiveShell.inspector_class = 'IPython.core.oinspect.Inspector' - -# See also: InteractiveShell.ipython_dir -# c.TerminalInteractiveShell.ipython_dir = '' - -## -# See also: InteractiveShell.logappend -# c.TerminalInteractiveShell.logappend = '' - -## -# See also: InteractiveShell.logfile -# c.TerminalInteractiveShell.logfile = '' - -## -# See also: InteractiveShell.logstart -# c.TerminalInteractiveShell.logstart = False - -## Select the loop runner that will be used to execute top-level asynchronous -# code -# See also: InteractiveShell.loop_runner -# c.TerminalInteractiveShell.loop_runner = 'IPython.core.interactiveshell._asyncio_runner' - -# Default: {} -# c.TerminalInteractiveShell.mime_renderers = {} - -## Cursor shape changes depending on vi mode: beam in vi insert mode, block in -# nav mode, underscore in replace mode. -# Default: True -# c.TerminalInteractiveShell.modal_cursor = True - -## Enable mouse support in the prompt (Note: prevents selecting text with the -# mouse) -# Default: False -# c.TerminalInteractiveShell.mouse_support = False - -# See also: InteractiveShell.object_info_string_level -# c.TerminalInteractiveShell.object_info_string_level = 0 - -## -# See also: InteractiveShell.pdb -# c.TerminalInteractiveShell.pdb = False - -## Display the current vi mode (when using vi editing mode). -# Default: True -# c.TerminalInteractiveShell.prompt_includes_vi_mode = True - -## Class used to generate Prompt token for prompt_toolkit -# Default: 'IPython.terminal.prompts.Prompts' -# c.TerminalInteractiveShell.prompts_class = 'IPython.terminal.prompts.Prompts' - -# See also: InteractiveShell.quiet -# c.TerminalInteractiveShell.quiet = False - -# See also: InteractiveShell.separate_in -# c.TerminalInteractiveShell.separate_in = '\n' - -# See also: InteractiveShell.separate_out -# c.TerminalInteractiveShell.separate_out = '' - -# See also: InteractiveShell.separate_out2 -# c.TerminalInteractiveShell.separate_out2 = '' - -## Add, disable or modifying shortcuts. -# -# Each entry on the list should be a dictionary with ``command`` key -# identifying the target function executed by the shortcut and at least -# one of the following: -# -# - ``match_keys``: list of keys used to match an existing shortcut, -# - ``match_filter``: shortcut filter used to match an existing shortcut, -# - ``new_keys``: list of keys to set, -# - ``new_filter``: a new shortcut filter to set -# -# The filters have to be composed of pre-defined verbs and joined by one -# of the following conjunctions: ``&`` (and), ``|`` (or), ``~`` (not). -# The pre-defined verbs are: -# -# - `always` -# - `never` -# - `has_line_below` -# - `has_line_above` -# - `is_cursor_at_the_end_of_line` -# - `has_selection` -# - `has_suggestion` -# - `vi_mode` -# - `vi_insert_mode` -# - `emacs_insert_mode` -# - `emacs_like_insert_mode` -# - `has_completions` -# - `insert_mode` -# - `default_buffer_focused` -# - `search_buffer_focused` -# - `ebivim` -# - `supports_suspend` -# - `is_windows_os` -# - `auto_match` -# - `focused_insert` -# - `not_inside_unclosed_string` -# - `readline_like_completions` -# - `preceded_by_paired_double_quotes` -# - `preceded_by_paired_single_quotes` -# - `preceded_by_raw_str_prefix` -# - `preceded_by_two_double_quotes` -# - `preceded_by_two_single_quotes` -# - `followed_by_closing_paren_or_end` -# - `preceded_by_opening_round_paren` -# - `preceded_by_opening_bracket` -# - `preceded_by_opening_brace` -# - `preceded_by_double_quote` -# - `preceded_by_single_quote` -# - `followed_by_closing_round_paren` -# - `followed_by_closing_bracket` -# - `followed_by_closing_brace` -# - `followed_by_double_quote` -# - `followed_by_single_quote` -# - `navigable_suggestions` -# - `cursor_in_leading_ws` -# -# To disable a shortcut set ``new_keys`` to an empty list. -# To add a shortcut add key ``create`` with value ``True``. -# -# When modifying/disabling shortcuts, ``match_keys``/``match_filter`` can -# be omitted if the provided specification uniquely identifies a shortcut -# to be modified/disabled. When modifying a shortcut ``new_filter`` or -# ``new_keys`` can be omitted which will result in reuse of the existing -# filter/keys. -# -# Only shortcuts defined in IPython (and not default prompt-toolkit -# shortcuts) can be modified or disabled. The full list of shortcuts, -# command identifiers and filters is available under -# :ref:`terminal-shortcuts-list`. -# Default: [] -# c.TerminalInteractiveShell.shortcuts = [] - -## Show rewritten input, e.g. for autocall. -# See also: InteractiveShell.show_rewritten_input -# c.TerminalInteractiveShell.show_rewritten_input = True - -## Use `raw_input` for the REPL, without completion and prompt colors. -# -# Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are: -# IPython own testing machinery, and emacs inferior-shell integration through elpy. -# -# This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT` -# environment variable is set, or the current terminal is not a tty. -# Default: False -# c.TerminalInteractiveShell.simple_prompt = False - -## Number of line at the bottom of the screen to reserve for the tab completion -# menu, search history, ...etc, the height of these menus will at most this -# value. Increase it is you prefer long and skinny menus, decrease for short and -# wide. -# Default: 6 -# c.TerminalInteractiveShell.space_for_menu = 6 - -## -# See also: InteractiveShell.sphinxify_docstring -# c.TerminalInteractiveShell.sphinxify_docstring = False - -## Automatically set the terminal title -# Default: True -# c.TerminalInteractiveShell.term_title = True - -## Customize the terminal title format. This is a python format string. -# Available substitutions are: {cwd}. -# Default: 'IPython: {cwd}' -# c.TerminalInteractiveShell.term_title_format = 'IPython: {cwd}' - -## The time in milliseconds that is waited for a mapped key -# sequence to complete. -# Default: 0.5 -# c.TerminalInteractiveShell.timeoutlen = 0.5 - -## Use 24bit colors instead of 256 colors in prompt highlighting. -# If your terminal supports true color, the following command should -# print ``TRUECOLOR`` in orange:: -# -# printf "\x1b[38;2;255;100;0mTRUECOLOR\x1b[0m\n" -# Default: False -# c.TerminalInteractiveShell.true_color = False - -## The time in milliseconds that is waited for a key code -# to complete. -# Default: 0.01 -# c.TerminalInteractiveShell.ttimeoutlen = 0.01 - -## Warn if running in a virtual environment with no IPython installed (so IPython -# from the global environment is used). -# See also: InteractiveShell.warn_venv -# c.TerminalInteractiveShell.warn_venv = True - -# See also: InteractiveShell.wildcards_case_sensitive -# c.TerminalInteractiveShell.wildcards_case_sensitive = True - -## Switch modes for the IPython exception handlers. -# See also: InteractiveShell.xmode -# c.TerminalInteractiveShell.xmode = 'Context' - -#------------------------------------------------------------------------------ -# HistoryAccessor(HistoryAccessorBase) configuration -#------------------------------------------------------------------------------ -## Access the history database without adding to it. -# -# This is intended for use by standalone history tools. IPython shells use -# HistoryManager, below, which is a subclass of this. - -## Options for configuring the SQLite connection -# -# These options are passed as keyword args to sqlite3.connect -# when establishing database connections. -# Default: {} -# c.HistoryAccessor.connection_options = {} - -## enable the SQLite history -# -# set enabled=False to disable the SQLite history, -# in which case there will be no stored history, no SQLite connection, -# and no background saving thread. This may be necessary in some -# threaded environments where IPython is embedded. -# Default: True -# c.HistoryAccessor.enabled = True - -## Path to file to use for SQLite history database. -# -# By default, IPython will put the history database in the IPython -# profile directory. If you would rather share one history among -# profiles, you can set this value in each, so that they are consistent. -# -# Due to an issue with fcntl, SQLite is known to misbehave on some NFS -# mounts. If you see IPython hanging, try setting this to something on a -# local disk, e.g:: -# -# ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite -# -# you can also use the specific value `:memory:` (including the colon -# at both end but not the back ticks), to avoid creating an history file. -# Default: traitlets.Undefined -# c.HistoryAccessor.hist_file = traitlets.Undefined - -#------------------------------------------------------------------------------ -# HistoryManager(HistoryAccessor) configuration -#------------------------------------------------------------------------------ -## A class to organize all history-related functionality in one place. - -## Options for configuring the SQLite connection -# See also: HistoryAccessor.connection_options -# c.HistoryManager.connection_options = {} - -## Write to database every x commands (higher values save disk access & power). -# Values of 1 or less effectively disable caching. -# Default: 0 -# c.HistoryManager.db_cache_size = 0 - -## Should the history database include output? (default: no) -# Default: False -# c.HistoryManager.db_log_output = False - -## enable the SQLite history -# See also: HistoryAccessor.enabled -# c.HistoryManager.enabled = True - -## Path to file to use for SQLite history database. -# See also: HistoryAccessor.hist_file -# c.HistoryManager.hist_file = traitlets.Undefined - -#------------------------------------------------------------------------------ -# MagicsManager(Configurable) configuration -#------------------------------------------------------------------------------ -## Object that handles all magic-related functionality for IPython. - -## Automatically call line magics without requiring explicit % prefix -# Default: True -# c.MagicsManager.auto_magic = True - -## Mapping from magic names to modules to load. -# -# This can be used in IPython/IPykernel configuration to declare lazy magics -# that will only be imported/registered on first use. -# -# For example:: -# -# c.MagicsManager.lazy_magics = { -# "my_magic": "slow.to.import", -# "my_other_magic": "also.slow", -# } -# -# On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or -# `%%my_other_magic`, the corresponding module will be loaded as an ipython -# extensions as if you had previously done `%load_ext ipython`. -# -# Magics names should be without percent(s) as magics can be both cell and line -# magics. -# -# Lazy loading happen relatively late in execution process, and complex -# extensions that manipulate Python/IPython internal state or global state might -# not support lazy loading. -# Default: {} -# c.MagicsManager.lazy_magics = {} - -#------------------------------------------------------------------------------ -# ProfileDir(LoggingConfigurable) configuration -#------------------------------------------------------------------------------ -## An object to manage the profile directory and its resources. -# -# The profile directory is used by all IPython applications, to manage -# configuration, logging and security. -# -# This object knows how to find, create and manage these directories. This -# should be used by any code that wants to handle profiles. - -## Set the profile location directly. This overrides the logic used by the -# `profile` option. -# Default: '' -# c.ProfileDir.location = '' - -#------------------------------------------------------------------------------ -# BaseFormatter(Configurable) configuration -#------------------------------------------------------------------------------ -## A base formatter class that is configurable. -# -# This formatter should usually be used as the base class of all formatters. -# It is a traited :class:`Configurable` class and includes an extensible -# API for users to determine how their objects are formatted. The following -# logic is used to find a function to format an given object. -# -# 1. The object is introspected to see if it has a method with the name -# :attr:`print_method`. If is does, that object is passed to that method -# for formatting. -# 2. If no print method is found, three internal dictionaries are consulted -# to find print method: :attr:`singleton_printers`, :attr:`type_printers` -# and :attr:`deferred_printers`. -# -# Users should use these dictionaries to register functions that will be -# used to compute the format data for their objects (if those objects don't -# have the special print methods). The easiest way of using these -# dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name` -# methods. -# -# If no function/callable is found to compute the format data, ``None`` is -# returned and this format type is not used. - -# Default: {} -# c.BaseFormatter.deferred_printers = {} - -# Default: True -# c.BaseFormatter.enabled = True - -# Default: {} -# c.BaseFormatter.singleton_printers = {} - -# Default: {} -# c.BaseFormatter.type_printers = {} - -#------------------------------------------------------------------------------ -# PlainTextFormatter(BaseFormatter) configuration -#------------------------------------------------------------------------------ -## The default pretty-printer. -# -# This uses :mod:`IPython.lib.pretty` to compute the format data of -# the object. If the object cannot be pretty printed, :func:`repr` is used. -# See the documentation of :mod:`IPython.lib.pretty` for details on -# how to write pretty printers. Here is a simple example:: -# -# def dtype_pprinter(obj, p, cycle): -# if cycle: -# return p.text('dtype(...)') -# if hasattr(obj, 'fields'): -# if obj.fields is None: -# p.text(repr(obj)) -# else: -# p.begin_group(7, 'dtype([') -# for i, field in enumerate(obj.descr): -# if i > 0: -# p.text(',') -# p.breakable() -# p.pretty(field) -# p.end_group(7, '])') - -# See also: BaseFormatter.deferred_printers -# c.PlainTextFormatter.deferred_printers = {} - -# Default: '' -# c.PlainTextFormatter.float_precision = '' - -## Truncate large collections (lists, dicts, tuples, sets) to this size. -# -# Set to 0 to disable truncation. -# Default: 1000 -# c.PlainTextFormatter.max_seq_length = 1000 - -# Default: 79 -# c.PlainTextFormatter.max_width = 79 - -# Default: '\n' -# c.PlainTextFormatter.newline = '\n' - -# Default: True -# c.PlainTextFormatter.pprint = True - -# See also: BaseFormatter.singleton_printers -# c.PlainTextFormatter.singleton_printers = {} - -# See also: BaseFormatter.type_printers -# c.PlainTextFormatter.type_printers = {} - -# Default: False -# c.PlainTextFormatter.verbose = False - -#------------------------------------------------------------------------------ -# Completer(Configurable) configuration -#------------------------------------------------------------------------------ -## Enable auto-closing dictionary keys. -# -# When enabled string keys will be suffixed with a final quote (matching the -# opening quote), tuple keys will also receive a separating comma if needed, and -# keys which are final will receive a closing bracket (``]``). -# Default: False -# c.Completer.auto_close_dict_keys = False - -## Enable unicode completions, e.g. \alpha . Includes completion of latex -# commands, unicode names, and expanding unicode characters back to latex -# commands. -# Default: True -# c.Completer.backslash_combining_completions = True - -## Enable debug for the Completer. Mostly print extra information for -# experimental jedi integration. -# Default: False -# c.Completer.debug = False - -## Policy for code evaluation under completion. -# -# Successive options allow to enable more eager evaluation for better -# completion suggestions, including for nested dictionaries, nested lists, -# or even results of function calls. -# Setting ``unsafe`` or higher can lead to evaluation of arbitrary user -# code on :kbd:`Tab` with potentially unwanted or dangerous side effects. -# -# Allowed values are: -# -# - ``forbidden``: no evaluation of code is permitted, -# - ``minimal``: evaluation of literals and access to built-in namespace; -# no item/attribute evaluationm no access to locals/globals, -# no evaluation of any operations or comparisons. -# - ``limited``: access to all namespaces, evaluation of hard-coded methods -# (for example: :any:`dict.keys`, :any:`object.__getattr__`, -# :any:`object.__getitem__`) on allow-listed objects (for example: -# :any:`dict`, :any:`list`, :any:`tuple`, ``pandas.Series``), -# - ``unsafe``: evaluation of all methods and function calls but not of -# syntax with side-effects like `del x`, -# - ``dangerous``: completely arbitrary evaluation. -# Choices: any of ['forbidden', 'minimal', 'limited', 'unsafe', 'dangerous'] -# Default: 'limited' -# c.Completer.evaluation = 'limited' - -## Activate greedy completion. -# -# .. deprecated:: 8.8 -# Use :std:configtrait:`Completer.evaluation` and :std:configtrait:`Completer.auto_close_dict_keys` instead. -# -# When enabled in IPython 8.8 or newer, changes configuration as -# follows: -# -# - ``Completer.evaluation = 'unsafe'`` -# - ``Completer.auto_close_dict_keys = True`` -# Default: False -# c.Completer.greedy = False - -## Experimental: restrict time (in milliseconds) during which Jedi can compute types. -# Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt -# performance by preventing jedi to build its cache. -# Default: 400 -# c.Completer.jedi_compute_type_timeout = 400 - -## Experimental: Use Jedi to generate autocompletions. Default to True if jedi is -# installed. -# Default: True -# c.Completer.use_jedi = True - -#------------------------------------------------------------------------------ -# IPCompleter(Completer) configuration -#------------------------------------------------------------------------------ -## Extension of the completer class with IPython-specific features - -## -# See also: Completer.auto_close_dict_keys -# c.IPCompleter.auto_close_dict_keys = False - -## Enable unicode completions, e.g. \alpha . Includes completion of latex -# commands, unicode names, and expanding unicode characters back to latex -# commands. -# See also: Completer.backslash_combining_completions -# c.IPCompleter.backslash_combining_completions = True - -## Enable debug for the Completer. Mostly print extra information for -# experimental jedi integration. -# See also: Completer.debug -# c.IPCompleter.debug = False - -## List of matchers to disable. -# -# The list should contain matcher identifiers (see -# :any:`completion_matcher`). -# Default: [] -# c.IPCompleter.disable_matchers = [] - -## Policy for code evaluation under completion. -# See also: Completer.evaluation -# c.IPCompleter.evaluation = 'limited' - -## Activate greedy completion. -# See also: Completer.greedy -# c.IPCompleter.greedy = False - -## Experimental: restrict time (in milliseconds) during which Jedi can compute -# types. -# See also: Completer.jedi_compute_type_timeout -# c.IPCompleter.jedi_compute_type_timeout = 400 - -## DEPRECATED as of version 5.0. -# -# Instruct the completer to use __all__ for the completion -# -# Specifically, when completing on ``object.``. -# -# When True: only those names in obj.__all__ will be included. -# -# When False [default]: the __all__ attribute is ignored -# Default: False -# c.IPCompleter.limit_to__all__ = False - -## Whether to merge completion results into a single list -# -# If False, only the completion results from the first non-empty -# completer will be returned. -# -# As of version 8.6.0, setting the value to ``False`` is an alias for: -# ``IPCompleter.suppress_competing_matchers = True.``. -# Default: True -# c.IPCompleter.merge_completions = True - -## Instruct the completer to omit private method names -# -# Specifically, when completing on ``object.``. -# -# When 2 [default]: all names that start with '_' will be excluded. -# -# When 1: all 'magic' names (``__foo__``) will be excluded. -# -# When 0: nothing will be excluded. -# Choices: any of [0, 1, 2] -# Default: 2 -# c.IPCompleter.omit__names = 2 - -## If True, emit profiling data for completion subsystem using cProfile. -# Default: False -# c.IPCompleter.profile_completions = False - -## Template for path at which to output profile data for completions. -# Default: '.completion_profiles' -# c.IPCompleter.profiler_output_dir = '.completion_profiles' - -## Whether to suppress completions from other *Matchers*. -# -# When set to ``None`` (default) the matchers will attempt to auto-detect -# whether suppression of other matchers is desirable. For example, at the -# beginning of a line followed by `%` we expect a magic completion to be the -# only applicable option, and after ``my_dict['`` we usually expect a completion -# with an existing dictionary key. -# -# If you want to disable this heuristic and see completions from all matchers, -# set ``IPCompleter.suppress_competing_matchers = False``. To disable the -# heuristic for specific matchers provide a dictionary mapping: -# ``IPCompleter.suppress_competing_matchers = {'IPCompleter.dict_key_matcher': -# False}``. -# -# Set ``IPCompleter.suppress_competing_matchers = True`` to limit completions to -# the set of matchers with the highest priority; this is equivalent to -# ``IPCompleter.merge_completions`` and can be beneficial for performance, but -# will sometimes omit relevant candidates from matchers further down the -# priority list. -# Default: None -# c.IPCompleter.suppress_competing_matchers = None - -## Experimental: Use Jedi to generate autocompletions. Default to True if jedi is -# installed. -# See also: Completer.use_jedi -# c.IPCompleter.use_jedi = True - -#------------------------------------------------------------------------------ -# ScriptMagics(Magics) configuration -#------------------------------------------------------------------------------ -## Magics for talking to scripts -# -# This defines a base `%%script` cell magic for running a cell -# with a program in a subprocess, and registers a few top-level -# magics that call %%script with common interpreters. - -## Extra script cell magics to define -# -# This generates simple wrappers of `%%script foo` as `%%foo`. -# -# If you want to add script magics that aren't on your path, -# specify them in script_paths -# Default: [] -# c.ScriptMagics.script_magics = [] - -## Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby' -# -# Only necessary for items in script_magics where the default path will not -# find the right interpreter. -# Default: {} -# c.ScriptMagics.script_paths = {} - -#------------------------------------------------------------------------------ -# LoggingMagics(Magics) configuration -#------------------------------------------------------------------------------ -## Magics related to all logging machinery. - -## Suppress output of log state when logging is enabled -# Default: False -# c.LoggingMagics.quiet = False - -#------------------------------------------------------------------------------ -# StoreMagics(Magics) configuration -#------------------------------------------------------------------------------ -## Lightweight persistence for python variables. -# -# Provides the %store magic. - -## If True, any %store-d variables will be automatically restored -# when IPython starts. -# Default: False -# c.StoreMagics.autorestore = False diff --git a/dots/.config/keepassxc/keepassxc.ini b/dots/.config/keepassxc/keepassxc.ini deleted file mode 100644 index d6caa1e..0000000 --- a/dots/.config/keepassxc/keepassxc.ini +++ /dev/null @@ -1,32 +0,0 @@ -[General] -ConfigVersion=2 - -[Browser] -CustomProxyLocation= -Enabled=true - -[GUI] -ApplicationTheme=dark -CompactMode=false -HidePreviewPanel=false -HideToolbar=false -MinimizeOnClose=true -MinimizeToTray=true -ShowTrayIcon=true -TrayIconAppearance=colorful - -[KeeShare] -Active="\n" -Foreign="\n\n \n\n" -Own="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9Ji74dnjo0qzbUFKEoNnMHsdX7mBXuJcu8zsl7vfkKLiAGIQiP9BQc/JnFr28W92fQz8uXVtm7NgnKJQkT7wzFyBdspmNDzosS58EIQVKe5p+uMaaGZ5z6j1DtLCFo7PLCnhasBluC0W1+37s7NtRD6bFo1r6QHupY63mBsSvJhAcmS+6bM7xS7PcK0WTVTsK1MWYZLOkYMWQ0AW/t4PZfqeKvalqheiR8oUIDeY7+7fqvQr5SAhL0yinbtaqWmPqcd5QWyPqVkbKclw4Uecw+JW+yR9uEOP9butP74r36LUUfsTJHE2/sB2KJFRN/aUm2ZEYhzexMYSfgnrq0KCLAgMBAAECggEACV8N7rN39BkUBV2qaPXLNKjFuZ6O2WnE28ejQ5LeZ0h5M6eDTGsa+BF2jhL7XYyzo0NiqvpnH+dWIkKJbG8i5OkdamcB4pJBkJZCj6LPL0yGcAbZmCLyzc1qMaOPJ1/f9YxUQDH/YItgbc7DEBwAFbkPyzT3ufRd7BuLLx1gu0iypHhBok9kXA4WgkUihLNXXVvSIGcVy+q9wpgOiw5jLC79qwqIp39Tlt6PKryODulqWIeoeSIgAu5tgUy4O3He6AZwqBprIfJSiJOwfdBd8FchQJQDgl0fyDR10VIUNbjgm+kxWssq4oNJ7+2n14Gdfwpy2K7oO9DYeqjBrv2p4QKBgQDqY8/5ufsJ9hKhQRX3vju+FEDLKvjjKH7/6puDwcvC1GgvshQSvCo9ZVIajwSmEoWq2LTDiPlUPFINKnALQiHCbRfNeS1Tws4cK4AAZnR+CGKkox9J5MWCDVzI2/82R9/9ZX4OO+As5+Od503Grmy+Zi0Redm+r4aK04gm3LfqGwKBgQDOlpOXFyYbb473TFkf9ZfyETZGkjlCzf4uPwPuJ3njWZfwPE2Gb+quZDLSmYp9JhzIFoapnQrjSFCVyzBYIIuz3jipb5MbQxc6FPSjw0pPowWdPkEL1CT5mpZFojop+I/TnEEG+Lv039O3cGlL2zagiBHRw0ediD6z0vnoOBeKUQKBgQDjlJBuKC9gp6XFHp4G05XMZHvZCNtqLHrLX28qSjPe80BJ9z1YR4032bYThYP9AAT7MripFskICh2dHPR3afm/fw9aeWsSZhab8XyyZsh7SwcEVkJeDBvdv720ZS9y8+y/bBkuFuL+lxVBz0GMRPXfFPRzgH10kZcwGl2bZjnIuwKBgQCVabQu95AZEbM9yps/ERom+ineGo2Ncnyep/bIvQZb1wWbu5F6ZOE/5boYNPJDl1gDor8cVzdzsG6QGBfL9SX1HgivCsJDWl+nI1bYRjsto8NAubDDxFhFqnd6v1z/1AT50C37w9P0xBlUt9mAAnjc2+y/YFQgbFSlLDaQrFjiMQKBgFJrLF21Uk6ALZa4R0eOyLKhuagw3uxmNvccNG8VL5DwYVCUS7/8SkPhO5yvbcA87Y1VnM20tUr047K4U83uFNxBnPMmxlhMsxtqjw+VV6Us6uh2ASaLZ9iP9iwkn5e37WLWX+XsewoGrW/YsONwIT0dnZDPRbxhPdJn8azSJqQrhMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9Ji74dnjo0qzbUFKEoNnMHsdX7mBXuJcu8zsl7vfkKLiAGIQiP9BQc/JnFr28W92fQz8uXVtm7NgnKJQkT7wzFyBdspmNDzosS58EIQVKe5p+uMaaGZ5z6j1DtLCFo7PLCnhasBluC0W1+37s7NtRD6bFo1r6QHupY63mBsSvJhAcmS+6bM7xS7PcK0WTVTsK1MWYZLOkYMWQ0AW/t4PZfqeKvalqheiR8oUIDeY7+7fqvQr5SAhL0yinbtaqWmPqcd5QWyPqVkbKclw4Uecw+JW+yR9uEOP9butP74r36LUUfsTJHE2/sB2KJFRN/aUm2ZEYhzexMYSfgnrq0KCLAgMBAAECggEACV8N7rN39BkUBV2qaPXLNKjFuZ6O2WnE28ejQ5LeZ0h5M6eDTGsa+BF2jhL7XYyzo0NiqvpnH+dWIkKJbG8i5OkdamcB4pJBkJZCj6LPL0yGcAbZmCLyzc1qMaOPJ1/f9YxUQDH/YItgbc7DEBwAFbkPyzT3ufRd7BuLLx1gu0iypHhBok9kXA4WgkUihLNXXVvSIGcVy+q9wpgOiw5jLC79qwqIp39Tlt6PKryODulqWIeoeSIgAu5tgUy4O3He6AZwqBprIfJSiJOwfdBd8FchQJQDgl0fyDR10VIUNbjgm+kxWssq4oNJ7+2n14Gdfwpy2K7oO9DYeqjBrv2p4QKBgQDqY8/5ufsJ9hKhQRX3vju+FEDLKvjjKH7/6puDwcvC1GgvshQSvCo9ZVIajwSmEoWq2LTDiPlUPFINKnALQiHCbRfNeS1Tws4cK4AAZnR+CGKkox9J5MWCDVzI2/82R9/9ZX4OO+As5+Od503Grmy+Zi0Redm+r4aK04gm3LfqGwKBgQDOlpOXFyYbb473TFkf9ZfyETZGkjlCzf4uPwPuJ3njWZfwPE2Gb+quZDLSmYp9JhzIFoapnQrjSFCVyzBYIIuz3jipb5MbQxc6FPSjw0pPowWdPkEL1CT5mpZFojop+I/TnEEG+Lv039O3cGlL2zagiBHRw0ediD6z0vnoOBeKUQKBgQDjlJBuKC9gp6XFHp4G05XMZHvZCNtqLHrLX28qSjPe80BJ9z1YR4032bYThYP9AAT7MripFskICh2dHPR3afm/fw9aeWsSZhab8XyyZsh7SwcEVkJeDBvdv720ZS9y8+y/bBkuFuL+lxVBz0GMRPXfFPRzgH10kZcwGl2bZjnIuwKBgQCVabQu95AZEbM9yps/ERom+ineGo2Ncnyep/bIvQZb1wWbu5F6ZOE/5boYNPJDl1gDor8cVzdzsG6QGBfL9SX1HgivCsJDWl+nI1bYRjsto8NAubDDxFhFqnd6v1z/1AT50C37w9P0xBlUt9mAAnjc2+y/YFQgbFSlLDaQrFjiMQKBgFJrLF21Uk6ALZa4R0eOyLKhuagw3uxmNvccNG8VL5DwYVCUS7/8SkPhO5yvbcA87Y1VnM20tUr047K4U83uFNxBnPMmxlhMsxtqjw+VV6Us6uh2ASaLZ9iP9iwkn5e37WLWX+XsewoGrW/YsONwIT0dnZDPRbxhPdJn8azSJqQr\n" -QuietSuccess=true - -[PasswordGenerator] -AdditionalChars= -ExcludedChars= -Length=40 -Logograms=true -WordCount=9 - -[SSHAgent] -Enabled=true diff --git a/dots/.config/mimeapps.list b/dots/.config/mimeapps.list deleted file mode 100644 index 83e2ae5..0000000 --- a/dots/.config/mimeapps.list +++ /dev/null @@ -1,20 +0,0 @@ -[Default Applications] -inode/x-empty=nvim.desktop -inode/directory=nvim.desktop -text/plain=nvim.desktop -text/html=firefoxdeveloperedition.desktop -image/gif=feh.desktop -image/jpeg=feh.desktop -image/png=feh.desktop -video/mp4=mpv.desktop -video/webm=mpv.desktop -model/stl=com.ultimaker.cura.desktop -application/pdf=org.pwmt.zathura.desktop -x-scheme-handler/msteams=teams-for-linux.desktop -x-scheme-handler/web+stremio=firefox.desktop -x-scheme-handler/http=firefoxdeveloperedition.desktop -x-scheme-handler/https=firefoxdeveloperedition.desktop -x-scheme-handler/chrome=firefoxdeveloperedition.desktop -x-scheme-handler/sidequest=SideQuest.desktop -x-scheme-handler/mailto=firefox.desktop -x-scheme-handler/webcal=firefox.desktop diff --git a/dots/.config/mpv/fonts/oscc.ttf b/dots/.config/mpv/fonts/oscc.ttf deleted file mode 100644 index 9d956e0..0000000 Binary files a/dots/.config/mpv/fonts/oscc.ttf and /dev/null differ diff --git a/dots/.config/mpv/input.conf b/dots/.config/mpv/input.conf deleted file mode 100644 index f33b559..0000000 --- a/dots/.config/mpv/input.conf +++ /dev/null @@ -1,15 +0,0 @@ -l seek +5 -h seek -5 -k seek +30 -j seek -30 - -+ add video-zoom 0.1 -- add video-zoom -0.1 -= set video-zoom 0; set video-pan-x 0; set video-pan-y 0 - -H add video-pan-x 0.01 -L add video-pan-x -0.01 -K add video-pan-y 0.01 -J add video-pan-y -0.01 - -m cycle mute diff --git a/dots/.config/mpv/mpv.conf b/dots/.config/mpv/mpv.conf deleted file mode 100644 index 7f3210e..0000000 --- a/dots/.config/mpv/mpv.conf +++ /dev/null @@ -1,16 +0,0 @@ -vo=gpu -profile=gpu-hq -hwdec=auto - -msg-color=yes - -cursor-autohide=300 -cursor-autohide-fs-only=yes -save-position-on-quit=yes -keep-open=yes - -# Custom osc -osc=no -cursor-autohide=3500 -osd-bar=no -osc-vidscale=no diff --git a/dots/.config/mpv/scripts/oscc.lua b/dots/.config/mpv/scripts/oscc.lua deleted file mode 100644 index 75d68d3..0000000 --- a/dots/.config/mpv/scripts/oscc.lua +++ /dev/null @@ -1,2495 +0,0 @@ --- Based on https://github.com/mpv-player/mpv/blob/master/player/lua/osc.lua - -local assdraw = require 'mp.assdraw' -local msg = require 'mp.msg' -local opt = require 'mp.options' -local utils = require 'mp.utils' - --- --- Parameters --- --- default user option values --- do not touch, change them in osc.conf -local user_opts = { - showwindowed = true, -- show OSC when windowed? - showfullscreen = true, -- show OSC when fullscreen? - scalewindowed = 1, -- scaling of the controller when windowed - scalefullscreen = 1, -- scaling of the controller when fullscreen - scaleforcedwindow = 2, -- scaling when rendered on a forced window - vidscale = false, -- scale the controller with the video? - barmargin = 0, -- vertical margin of top/bottombar - boxalpha = 0, -- alpha of the background box, - -- 0 (opaque) to 255 (fully transparent) - seekbaralpha = 255, - disabledbtnsalpha = 128, - hidetimeout = 3500, -- duration in ms until the OSC hides if no - -- mouse movement. enforced non-negative for the - -- user, but internally negative is "always-on". - fadeduration = 0, -- duration of fade out in ms, 0 = no fade - deadzonesize = 0, -- size of deadzone - minmousemove = 0, -- minimum amount of pixels the mouse has to - -- move between ticks to make the OSC show up - iamaprogrammer = false, -- use native mpv values and disable OSC - -- internal track list management (and some - -- functions that depend on it) - layout = "bottombar", - oscboxheight = 80, - oscboxwidth = 768, - seekbarstyle = "bar", -- bar, knob - pbseekbarheight = 8, -- playback seekbar, height of the box and handle - pbseekbarhandlesize = 8, - volseekbar = true, -- volume seekbar visibility, true/nil - volseekbarstyle = "bar", -- volknob, bar - volboxheight = 2, -- volume seekbar height - volboxwidth = 64, - volhandlesize = 8, - handlesize = 1, -- size ratio of the diamond and knob handle - seekrangestyle = "inverted",-- bar, line, slider, inverted or none - seekrangeseparate = true, -- wether the seekranges overlay on the bar-style seekbar - seekrangealpha = 210, -- transparency of seekranges - seekbarkeyframes = true, -- use keyframes when dragging the seekbar - tooltipborder = 1, -- border of tooltip in bottom/topbar - tooltipfontsize = 17.5, - tooltipseekbar = false, -- following cursor bar over the playback seekbar - tooltipseekbaralpha = 230, - timetotal = false, -- display total time instead of remaining time? - timems = false, -- display timecodes with milliseconds? - visibility = "auto", -- only used at init to set visibility_mode(...) - livemarkers = true, -- update seekbar chapter markers on duration change - chapters_osd = true, -- whether to show chapters OSD on next/prev - playlist_osd = true, -- whether to show playlist OSD on next/prev - chapter_fmt = "Chapter: %s", -- chapter print format for seekbar-hover. "no" to disable -} - --- read options from config and command-line -opt.read_options(user_opts, "osc", function(list) update_options(list) end) - -local osc_param = { -- calculated by osc_init() - playresy = 0, -- canvas size Y - playresx = 0, -- canvas size X - display_aspect = 1, - unscaled_y = 0, - areas = {}, - video_margins = { - l = 0, r = 0, t = 0, b = 0, -- left/right/top/bottom - }, -} - -local osc_styles = { - smallButtonsLlabel = "{\\fs13\\fn" .. mp.get_property("options/osd-font") .. "}", - - elementDown = "{\\1c&H9E9E9E}", - box = "{\\rDefault\\blur0\\bord0\\1c&H101010\\3c&HEFEFEF}", - seekbar = "{\\1c&HEFEFEF}", - - --buttons - buttonsLeft = "{\\blur0\\bord0\\1c&HEFEFEF\\3c&HEFEFEF\\fs17.5\\fnoscc}", - buttonsRight = "{\\blur0\\bord0\\1c&HEFEFEF\\3c&HEFEFEF\\fs17.5\\fnoscc}", - - --times - timecodesBar = "{\\blur0\\bord0\\1c&HEFEFEF\\3c&HEFEFEF\\fs17.5}", - timePosBar = "{\\blur2.4\\bord".. user_opts.tooltipborder .."\\1c&HEFEFEF\\3c&H000000\\fs" .. user_opts.tooltipfontsize .."}", -} - --- internal states, do not touch -local state = { - showtime, -- time of last invocation (last mouse move) - osc_visible = false, - anistart, -- time when the animation started - anitype, -- current type of animation - animation, -- current animation alpha - mouse_down_counter = 0, -- used for softrepeat - active_element = nil, -- nil = none, 0 = background, 1+ = see elements[] - active_event_source = nil, -- the "button" that issued the current event - rightTC_trem = not user_opts.timetotal, -- if the right timecode should display total or remaining time - tc_ms = user_opts.timems, -- Should the timecodes display their time with milliseconds - mp_screen_sizeX, mp_screen_sizeY, -- last screen-resolution, to detect resolution changes to issue reINITs - initREQ = false, -- is a re-init request pending? - marginsREQ = false, -- is a margins update pending? - last_mouseX, last_mouseY, -- last mouse position, to detect significant mouse movement - mouse_in_window = false, - message_text, - message_hide_timer, - fullscreen = false, - tick_timer = nil, - tick_last_time = 0, -- when the last tick() was run - hide_timer = nil, - cache_state = nil, - idle = false, - enabled = true, - input_enabled = true, - showhide_enabled = false, - dmx_cache = 0, - using_video_margins = false, - border = true, - maximized = false, - osd = mp.create_osd_overlay("ass-events"), - chapter_list = {}, -- sorted by time -} - - - -local window_control_box_width = 80 -local tick_delay = 0.03 - -local is_december = os.date("*t").month == 12 - --- --- Helperfunctions --- - -function kill_animation() - state.anistart = nil - state.animation = nil - state.anitype = nil -end - -function set_osd(res_x, res_y, text) - if state.osd.res_x == res_x and - state.osd.res_y == res_y and - state.osd.data == text then - return - end - state.osd.res_x = res_x - state.osd.res_y = res_y - state.osd.data = text - state.osd.z = 1000 - state.osd:update() -end - -local margins_opts = { - {"l", "video-margin-ratio-left"}, - {"r", "video-margin-ratio-right"}, - {"t", "video-margin-ratio-top"}, - {"b", "video-margin-ratio-bottom"}, -} - --- scale factor for translating between real and virtual ASS coordinates -function get_virt_scale_factor() - local w, h = mp.get_osd_size() - if w <= 0 or h <= 0 then - return 0, 0 - end - return osc_param.playresx / w, osc_param.playresy / h -end - --- return mouse position in virtual ASS coordinates (playresx/y) -function get_virt_mouse_pos() - if state.mouse_in_window then - local sx, sy = get_virt_scale_factor() - local x, y = mp.get_mouse_pos() - return x * sx, y * sy - else - return -1, -1 - end -end - -function set_virt_mouse_area(x0, y0, x1, y1, name) - local sx, sy = get_virt_scale_factor() - mp.set_mouse_area(x0 / sx, y0 / sy, x1 / sx, y1 / sy, name) -end - -function scale_value(x0, x1, y0, y1, val) - local m = (y1 - y0) / (x1 - x0) - local b = y0 - (m * x0) - return (m * val) + b -end - --- returns hitbox spanning coordinates (top left, bottom right corner) --- according to alignment -function get_hitbox_coords(x, y, an, w, h) - - local alignments = { - [1] = function () return x, y-h, x+w, y end, - [2] = function () return x-(w/2), y-h, x+(w/2), y end, - [3] = function () return x-w, y-h, x, y end, - - [4] = function () return x, y-(h/2), x+w, y+(h/2) end, - [5] = function () return x-(w/2), y-(h/2), x+(w/2), y+(h/2) end, - [6] = function () return x-w, y-(h/2), x, y+(h/2) end, - - [7] = function () return x, y, x+w, y+h end, - [8] = function () return x-(w/2), y, x+(w/2), y+h end, - [9] = function () return x-w, y, x, y+h end, - } - - return alignments[an]() -end - -function get_hitbox_coords_geo(geometry) - return get_hitbox_coords(geometry.x, geometry.y, geometry.an, - geometry.w, geometry.h) -end - -function get_element_hitbox(element) - return element.hitbox.x1, element.hitbox.y1, - element.hitbox.x2, element.hitbox.y2 -end - -function mouse_hit(element) - return mouse_hit_coords(get_element_hitbox(element)) -end - -function mouse_hit_coords(bX1, bY1, bX2, bY2) - local mX, mY = get_virt_mouse_pos() - return (mX >= bX1 and mX <= bX2 and mY >= bY1 and mY <= bY2) -end - -function limit_range(min, max, val) - if val > max then - val = max - elseif val < min then - val = min - end - return val -end - --- translate value into element coordinates -function get_slider_ele_pos_for(element, val) - - local ele_pos = scale_value( - element.slider.min.value, element.slider.max.value, - element.slider.min.ele_pos, element.slider.max.ele_pos, - val) - - return limit_range( - element.slider.min.ele_pos, element.slider.max.ele_pos, - ele_pos) -end - --- translates global (mouse) coordinates to value -function get_slider_value_at(element, glob_pos) - - local val = scale_value( - element.slider.min.glob_pos, element.slider.max.glob_pos, - element.slider.min.value, element.slider.max.value, glob_pos) - - return limit_range( - element.slider.min.value, element.slider.max.value, val) - -end - --- get value at current mouse position -function get_slider_value(element) - return get_slider_value_at(element, get_virt_mouse_pos()) -end - - -function countone(val) - if not (user_opts.iamaprogrammer) then - val = val + 1 - end - return val -end - --- align: -1 .. +1 --- frame: size of the containing area --- obj: size of the object that should be positioned inside the area --- margin: min. distance from object to frame (as long as -1 <= align <= +1) -function get_align(align, frame, obj, margin) - return (frame / 2) + (((frame / 2) - margin - (obj / 2)) * align) -end - --- multiplies two alpha values, formular can probably be improved -function mult_alpha(alphaA, alphaB) - return 255 - (((1-(alphaA/255)) * (1-(alphaB/255))) * 255) -end - -function add_area(name, x1, y1, x2, y2) - -- create area if needed - if (osc_param.areas[name] == nil) then - osc_param.areas[name] = {} - end - table.insert(osc_param.areas[name], {x1=x1, y1=y1, x2=x2, y2=y2}) -end - -function ass_append_alpha(ass, alpha, modifier) - local ar = {} - - for ai, av in pairs(alpha) do - av = mult_alpha(av, modifier) - if state.animation then - av = mult_alpha(av, state.animation) - end - ar[ai] = av - end - - ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}", - ar[1], ar[2], ar[3], ar[4])) -end - -function ass_draw_rr_h_cw(ass, x0, y0, x1, y1, r1, hexagon, r2) - if hexagon then - ass:hexagon_cw(x0, y0, x1, y1, r1, r2) - else - ass:round_rect_cw(x0, y0, x1, y1, r1, r2) - end -end - -function ass_draw_rr_h_ccw(ass, x0, y0, x1, y1, r1, hexagon, r2) - if hexagon then - ass:hexagon_ccw(x0, y0, x1, y1, r1, r2) - else - ass:round_rect_ccw(x0, y0, x1, y1, r1, r2) - end -end - - --- --- Tracklist Management --- - -local nicetypes = {video = "Video", audio = "Audio", sub = "Subtitle"} - --- updates the OSC internal playlists, should be run each time the track-layout changes -function update_tracklist() - local tracktable = mp.get_property_native("track-list", {}) - - -- by osc_id - tracks_osc = {} - tracks_osc.video, tracks_osc.audio, tracks_osc.sub = {}, {}, {} - -- by mpv_id - tracks_mpv = {} - tracks_mpv.video, tracks_mpv.audio, tracks_mpv.sub = {}, {}, {} - for n = 1, #tracktable do - if not (tracktable[n].type == "unknown") then - local type = tracktable[n].type - local mpv_id = tonumber(tracktable[n].id) - - -- by osc_id - table.insert(tracks_osc[type], tracktable[n]) - - -- by mpv_id - tracks_mpv[type][mpv_id] = tracktable[n] - tracks_mpv[type][mpv_id].osc_id = #tracks_osc[type] - end - end -end - --- return a nice list of tracks of the given type (video, audio, sub) -function get_tracklist(type) - local msg = "Available " .. nicetypes[type] .. " Tracks: " - if #tracks_osc[type] == 0 then - msg = msg .. "none" - else - for n = 1, #tracks_osc[type] do - local track = tracks_osc[type][n] - local lang, title, selected = "unknown", "", "○" - if not(track.lang == nil) then lang = track.lang end - if not(track.title == nil) then title = track.title end - if (track.id == tonumber(mp.get_property(type))) then - selected = "●" - end - msg = msg.."\n"..selected.." "..n..": ["..lang.."] "..title - end - end - return msg -end - --- relatively change the track of given by tracks - --(+1 -> next, -1 -> previous) -function set_track(type, next) - local current_track_mpv, current_track_osc - if (mp.get_property(type) == "no") then - current_track_osc = 0 - else - current_track_mpv = tonumber(mp.get_property(type)) - current_track_osc = tracks_mpv[type][current_track_mpv].osc_id - end - local new_track_osc = (current_track_osc + next) % (#tracks_osc[type] + 1) - local new_track_mpv - if new_track_osc == 0 then - new_track_mpv = "no" - else - new_track_mpv = tracks_osc[type][new_track_osc].id - end - - mp.commandv("set", type, new_track_mpv) - - if (new_track_osc == 0) then - show_message(nicetypes[type] .. " Track: none") - else - show_message(nicetypes[type] .. " Track: " - .. new_track_osc .. "/" .. #tracks_osc[type] - .. " [".. (tracks_osc[type][new_track_osc].lang or "unknown") .."] " - .. (tracks_osc[type][new_track_osc].title or "")) - end -end - --- get the currently selected track of , OSC-style counted -function get_track(type) - local track = mp.get_property(type) - if track ~= "no" and track ~= nil then - local tr = tracks_mpv[type][tonumber(track)] - if tr then - return tr.osc_id - end - end - return 0 -end - - --- Element Management --- - -local elements = {} - -function prepare_elements() - - -- remove elements without layout or invisble - local elements2 = {} - for n, element in pairs(elements) do - if not (element.layout == nil) and (element.visible) then - table.insert(elements2, element) - end - end - elements = elements2 - - function elem_compare (a, b) - return a.layout.layer < b.layout.layer - end - - table.sort(elements, elem_compare) - - - for _,element in pairs(elements) do - - local elem_geo = element.layout.geometry - - -- Calculate the hitbox - local bX1, bY1, bX2, bY2 = get_hitbox_coords_geo(elem_geo) - element.hitbox = {x1 = bX1, y1 = bY1, x2 = bX2, y2 = bY2} - - local style_ass = assdraw.ass_new() - - -- prepare static elements - style_ass:append("{}") -- hack to troll new_event into inserting a \n - style_ass:new_event() - style_ass:pos(elem_geo.x, elem_geo.y) - style_ass:an(elem_geo.an) - style_ass:append(element.layout.style) - - element.style_ass = style_ass - - local static_ass = assdraw.ass_new() - - - if (element.type == "box") then - --draw box - static_ass:draw_start() - ass_draw_rr_h_cw(static_ass, 0, 0, elem_geo.w, elem_geo.h, - element.layout.box.radius, element.layout.box.hexagon) - static_ass:draw_stop() - - elseif (element.type == "slider") then - --draw static slider parts - - local r1 = 0 - local r2 = 0 - local slider_lo = element.layout.slider - -- offset between element outline and drag-area - local foV = slider_lo.border + slider_lo.gap - - -- calculate positions of min and max points - if (slider_lo.stype ~= "bar") then - r1 = elem_geo.h / 2 - element.slider.min.ele_pos = elem_geo.h / 2 - element.slider.max.ele_pos = elem_geo.w - (elem_geo.h / 2) - if (slider_lo.stype == "diamond") then - r2 = (elem_geo.h - 2 * slider_lo.border) / 2 - elseif (slider_lo.stype == "knob") then - r2 = r1 - elseif (slider_lo.stype == "volknob") then - r2 = r1 - end - else - element.slider.min.ele_pos = - slider_lo.border + slider_lo.gap - element.slider.max.ele_pos = - elem_geo.w - (slider_lo.border + slider_lo.gap) - end - - element.slider.min.glob_pos = - element.hitbox.x1 + element.slider.min.ele_pos - element.slider.max.glob_pos = - element.hitbox.x1 + element.slider.max.ele_pos - - -- -- -- - - static_ass:draw_start() - - -- the box - ass_draw_rr_h_cw(static_ass, 0, 0, elem_geo.w, elem_geo.h, r1, slider_lo.stype == "diamond") - - -- the "hole" - ass_draw_rr_h_ccw(static_ass, slider_lo.border, slider_lo.border, - elem_geo.w - slider_lo.border, elem_geo.h - slider_lo.border, - r2, slider_lo.stype == "diamond") - - -- marker nibbles - if not (element.slider.markerF == nil) then - local markers = element.slider.markerF() - for _,marker in pairs(markers) do - if (marker > element.slider.min.value) and - (marker < element.slider.max.value) then - - local s = get_slider_ele_pos_for(element, marker) - local a = user_opts.pbseekbarheight / 2 - local b = user_opts.pbseekbarhandlesize / 2 - - static_ass:rect_cw(s - 1.25, a + b, - s + 1.25, b - a); - - end - end - end - end - - element.static_ass = static_ass - - - -- if the element is supposed to be disabled, - -- style it accordingly and kill the eventresponders - if not (element.enabled) then - element.layout.alpha[1] = user_opts.disabledbtnsalpha - element.eventresponder = nil - end - end -end - - --- --- Element Rendering --- - --- returns nil or a chapter element from the native property chapter-list -function get_chapter(possec) - local cl = state.chapter_list -- sorted, get latest before possec, if any - - for n=#cl,1,-1 do - if possec >= cl[n].time then - return cl[n] - end - end -end - -function render_elements(master_ass) - -- when the slider is dragged or hovered and we have a target chapter name - -- then we use it instead of the normal title. we calculate it before the - -- render iterations because the title may be rendered before the slider. - state.forced_title = nil - local se, ae = state.slider_element, elements[state.active_element] - - - if user_opts.chapter_fmt ~= "no" and se and (ae == se or (not ae and mouse_hit(se))) then - local dur = mp.get_property_number("duration", 0) - if dur > 0 then - local possec = get_slider_value(se) * dur / 100 -- of mouse pos - local ch = get_chapter(possec) - if ch and ch.title and ch.title ~= "" then - show_message(string.format(user_opts.chapter_fmt, ch.title)) - end - end - end - - for n=1, #elements do - local element = elements[n] - - local style_ass = assdraw.ass_new() - style_ass:merge(element.style_ass) - ass_append_alpha(style_ass, element.layout.alpha, 0) - - if element.eventresponder and (state.active_element == n) then - - -- run render event functions - if not (element.eventresponder.render == nil) then - element.eventresponder.render(element) - end - - if mouse_hit(element) then - -- mouse down styling - if (element.styledown) then - style_ass:append(osc_styles.elementDown) - end - - if (element.softrepeat) and (state.mouse_down_counter >= 15 - and state.mouse_down_counter % 5 == 0) then - - element.eventresponder[state.active_event_source.."_down"](element) - end - state.mouse_down_counter = state.mouse_down_counter + 1 - end - - end - - local elem_ass = assdraw.ass_new() - - elem_ass:merge(style_ass) - - if not (element.type == "button") then - elem_ass:merge(element.static_ass) - end - - if (element.type == "slider") then - - local slider_lo = element.layout.slider - local elem_geo = element.layout.geometry - local s_min = element.slider.min.value - local s_max = element.slider.max.value - - -- draw pos marker - local foH, xp - local pos = element.slider.posF() - local foV = slider_lo.border + slider_lo.gap - local innerH = elem_geo.h - (2 * foV) - local seekRanges = element.slider.seekRangesF() - local seekRangeLineHeight = innerH / 5 - local handlesize = user_opts.handlesize - - - if slider_lo.stype ~= "bar" then - foH = elem_geo.h / 2 - else - foH = slider_lo.border + slider_lo.gap - end - - if pos then - xp = get_slider_ele_pos_for(element, pos) - local r = (handlesize * innerH) / 2 - local h = elem_geo.h / 2 - local pbh = user_opts.pbseekbarheight / 2 - local vbh = user_opts.volboxheight / 2 - - if slider_lo.stype == "knob" then - - ass_draw_rr_h_cw(elem_ass, xp - r, foH - r, xp + r, foH + r,r) - ass_draw_rr_h_cw(elem_ass, 0, h - pbh, xp, h + pbh, 0) - - elseif slider_lo.stype == "volknob" then - - ass_draw_rr_h_cw(elem_ass, xp - r, foH - r, xp + r, foH + r,r) - ass_draw_rr_h_cw(elem_ass, 0, h - vbh, xp, h + vbh, 0) - - else - - local h = 0 - - if seekRanges and user_opts.seekrangeseparate and slider_lo.rtype ~= "inverted" then - h = seekRangeLineHeight - end - - elem_ass:rect_cw(foH, foV, xp, elem_geo.h - foV - h) - - if seekRanges and not user_opts.seekrangeseparate and slider_lo.rtype ~= "inverted" then - -- Punch holes for the seekRanges to be drawn later - for _,range in pairs(seekRanges) do - if range["start"] < pos then - local pstart = get_slider_ele_pos_for(element, range["start"]) - local pend = xp - - if pos > range["end"] then - pend = get_slider_ele_pos_for(element, range["end"]) - end - elem_ass:rect_ccw(pstart, elem_geo.h - foV - seekRangeLineHeight, pend, elem_geo.h - foV) - end - end - end - end - - if slider_lo.rtype == "slider" then - ass_draw_rr_h_cw(elem_ass, foH - innerH / 6, foH - innerH / 6, - xp, foH + innerH / 6, - innerH / 6, slider_lo.stype == "diamond", 0) - ass_draw_rr_h_cw(elem_ass, xp, foH - innerH / 15, - elem_geo.w - foH + innerH / 15, foH + innerH / 15, - 0, slider_lo.stype == "diamond", innerH / 15) - for _,range in pairs(seekRanges or {}) do - local pstart = get_slider_ele_pos_for(element, range["start"]) - local pend = get_slider_ele_pos_for(element, range["end"]) - ass_draw_rr_h_ccw(elem_ass, pstart, foH - innerH / 21, - pend, foH + innerH / 21, - innerH / 21, slider_lo.stype == "diamond") - end - end - end - - if seekRanges then - if slider_lo.rtype ~= "inverted" then - elem_ass:draw_stop() - elem_ass:merge(element.style_ass) - ass_append_alpha(elem_ass, element.layout.alpha, user_opts.seekrangealpha) - elem_ass:merge(element.static_ass) - end - - for _,range in pairs(seekRanges) do - local pstart = get_slider_ele_pos_for(element, range["start"]) - local pend = get_slider_ele_pos_for(element, range["end"]) - - if slider_lo.rtype == "slider" then - ass_draw_rr_h_cw(elem_ass, pstart, foH - innerH / 21, - pend, foH + innerH / 21, - innerH / 21, slider_lo.stype == "diamond") - elseif slider_lo.rtype == "line" then - if slider_lo.stype == "bar" then - elem_ass:rect_cw(pstart, elem_geo.h - foV - seekRangeLineHeight, pend, elem_geo.h - foV) - else - ass_draw_rr_h_cw(elem_ass, pstart - innerH / 8, foH - innerH / 8, - pend + innerH / 8, foH + innerH / 8, - innerH / 8, slider_lo.stype == "diamond") - end - elseif slider_lo.rtype == "bar" then - if slider_lo.stype ~= "bar" then - ass_draw_rr_h_cw(elem_ass, pstart - innerH / 2, foV, - pend + innerH / 2, foV + innerH, - innerH / 2, slider_lo.stype == "diamond") - elseif range["end"] >= (pos or 0) then - elem_ass:rect_cw(pstart, foV, pend, elem_geo.h - foV) - else - elem_ass:rect_cw(pstart, elem_geo.h - foV - seekRangeLineHeight, pend, elem_geo.h - foV) - end - elseif slider_lo.rtype == "inverted" then - if slider_lo.stype ~= "bar" then - ass_draw_rr_h_ccw(elem_ass, pstart, (elem_geo.h / 2) - 1, pend, - (elem_geo.h / 2) + 1, - 1, slider_lo.stype == "diamond") - else - elem_ass:rect_ccw(pstart, (elem_geo.h / 2) - 1, pend, (elem_geo.h / 2) + 1) - end - end - end - end - - elem_ass:draw_stop() - - - -- add tooltip - if not (element.slider.tooltipF == nil) then - - if mouse_hit(element) then - local sliderpos = get_slider_value(element) - local tooltiplabel = element.slider.tooltipF(sliderpos) - - local an = slider_lo.tooltip_an - - local ty, tx - - tx = get_virt_mouse_pos() - ty = element.hitbox.y1 - 8 - - if user_opts.layout == "topbar" then - ty = element.hitbox.y2 + user_opts.tooltipfontsize + 8 - end - - local ta = 55 --left margin - local tb = element.hitbox.x2 - ta --right margin - - - local playersx = osc_param.playresx - local oscboxwidth = user_opts.oscboxwidth - local sum = s_min + ta - - - if tx > sum then - ta = tx - if (tx > element.hitbox.x2 - 55) then - ta = tb - end - end - - if playersx == oscboxwidth then - tx = ta - end - - -- tooltip label - elem_ass:new_event() - elem_ass:pos(tx, ty) - elem_ass:an(an) - elem_ass:append(slider_lo.tooltip_style) - elem_ass:append(tooltiplabel) - - -- tooltip seekbar - if user_opts.tooltipseekbar then - local ww = (playersx - oscboxwidth) / 2 - - elem_ass:merge(style_ass) - ass_append_alpha(elem_ass, element.layout.alpha, user_opts.tooltipseekbaralpha) - elem_ass:merge(element.static_ass) - - elem_ass:rect_ccw(0, 0, tx - ww, elem_geo.h) - end - - - end - end - - elseif (element.type == "button") then - - local buttontext - if type(element.content) == "function" then - buttontext = element.content() -- function objects - elseif not (element.content == nil) then - buttontext = element.content -- text objects - end - - local maxchars = element.layout.button.maxchars - if not (maxchars == nil) and (#buttontext > maxchars) then - local max_ratio = 1.25 -- up to 25% more chars while shrinking - local limit = math.max(0, math.floor(maxchars * max_ratio) - 3) - if (#buttontext > limit) then - while (#buttontext > limit) do - buttontext = buttontext:gsub(".[\128-\191]*$", "") - end - buttontext = buttontext .. "..." - end - local _, nchars2 = buttontext:gsub(".[\128-\191]*", "") - local stretch = (maxchars/#buttontext)*100 - buttontext = string.format("{\\fscx%f}", - (maxchars/#buttontext)*100) .. buttontext - end - - elem_ass:append(buttontext) - end - - master_ass:merge(elem_ass) - end -end - --- --- Message display --- - --- pos is 1 based -function limited_list(prop, pos) - local proplist = mp.get_property_native(prop, {}) - local count = #proplist - if count == 0 then - return count, proplist - end - - local fs = tonumber(mp.get_property('options/osd-font-size')) - local max = math.ceil(osc_param.unscaled_y*0.75 / fs) - if max % 2 == 0 then - max = max - 1 - end - local delta = math.ceil(max / 2) - 1 - local begi = math.max(math.min(pos - delta, count - max + 1), 1) - local endi = math.min(begi + max - 1, count) - - local reslist = {} - for i=begi, endi do - local item = proplist[i] - item.current = (i == pos) and true or nil - table.insert(reslist, item) - end - return count, reslist -end - -function get_playlist() - local pos = mp.get_property_number('playlist-pos', 0) + 1 - local count, limlist = limited_list('playlist', pos) - if count == 0 then - return 'Empty playlist.' - end - - local message = string.format('Playlist %d/%d:\n', pos, count) - for i, v in ipairs(limlist) do - local title = v.title - local _, filename = utils.split_path(v.filename) - if title == nil then - title = filename - end - message = string.format('%s %s %s\n', message, - (v.current and '●' or '○'), title) - end - return message -end - -function get_chapterlist() - local pos = mp.get_property_number('chapter', 0) + 1 - local count, limlist = limited_list('chapter-list', pos) - if count == 0 then - return 'No chapters.' - end - - local message = string.format('Chapters %d/%d:\n', pos, count) - for i, v in ipairs(limlist) do - local time = mp.format_time(v.time) - local title = v.title - if title == nil then - title = string.format('Chapter %02d', i) - end - message = string.format('%s%s %s %s\n', message, time, - (v.current and '●' or '○'), title) - end - return message -end - -function show_message(text, duration) - - --print("text: "..text.." duration: " .. duration) - if duration == nil then - duration = tonumber(mp.get_property("options/osd-duration")) / 1000 - elseif not type(duration) == "number" then - print("duration: " .. duration) - end - - -- cut the text short, otherwise the following functions - -- may slow down massively on huge input - text = string.sub(text, 0, 4000) - - -- replace actual linebreaks with ASS linebreaks - text = string.gsub(text, "\n", "\\N") - - state.message_text = text - - if not state.message_hide_timer then - state.message_hide_timer = mp.add_timeout(0, request_tick) - end - state.message_hide_timer:kill() - state.message_hide_timer.timeout = duration - state.message_hide_timer:resume() - request_tick() -end - -function render_message(ass) - if state.message_hide_timer and state.message_hide_timer:is_enabled() and - state.message_text - then - local _, lines = string.gsub(state.message_text, "\\N", "") - - local fontsize = tonumber(mp.get_property("options/osd-font-size")) - local outline = tonumber(mp.get_property("options/osd-border-size")) - local maxlines = math.ceil(osc_param.unscaled_y*0.75 / fontsize) - local counterscale = osc_param.playresy / osc_param.unscaled_y - - fontsize = fontsize * counterscale / math.max(0.65 + math.min(lines/maxlines, 1), 1) - outline = outline * counterscale / math.max(0.75 + math.min(lines/maxlines, 1)/2, 1) - - local style = "{\\bord" .. outline .. "\\fs" .. fontsize .. "}" - - - ass:new_event() - ass:append(style .. state.message_text) - else - state.message_text = nil - end -end - --- --- Initialisation and Layout --- - -function new_element(name, type) - elements[name] = {} - elements[name].type = type - - -- add default stuff - elements[name].eventresponder = {} - elements[name].visible = true - elements[name].enabled = true - elements[name].softrepeat = false - elements[name].styledown = (type == "button") - elements[name].state = {} - - if (type == "slider") then - elements[name].slider = {min = {value = 0}, max = {value = 100}} - end - - - return elements[name] -end - -function add_layout(name) - if not (elements[name] == nil) then - -- new layout - elements[name].layout = {} - - -- set layout defaults - elements[name].layout.layer = 50 - elements[name].layout.alpha = {[1] = 0, [2] = 255, [3] = 255, [4] = 255} - - if (elements[name].type == "button") then - elements[name].layout.button = { - maxchars = nil, - } - elseif (elements[name].type == "slider") then - -- slider defaults - elements[name].layout.slider = { - border = 1, - gap = 1, - stype = "slider", - adjust_tooltip = true, - tooltip_style = "", - tooltip_an = 2, - alpha = {[1] = 0, [2] = 255, [3] = 88, [4] = 255}, - } - elseif (elements[name].type == "box") then - elements[name].layout.box = {radius = 0, hexagon = false} - end - - return elements[name].layout - else - msg.error("Can't add_layout to element \""..name.."\", doesn't exist.") - end -end - - - -local layouts = {} - -function bar_layout(direction) - local osc_geo = { - x, - y, - an = 4, - w = user_opts.oscboxwidth, - h = user_opts.oscboxheight, - } - - - local btnw_left = string.match(osc_styles.buttonsLeft, "fs(.%d)") - local btnw_right = string.match(osc_styles.buttonsRight, "fs(.%d)") - - local btnw_rightlbl = btnw_right + string.match(osc_styles.smallButtonsLlabel, "fs(.%d)") + 12 - - - local btnwtime = string.match(osc_styles.timecodesBar, "fs(.%d)") - local timew = btnwtime * 8 - local timewfull = btnwtime * 11.5 - - - local padd = 30 - - local marg_b = 32 - local marg_s = 12 - local marg_r = 22 - - - local osc_paramsx = osc_param.playresx - - if (osc_paramsx < osc_geo.w) then - osc_param.playresy = osc_geo.w / osc_param.display_aspect - osc_param.playresx = osc_param.playresy * osc_param.display_aspect - end - - --bottom margin osc - local hlf = osc_geo.h / 2 - local hlfw = osc_geo.w / 2 - - osc_geo.x = osc_param.playresx / 2 - hlfw - osc_geo.y = user_opts.barmargin - hlf - - if user_opts.layout == "topbar" then - osc_geo.y = hlf - user_opts.barmargin - end - - - - - if direction < 0 then - osc_geo.y = osc_geo.y + osc_param.playresy - end - - local sh = user_opts.pbseekbarheight / 2 - local shh = sh - 1 - - local line1 = osc_geo.y + direction * (osc_geo.h / 2 - sh) - local line2 - line2 = osc_geo.y - direction + shh - - if user_opts.layout == "topbar" then - line2 = osc_geo.y - direction - shh - end - - - add_area("input", get_hitbox_coords(osc_geo.x, osc_geo.y, osc_geo.an, osc_geo.w, osc_geo.h)) - - local lo, geo - - - -- Background bar - new_element("bgbox", "box") - lo = add_layout("bgbox") - - lo.geometry = osc_geo - lo.layer = 10 - lo.style = osc_styles.box - lo.alpha[1] = user_opts.boxalpha - - - - -- Playback control buttons - geo = { x = osc_geo.x + padd, y = line2, an = 4, - w = btnw_left, h = btnw_left} - - local bw = 8 - local bw2 = bw * 2 - - - -- Left - -- Play/Pause - lo = add_layout("playpause") - lo.geometry = geo - lo.style = osc_styles.buttonsLeft - - -- Chapter prev - geo = { x = geo.x + bw + marg_b, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("ch_prev") - lo.geometry = geo - lo.style = osc_styles.buttonsLeft - - -- Playlist prev - geo = { x = geo.x + bw2 + marg_s, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("pl_prev") - lo.geometry = geo - lo.style = osc_styles.buttonsLeft - - - -- Playlist next - geo = { x = geo.x + marg_s + bw, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("pl_next") - lo.geometry = geo - lo.style = osc_styles.buttonsLeft - - - -- Chapter next - geo = { x = geo.x + bw + marg_s, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("ch_next") - lo.geometry = geo - lo.style = osc_styles.buttonsLeft - - - -- Left timecode - geo = { x = geo.x + bw2 + marg_b, y = geo.y, an = geo.an, w = timew, h = btnw_right } - - if state.tc_ms then - geo["w"] = timewfull - end - - lo = add_layout("tc_left") - lo.geometry = geo - lo.style = osc_styles.timecodesBar - - -- Cache - geo = { x = geo.x + geo.w + marg_s, y = geo.y, - an = geo.an, w = 0, h = 0 } - lo = add_layout("cache") - lo.geometry = geo - lo.style = osc_styles.timecodesBar - - - - -- Right - -- Seekbarvol - - if user_opts.volseekbar then - - local volboxheight = user_opts.volboxheight - local volboxwidth = user_opts.volboxwidth - local volhandlesize = user_opts.volhandlesize - - geo = { x = osc_geo.x + osc_geo.w - volboxwidth - padd, y = geo.y, an = geo.an, w = volboxwidth, h = volboxheight } - new_element("bgbarvol", "box") - lo = add_layout("bgbarvol") - - lo.geometry = geo - lo.layer = 15 - lo.style = osc_styles.timecodesBar - lo.alpha[1] = user_opts.seekbaralpha - if not (user_opts["seekbarstyle"] == "bar") then - lo.box.radius = geo.h / 2 - lo.box.hexagon = user_opts["seekbarstyle"] == "diamond" - end - - lo = add_layout("volseekbar") - lo.geometry = { x = geo.x, y = geo.y, an = geo.an, - w = geo.w, h = volhandlesize } - lo.style = osc_styles.timecodesBar - lo.slider.border = 1 - lo.slider.gap = 0 - lo.slider.stype = user_opts["volseekbarstyle"] - - end - - -- Volume - if user_opts.volseekbar then - geo = { x = geo.x - bw2 - marg_s, y = geo.y, an = geo.an, w = btnw_right, h = btnw_right } - else - geo = { x = osc_geo.x + osc_geo.w - bw2 - padd, y = geo.y, an = geo.an, w = btnw_right, h = btnw_right } - end - - lo = add_layout("volume") - lo.geometry = geo - lo.style = osc_styles.buttonsRight - - - - -- Right - local bw3 = bw * 4.7 - local bw4 = bw * 5.3 - - - -- Shuffle - geo = { x = geo.x - bw2 - marg_b, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("cy_shuf") - lo.geometry = geo - lo.style = osc_styles.buttonsRight - - -- Loop - geo = { x = geo.x - bw3 - marg_r, y = geo.y, an = geo.an, w = btnw_rightlbl, h = geo.h } - lo = add_layout("cy_loop") - lo.geometry = geo - lo.style = osc_styles.buttonsRight - - -- Ontop - geo = { x = geo.x - bw4 - marg_r, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("cy_ontop") - lo.geometry = geo - lo.style = osc_styles.buttonsRight - - - -- Closed Captures selection buttons - geo = { x = geo.x - bw4 - marg_r, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("cy_sub") - lo.geometry = geo - lo.style = osc_styles.buttonsRight - - - -- Track selection buttons - geo = { x = geo.x - bw4 - marg_r, y = geo.y, an = geo.an, w = geo.w, h = geo.h} - lo = add_layout("cy_audio") - lo.geometry = geo - lo.style = osc_styles.buttonsRight - - - - - - -- Seekbar - - local heightbar = user_opts.pbseekbarheight - local heighthandle = user_opts.pbseekbarhandlesize - - new_element("bgbar1", "box") - lo = add_layout("bgbar1") - lo.geometry = { x = osc_geo.x, y = line1, an = geo.an, - w = osc_geo.w, h = heightbar } - lo.layer = 15 - lo.style = osc_styles.timecodesBar - lo.alpha[1] = user_opts.seekbaralpha - if not (user_opts["seekbarstyle"] == "bar") then - lo.box.radius = 0 - lo.box.hexagon = user_opts["seekbarstyle"] == "diamond" - end - - lo = add_layout("seekbar") - lo.geometry = { x = osc_geo.x, y = line1, an = geo.an, - w = osc_geo.w, h = heighthandle } - lo.style = osc_styles.seekbar - lo.slider.border = 1 - lo.slider.gap = 0 - lo.slider.tooltip_style = osc_styles.timePosBar - lo.slider.tooltip_an = 2 - lo.slider.stype = user_opts["seekbarstyle"] - lo.slider.rtype = user_opts["seekrangestyle"] - -end - - -layouts["bottombar"] = function() - bar_layout(-1) -end - -layouts["topbar"] = function() - bar_layout(1) -end - --- Validate string type user options -function validate_user_opts() - if layouts[user_opts.layout] == nil then - msg.warn("Invalid setting \""..user_opts.layout.."\" for layout") - user_opts.layout = "bottombar" - end - - if user_opts.seekbarstyle ~= "bar" and - user_opts.seekbarstyle ~= "diamond" and - user_opts.seekbarstyle ~= "knob" then - msg.warn("Invalid setting \"" .. user_opts.seekbarstyle - .. "\" for seekbarstyle") - user_opts.seekbarstyle = "bar" - end - - if user_opts.seekrangestyle ~= "bar" and - user_opts.seekrangestyle ~= "line" and - user_opts.seekrangestyle ~= "slider" and - user_opts.seekrangestyle ~= "inverted" and - user_opts.seekrangestyle ~= "none" then - msg.warn("Invalid setting \"" .. user_opts.seekrangestyle - .. "\" for seekrangestyle") - user_opts.seekrangestyle = "inverted" - end - - if user_opts.seekrangestyle == "slider" and - user_opts.seekbarstyle == "bar" then - msg.warn("Using \"slider\" seekrangestyle together with \"bar\" seekbarstyle is not supported") - user_opts.seekrangestyle = "inverted" - end - -end - -function update_options(list) - validate_user_opts() - request_tick() - visibility_mode(user_opts.visibility, true) - update_duration_watch() - request_init() -end - --- OSC INIT -function osc_init() - msg.debug("osc_init") - - -- set canvas resolution according to display aspect and scaling setting - local baseResY = 720 - local display_w, display_h, display_aspect = mp.get_osd_size() - local scale = 1 - - if (mp.get_property("video") == "no") then -- dummy/forced window - scale = user_opts.scaleforcedwindow - elseif state.fullscreen then - scale = user_opts.scalefullscreen - else - scale = user_opts.scalewindowed - end - - if user_opts.vidscale then - osc_param.unscaled_y = baseResY - else - osc_param.unscaled_y = display_h - end - osc_param.playresy = osc_param.unscaled_y / scale - if (display_aspect > 0) then - osc_param.display_aspect = display_aspect - end - osc_param.playresx = osc_param.playresy * osc_param.display_aspect - - - -- stop seeking with the slider to prevent skipping files - state.active_element = nil - - osc_param.video_margins = {l = 0, r = 0, t = 0, b = 0} - - elements = {} - - -- some often needed stuff - local pl_count = mp.get_property_number("playlist-count", 0) - local have_pl = (pl_count > 1) - local pl_pos = mp.get_property_number("playlist-pos", 0) + 1 - local have_ch = (mp.get_property_number("chapters", 0) > 0) - local loop = mp.get_property("loop-playlist", "no") - - local ne - - - -- playlist buttons - - -- prev - ne = new_element("pl_prev", "button") - - ne.content = "\xee\x80\x83" - ne.enabled = (pl_pos > 1) or (loop ~= "no") - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("playlist-prev", "weak") - if user_opts.playlist_osd then - show_message(get_playlist(), 3) - end - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_playlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_playlist(), 3) end - - --next - ne = new_element("pl_next", "button") - - ne.content = "\xee\x80\x84" - ne.enabled = (have_pl and (pl_pos < pl_count)) or (loop ~= "no") - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("playlist-next", "weak") - if user_opts.playlist_osd then - show_message(get_playlist(), 3) - end - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_playlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_playlist(), 3) end - - - - -- big buttons - - - --playpause - ne = new_element("playpause", "button") - - ne.content = function () - if mp.get_property("pause") == "yes" then - return ('\xee\x80\x81') - else - return ('\xee\x80\x80') - end - end - - ne.eventresponder["mbtn_left_up"] = - function () mp.commandv("cycle", "pause") end - - - - --skipback - ne = new_element("skipback", "button") - - ne.softrepeat = true - ne.content = "\238\128\132" - ne.eventresponder["mbtn_left_down"] = - function () mp.commandv("seek", -5, "relative", "keyframes") end - ne.eventresponder["shift+mbtn_left_down"] = - function () mp.commandv("frame-back-step") end - ne.eventresponder["mbtn_right_down"] = - function () mp.commandv("seek", -30, "relative", "keyframes") end - - - --skipfrwd - ne = new_element("skipfrwd", "button") - - ne.softrepeat = true - ne.content = "\238\128\133" - ne.eventresponder["mbtn_left_down"] = - function () mp.commandv("seek", 10, "relative", "keyframes") end - ne.eventresponder["shift+mbtn_left_down"] = - function () mp.commandv("frame-step") end - ne.eventresponder["mbtn_right_down"] = - function () mp.commandv("seek", 60, "relative", "keyframes") end - - - --ch_prev - ne = new_element("ch_prev", "button") - - ne.enabled = have_ch - ne.content = "\xee\x80\x82" - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("add", "chapter", -1) - if user_opts.chapters_osd then - show_message(get_chapterlist(), 3) - end - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_chapterlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_chapterlist(), 3) end - - - --ch_next - ne = new_element("ch_next", "button") - - ne.enabled = have_ch - ne.content = "\xee\x80\x85" - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("add", "chapter", 1) - if user_opts.chapters_osd then - show_message(get_chapterlist(), 3) - end - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_chapterlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_chapterlist(), 3) end - - -- - update_tracklist() - - - --cy_audio - ne = new_element("cy_audio", "button") - - ne.enabled = (#tracks_osc.audio > 0) - ne.content = function () - local aid = "–" - if not (get_track("audio") == 0) then - aid = get_track("audio") - end - return ("\xee\x80\x86" .. osc_styles.smallButtonsLlabel - .. " " .. aid .. "/" .. #tracks_osc.audio) - end - - ne.eventresponder["mbtn_left_up"] = - function () set_track("audio", 1) end - ne.eventresponder["mbtn_right_up"] = - function () set_track("audio", -1) end - ne.eventresponder["shift+mbtn_left_down"] = - function () show_message(get_tracklist("audio"), 2) end - - - --cy_sub - ne = new_element("cy_sub", "button") - - ne.enabled = (#tracks_osc.sub > 0) - ne.content = function () - local sid = "–" - if not (get_track("sub") == 0) then - sid = get_track("sub") - end - return ("\xee\x80\x87" .. osc_styles.smallButtonsLlabel - .. " " .. sid .. "/" .. #tracks_osc.sub) - end - ne.eventresponder["mbtn_left_up"] = - function () set_track("sub", 1) end - ne.eventresponder["mbtn_right_up"] = - function () set_track("sub", -1) end - ne.eventresponder["shift+mbtn_left_down"] = - function () show_message(get_tracklist("sub"), 2) end - - - --cy_loop - ne = new_element("cy_loop", "button") - - local lf = "Loop current file: " - local lp = "Loop current playlist: " - local ico = "\xee\x80\x88" .. osc_styles.smallButtonsLlabel - - local y = "yes" - local n = "no" - - ne.content = function () - if (mp.get_property("loop") == n) then - return (ico .. " No") - else - return (ico .. " Yes") - end - end - - ne.eventresponder["mbtn_left_up"] = - function () - - if (mp.get_property("loop") == n) then - mp.set_property("loop", y) - show_message(lf .. y) - else - mp.set_property("loop", n) - show_message(lf .. n) - end - end - - ne.eventresponder["shift+mbtn_left_up"] = - function () - if (mp.get_property("loop-playlist") == n) then - mp.set_property("loop-playlist", y) - show_message(lp .. y) - else - mp.set_property("loop-playlist", n) - show_message(lp .. n) - end - end - - - --cy_shuf - ne = new_element("cy_shuf", "button") - - ne.content = "\xee\x80\x89" - ne.enabled = have_pl - - ne.eventresponder["mbtn_left_up"] = - - function () - mp.commandv("playlist-shuffle") - show_message("Shuffled") - - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_playlist(), 3) end - - - --cy_ontop - ne = new_element("cy_ontop", "button") - - local t = "Stay on top: " - local b = "Border: " - local ico = "\xee\x80\x8f" .. osc_styles.smallButtonsLlabel - - local y = "yes" - local n = "no" - - ne.content = function () - if (mp.get_property("ontop") == "no") then - return (ico .. " No") - else - return (ico .. " Yes") - end - - end - - ne.eventresponder["mbtn_left_up"] = - function () - if (mp.get_property("ontop") == n) then - mp.set_property("ontop", y) - show_message(t .. y) - else - mp.set_property("ontop", n) - show_message(t .. n) - end - end - - ne.eventresponder["shift+mbtn_left_up"] = - function () - if (mp.get_property("border") == n) then - mp.set_property("border", y) - show_message(b .. y) - else - mp.set_property("border", n) - show_message(b .. n) - end - end - - - --tog_fs - ne = new_element("tog_fs", "button") - ne.content = function () - if (state.fullscreen) then - return ('\xee\x80\x8e') - else - return ('\xee\x80\x8d') - end - end - ne.eventresponder["mbtn_left_up"] = - function () mp.commandv("cycle", "fullscreen") end - - - --seekbar - ne = new_element("seekbar", "slider") - - ne.enabled = not (mp.get_property("percent-pos") == nil) - state.slider_element = ne.enabled and ne or nil -- used for forced_title - ne.slider.markerF = function () - local duration = mp.get_property_number("duration", nil) - if not (duration == nil) then - local chapters = mp.get_property_native("chapter-list", {}) - local markers = {} - for n = 1, #chapters do - markers[n] = (chapters[n].time / duration * 100) - end - - return markers - - else - return {} - end - - - end - ne.slider.posF = - function () return mp.get_property_number("percent-pos", nil) end - ne.slider.tooltipF = function (pos) - local duration = mp.get_property_number("duration", nil) - if not ((duration == nil) or (pos == nil)) then - possec = duration * (pos / 100) - return mp.format_time(possec) - else - return "" - end - end - ne.slider.seekRangesF = function() - if user_opts.seekrangestyle == "none" then - return nil - end - local cache_state = state.cache_state - if not cache_state then - return nil - end - local duration = mp.get_property_number("duration", nil) - if (duration == nil) or duration <= 0 then - return nil - end - local ranges = cache_state["seekable-ranges"] - if #ranges == 0 then - return nil - end - local nranges = {} - for _, range in pairs(ranges) do - nranges[#nranges + 1] = { - ["start"] = 100 * range["start"] / duration, - ["end"] = 100 * range["end"] / duration, - } - end - return nranges - end - ne.eventresponder["mouse_move"] = --keyframe seeking when mouse is dragged - function (element) - -- mouse move events may pile up during seeking and may still get - -- sent when the user is done seeking, so we need to throw away - -- identical seeks - local seekto = get_slider_value(element) - if (element.state.lastseek == nil) or - (not (element.state.lastseek == seekto)) then - local flags = "absolute-percent" - if not user_opts.seekbarkeyframes then - flags = flags .. "+exact" - end - mp.commandv("seek", seekto, flags) - element.state.lastseek = seekto - end - - end - ne.eventresponder["mbtn_left_down"] = --exact seeks on single clicks - function (element) mp.commandv("seek", get_slider_value(element), - "absolute-percent", "exact") end - ne.eventresponder["reset"] = - function (element) element.state.lastseek = nil end - - - - --volseekbar - - if user_opts.volseekbar then - - - ne = new_element("volseekbar", "slider") - - ne.slider.posF = - function () return mp.get_property_osd("volume") end - - ne.slider.seekRangesF = function() - return nil end - - ne.eventresponder["mouse_move"] = - function (element) - - local seekto = get_slider_value(element) - - mp.commandv("set", "volume", seekto) - - end - - ne.eventresponder["mbtn_left_down"] = --exact seeks on single clicks - function (element) - mp.commandv("set", "volume", get_slider_value(element)) - end - - end - - - - - -- tc_left (current pos) - ne = new_element("tc_left", "button") - - ne.content = function () - - if (state.tc_ms) then - - if (state.rightTC_trem) then - return (mp.get_property_osd("playback-time/full")) .. " / " .. (mp.get_property_osd("playtime-remaining/full")) - else - return (mp.get_property_osd("playback-time/full")) .. " / " .. (mp.get_property_osd("duration/full")) - end - - else - - if (state.rightTC_trem) then - return (mp.get_property_osd("playback-time")) .. " / " .. (mp.get_property_osd("playtime-remaining")) - else - return (mp.get_property_osd("playback-time")) .. " / " .. (mp.get_property_osd("duration")) - end - - end - - end - - ne.eventresponder["mbtn_left_up"] = function () - state.tc_ms = not state.tc_ms - request_init() - end - - ne.eventresponder["shift+mbtn_left_up"] = function () - state.rightTC_trem = not state.rightTC_trem - end - - - --cache - ne = new_element("cache", "button") - - ne.content = function () - local cache_state = state.cache_state - if not (cache_state and cache_state["seekable-ranges"] and - #cache_state["seekable-ranges"] > 0) then - -- probably not a network stream - return "" - end - local dmx_cache = cache_state and cache_state["cache-duration"] - local thresh = math.min(state.dmx_cache * 0.05, 5) -- 5% or 5s - if dmx_cache and math.abs(dmx_cache - state.dmx_cache) >= thresh then - state.dmx_cache = dmx_cache - else - dmx_cache = state.dmx_cache - end - local min = math.floor(dmx_cache / 60) - local sec = math.floor(dmx_cache % 60) -- don't round e.g. 59.9 to 60 - return (min > 0 and - string.format(" %sm%02.0fs", min, sec) or - string.format(" %3.0fs", sec)) - end - - ne.eventresponder["mbtn_left_up"] = - function () show_message("Cache") end - - -- volume - ne = new_element("volume", "button") - - ne.content = function() - local volume = mp.get_property_number("volume", 0) - local mute = mp.get_property_native("mute") - local volicon = {"\xee\x80\x8a", "\xee\x80\x8b",} - if volume == 0 or mute then - return "\xee\x80\x8c" - else - return volicon[math.min(2,math.ceil(volume / (100/2)))] - end - end - ne.eventresponder["mbtn_left_up"] = - function () mp.commandv("cycle", "mute") end - - ne.eventresponder["wheel_up_press"] = - function () mp.commandv("osd-auto", "add", "volume", 5) end - ne.eventresponder["wheel_down_press"] = - function () mp.commandv("osd-auto", "add", "volume", -5) end - - ne.eventresponder["shift+mbtn_left_down"] = - function () show_message("Volume: " .. mp.get_property_osd("volume") .. "%") end - - - -- load layout - layouts[user_opts.layout]() - - --do something with the elements - prepare_elements() - update_margins() -end - -function reset_margins() - if state.using_video_margins then - for _, opt in ipairs(margins_opts) do - mp.set_property_number(opt[2], 0.0) - end - state.using_video_margins = false - end -end - -function update_margins() - local margins = osc_param.video_margins - - -- Don't use margins if it's visible only temporarily. - if (not state.osc_visible) or (get_hidetimeout() >= 0) or - (state.fullscreen and not user_opts.showfullscreen) or - (not state.fullscreen and not user_opts.showwindowed) - then - margins = {l = 0, r = 0, t = 0, b = 0} - end - - reset_margins() - - - utils.shared_script_property_set("osc-margins", - string.format("%f,%f,%f,%f", margins.l, margins.r, margins.t, margins.b)) -end - -function shutdown() - reset_margins() - utils.shared_script_property_set("osc-margins", nil) -end - --- --- Other important stuff --- - - -function show_osc() - -- show when disabled can happen (e.g. mouse_move) due to async/delayed unbinding - if not state.enabled then return end - - msg.trace("show_osc") - --remember last time of invocation (mouse move) - state.showtime = mp.get_time() - - osc_visible(true) - - if (user_opts.fadeduration > 0) then - state.anitype = nil - end -end - -function hide_osc() - msg.trace("hide_osc") - if not state.enabled then - -- typically hide happens at render() from tick(), but now tick() is - -- no-op and won't render again to remove the osc, so do that manually. - state.osc_visible = false - render_wipe() - elseif (user_opts.fadeduration > 0) then - if not(state.osc_visible == false) then - state.anitype = "out" - request_tick() - end - else - osc_visible(false) - end -end - -function osc_visible(visible) - if state.osc_visible ~= visible then - state.osc_visible = visible - update_margins() - end - request_tick() -end - -function pause_state(name, enabled) - state.paused = enabled - request_tick() -end - -function cache_state(name, st) - state.cache_state = st - request_tick() -end - --- Request that tick() is called (which typically re-renders the OSC). --- The tick is then either executed immediately, or rate-limited if it was --- called a small time ago. -function request_tick() - if state.tick_timer == nil then - state.tick_timer = mp.add_timeout(0, tick) - end - - if not state.tick_timer:is_enabled() then - local now = mp.get_time() - local timeout = tick_delay - (now - state.tick_last_time) - if timeout < 0 then - timeout = 0 - end - state.tick_timer.timeout = timeout - state.tick_timer:resume() - end -end - -function mouse_leave() - if get_hidetimeout() >= 0 then - hide_osc() - end - -- reset mouse position - state.last_mouseX, state.last_mouseY = nil, nil - state.mouse_in_window = false -end - -function request_init() - state.initREQ = true - request_tick() -end - --- Like request_init(), but also request an immediate update -function request_init_resize() - request_init() - -- ensure immediate update - state.tick_timer:kill() - state.tick_timer.timeout = 0 - state.tick_timer:resume() -end - -function render_wipe() - msg.trace("render_wipe()") - state.osd.data = "" -- allows set_osd to immediately update on enable - state.osd:remove() -end - -function render() - msg.trace("rendering") - local current_screen_sizeX, current_screen_sizeY, aspect = mp.get_osd_size() - local mouseX, mouseY = get_virt_mouse_pos() - local now = mp.get_time() - - -- check if display changed, if so request reinit - if not (state.mp_screen_sizeX == current_screen_sizeX - and state.mp_screen_sizeY == current_screen_sizeY) then - - request_init_resize() - - state.mp_screen_sizeX = current_screen_sizeX - state.mp_screen_sizeY = current_screen_sizeY - end - - -- init management - if state.active_element then - -- mouse is held down on some element - keep ticking and igore initReq - -- till it's released, or else the mouse-up (click) will misbehave or - -- get ignored. that's because osc_init() recreates the osc elements, - -- but mouse handling depends on the elements staying unmodified - -- between mouse-down and mouse-up (using the index active_element). - request_tick() - elseif state.initREQ then - osc_init() - state.initREQ = false - - -- store initial mouse position - if (state.last_mouseX == nil or state.last_mouseY == nil) - and not (mouseX == nil or mouseY == nil) then - - state.last_mouseX, state.last_mouseY = mouseX, mouseY - end - end - - - -- fade animation - if not(state.anitype == nil) then - - if (state.anistart == nil) then - state.anistart = now - end - - if (now < state.anistart + (user_opts.fadeduration/1000)) then - - if (state.anitype == "in") then --fade in - osc_visible(true) - state.animation = scale_value(state.anistart, - (state.anistart + (user_opts.fadeduration/1000)), - 255, 0, now) - elseif (state.anitype == "out") then --fade out - state.animation = scale_value(state.anistart, - (state.anistart + (user_opts.fadeduration/1000)), - 0, 255, now) - end - - else - if (state.anitype == "out") then - osc_visible(false) - end - kill_animation() - end - else - kill_animation() - end - - - - - - do_enable_keybindings() - - -- --mouse input area - local mouse_over_osc = false - - for _,cords in ipairs(osc_param.areas["input"]) do - if state.osc_visible then -- activate only when OSC is actually visible - set_virt_mouse_area(cords.x1, cords.y1, cords.x2, cords.y2, "input") - end - if state.osc_visible ~= state.input_enabled then - - if state.osc_visible then - mp.enable_key_bindings("input") - else - mp.disable_key_bindings("input") - end - - state.input_enabled = state.osc_visible - - end - - if (mouse_hit_coords(cords.x1, cords.y1, cords.x2, cords.y2)) then - mouse_over_osc = true - end - - end - - - -- autohide - if not (state.showtime == nil) and (get_hidetimeout() >= 0) then - local timeout = state.showtime + (get_hidetimeout()/1000) - now - if timeout <= 0 then - if (state.active_element == nil) and not (mouse_over_osc) then - hide_osc() - end - else - -- the timer is only used to recheck the state and to possibly run - -- the code above again - if not state.hide_timer then - state.hide_timer = mp.add_timeout(0, tick) - end - state.hide_timer.timeout = timeout - -- re-arm - state.hide_timer:kill() - state.hide_timer:resume() - end - end - - - -- actual rendering - local ass = assdraw.ass_new() - - -- Messages - render_message(ass) - - -- actual OSC - if state.osc_visible then - render_elements(ass) - end - - -- submit - set_osd(osc_param.playresy * osc_param.display_aspect, - osc_param.playresy, ass.text) -end - --- --- Eventhandling --- - -local function element_has_action(element, action) - return element and element.eventresponder and - element.eventresponder[action] -end - -function process_event(source, what) - local action = string.format("%s%s", source, - what and ("_" .. what) or "") - - if what == "down" or what == "press" then - - for n = 1, #elements do - - if mouse_hit(elements[n]) and - elements[n].eventresponder and - (elements[n].eventresponder[source .. "_up"] or - elements[n].eventresponder[action]) then - - if what == "down" then - state.active_element = n - state.active_event_source = source - end - -- fire the down or press event if the element has one - if element_has_action(elements[n], action) then - elements[n].eventresponder[action](elements[n]) - end - - end - end - - elseif what == "up" then - - if elements[state.active_element] then - local n = state.active_element - - if n == 0 then - --click on background (does not work) - elseif element_has_action(elements[n], action) and - mouse_hit(elements[n]) then - - elements[n].eventresponder[action](elements[n]) - end - - --reset active element - if element_has_action(elements[n], "reset") then - elements[n].eventresponder["reset"](elements[n]) - end - - end - state.active_element = nil - state.mouse_down_counter = 0 - - elseif source == "mouse_move" then - - state.mouse_in_window = true - - local mouseX, mouseY = get_virt_mouse_pos() - if (user_opts.minmousemove == 0) or - (not ((state.last_mouseX == nil) or (state.last_mouseY == nil)) and - ((math.abs(mouseX - state.last_mouseX) >= user_opts.minmousemove) - or (math.abs(mouseY - state.last_mouseY) >= user_opts.minmousemove) - ) - ) then - show_osc() - end - state.last_mouseX, state.last_mouseY = mouseX, mouseY - - local n = state.active_element - if element_has_action(elements[n], action) then - elements[n].eventresponder[action](elements[n]) - end - end - - -- ensure rendering after any (mouse) event - icons could change etc - request_tick() -end - - - --- called by mpv on every frame -function tick() - if state.marginsREQ == true then - update_margins() - state.marginsREQ = false - end - - if (not state.enabled) then return end - - if (state.idle) then - - -- render idle message - msg.trace("idle message") - local icon_x, icon_y = 320 - 26, 140 - local line_prefix = ("{\\rDefault\\an7\\1a&H00&\\bord0\\shad0\\pos(%f,%f)}"):format(icon_x, icon_y) - - local ass = assdraw.ass_new() - - ass:new_event() - ass:pos(320, icon_y+65) - ass:an(8) - ass:append("Drop files or URLs to play here.") - set_osd(640, 360, ass.text) - - if state.showhide_enabled then - mp.disable_key_bindings("showhide") - state.showhide_enabled = false - end - - - elseif (state.fullscreen and user_opts.showfullscreen) - or (not state.fullscreen and user_opts.showwindowed) then - - -- render the OSC - render() - else - -- Flush OSD - render_wipe() - end - - state.tick_last_time = mp.get_time() - - if state.anitype ~= nil then - -- state.anistart can be nil - animation should now start, or it can - -- be a timestamp when it started. state.idle has no animation. - if not state.idle and - (not state.anistart or - mp.get_time() < 1 + state.anistart + user_opts.fadeduration/1000) - then - -- animating or starting, or still within 1s past the deadline - request_tick() - else - kill_animation() - end - end -end - - -function do_enable_keybindings() - if state.enabled then - if not state.showhide_enabled then - mp.enable_key_bindings("showhide", "allow-vo-dragging+allow-hide-cursor") - end - state.showhide_enabled = true - end -end - -function enable_osc(enable) - state.enabled = enable - if enable then - do_enable_keybindings() - else - hide_osc() -- acts immediately when state.enabled == false - if state.showhide_enabled then - mp.disable_key_bindings("showhide") - end - state.showhide_enabled = false - end -end - --- duration is observed for the sole purpose of updating chapter markers --- positions. live streams with chapters are very rare, and the update is also --- expensive (with request_init), so it's only observed when we have chapters --- and the user didn't disable the livemarkers option (update_duration_watch). -function on_duration() request_init() end - -local duration_watched = false -function update_duration_watch() - local want_watch = user_opts.livemarkers and - (mp.get_property_number("chapters", 0) or 0) > 0 and - true or false -- ensure it's a boolean - - if (want_watch ~= duration_watched) then - if want_watch then - mp.observe_property("duration", nil, on_duration) - else - mp.unobserve_property(on_duration) - end - duration_watched = want_watch - end -end - -validate_user_opts() -update_duration_watch() - -mp.register_event("shutdown", shutdown) -mp.register_event("start-file", request_init) -mp.observe_property("track-list", nil, request_init) -mp.observe_property("playlist", nil, request_init) -mp.observe_property("chapter-list", "native", function(_, list) - list = list or {} -- safety, shouldn't return nil - table.sort(list, function(a, b) return a.time < b.time end) - state.chapter_list = list - update_duration_watch() - request_init() -end) - -mp.register_script_message("osc-message", show_message) -mp.register_script_message("osc-chapterlist", function(dur) - show_message(get_chapterlist(), dur) -end) -mp.register_script_message("osc-playlist", function(dur) - show_message(get_playlist(), dur) -end) -mp.register_script_message("osc-tracklist", function(dur) - local msg = {} - for k,v in pairs(nicetypes) do - table.insert(msg, get_tracklist(k)) - end - show_message(table.concat(msg, '\n\n'), dur) -end) - -mp.observe_property("fullscreen", "bool", - function(name, val) - state.fullscreen = val - state.marginsREQ = true - request_init_resize() - end -) - -mp.observe_property("border", "bool", - function(name, val) - state.border = val - request_init_resize() - end -) -mp.observe_property("window-maximized", "bool", - function(name, val) - state.maximized = val - request_init_resize() - end -) -mp.observe_property("idle-active", "bool", - function(name, val) - state.idle = val - request_tick() - end -) -mp.observe_property("pause", "bool", pause_state) -mp.observe_property("demuxer-cache-state", "native", cache_state) -mp.observe_property("vo-configured", "bool", function(name, val) - request_tick() -end) -mp.observe_property("playback-time", "number", function(name, val) - request_tick() -end) - -mp.observe_property("osd-dimensions", "native", function(name, val) - -- (we could use the value instead of re-querying it all the time, but then - -- we might have to worry about property update ordering) - request_init_resize() -end) - --- mouse show/hide bindings -mp.set_key_bindings({ - {"mouse_move", function(e) process_event("mouse_move", nil) end}, - {"mouse_leave", mouse_leave}, -}, "showhide", "force") -do_enable_keybindings() - ---mouse input bindings -mp.set_key_bindings({ - {"mbtn_left", function(e) process_event("mbtn_left", "up") end, - function(e) process_event("mbtn_left", "down") end}, - {"shift+mbtn_left", function(e) process_event("shift+mbtn_left", "up") end, - function(e) process_event("shift+mbtn_left", "down") end}, - {"mbtn_right", function(e) process_event("mbtn_right", "up") end, - function(e) process_event("mbtn_right", "down") end}, - -- alias to shift_mbtn_left for single-handed mouse use - {"mbtn_mid", function(e) process_event("shift+mbtn_left", "up") end, - function(e) process_event("shift+mbtn_left", "down") end}, - {"wheel_up", function(e) process_event("wheel_up", "press") end}, - {"wheel_down", function(e) process_event("wheel_down", "press") end}, - {"mbtn_left_dbl", "ignore"}, - {"shift+mbtn_left_dbl", "ignore"}, - {"mbtn_right_dbl", "ignore"}, -}, "input", "force") -mp.enable_key_bindings("input") - -function get_hidetimeout() - if user_opts.visibility == "always" then - return -1 -- disable autohide - end - return user_opts.hidetimeout -end - -function always_on(val) - if state.enabled then - if val then - show_osc() - else - hide_osc() - end - end -end - - --- mode can be auto/always/never/cycle --- the modes only affect internal variables and not stored on its own. -function visibility_mode(mode, no_osd) - if mode == "cycle" then - if not state.enabled then - mode = "auto" - elseif user_opts.visibility ~= "always" then - mode = "always" - else - mode = "never" - end - end - - if mode == "auto" then - always_on(false) - enable_osc(true) - elseif mode == "always" then - enable_osc(true) - always_on(true) - elseif mode == "never" then - enable_osc(false) - else - msg.warn("Ignoring unknown visibility mode '" .. mode .. "'") - return - end - - if not no_osd and tonumber(mp.get_property("osd-level")) >= 1 then - mp.osd_message("OSC visibility: " .. mode) - end - - -- Reset the input state on a mode change. The input state will be - -- recalcuated on the next render cycle, except in 'never' mode where it - -- will just stay disabled. - mp.disable_key_bindings("input") - state.input_enabled = false - - update_margins() - request_tick() -end - -visibility_mode(user_opts.visibility, true) -mp.register_script_message("osc-visibility", visibility_mode) -mp.add_key_binding(nil, "visibility", function() visibility_mode("cycle") end) -set_virt_mouse_area(0, 0, 0, 0, "input") diff --git a/dots/.config/pipewire/pipewire-pulse.conf b/dots/.config/pipewire/pipewire-pulse.conf deleted file mode 100644 index 05c2ef5..0000000 --- a/dots/.config/pipewire/pipewire-pulse.conf +++ /dev/null @@ -1,60 +0,0 @@ -context.properties = {} -context.spa-libs = { - audio.convert.* = audioconvert/libspa-audioconvert - support.* = support/libspa-support -} -context.modules = [ - { name = libpipewire-module-rt - args = { nice.level = -11 } - flags = [ ifexists nofail ] - } - { name = libpipewire-module-protocol-native } - { name = libpipewire-module-client-node } - { name = libpipewire-module-adapter } - { name = libpipewire-module-metadata } - - { name = libpipewire-module-protocol-pulse - args = { } - } -] - -context.exec = [ - { path = "pactl" args = "load-module module-always-sink" } - # Automatically switch to (bluetooth) headphones - { path = "pactl" args = "load-module module-switch-on-connect" } -] - -stream.properties = { } - -pulse.properties = { - server.address = [ "unix:native" ] - vm.overrides = { pulse.min.quantum = 1024/48000 } -} - -pulse.rules = [ - { - matches = [ { } ] - actions = { update-props = { } } - } - { - matches = [ - { application.process.binary = "teams" } - { application.process.binary = "teams-insiders" } - { application.process.binary = "skypeforlinux" } - ] - actions = { quirks = [ force-s16-info ] } - } - { - matches = [ { application.process.binary = "firefox" } ] - actions = { quirks = [ remove-capture-dont-move ] } - } - { - matches = [ { application.name = "~speech-dispatcher*" } ] - actions = { - update-props = { - pulse.min.req = 1024/48000 # 21ms - pulse.min.quantum = 1024/48000 # 21ms - } - } - } -] diff --git a/dots/.config/rclone/rclone.conf.example b/dots/.config/rclone/rclone.conf.example deleted file mode 100644 index f5ea70c..0000000 --- a/dots/.config/rclone/rclone.conf.example +++ /dev/null @@ -1,11 +0,0 @@ -[google-drive] -type = drive -scope = drive -token = - -[onedrive-vub] -type = webdav -url = -vendor = sharepoint -user = -pass = diff --git a/dots/.config/solaar/config.json b/dots/.config/solaar/config.json deleted file mode 100644 index aeadcbf..0000000 --- a/dots/.config/solaar/config.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "101B:E2D1E989": { - "_name": "Marathon Mouse M705 (M-R0009)", - "side-scroll": true, - "smooth-scroll": true - }, - "405E:C347528E": { - "_absent": [ - "hi-res-scroll", - "lowres-smooth-scroll", - "smart-shift", - "thumb-scroll-mode", - "thumb-scroll-invert", - "onboard_profiles", - "report_rate", - "dpi", - "dpi-sliding", - "speed-change", - "backlight", - "backlight-timed", - "fn-swap", - "disable-keyboard-keys", - "divert-crown", - "crown-smooth", - "divert-gkeys", - "m-key-leds", - "mr-key-led", - "multiplatform", - "gesture2-gestures", - "gesture2-divert", - "gesture2-params" - ], - "_modelId": "B015405E0000", - "_name": "M720 Triathlon Multi-Device Mouse", - "_sensitive": { - "change-host": true, - "divert-keys": true, - "hires-smooth-invert": false, - "hires-smooth-resolution": false, - "mouse-gestures": false, - "pointer_speed": false, - "reprogrammable-keys": true - }, - "_serial": "C347528E", - "_unitId": "F204EB17", - "divert-keys": { - "208": 0, - "215": 0, - "82": 0, - "83": 0, - "86": 0, - "91": 0, - "93": 0 - }, - "hires-smooth-invert": false, - "hires-smooth-resolution": false, - "mouse-gestures": 0, - "pointer_speed": 195, - "reprogrammable-keys": { - "208": 208, - "80": 80, - "81": 81, - "82": 82, - "83": 83, - "86": 86, - "91": 91, - "93": 93 - } - }, - "_version": "1.1.2" -} \ No newline at end of file diff --git a/dots/.config/spotify/README.md b/dots/.config/spotify/README.md deleted file mode 100644 index 1f0704b..0000000 --- a/dots/.config/spotify/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Spotify cache size - -The contents of `prefs.example` can be added to the `prefs` file in this -directory to change the cache size to 1GB. diff --git a/dots/.config/spotify/prefs.example b/dots/.config/spotify/prefs.example deleted file mode 100644 index 00afc95..0000000 --- a/dots/.config/spotify/prefs.example +++ /dev/null @@ -1 +0,0 @@ -storage.size=1024 diff --git a/dots/.config/systemd/user/save-passwddb.service b/dots/.config/systemd/user/save-passwddb.service deleted file mode 100644 index c65d2a9..0000000 --- a/dots/.config/systemd/user/save-passwddb.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Save KeypassXC password database to cloud -Wants=network-online.target -After=network-online.target - -[Service] -Type=oneshot -ExecStart=/home/h/.bin/save-passwddb - -[Install] -WantedBy=multi-user.target diff --git a/dots/.config/systemd/user/save-passwddb.timer b/dots/.config/systemd/user/save-passwddb.timer deleted file mode 100644 index 7a06535..0000000 --- a/dots/.config/systemd/user/save-passwddb.timer +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Save Keepass password database to cloud daily - -[Timer] -OnCalendar=daily -RandomizedDelaySec=12h -Persistent=true - -[Install] -WantedBy=timers.target diff --git a/dots/.config/user-dirs.conf b/dots/.config/user-dirs.conf deleted file mode 100644 index f184210..0000000 --- a/dots/.config/user-dirs.conf +++ /dev/null @@ -1 +0,0 @@ -enabled=False diff --git a/dots/.config/user-dirs.dirs b/dots/.config/user-dirs.dirs deleted file mode 100644 index 6d8893b..0000000 --- a/dots/.config/user-dirs.dirs +++ /dev/null @@ -1,15 +0,0 @@ -# This file is written by xdg-user-dirs-update -# If you want to change or add directories, just edit the line you're -# interested in. All local changes will be retained on the next run. -# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped -# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an -# absolute path. No other format is supported. -# -XDG_DESKTOP_DIR="$HOME/" -XDG_DOWNLOAD_DIR="$HOME/dl" -XDG_DOCUMENTS_DIR="$HOME/doc" -XDG_PUBLICSHARE_DIR="$HOME/" -XDG_MUSIC_DIR="$HOME/" -XDG_PICTURES_DIR="$HOME/" -XDG_TEMPLATES_DIR="$HOME/" -XDG_VIDEOS_DIR="$HOME/" diff --git a/dots/.config/yamllint/config b/dots/.config/yamllint/config deleted file mode 100644 index 3557381..0000000 --- a/dots/.config/yamllint/config +++ /dev/null @@ -1,6 +0,0 @@ ---- - -extends: default -rules: - document-start: disable - comments-indentation: disable diff --git a/home/hosts/andromache/default.nix b/home/hosts/andromache/default.nix index f5da9fe..675923f 100644 --- a/home/hosts/andromache/default.nix +++ b/home/hosts/andromache/default.nix @@ -45,6 +45,7 @@ }; keyboard.vortexCore.enable = true; keepassxc.enable = true; + mpv.enable = true; music.enable = true; newsboat.enable = true; nvim.enable = true; diff --git a/home/hosts/astyanax/default.nix b/home/hosts/astyanax/default.nix index aff4e3e..9ec8681 100644 --- a/home/hosts/astyanax/default.nix +++ b/home/hosts/astyanax/default.nix @@ -38,6 +38,7 @@ }; k8s.k9s.enable = true; keepassxc.enable = true; + mpv.enable = true; music.enable = true; newsboat.enable = true; my.xdg.enable = true; diff --git a/home/modules/browser/default.nix b/home/modules/browser/default.nix index 584ecd7..d0ef5c1 100644 --- a/home/modules/browser/default.nix +++ b/home/modules/browser/default.nix @@ -9,6 +9,7 @@ ./firefox.nix ./librewolf.nix ./chromium.nix + ./tridactyl.nix ]; options.browser = { diff --git a/home/modules/browser/tridactyl.nix b/home/modules/browser/tridactyl.nix new file mode 100644 index 0000000..2362a50 --- /dev/null +++ b/home/modules/browser/tridactyl.nix @@ -0,0 +1,17 @@ +{ + config, + lib, + ... +}: + +let + browsers = [ + config.browser.primary + config.browser.secondary + ]; +in +{ + config = lib.mkIf (lib.elem "firefox" browsers || lib.elem "librewolf" browsers) { + xdg.configFile."tridactyl/tridactylrc".source = ./tridactylrc; + }; +} diff --git a/dots/.config/tridactyl/tridactylrc b/home/modules/browser/tridactylrc similarity index 100% rename from dots/.config/tridactyl/tridactylrc rename to home/modules/browser/tridactylrc diff --git a/home/modules/git/github.nix b/home/modules/git/github.nix index de109da..1af581c 100644 --- a/home/modules/git/github.nix +++ b/home/modules/git/github.nix @@ -6,6 +6,26 @@ { config = lib.mkIf (config.git.enable && config.git.github.enable) { - programs.gh.enable = true; + programs.gh = { + enable = true; + settings = { + git_protocol = "ssh"; + prompt = "enabled"; + aliases = { + co = "pr checkout"; + c = "repo clone"; + f = "repo fork"; + rc = "repo create"; + rv = "repo view"; + re = "repo edit"; + rm = "repo remove"; + rn = "repo rename"; + lr = "repo list"; + li = "issue list"; + al = "alias"; + al- = "alias delete"; + }; + }; + }; }; } diff --git a/home/modules/mpv/default.nix b/home/modules/mpv/default.nix new file mode 100644 index 0000000..2c6b3c4 --- /dev/null +++ b/home/modules/mpv/default.nix @@ -0,0 +1,38 @@ +{ config, lib, ... }: + +{ + options.mpv.enable = lib.mkOption { + default = false; + type = lib.types.bool; + }; + + config = lib.mkIf config.mpv.enable { + programs.mpv = { + enable = true; + config = { + vo = "gpu"; + profile = "gpu-hq"; + hwdec = "auto"; + msg-color = "yes"; + cursor-autohide = 300; + cursor-autohide-fs-only = "yes"; + save-position-on-quit = "yes"; + keep-open = "yes"; + }; + bindings = { + l = "seek +5"; + h = "seek -5"; + k = "seek +30"; + j = "seek -30"; + "+" = "add video-zoom 0.1"; + "-" = "add video-zoom -0.1"; + "=" = "set video-zoom 0; set video-pan-x 0; set video-pan-y 0"; + H = "add video-pan-x 0.01"; + L = "add video-pan-x -0.01"; + K = "add video-pan-y 0.01"; + J = "add video-pan-y -0.01"; + m = "cycle mute"; + }; + }; + }; +} diff --git a/home/modules/music/default.nix b/home/modules/music/default.nix index 39a8300..fc06242 100644 --- a/home/modules/music/default.nix +++ b/home/modules/music/default.nix @@ -23,6 +23,10 @@ in config = lib.mkIf cfg.enable { home.packages = [ spotifyWithWayland ]; + home.activation.spotifyCacheSize = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + run mkdir -p ${config.xdg.configHome}/spotify + run ${lib.getExe pkgs.crudini} --ini-options=nospace --set ${config.xdg.configHome}/spotify/prefs "" storage.size 1024 + ''; programs.ncspot = { enable = true; settings = { diff --git a/modules/audio/default.nix b/modules/audio/default.nix index 160af45..39b3f91 100644 --- a/modules/audio/default.nix +++ b/modules/audio/default.nix @@ -21,7 +21,6 @@ alsa.support32Bit = true; pulse.enable = true; }; - pulseaudio.extraConfig = "load-module module-switch-on-connect"; }; }; }