diff --git a/features/headphones/default.nix b/features/headphones/default.nix index 307b722..f58f0ba 100644 --- a/features/headphones/default.nix +++ b/features/headphones/default.nix @@ -5,15 +5,51 @@ pkgs, ... }: { - options.azos.headphones-whmx4000.enable = lib.mkOption { - default = true; - type = lib.types.bool; + options.azos.headphones = { + enable = lib.mkOption { + default = false; + example = true; + type = lib.types.bool; + }; + devices = lib.mkOption { + default = []; + type = lib.types.listOf (lib.types.submodule { + options = { + mac = lib.mkOption {type = lib.types.str;}; + name = lib.mkOption {type = lib.types.str;}; + }; + }); + description = "Headphone devices; first entry is the default connect target."; + }; }; - config = lib.mkIf config.azos.headphones-whmx4000.enable { - home.packages = [ - (pkgs.writeShellScriptBin - "azos-connect-headphones-whmx4000" - "echo \"connect AC:80:0A:AF:E1:C2\" | bluetoothctl") + + config = lib.mkIf config.azos.headphones.enable { + home.packages = let + deviceEntries = + lib.concatMapStrings + (d: " ${lib.escapeShellArg "${d.mac} ${d.name}"}\n") + config.azos.headphones.devices; + defaultMac = + if config.azos.headphones.devices == [] + then "" + else (lib.head config.azos.headphones.devices).mac; + in [ + (pkgs.writeShellScriptBin "azos-connect-headphones" '' + DEVICES=( + ${deviceEntries}) + + case "$1" in + --list) + printf '%s\n' "''${DEVICES[@]}" + ;; + --mac) + echo "connect $2" | bluetoothctl + ;; + *) + echo "connect ${defaultMac}" | bluetoothctl + ;; + esac + '') ]; }; }; diff --git a/features/lauretta/emacs/config.org b/features/lauretta/emacs/config.org index 041b2ae..08004b6 100644 --- a/features/lauretta/emacs/config.org +++ b/features/lauretta/emacs/config.org @@ -43,9 +43,24 @@ ** Headphones #+begin_src emacs-lisp -(defun azos/connect-headphones () - (interactive) - (start-process-shell-command "connect-headphones" nil "azos-connect-headphones-whmx4000")) +(defun azos/connect-headphones (&optional arg) + "Connect to headphones via bluetoothctl. +Without prefix ARG, connects to the first device in the list. +With prefix ARG, prompts to choose from all configured devices." + (interactive "P") + (if (not arg) + (start-process-shell-command "connect-headphones" nil "azos-connect-headphones") + (let* ((raw (shell-command-to-string "azos-connect-headphones --list")) + (lines (split-string (string-trim raw) "\n" t)) + (choices (mapcar (lambda (line) + (let ((space (string-match " " line))) + (cons (substring line (1+ space)) + (substring line 0 space)))) + lines)) + (name (completing-read "Connect headphones: " (mapcar #'car choices) nil t)) + (mac (cdr (assoc name choices)))) + (start-process-shell-command "connect-headphones" nil + (concat "azos-connect-headphones --mac " mac))))) (define-key azos/global-minor-mode/open-keymap (kbd "h") 'azos/connect-headphones) diff --git a/home-manager/home.nix b/home-manager/home.nix index b645731..778c0b3 100755 --- a/home-manager/home.nix +++ b/home-manager/home.nix @@ -41,6 +41,18 @@ azos.suites.lauretta.enable = true; azos.chess.enable = true; azos.name = "Aner Zakobar"; + + azos.headphones.enable = true; + azos.headphones.devices = [ + { + mac = "AC:80:0A:AF:E1:C2"; + name = "Aner's Headphones"; + } + { + mac = "AC:80:0A:A1:5F:53"; + name = "Chen's Headphones"; + } + ]; azos.roam-backup.enable = true; home = { diff --git a/nixos/configuration-beacon-wsl.nix b/nixos/configuration-beacon-wsl.nix index 388005c..39cb28a 100644 --- a/nixos/configuration-beacon-wsl.nix +++ b/nixos/configuration-beacon-wsl.nix @@ -34,6 +34,7 @@ networking.hostName = "beacon"; networking.firewall.allowedTCPPorts = [ 22 ]; + programs.nix-ld.enable = true; time.timeZone = "Asia/Jerusalem"; # GPU is exposed through WSL2 paravirtualization; no Linux NVIDIA KM needed @@ -51,7 +52,7 @@ isNormalUser = true; extraGroups = ["wheel" "video"]; openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDfzDDO5juINctECmWlsYtGghEiX/RnTJ1cazLvOWSrPfsTyEd+B1+Ig8kFefNryjkpApfRXqj5KtLPNlpLfdVBrOIfhIveEp2MGqhgOGZFNVxQyXnZgii8Zdh4cqZ2O3pZpMsaAQBaJ9nH6dK0dJjicWT5f6TqwrVcInywRc5SuyizoSxoFmg7ch2rnlVi0j5XMVqdh8XLzHXZ7yWCzXy7+hWl/d7pwpyuzoK8dBw2EU9TauhgRDruom5Q9vWJTLStALC9pAIb0v9UFj9y+1zwx7pXsXp5F1g73EYrE4QR+QQ6z2LebuK280W0t+VA/fSCEB13DnkmofgqZQxX5MSCmrxZ5lTFp1FjW6yJo7As9FheF/GECowYkMRIx4IiQsjjHjZqlLRpLas11yAp6tGoZnw59hFo6Lu0Kva39jGVVmioYHtAeE5rD5w+v5kseJR4jlQ8aKB5yOjYUQOIz2AHQyoidgaeR2jPWqZUeRQbACI+/p3CHO45r3hrjATtGloBg0xF95Qws7Be3mjHVhbBLOoob8MdZ8nYAGnhlWrZphlkvXsHC6OUkuDJW00tmMjWXRlFwhFJ+nqUQCgLVjxVHQJ5rq9GeXBUuNXAeCm5BKBsdq+9qqVlt7D9iGyfr0lcZ7peKz/96KwPCWpG2En1Ur0/cVcbWnXEfG/xWO10tQ== openpgp:0xFA67FAB0" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDMdozJewuuqG4VuwGhI5Uw2xDIUrkQwyPGQ2q3tvnPq/VoV+zfdnou42I6XYEfOGd6xfLR0byOGCk1Ia1F/picBsxADEaJFBnTny5MWNA5MxwJIYUPW5+kFN1TmxdNGmj0WJ8qZeKkS3ffixdHlHTVu4Rzrlu8qDdw8TmgcvD7sHpNaBB+hwG9B/s5BAozfXvyXtW51lLLrEZdmUXJxAP51ubVgysZ985PA89o4G7LUE20IKAj3rgylLwq+Lz2PoGmVCptPTknLLzGlxTy2mU/tESJtS4iUvshSYiKak73BSen88xLWL/eZGFzOLW4TNem/qT0ykqK1s1BaGWCcQiDWN+Lpa3XqTbFN054MfhLdEMp+NjrdsCbZORzp9p2ZPDqi5jI1Hy7IN/8VzzB+T13MX6YhW7CBBqUZaivGhVQGsNjrFusPGhCaZrzNJ1l4qssLAlOh9qdaYzqDe+BIHsty55vw4Ph+Axou82babpLoiQzkCol2TWjPr7JSfHFkm6CmoTQ7mK8m7jRCodmxF+BEe4Usr+HrTKDc9fr5P4mdfL0O+ZPrlkPuG1zBTMal9MPxeCk4emzOZf7vBMNzb0aKHbOtSdVk/IcjatlDd2EIo34e5A6anLRMAdxb7901mnCAcjvCn6+ArNV8nr+NBk1+UvumZ+Q59LTrAkgRt3rBw== cardno:29_109_265" ]; };