--- Hi all, I've had some annoyances where Emms only supports changing the global system volume OOTB when I really want to /just/ change mpv's volume. I took a first stab at a patch, but it definitely shouldn't be merged since a) emms-volume-mpv-change is a bit ugly and b) I haven't done any copyright assignment yet.
I'd appreciate any feedback people have. If you all think this patch is worthwhile, I'm happy to complete the appropriate paperwork and update the documentation. That being said, the patch is pretty short so I understand if we feel it should remain separate. If this patch isn't the one, hopefully someone can push mpv volume adjustment across the finish line. Seems like a "high-demand" feature. [1] [2]. Some thoughts: 1. Should emms-volume-mpv be merged with emms-player-mpv, similar to emms-player-mpd? Or should it remain in a separate file? 2. I'd like to add some synchronous paint over the async handler-based emms-player-mpv-ipc-req-send functions to support functions like emms-volume-mpv-get, but can't think of a good solution. Busy-waiting seems like the only option. 3. Any other useful features? I know [3] brought up ao-volume which is worth including, although in certain cases software gain may be the only option if the source is exceptionally quiet. I think the perfect solution is more complicated than "use ao-volume", especially as ao-volume's behavior changes depending on the underlying implementation. My goal with this patch is to avoid tweaking system volume, be a shame if that only works for a fraction of users. 4. I really really hate fetching properties one by one and registering new handlers every time. [1]: https://lists.gnu.org/archive/html/emms-help/2023-01/msg00034.html [2]: https://lists.gnu.org/archive/html/emms-help/2020-12/msg00006.html [3]: https://lists.gnu.org/archive/html/emms-help/2023-02/msg00000.html emms-volume-mpv.el | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 emms-volume-mpv.el diff --git a/emms-volume-mpv.el b/emms-volume-mpv.el new file mode 100644 index 0000000..5230066 --- /dev/null +++ b/emms-volume-mpv.el @@ -0,0 +1,86 @@ +;;; emms-volume-mpv.el --- Volume function to adjust mpv volume easily -*- lexical-binding: t; -*- + +;; FIXME Copyright assignment + +;; Author: Richard Sent <rich...@freakingpenguin.com> + +;; This file is part of EMMS. + +;; EMMS is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; EMMS is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with EMMS; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: +;; +;; This file defines a function to raise or lower the volume of mpv It +;; can be used stand-alone by passing a process object, though it is +;; meant for usage with Emms, particularly with emms-volume.el and +;; emms-player-mpv.el. +;; +;; This does not adjust the global system volume. Instead, it adjusts +;; the volume of mpv directly. +;; +;; To use add the following to your Emms configuration +;; (setq emms-volume-change-function 'emms-volume-mpv-change) + +;;; History: + +;; January 2025: First release, partly based on emms-volume-pulse.el. + +;;; Code: + +(defun emms-volume-mpv--get-property-safe (property handler &optional proc) + "Passes the value for PROPERTY to HANDLER using mpv process PROC. +If an error occurs, exit with an appropriate message." + (emms-player-mpv-ipc-req-send + `(get_property ,property) + #'(lambda (value error) + (if error + (error "Failed to get mpv %s with error %s" property error) + (funcall handler value))) + proc)) + +(defun emms-volume-mpv-limit (v volume-max) + "Limit V to the range [0 - emms-mpv-volume-max]." + (max (min v volume-max) 0)) + +;;;###autoload +(defun emms-volume-mpv-change (amount &optional proc) + "Change volume by AMOUNT using mpv process PROC." + (unless (or emms-player-mpv-ipc-proc proc) + (error "mpv is not currently running.")) + ;; We need to retrieve volume-max from mpv so we know where to clamp + ;; the volume. We can't set and retrieve because mpv does not clamp + ;; the stored volume, i.e. volume can be > volume-max. Otherwise the + ;; output would be inaccurate and problems would arise if we set + ;; volume to >1000. + (emms-volume-mpv--get-property-safe + 'volume-max + #'(lambda (volume-max) + (emms-volume-mpv--get-property-safe + 'volume + #'(lambda (volume) + ;; set_property does not return the value of the property, + ;; ergo we print it here. + (message "Volume is %d%%" + (let ((next-vol (emms-volume-mpv-limit (+ volume amount) volume-max))) + (emms-player-mpv-ipc-req-send `(set_property volume ,next-vol) + nil proc) + next-vol))) + proc)) + proc)) + +(provide 'emms-volume-mpv) + +;;; emms-volume-mpv.el ends here -- 2.47.1