;;; $Id: mamixer.el,v 1.9 2007/08/25 11:31:05 minh Exp $ ;;; Copyright (c) 2007 Nhat Minh LĂȘ. All rights reserved. ;;; ;;; Redistribution and use in source and binary forms, with or without ;;; modification, are permitted provided that the following conditions ;;; are met: ;;; ;;; 1. Redistributions of source code must retain the above copyright ;;; notice, this list of conditions and the following disclaimer. ;;; ;;; 2. Redistributions in binary form must reproduce the above ;;; copyright notice, this list of conditions and the following ;;; disclaimer in the documentation and/or other materials provided ;;; with the distribution. ;;; ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;;; Another amixer minor mode (defgroup mamixer nil "Another amixer minor mode." :version "1.0" :group 'multimedia) (defcustom mamixer-program "amixer" "Amixer program name." :type 'string :group 'mamixer) (defcustom mamixer-default-control-name "Master" "Default amixer control to mix." :type 'string :group 'mamixer) (defcustom mamixer-basic-increment 4 "Increment by which to increase or decrease the volume when none is given." :type 'integer :group 'mamixer) (defcustom mamixer-spawn-single-process nil "If non-nil, use a single process. The amixer program does not handle external modifications to the volume, so using a single process will not take external changes into account unless `mamixer-update-volume' is called." :type 'boolean :group 'mamixer) (defvar mamixer-process nil "Private. Amixer process object.") (defvar mamixer-current-volume nil "Private. Amixer current volume. Applications should use the functions `mamixer-current-volume' and `mamixer-set-volume'.") (defvar mamixer-mode-string "" "Private. Computed mode line string.") (defun mamixer-current-volume () "Return `mamixer-current-volume'." mamixer-current-volume) (defun mamixer-update-mode-line () "Private. Update mode line." (setq mamixer-mode-string (format "%d%%-" mamixer-current-volume)) (force-mode-line-update)) (defun mamixer-filter-output (process output) "Private. Handle amixer process output. If `mamixer-minor-mode' is active, update the mode line to reflect changes." (when (and mamixer-minor-mode (string-match "\\[\\([0-9]+\\)%\\]" output)) (setq mamixer-current-volume (string-to-number (match-string 1 output))) (mamixer-update-mode-line))) (defun mamixer-try-spawn-process () "Private. Spawn an amixer process if none exists." (when (or (not (processp mamixer-process)) (not (eq (process-status mamixer-process) 'run))) (setq mamixer-process (start-process "amixer" nil mamixer-program "-s")) (set-process-filter mamixer-process 'mamixer-filter-output) (set-process-query-on-exit-flag mamixer-process nil))) (defun mamixer-update-volume (&optional control) "Synchronize stored volume with real value. This is useful if you have made external changes." (interactive) (let* ((ctl (if (not (stringp control)) mamixer-default-control-name control)) (proc (start-process "amixer" nil mamixer-program "sget" ctl))) (set-process-filter proc 'mamixer-filter-output)) (unless (or (not (processp mamixer-process)) (not (eq (process-status mamixer-process) 'run))) (process-send-eof mamixer-process))) (defun mamixer-alter-volume (operation &optional increment control) "Private. Increase or decrease volume of CONTROL by INCREMENT. OPERATION is either a character, `+' or `-'. CONTROL defaults to `mamixer-default-control-name'. INCREMENT defaults `mamixer-basic-increment'." (let ((inc (cond ((consp increment) (car increment)) ((integerp increment) increment) (t mamixer-basic-increment))) (ctl (if (not (stringp control)) mamixer-default-control-name control))) (if (not mamixer-spawn-single-process) (let ((proc (start-process "amixer" nil mamixer-program "sset" ctl (format "%d%%%c" inc operation)))) (set-process-filter proc 'mamixer-filter-output)) (mamixer-try-spawn-process) (process-send-string mamixer-process (format "sset %s %d%%%c\n" ctl inc operation))))) (defun mamixer-increase-volume (&optional increment control) "Increase volume of CONTROL by INCREMENT. CONTROL defaults to `mamixer-default-control-name'. INCREMENT defaults `mamixer-basic-increment'." (interactive "P") (mamixer-alter-volume ?+ increment control)) (defun mamixer-decrease-volume (&optional increment control) "Decrease volume of CONTROL by INCREMENT. CONTROL defaults to `mamixer-default-control-name'. INCREMENT defaults `mamixer-basic-increment'." (interactive "P") (mamixer-alter-volume ?- increment control)) (defun mamixer-set-volume (value &optional control) "Set volume of CONTROL to VALUE. CONTROL defaults to `mamixer-default-control-name'." (let ((ctl (if (null control) mamixer-default-control-name control))) (if (not mamixer-spawn-single-process) (let ((proc (start-process "amixer" nil mamixer-program "sset" ctl (format "%d%%" value)))) (set-process-filter proc 'mamixer-filter-output)) (mamixer-try-spawn-process) (process-send-string mamixer-process (format "sset %s %d%%\n" ctl value))))) (define-minor-mode mamixer-minor-mode "Display volume in mode line." nil nil nil :require 'mamixer :group 'mamixer :global t (if (and (not mamixer-minor-mode) (member '(t mamixer-mode-string) global-mode-string)) (setq global-mode-string (delete '(t mamixer-mode-string) global-mode-string)) (mamixer-update-volume) (when mamixer-spawn-single-process (mamixer-try-spawn-process)) (or (member '(t mamixer-mode-string) global-mode-string) (setq global-mode-string (cons '(t mamixer-mode-string) global-mode-string))))) (provide 'mamixer)