Compare commits

...

2 Commits

Author SHA1 Message Date
9890f6d0f3 Add README 2022-06-05 11:43:04 +02:00
4d4857b525 Add `refresh' argument to some parameter handling functions 2022-06-05 11:42:10 +02:00
3 changed files with 125 additions and 17 deletions

108
README.org Normal file
View File

@ -0,0 +1,108 @@
#+TITLE: pipewire-0
pipewire-0 is an [[https://www.gnu.org/software/emacs][Emacs]] interface to [[https://pipewire.org][PipeWire]]. It provides a library
to access some PipeWire functionality and a simple user interface to
handle audio devices. It allows displaying PipeWire devices and
clients, changing volumes and muting and unmuting of PipeWire sinks
and sources and setting default sinks and sources.
It is an experimental initial version that may be quite buggy. It
works for me but may not work in other environments. Feel free to use
it, fix it, fork it. [[*Contact][Contact me]] if you want to discuss anything.
* Usage
** Installation
pipewire-0 currently requires presence of PipeWire command line tools,
namely [[https://docs.pipewire.org/page_man_pw_cli_1.html][pw-cli]] and [[https://docs.pipewire.org/page_man_pw_metadata_1.html][pw-metadata]].
To install pipewire-0, put the *.el files to a site-lisp directory and
add the following line to your Emacs configuration:
#+begin_src elisp
(require pw-ui)
#+end_src
Or if you use [[https://github.com/radian-software/straight.el][straight.el]], you can install pipewire-0 as follows:
#+begin_src elisp
(straight-use-package
'(pipewire-0 :type git
:repo "https://git.zamazal.org/pdm/pipewire-0"
:local-repo "pipewire-0"))
#+end_src
** User interface
=M-x pipewire= enters a buffer with PipeWire objects:
#+ATTR_HTML: :alt Emacs PipeWire buffer
[[./screenshot.jpg]]
Use =C-h m= to display basic help.
Most of the interactive functions can be used anywhere:
- =pipewire-increase-volume=
- =pipewire-decrase-volume=
- =pipewire-set-volume=
- =pipewire-toggle-muted=
- =pipewire-set-default=
They can be bound to multimedia keys:
#+begin_src elisp
(global-set-key (kbd "<XF86AudioMute>") 'pipewire-toggle-muted)
(global-set-key (kbd "<XF86AudioLowerVolume>") 'pipewire-decrease-volume)
(global-set-key (kbd "<XF86AudioRaiseVolume>") 'pipewire-increase-volume)
#+end_src
** Configuration
=M-x customize-group RET pipewire RET=
** Library
pipewire-0 consists of the following source files:
- [[file:pw-lib.el][pw-lib.el]] :: PipeWire library to be used in Elisp programs.
- [[file:pw-access.el][pw-access.el]] :: PipeWire communication interface, not supposed to be
used outside =pw-lib=.
- [[file:pw-ui.el][pw-ui.el]] :: User commands and interface.
Look into [[file:pw-lib.el][pw-lib.el]] to see what public =pw-lib-*= functions are
available there. For example, the following snippet can be used to
display current volume level of the default audio sink:
#+begin_src elisp
(let ((object (pw-lib-default-audio-sink)))
(format "%s%s"
(pw-lib-volume object t)
(if (pw-lib-muted-p object) "(M)" "")))
#+end_src
* Notes
PipeWire is currently accessed using [[https://docs.pipewire.org/page_man_pw_cli_1.html][pw-cli]] command line utility. Its
output is apparently undocumented and changes between versions so this
is not a reliable way to communicate with PipeWire. But I dont know
about anything better currently. Nevertheless, its easy to replace
pw-cli with something else in [[file:pw-access.el][pw-access.el]].
** Why is it named pipewire-0?
I wrote pipewire-0 because I couldnt find any Emacs interface to
PipeWire. I would name it simply pipewire or pipewire-el but I expect
that someone will write a full-fledged PipeWire interface sooner or
later. Id like to avoid confusion and reserve the plain name for the
future interface, while having the basic above zero, pipewire-0,
support for now.
* Contact
pipewire-0 is available at [[https://git.zamazal.org/pdm/pipewire-0][git.zamazal.org]]. You can file issues
there.
If you dont want to discuss things publicly or to bother registering
at yet another web site, you can reach me at [[mailto:pdm@zamazal.org][pdm@zamazal.org]].

View File

@ -84,16 +84,16 @@ E.g. \"Device\", \"Node\", \"Port\", \"Client\", ..."
object object
(pw-lib-get-object (pw-lib-object-value object "node.id")))) (pw-lib-get-object (pw-lib-object-value object "node.id"))))
(defun pw-lib--node-parameters (object-or-id) (defun pw-lib--node-parameters (object-or-id &optional refresh)
(let* ((object (if (numberp object-or-id) (let* ((object (if (numberp object-or-id)
(pw-lib-get-object object-or-id) (pw-lib-get-object object-or-id)
object-or-id)) object-or-id))
(node (pw-lib--node object)) (node (pw-lib--node object))
(parameters (pw-lib-object-value node 'parameters))) (parameters (pw-lib-object-value node 'parameters)))
(unless parameters (when (or refresh (not parameters))
(setq parameters (pw-access-properties pw-lib--accessor (pw-lib-object-id node))) (setq parameters (pw-access-properties pw-lib--accessor (pw-lib-object-id node)))
(setcdr node (cons (cons 'parameters parameters) (setcdr node (cons (cons 'parameters parameters)
(cdr node)))) (assq-delete-all 'parameters (cdr node)))))
parameters)) parameters))
(defun pw-lib-default-nodes () (defun pw-lib-default-nodes ()
@ -152,9 +152,9 @@ version, call `pw-lib-refresh' first."
(defun pw-lib--volume-float (volume) (defun pw-lib--volume-float (volume)
(/ (float volume) 100)) (/ (float volume) 100))
(defun pw-lib--object-parameters (object) (defun pw-lib--object-parameters (object &optional refresh)
(let* ((node-p (equal (pw-lib-object-type object) "Node")) (let* ((node-p (equal (pw-lib-object-type object) "Node"))
(parameters (pw-lib--node-parameters object)) (parameters (pw-lib--node-parameters object refresh))
(monitor-p (unless node-p (monitor-p (unless node-p
(equal (pw-lib-object-value object "port.monitor") "true"))) (equal (pw-lib-object-value object "port.monitor") "true")))
(node-id (pw-lib-object-id (pw-lib--node object))) (node-id (pw-lib-object-id (pw-lib--node object)))
@ -162,37 +162,37 @@ version, call `pw-lib-refresh' first."
(pw-lib-object-value object "port.id")))) (pw-lib-object-value object "port.id"))))
(list node-p parameters monitor-p node-id port-id))) (list node-p parameters monitor-p node-id port-id)))
(defun pw-lib-muted-p (object) (defun pw-lib-muted-p (object &optional refresh)
"Return whether the given PipeWire object is muted. "Return whether the given PipeWire object is muted.
Applicable only to Nodes and Ports. Applicable only to Nodes and Ports.
Note that PipeWire data is cached, if you need its up-to-date If REFRESH is non-nil then retrive fresh information from PipeWire
version, call `pw-lib-refresh' first." rather than using cached data to obtain the result."
(cl-destructuring-bind (node-p parameters monitor-p node-id port-id) (cl-destructuring-bind (node-p parameters monitor-p node-id port-id)
(pw-lib--object-parameters object) (pw-lib--object-parameters object refresh)
(eq (cdr (assoc (if monitor-p "monitorMute" "mute") parameters)) 'true))) (eq (cdr (assoc (if monitor-p "monitorMute" "mute") parameters)) 'true)))
(defun pw-lib-toggle-mute (object) (defun pw-lib-toggle-mute (object &optional refresh)
"Toggle mute status of the given PipeWire OBJECT. "Toggle mute status of the given PipeWire OBJECT.
Return the new boolean mute status of OBJECT. Return the new boolean mute status of OBJECT.
Applicable only to Nodes and Ports. Applicable only to Nodes and Ports.
Note that PipeWire data is cached, if you need its up-to-date If REFRESH is non-nil then retrive fresh information from PipeWire
version, call `pw-lib-refresh' first." rather than using cached data to obtain the result."
(cl-destructuring-bind (node-p parameters monitor-p node-id port-id) (cl-destructuring-bind (node-p parameters monitor-p node-id port-id)
(pw-lib--object-parameters object) (pw-lib--object-parameters object refresh)
(let* ((mute (not (pw-lib-muted-p object))) (let* ((mute (not (pw-lib-muted-p object)))
(property (if monitor-p "monitorMute" "mute")) (property (if monitor-p "monitorMute" "mute"))
(value (if mute "true" "false"))) (value (if mute "true" "false")))
(pw-access-set-properties pw-lib--accessor node-id (list (cons property value))) (pw-access-set-properties pw-lib--accessor node-id (list (cons property value)))
mute))) mute)))
(defun pw-lib-volume (object) (defun pw-lib-volume (object &optional refresh)
"Return volume of the given PipeWire object. "Return volume of the given PipeWire object.
The returned value is an integer in the range 0-100. The returned value is an integer in the range 0-100.
Applicable only to Nodes and Ports. Applicable only to Nodes and Ports.
Note that PipeWire data is cached, if you need its up-to-date If REFRESH is non-nil then retrive fresh information from PipeWire
version, call `pw-lib-refresh' first." rather than using cached data to obtain the result."
(cl-destructuring-bind (node-p parameters monitor-p node-id port-id) (cl-destructuring-bind (node-p parameters monitor-p node-id port-id)
(pw-lib--object-parameters object) (pw-lib--object-parameters object refresh)
(pw-lib--volume-% (pw-lib--volume-%
(if node-p (if node-p
(cdr (assoc "volume" parameters)) (cdr (assoc "volume" parameters))

BIN
screenshot.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB