From e3c9b33170f1064077aa8578342369657b9e059c Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Thu, 13 Jan 2011 10:34:09 -0600 Subject: Added volume monitor based on alsa-mixer. --- src/Plugins/Monitors.hs | 12 ++++++++++++ src/Plugins/Monitors/Volume.hs | 36 ++++++++++++++++++++++++++++++++++++ xmobar.cabal | 8 ++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/Plugins/Monitors/Volume.hs diff --git a/src/Plugins/Monitors.hs b/src/Plugins/Monitors.hs index 9887d74..14d97a2 100644 --- a/src/Plugins/Monitors.hs +++ b/src/Plugins/Monitors.hs @@ -38,6 +38,9 @@ import Plugins.Monitors.Wireless #ifdef LIBMPD import Plugins.Monitors.MPD #endif +#ifdef ALSA +import Plugins.Monitors.Volume +#endif data Monitors = Weather Station Args Rate | Network Interface Args Rate @@ -60,6 +63,9 @@ data Monitors = Weather Station Args Rate #endif #ifdef LIBMPD | MPD Args Rate +#endif +#ifdef ALSA + | Volume String String Args Rate #endif deriving (Show,Read,Eq) @@ -94,6 +100,9 @@ instance Exec Monitors where #endif #ifdef LIBMPD alias (MPD _ _) = "mpd" +#endif +#ifdef ALSA + alias (Volume m c _ _) = m ++ ":" ++ c #endif start (Weather s a r) = runM (a ++ [s]) weatherConfig runWeather r start (Network i a r) = runM (a ++ [i]) netConfig runNet r @@ -117,3 +126,6 @@ instance Exec Monitors where #ifdef LIBMPD start (MPD a r) = runM a mpdConfig runMPD r #endif +#ifdef ALSA + start (Volume m c a r) = runM a volumeConfig (runVolume m c) r +#endif diff --git a/src/Plugins/Monitors/Volume.hs b/src/Plugins/Monitors/Volume.hs new file mode 100644 index 0000000..c7814a8 --- /dev/null +++ b/src/Plugins/Monitors/Volume.hs @@ -0,0 +1,36 @@ +module Plugins.Monitors.Volume (runVolume, volumeConfig) where + +import Control.Monad ( liftM ) +import Data.Maybe +import Plugins.Monitors.Common +import Sound.ALSA.Mixer + +percent :: Integer -> Integer -> Integer -> Float +percent v' lo' hi' = (v - lo) / (hi - lo) + where v = fromIntegral v' + lo = fromIntegral lo' + hi = fromIntegral hi' + +volumeConfig :: IO MConfig +volumeConfig = mkMConfig "Vol: % " + ["volume","dB","on","off"] + +runVolume :: String -> String -> [String] -> Monitor String +runVolume mixerName controlName _ = do + control <- liftM fromJust $ io $ getControlByName mixerName controlName + let volumeControl = fromJust $ maybe (playback $ volume control) Just + (common $ volume control) + switchControl = fromJust $ maybe (playback $ switch control) Just + (common $ switch control) + (lo, hi) <- io $ getRange volumeControl + val <- liftM fromJust $ io $ getChannel FrontLeft $ value volumeControl + db <- liftM fromJust $ io $ getChannel FrontLeft $ dB volumeControl + sw <- liftM fromJust $ io $ getChannel FrontLeft $ switchControl + p <- showPercentsWithColors [ percent val lo hi ] + let d :: Double + d = fromIntegral db / 100.0 + dStr = showDigits 2 d + parseTemplate $ p ++ [ dStr ] + ++ [ if sw then "[on] " else "" + , if sw then "" else "[off]" + ] diff --git a/xmobar.cabal b/xmobar.cabal index e5ee507..0eac0fa 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -53,6 +53,10 @@ flag all_extensions description: Includes all optional extensions. default: False +flag with_alsa + description: Use alsa-mixer to get the volume from soundcards. + default: False + executable xmobar hs-source-dirs: src main-is: Main.hs @@ -109,3 +113,7 @@ executable xmobar build-depends: libmpd >= 0.5 other-modules: Plugins.Monitors.MPD cpp-options: -DLIBMPD + + if flag(with_alsa) || flag(all_extensions) + build-depends: alsa-mixer + cpp-options: -DALSA -- cgit v1.2.3 From 09a8ea406d58d972d318a8884d0a4ef292f44744 Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Thu, 13 Jan 2011 10:50:20 -0600 Subject: Documented volume monitor in README. --- README | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README b/README index b83a7f0..1e300bb 100644 --- a/README +++ b/README @@ -120,6 +120,10 @@ Otherwise, you'll need to install them yourself. headers in your system (e.g., install `libiw-dev` in Debian-based systems). +`with_alsa` +: Support for ALSA sound cards. Enables the Volume plugin. Requires the + [alsa-mixer] package. + `all_extensions` : Enables all the extensions above. @@ -616,6 +620,18 @@ Monitors have default aliases. Run MBox [("I ", "inbox", "red"), ("O ", "~/foo/mbox", "")] ["-d", "/var/mail/", "-p", " "] "mbox" +`Volume Mixer Element Args RefreshRate` + +- Aliases to the mixer name and element name separated by a colon. Thus, + `Volume "default" "Master" [] 10` can be used as `%default:Master`. +- Args: default monitor arguments (see below) +- Variables that can be used with the `-t`/`--template` argument: + `vol`, `db`, `on`, `off` +- Default template: `Vol: % ` +- Requires the package [alsa-mixer] installed in your system. In addition, + to activate this plugin you must pass `--flags="with_alsa"` during + compilation. + `XPropertyLog PropName` - Aliases to `PropName` @@ -998,3 +1014,4 @@ Copyright © 2010 Jose Antonio Ortega Ruiz [libmpd]: http://hackage.haskell.org/package/libmpd/ [sawfish]: http://sawfish.wikia.com/ [utf8-string]: http://hackage.haskell.org/package/utf8-string/ +[alsa-mixer]: http://hackage.haskell.org/package/alsa-mixer -- cgit v1.2.3 From 24fe3c3aef1dd1cb61c83677d49a3a50330962b7 Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Thu, 13 Jan 2011 12:08:51 -0600 Subject: Added version constraint for alsa-mixer. --- xmobar.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmobar.cabal b/xmobar.cabal index 0eac0fa..2990b50 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -115,5 +115,5 @@ executable xmobar cpp-options: -DLIBMPD if flag(with_alsa) || flag(all_extensions) - build-depends: alsa-mixer + build-depends: alsa-mixer == 0.1.* cpp-options: -DALSA -- cgit v1.2.3 From d444ebca849d77eec58243f800f0f675e1469dc8 Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Thu, 13 Jan 2011 12:57:24 -0600 Subject: Improved volume monitor. Featuring: configurable status strings, status colors, and dB thresholds. --- src/Plugins/Monitors/Volume.hs | 88 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/src/Plugins/Monitors/Volume.hs b/src/Plugins/Monitors/Volume.hs index c7814a8..960b5e4 100644 --- a/src/Plugins/Monitors/Volume.hs +++ b/src/Plugins/Monitors/Volume.hs @@ -4,6 +4,42 @@ import Control.Monad ( liftM ) import Data.Maybe import Plugins.Monitors.Common import Sound.ALSA.Mixer +import System.Console.GetOpt + +data VolumeOpts = VolumeOpts + { onString :: String + , offString :: String + , onColor :: Maybe String + , offColor :: Maybe String + , highDbThresh :: Float + , lowDbThresh :: Float + } + +defaultOpts :: VolumeOpts +defaultOpts = VolumeOpts + { onString = "[on] " + , offString = "[off]" + , onColor = Just "green" + , offColor = Just "red" + , highDbThresh = -5.0 + , lowDbThresh = -30.0 + } + +options :: [OptDescr (VolumeOpts -> VolumeOpts)] +options = + [ Option "O" ["on"] (ReqArg (\x o -> o { onString = x }) "") "" + , Option "o" ["off"] (ReqArg (\x o -> o { offString = x }) "") "" + , Option "" ["lowd"] (ReqArg (\x o -> o { lowDbThresh = read x }) "") "" + , Option "" ["highd"] (ReqArg (\x o -> o { highDbThresh = read x }) "") "" + , Option "C" ["onc"] (ReqArg (\x o -> o { onColor = Just x }) "") "" + , Option "c" ["offc"] (ReqArg (\x o -> o { offColor = Just x }) "") "" + ] + +parseOpts :: [String] -> IO VolumeOpts +parseOpts argv = + case getOpt Permute options argv of + (o, _, []) -> return $ foldr id defaultOpts o + (_, _, errs) -> ioError . userError $ concat errs percent :: Integer -> Integer -> Integer -> Float percent v' lo' hi' = (v - lo) / (hi - lo) @@ -12,11 +48,45 @@ percent v' lo' hi' = (v - lo) / (hi - lo) hi = fromIntegral hi' volumeConfig :: IO MConfig -volumeConfig = mkMConfig "Vol: % " - ["volume","dB","on","off"] +volumeConfig = mkMConfig "Vol: % " + ["volume","dB","status"] + +formatVol :: Integer -> Integer -> Integer -> Monitor String +formatVol v lo hi = + showPercentWithColors $ percent v lo hi + +switchHelper :: VolumeOpts + -> (VolumeOpts -> Maybe String) + -> (VolumeOpts -> String) + -> Monitor String +switchHelper opts cHelp strHelp = return $ + (colorHelper $ cHelp opts) + ++ strHelp opts + ++ (maybe "" (const "") $ cHelp opts) + +formatSwitch :: VolumeOpts -> Bool -> Monitor String +formatSwitch opts True = switchHelper opts onColor onString +formatSwitch opts False = switchHelper opts offColor offString + +colorHelper :: Maybe String -> String +colorHelper = maybe "" (\c -> "") + +formatDb :: VolumeOpts -> Float -> Monitor String +formatDb opts db = do + h <- getConfigValue highColor + m <- getConfigValue normalColor + l <- getConfigValue lowColor + let digits = showDigits 0 db + startColor | db >= highDbThresh opts = colorHelper h + | db < lowDbThresh opts = colorHelper l + | otherwise = colorHelper m + stopColor | null startColor = "" + | otherwise = "" + return $ startColor ++ digits ++ stopColor runVolume :: String -> String -> [String] -> Monitor String -runVolume mixerName controlName _ = do +runVolume mixerName controlName argv = do + opts <- io $ parseOpts argv control <- liftM fromJust $ io $ getControlByName mixerName controlName let volumeControl = fromJust $ maybe (playback $ volume control) Just (common $ volume control) @@ -26,11 +96,7 @@ runVolume mixerName controlName _ = do val <- liftM fromJust $ io $ getChannel FrontLeft $ value volumeControl db <- liftM fromJust $ io $ getChannel FrontLeft $ dB volumeControl sw <- liftM fromJust $ io $ getChannel FrontLeft $ switchControl - p <- showPercentsWithColors [ percent val lo hi ] - let d :: Double - d = fromIntegral db / 100.0 - dStr = showDigits 2 d - parseTemplate $ p ++ [ dStr ] - ++ [ if sw then "[on] " else "" - , if sw then "" else "[off]" - ] + p <- formatVol val lo hi + d <- formatDb opts $ fromIntegral db / 100.0 + s <- formatSwitch opts sw + parseTemplate $ [ p, d, s ] -- cgit v1.2.3 From 0d9c121385d428d0b9ba82aa956ca5123e395f09 Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Thu, 13 Jan 2011 13:16:55 -0600 Subject: Updated README for improved volume monitor. --- README | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/README b/README index 1e300bb..9b608a1 100644 --- a/README +++ b/README @@ -623,10 +623,26 @@ Monitors have default aliases. `Volume Mixer Element Args RefreshRate` - Aliases to the mixer name and element name separated by a colon. Thus, - `Volume "default" "Master" [] 10` can be used as `%default:Master`. -- Args: default monitor arguments (see below) + `Volume "default" "Master" [] 10` can be used as `%default:Master%`. +- Args: default monitor arguments (see below). Also accepts: + - `-O` _string_ On string + - The string used in place of `` when the mixer element + is on. + - Long option: `--on` + - `-o` _string_ Off string + - The string used in place of `` when the mixer element + is off. + - Long option: `--off` + - `-C` _color_ On color + - The color to be used for `` when the mixer element is on. + - Long option: `--onc` + - `-c` _color_ Off color + - The color to be used for `` when the mixer element is off. + - Long option: `--offc` + - `--highd` _number_ High threshold for dB + - `--lowd` _number_ Low threshold for dB - Variables that can be used with the `-t`/`--template` argument: - `vol`, `db`, `on`, `off` + `vol`, `dB`, `status` - Default template: `Vol: % ` - Requires the package [alsa-mixer] installed in your system. In addition, to activate this plugin you must pass `--flags="with_alsa"` during -- cgit v1.2.3 From 01b569b0b39d678e52009e590061902d392ca25e Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Thu, 13 Jan 2011 13:19:59 -0600 Subject: Added more graceful failure strategies to volume monitor. --- src/Plugins/Monitors/Volume.hs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Plugins/Monitors/Volume.hs b/src/Plugins/Monitors/Volume.hs index 960b5e4..380df30 100644 --- a/src/Plugins/Monitors/Volume.hs +++ b/src/Plugins/Monitors/Volume.hs @@ -93,10 +93,16 @@ runVolume mixerName controlName argv = do switchControl = fromJust $ maybe (playback $ switch control) Just (common $ switch control) (lo, hi) <- io $ getRange volumeControl - val <- liftM fromJust $ io $ getChannel FrontLeft $ value volumeControl - db <- liftM fromJust $ io $ getChannel FrontLeft $ dB volumeControl - sw <- liftM fromJust $ io $ getChannel FrontLeft $ switchControl - p <- formatVol val lo hi - d <- formatDb opts $ fromIntegral db / 100.0 - s <- formatSwitch opts sw + val <- io $ getChannel FrontLeft $ value volumeControl + db <- io $ getChannel FrontLeft $ dB volumeControl + sw <- io $ getChannel FrontLeft $ switchControl + p <- case val of + Just x -> formatVol x lo hi + Nothing -> formatVol hi lo hi + d <- case db of + Just x -> formatDb opts $ fromIntegral x / 100.0 + Nothing -> formatDb opts 0.0 + s <- case sw of + Just x -> formatSwitch opts x + Nothing -> formatSwitch opts True parseTemplate $ [ p, d, s ] -- cgit v1.2.3 From 6591f7e59909dee011abe1ce9df16d03a797de97 Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Thu, 13 Jan 2011 19:11:59 -0600 Subject: Corrected spelling error in README. --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 9b608a1..2174334 100644 --- a/README +++ b/README @@ -642,7 +642,7 @@ Monitors have default aliases. - `--highd` _number_ High threshold for dB - `--lowd` _number_ Low threshold for dB - Variables that can be used with the `-t`/`--template` argument: - `vol`, `dB`, `status` + `volume`, `dB`, `status` - Default template: `Vol: % ` - Requires the package [alsa-mixer] installed in your system. In addition, to activate this plugin you must pass `--flags="with_alsa"` during -- cgit v1.2.3 From ce23b849f7aff963a1e6a84da5281b6a4aaff241 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Sat, 15 Jan 2011 00:03:43 +0100 Subject: Volume monitor: minor linting and file header --- src/Plugins/Monitors/Volume.hs | 22 ++++++++++++++++++---- xmobar.cabal | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/Plugins/Monitors/Volume.hs b/src/Plugins/Monitors/Volume.hs index 380df30..72a9b0e 100644 --- a/src/Plugins/Monitors/Volume.hs +++ b/src/Plugins/Monitors/Volume.hs @@ -1,3 +1,17 @@ +----------------------------------------------------------------------------- +-- | +-- Module : Plugins.Monitors.Volume +-- Copyright : (c) 2011 Thomas Tuegel +-- License : BSD-style (see LICENSE) +-- +-- Maintainer : Jose A. Ortega Ruiz +-- Stability : unstable +-- Portability : unportable +-- +-- A monitor for ALSA soundcards +-- +----------------------------------------------------------------------------- + module Plugins.Monitors.Volume (runVolume, volumeConfig) where import Control.Monad ( liftM ) @@ -60,9 +74,9 @@ switchHelper :: VolumeOpts -> (VolumeOpts -> String) -> Monitor String switchHelper opts cHelp strHelp = return $ - (colorHelper $ cHelp opts) + colorHelper (cHelp opts) ++ strHelp opts - ++ (maybe "" (const "") $ cHelp opts) + ++ maybe "" (const "") (cHelp opts) formatSwitch :: VolumeOpts -> Bool -> Monitor String formatSwitch opts True = switchHelper opts onColor onString @@ -95,7 +109,7 @@ runVolume mixerName controlName argv = do (lo, hi) <- io $ getRange volumeControl val <- io $ getChannel FrontLeft $ value volumeControl db <- io $ getChannel FrontLeft $ dB volumeControl - sw <- io $ getChannel FrontLeft $ switchControl + sw <- io $ getChannel FrontLeft switchControl p <- case val of Just x -> formatVol x lo hi Nothing -> formatVol hi lo hi @@ -105,4 +119,4 @@ runVolume mixerName controlName argv = do s <- case sw of Just x -> formatSwitch opts x Nothing -> formatSwitch opts True - parseTemplate $ [ p, d, s ] + parseTemplate [ p, d, s ] diff --git a/xmobar.cabal b/xmobar.cabal index 2990b50..343570d 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -116,4 +116,5 @@ executable xmobar if flag(with_alsa) || flag(all_extensions) build-depends: alsa-mixer == 0.1.* + other-modules: Plugins.Monitors.Volume cpp-options: -DALSA -- cgit v1.2.3