[StumpWM] Add bluetooth utility code
This commit is contained in:
parent
0b9e9d2655
commit
667ebc8db3
@ -138,6 +138,7 @@ Now, we’ll load a couple of my custom files that will be described below:
|
|||||||
#+name: first-loaded-files
|
#+name: first-loaded-files
|
||||||
| File to be loaded |
|
| File to be loaded |
|
||||||
|-------------------|
|
|-------------------|
|
||||||
|
| bluetooth.lisp |
|
||||||
| commands.lisp |
|
| commands.lisp |
|
||||||
| placement.lisp |
|
| placement.lisp |
|
||||||
| keybindings.lisp |
|
| keybindings.lisp |
|
||||||
@ -155,8 +156,9 @@ Now, we’ll load a couple of my custom files that will be described below:
|
|||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
This is equivalent to the Common Lisp code:
|
This is equivalent to the Common Lisp code:
|
||||||
#+RESULTS[5ec83707b957847594f436dfabc8458904c4ab8b]: gen-load-files
|
#+RESULTS[29848aaa616d9b2a828a5602ea6b42dd344efaf2]: gen-load-files
|
||||||
#+begin_src lisp
|
#+begin_src lisp
|
||||||
|
(load "~/.stumpwm.d/bluetooth.lisp")
|
||||||
(load "~/.stumpwm.d/commands.lisp")
|
(load "~/.stumpwm.d/commands.lisp")
|
||||||
(load "~/.stumpwm.d/placement.lisp")
|
(load "~/.stumpwm.d/placement.lisp")
|
||||||
(load "~/.stumpwm.d/keybindings.lisp")
|
(load "~/.stumpwm.d/keybindings.lisp")
|
||||||
@ -896,6 +898,165 @@ Binwarp mode is now available from the keybind ~s-m~ at top level.
|
|||||||
((kbd "q") "exit-binwarp"))
|
((kbd "q") "exit-binwarp"))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
** Bluetooth
|
||||||
|
:PROPERTIES:
|
||||||
|
:CUSTOM_ID: Utilities-Bluetooth-rns0nr902aj0
|
||||||
|
:header-args:lisp: :mkdirp yes :tangle ~/.stumpwm.d/bluetooth.lisp :noweb yes
|
||||||
|
:END:
|
||||||
|
Although there is a bluetooth module for the modeline, this is about
|
||||||
|
the extent to which StumpWM can interact with the system’s bluetooth.
|
||||||
|
However, I wish for some more interecactivity, like powering on and
|
||||||
|
off bluetooth, connecting to devices and so on.
|
||||||
|
|
||||||
|
First, out code relies on ~cl-ppcre~, so let’s quickload it.
|
||||||
|
#+begin_src lisp
|
||||||
|
(ql:quickload :cl-ppcre)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Let’s indicate which command we’ll be using.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defvar *bluetooth-command* "bluetoothctl"
|
||||||
|
"Base command for interacting with bluetooth.")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
*** Utilities
|
||||||
|
:PROPERTIES:
|
||||||
|
:CUSTOM_ID: Utilities-Bluetooth-Utilities-3zicf7k03aj0
|
||||||
|
:END:
|
||||||
|
We’ll need a couple of functions that will take care of stuff for us
|
||||||
|
so we don’t have to repeat ourselves. The first one is a way for us to
|
||||||
|
share a message. The function ~bluetooth-message~ will first display
|
||||||
|
~Bluetooth:~ in green, then it will display the message we want it to
|
||||||
|
display.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defun bluetooth-message (&rest message)
|
||||||
|
(message (format nil
|
||||||
|
"^2Bluetooth:^7 ~{~A~^ ~}"
|
||||||
|
message)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
This function is a builder function which will create our commands.
|
||||||
|
For instance, src_lisp[:exports code]{(bluetooth-make-command "power"
|
||||||
|
"on")} will return ~"bluetoothctl power on"~ with ~*bluetooth-ctl*~ set as
|
||||||
|
~"bluetoothctl"~ --- simply put, it joins ~*bluetooth-command*~ with ~args~
|
||||||
|
with a space as their separator.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defun bluetooth-make-command (&rest args)
|
||||||
|
(format nil
|
||||||
|
"~a ~{~A~^ ~}"
|
||||||
|
,*bluetooth-command*
|
||||||
|
args))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Now we can put ~bluetooth-make-command~ to use with ~bluetooth-command~
|
||||||
|
which will actually run the result of the former. As you can see, it
|
||||||
|
also collects the output so we can display it later in another
|
||||||
|
function.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defmacro bluetooth-command (&rest args)
|
||||||
|
`(run-shell-command (bluetooth-make-command ,@args) t))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Finally, ~bluetooth-message-command~ is the function that both executes
|
||||||
|
and also displays the result of the bluetooth command we wanted to see
|
||||||
|
executed. Each argument of the command is a separate string. For
|
||||||
|
instance, if we want to power on the bluetooth on our device, we can
|
||||||
|
call src_lisp[:exports code]{(bluetooth-message-command "power"
|
||||||
|
"on")}.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defmacro bluetooth-message-command (&rest args)
|
||||||
|
`(bluetooth-message (bluetooth-command ,@args)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
*** Toggle Bluetooth On and Off
|
||||||
|
:PROPERTIES:
|
||||||
|
:CUSTOM_ID: Utilities-Bluetooth-Toggle-Bluetooth-On-and-Off-9pyfbtd02aj0
|
||||||
|
:END:
|
||||||
|
This part is easy. Now that we can call our bluetooth commands easily,
|
||||||
|
we can easily define how to turn on bluetooth.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defcommand bluetooth-turn-on () ()
|
||||||
|
"Turn on bluetooth."
|
||||||
|
(bluetooth-message-command "power" "on"))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
And how to power it off.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defcommand bluetooth-turn-off () ()
|
||||||
|
"Turn off bluetooth."
|
||||||
|
(bluetooth-message-command "power" "off"))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
*** Bluetooth Devices
|
||||||
|
:PROPERTIES:
|
||||||
|
:CUSTOM_ID: Utilities-Bluetooth-Bluetooth-Devices-196gbtd02aj0
|
||||||
|
:END:
|
||||||
|
In order to manipulate bluetooth device, which we can represent as a
|
||||||
|
MAC address and a name, we can create a structure that will make use
|
||||||
|
of a constructor for simpler use. The constructor
|
||||||
|
~make-bluetooth-device-from-command~ expects an entry such as ~Device
|
||||||
|
00:00:00:00:00:00 Home Speaker~. The constructor discards the term
|
||||||
|
~Device~ and stores the MAC address separately from the rest of the
|
||||||
|
string which is assumed to be the full name of the device.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defstruct (bluetooth-device
|
||||||
|
(:constructor
|
||||||
|
make-bluetooth-device (&key (address "")
|
||||||
|
(name nil)))
|
||||||
|
(:constructor
|
||||||
|
make-bluetooth-device-from-command
|
||||||
|
(&key (raw-name "")
|
||||||
|
&aux (address (cadr (cl-ppcre:split " " raw-name)))
|
||||||
|
(full-name (format nil "~{~A~^ ~}" (cddr (cl-ppcre:split " " raw-name)))))))
|
||||||
|
address
|
||||||
|
(full-name (progn
|
||||||
|
(format nil "~{~A~^ ~}" name))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
We can now collect our devices easily.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defun bluetooth-get-devices ()
|
||||||
|
(let ((literal-devices (bluetooth-command "devices")))
|
||||||
|
(mapcar (lambda (device)
|
||||||
|
(make-bluetooth-device-from-command :raw-name device))
|
||||||
|
(cl-ppcre:split "\\n" literal-devices))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
*** Connect to a device
|
||||||
|
:PROPERTIES:
|
||||||
|
:CUSTOM_ID: Utilities-Bluetooth-Connect-to-a-device-tjqcf7k03aj0
|
||||||
|
:END:
|
||||||
|
When we want to connect to a bluetooth device, we always need
|
||||||
|
bluetooth turned on, so ~bluetooth-turn-on~ will always be called. Then
|
||||||
|
the function will attempt to connect to the device specified by the
|
||||||
|
~device~ argument, whether the argument is a bluetooth structure as
|
||||||
|
defined above or a plain MAC address.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defun bluetooth-connect-device (device)
|
||||||
|
(progn
|
||||||
|
(bluetooth-turn-on)
|
||||||
|
(cond ((bluetooth-device-p device) ;; it is a bluetooth-device structure
|
||||||
|
(bluetooth-message-command "connect"
|
||||||
|
(bluetooth-device-address device)))
|
||||||
|
((stringp device) ;; assume it is a MAC address
|
||||||
|
(bluetooth-message-command "connect" device))
|
||||||
|
(t (message (format nil "Cannot work with device ~a" device))))))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
The command to connect to a device displays a choice between the
|
||||||
|
collected bluetooth device and the user only has to select it. It will
|
||||||
|
then attempt to connect to it.
|
||||||
|
#+begin_src lisp
|
||||||
|
(defcommand bluetooth-connect () ()
|
||||||
|
(let* ((devices (bluetooth-get-devices))
|
||||||
|
(choice (cdr (stumpwm:select-from-menu
|
||||||
|
(stumpwm:current-screen)
|
||||||
|
(mapcar (lambda (device)
|
||||||
|
`(,(bluetooth-device-full-name device) . ,device))
|
||||||
|
devices)))))
|
||||||
|
(bluetooth-connect-device choice)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
** NetworkManager integration
|
** NetworkManager integration
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:CUSTOM_ID: Utilities-NetworkManager-integration-nm7jxbt0z9j0
|
:CUSTOM_ID: Utilities-NetworkManager-integration-nm7jxbt0z9j0
|
||||||
|
Loading…
Reference in New Issue
Block a user