diff --git a/Monky/Battery.hs b/Monky/Battery.hs
--- a/Monky/Battery.hs
+++ b/Monky/Battery.hs
@@ -131,7 +131,7 @@
   let gap = if online == 0 then now else full - now
   change <- readValue c
   let avg = (change * 20 + s * 80) `div` 100
-  return (if avg >= 3600 then gap `div` (avg `div` 3600) else 0, avg)
+  return (sdivUBound gap (avg `div` 3600) 0, avg)
 
 -- |Get current loading speed in Watt/s
 getLoading :: BatteryHandle -> IO Float
diff --git a/Monky/Examples/Alsa.hs b/Monky/Examples/Alsa.hs
--- a/Monky/Examples/Alsa.hs
+++ b/Monky/Examples/Alsa.hs
@@ -16,57 +16,18 @@
     You should have received a copy of the GNU Lesser General Public License
     along with Monky.  If not, see <http://www.gnu.org/licenses/>.
 -}
-{-# LANGUAGE OverloadedStrings #-}
 {-|
 Module      : Monky.Examples.Alsa
-Description : An example module instance for the alsa module
+Description : Proxy module for backwards compat. See Monky.Examples.Sound.Alsa
 Maintainer  : ongy
 Stability   : testing
 Portability : Linux
 
 -}
-module Monky.Examples.Alsa
+module Monky.Examples.Alsa {-# DEPRECATED "Use Monky.Examples.Sound.Alsa" #-}
   ( getVOLHandle
   , AlsaH
   )
 where
 
-import Monky.Alsa hiding (getVOLHandle)
-import qualified Monky.Alsa as A (getVOLHandle)
-import Monky.Modules
-import Monky.Examples.Utility
-
-import Formatting
-import Data.Text (Text)
-
-{- ALSA module -}
-getVolumeStr :: VOLHandle -> IO Text
-getVolumeStr h = do
-  updateVOLH h
-  m <- getMute h
-  v <- getVolumePercent h
-  if m
-    then return "Mute"
-    else return $ sformat ((left 3 ' ' %. int) % "%") v
-
-getVOLOutput :: VOLHandle -> IO [MonkyOut]
-getVOLOutput h = do
-  out <- getVolumeStr h
-  return [MonkyPlain out]
-
-instance PollModule AlsaH where
-  getOutput (AH h) = getVOLOutput h
-
-instance EvtModule AlsaH where
-  startEvtLoop (AH h) r = do
-    [fd] <- getPollFDs h
-    r =<< getOutput (AH h)
-    loopFd h fd r getVOLOutput
-
--- |The handle type for this module
-newtype AlsaH = AH VOLHandle
-
--- |Get a handle which allows access to audio (alsa) subsystem information
-getVOLHandle :: String -- ^The audio-card to use
-             -> IO AlsaH
-getVOLHandle = fmap AH . A.getVOLHandle
+import Monky.Examples.Sound.Alsa
diff --git a/Monky/Examples/Battery.hs b/Monky/Examples/Battery.hs
--- a/Monky/Examples/Battery.hs
+++ b/Monky/Examples/Battery.hs
@@ -45,10 +45,10 @@
 batteryColor :: BatteryState -> Int -> Text
 batteryColor BatLoading _ = "#5fff5f"
 batteryColor _ p
-  | p < 20 = "#ffff00"
-  | p < 15 = "#ffd700"
-  | p < 10 = "#ffaf00"
   | p <  5 = "#ff0000"
+  | p < 10 = "#ffaf00"
+  | p < 15 = "#ffd700"
+  | p < 20 = "#ffff00"
   | otherwise = ""
 
 batterySymbol :: BatteryState -> Int -> Text
diff --git a/Monky/Examples/Modify.hs b/Monky/Examples/Modify.hs
--- a/Monky/Examples/Modify.hs
+++ b/Monky/Examples/Modify.hs
@@ -47,6 +47,7 @@
   , IOModifyHandle
   , getIOModifyHandle
 
+  , changeImage
   )
 where
 
@@ -62,7 +63,7 @@
 
 -- |Get a handle to purely modify another modules output
 getModifyHandle :: ([MonkyOut] -> [MonkyOut]) -> IO a -> IO (ModifyHandle a)
-getModifyHandle fun = fmap (MH fun)
+getModifyHandle = fmap . MH
 
 instance PollModule a => PollModule (ModifyHandle a) where
   initialize (MH _ m) = initialize m
@@ -85,3 +86,8 @@
 
 instance EvtModule a => EvtModule (IOModifyHandle a) where
   startEvtLoop (IOMH fun m) f = startEvtLoop m (\e -> f =<< fun e)
+
+-- |Change the replacemant char in an monky image (if your font doesn't support it), returns initial value if not an image
+changeImage :: Char -> MonkyOut -> MonkyOut
+changeImage c (MonkyImage x _) = MonkyImage x c
+changeImage _ x                = x
diff --git a/Monky/Examples/Sound/Alsa.hs b/Monky/Examples/Sound/Alsa.hs
new file mode 100644
--- /dev/null
+++ b/Monky/Examples/Sound/Alsa.hs
@@ -0,0 +1,72 @@
+{-
+    Copyright 2015,2016 Markus Ongyerth
+
+    This file is part of Monky.
+
+    Monky is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Monky 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with Monky.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{-# LANGUAGE OverloadedStrings #-}
+{-|
+Module      : Monky.Examples.Sound.Alsa
+Description : An example module instance for the alsa module
+Maintainer  : ongy
+Stability   : testing
+Portability : Linux
+
+-}
+module Monky.Examples.Sound.Alsa
+  ( getVOLHandle
+  , AlsaH
+  )
+where
+
+import Monky.Alsa hiding (getVOLHandle)
+import qualified Monky.Alsa as A (getVOLHandle)
+import Monky.Modules
+import Monky.Examples.Utility
+
+import Formatting
+import Data.Text (Text)
+
+{- ALSA module -}
+getVolumeStr :: VOLHandle -> IO Text
+getVolumeStr h = do
+  updateVOLH h
+  m <- getMute h
+  v <- getVolumePercent h
+  if m
+    then return "Mute"
+    else return $ sformat ((left 3 ' ' %. int) % "%") v
+
+getVOLOutput :: VOLHandle -> IO [MonkyOut]
+getVOLOutput h = do
+  out <- getVolumeStr h
+  return [MonkyPlain out]
+
+instance PollModule AlsaH where
+  getOutput (AH h) = getVOLOutput h
+
+instance EvtModule AlsaH where
+  startEvtLoop (AH h) r = do
+    [fd] <- getPollFDs h
+    r =<< getOutput (AH h)
+    loopFd h fd r getVOLOutput
+
+-- |The handle type for this module
+newtype AlsaH = AH VOLHandle
+
+-- |Get a handle which allows access to audio (alsa) subsystem information
+getVOLHandle :: String -- ^The audio-card to use
+             -> IO AlsaH
+getVOLHandle = fmap AH . A.getVOLHandle
diff --git a/Monky/Examples/Sound/Pulse.hs b/Monky/Examples/Sound/Pulse.hs
new file mode 100644
--- /dev/null
+++ b/Monky/Examples/Sound/Pulse.hs
@@ -0,0 +1,173 @@
+{-
+    Copyright 2016 Markus Ongyerth
+
+    This file is part of Monky.
+
+    Monky is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Monky 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with Monky.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE CPP #-}
+{-|
+Module      : Monky.Examples.Sound.Pulse
+Description : Integration example for pulseaudio library.
+Maintainer  : ongy
+Stability   : experimental
+Portability : Linux
+
+Some of this may move into Monky.Sound.Pulse in a near-ish future.
+-}
+module Monky.Examples.Sound.Pulse
+    ( PulseH
+
+    , startPulse
+    , startPulseMaybe
+    , getPulseHandle
+    )
+where
+
+import Monky.Modules
+import Data.Maybe (fromMaybe)
+import Control.Monad (void)
+import Control.Concurrent.MVar
+import Control.Concurrent
+
+import System.Environment (getProgName)
+
+import Sound.Pulse.Context
+import Sound.Pulse.Mainloop
+import Sound.Pulse.Mainloop.Simple
+
+import Sound.Pulse.Volume
+import Sound.Pulse.Subscribe
+import Sound.Pulse.Serverinfo
+import Sound.Pulse.Sinkinfo
+
+import System.IO (hPutStrLn, stderr)
+import Data.Word (Word32)
+import Data.List (genericLength)
+import Formatting
+
+#if MIN_VERSION_base(4,8,0)
+#else
+import Control.Applicative ((<$>), (<*>))
+#endif
+
+-- |Pulse handle.
+-- This module uses continuations, the handle is not really used
+data PulseH = PulseH (Maybe String)
+
+-- |Format a given sink to the output string.
+printSink :: ([MonkyOut] -> IO ()) -> Sinkinfo -> IO ()
+printSink fun sink = do
+    let norm = 0x10000 :: Double
+    let (CVolume vol) = siVolume sink
+    let mute = siMute sink
+    -- this is taken from pulseaudio pa_volume_snprint, +- rounding this is
+    -- equal to pavucontrol
+    let rvols =  map (\v -> (fromIntegral v*100+norm/2) / norm) vol
+    let rvol = sum rvols / genericLength rvols
+    let str = if mute
+        then "Mute"
+        else sformat ((left 3 ' ' %. int) % "%") (round rvol :: Int)
+    fun [MonkyPlain str]
+
+-- |Start the subscription loop that will give us the updates.
+startLoop :: Context -> ([MonkyOut] -> IO ()) -> Sinkinfo -> IO ()
+startLoop cxt cfun info = do 
+    void $ subscribeEvents cxt [SubscriptionMaskSink] fun
+    printSink cfun info
+    where fun :: ((SubscriptionEventFacility, SubscriptionEventType) -> Word32 -> IO ())
+          fun _ 0 = void $ getContextSinkByIndex cxt (siIndex info) (printSink cfun)
+          fun _ _ = return ()
+
+-- |Use the name (string) to find the index, print once and find the main loop
+startWithName :: Context -> String -> ([MonkyOut] -> IO ()) -> IO ()
+startWithName cxt name fun = void $ getContextSinkByName cxt name (startLoop cxt fun)
+
+-- |Get the default sink and start the main loop
+getDefaultSink :: Context -> ([MonkyOut] -> IO ()) -> IO ()
+getDefaultSink cxt cfun = void $ getServerInfo cxt fun
+    where fun :: ServerInfo -> IO ()
+          fun serv = let name = defaultSinkName serv
+                     in startWithName cxt name cfun
+
+-- |Try to start pulse loop. silently fail!
+startPulse :: Maybe String -> ([MonkyOut] -> IO ()) -> IO ()
+startPulse = startPulseMaybe (return ())
+
+
+-- |Connect to pulse server and try to start the main loop for this module.
+startPulseMaybe
+    :: IO () -- ^The continuation if everything fails
+    -> Maybe String -- ^Sink to use (Nothing for default)
+    -> ([MonkyOut] -> IO ()) -- ^Output function
+    -> IO ()
+startPulseMaybe ret sinkName fun = do
+    impl <- getMainloopImpl
+    name <- getProgName
+    cxt <- getContext impl name
+    setStateCallback cxt $ do
+        state <- getContextState cxt
+        case state of
+            ContextFailed -> do
+                hPutStrLn stderr "Could not connect to pulse :("
+                quitLoop impl (-1)
+            ContextReady -> fromMaybe
+                (getDefaultSink cxt fun )
+                (startWithName cxt <$> sinkName <*> return fun)
+            _ -> return ()
+    _ <- connectContext cxt Nothing []
+    _ <- doLoop impl
+    ret
+
+instance EvtModule PulseH where
+    startEvtLoop (PulseH server) fun = startPulseMaybe (fun [MonkyPlain "None"]) server fun
+
+
+--startSyncPulse
+--    :: IO Bool
+--startSyncPulse = do
+--    impl <- getMainloopImpl
+--    cxt <- getContext impl "monky" -- should we get the exe name?
+--    var <- newEmptyMVar
+--    setStateCallback cxt $ do
+--        state <- getContextState cxt
+--        case state of
+--            ContextFailed -> do
+--                hPutStrLn stderr "Could not connect to pulse :("
+--                quitLoop impl (-1)
+--                putMVar var False
+--            ContextReady ->
+--                putMVar var True
+--            _ -> return ()
+--    _ <- connectContext cxt Nothing []
+--    _ <- forkIO . void $ doLoop impl
+--    -- Should we care?
+--    readMVar var
+
+-- This (most of it) should move into pulseaudio package, not doing that yet.
+-- instance PollModule PulseH where
+--     initialize (PulseH _) = do
+--         running <- startSyncPulse
+--         if running
+--            then return ()
+--            else return ()
+--     getOutput _ = return []
+
+-- |Get the handle for pulse integration.
+getPulseHandle
+    :: Maybe String -- ^The servername (Nothing will use environment variable)
+    -> IO PulseH
+getPulseHandle = return . PulseH
diff --git a/Monky/Examples/Wifi.hs b/Monky/Examples/Wifi.hs
--- a/Monky/Examples/Wifi.hs
+++ b/Monky/Examples/Wifi.hs
@@ -22,8 +22,13 @@
 Maintainer  : ongy
 Stability   : experimental
 Portability : Linux
+
+FormatSignal only makes sense when used in a pollModule. But even in pollModule
+context updates may take a while because of some buffering by drivers or
+netlink subsystem.
 -}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE CPP #-}
 module Monky.Examples.Wifi
   ( getWifiHandle
@@ -33,6 +38,8 @@
 where
 
 import Formatting
+import Data.Word (Word32, Word8)
+import Data.Int (Int32)
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Maybe (fromMaybe)
@@ -56,7 +63,7 @@
   | FormatRates -- ^Print the current network max supported rate (always 54Mbit/s for me)
   | FormatName -- ^Print the ESSID of the current network, may look weird because SSIDs are
   | FormatFreq -- ^Print the frequency the current network sends on (related to channel)
-  | FormatMBM -- ^I think something something signal strength
+  | FormatSignal -- ^Print link quality (0-100)
   | FormatText Text -- ^Print a plaintext string
 
 getFun :: WifiFormat -> WifiStats -> Text
@@ -64,12 +71,27 @@
 getFun FormatRates      = flip convertUnitSI "B" . maximum . wifiRates
 getFun FormatName       = T.pack . wifiName
 getFun FormatFreq       = sformat int . wifiFreq
-getFun FormatMBM        = sformat int . wifiMBM
+getFun FormatSignal     = sformat int . doStrength . wifiSig
 getFun (FormatText str) = const str
 
 getFunction :: [WifiFormat] -> WifiStats -> Text
 getFunction xs = T.concat . (\a -> map (($ a) . getFun) xs)
 
+-- |Do the calculation for MBM
+-- This is taken from NetworkManager
+doMBM :: Word32 -> Word8
+doMBM e =
+  let noiseFloor = -90
+      signalMax  = -20
+      work :: Int32 = fromIntegral e
+      clamped :: Float = min signalMax $ max noiseFloor $ fromIntegral $ work `div` 100
+      in floor (100 - 70 * ((signalMax - clamped) / (signalMax - noiseFloor)))
+
+-- Helper for FormatSignal that splits signal types
+doStrength :: Signal -> Word8
+doStrength (SigMBM mbm) = doMBM mbm
+doStrength (SigUNSPEC unspec) = unspec
+
 -- |Get a wifi handle
 getWifiHandle
   :: [WifiFormat] -- ^Format "String" for output generation
@@ -93,6 +115,7 @@
 instance EvtModule WifiHandle where
   startEvtLoop h@(WH s _ _ _) r = do
     r =<< getOutput h
+    prepareEvents s
     loopFd h (getWifiFd s) r getEventOutput
 
 instance PollModule WifiHandle where
diff --git a/Monky/Outputs/Dzen2.hs b/Monky/Outputs/Dzen2.hs
--- a/Monky/Outputs/Dzen2.hs
+++ b/Monky/Outputs/Dzen2.hs
@@ -29,10 +29,11 @@
 module Monky.Outputs.Dzen2
   ( DzenOutput
   , getDzenOut
+  , getDzenOut'
   )
 where
 
-import Data.Composition ((.:))
+import System.Directory(getCurrentDirectory)
 import System.IO (hFlush, stdout)
 import Monky.Modules
 
@@ -86,4 +87,14 @@
   :: Int -- ^The height of your dzen bar in pixel (required for block-drawing)
   -> Text -- ^Path to the directory cointaining your .xbm files.
   -> IO DzenOutput
-getDzenOut = return .: DzenOutput
+getDzenOut h = return . DzenOutput h . flip T.append "/"
+
+
+-- |Get the output handle for dzen2 formatting. Will asume your .xbm files are
+-- |in <monkydir>/xbm/
+getDzenOut'
+    :: Int -- ^The height of your dzen bar in pixel (for block drawing)
+    -> IO DzenOutput
+getDzenOut' h = do
+    pwd <- getCurrentDirectory
+    getDzenOut h (T.pack pwd `T.append` "/xbm/")
diff --git a/Monky/Outputs/Fallback.hs b/Monky/Outputs/Fallback.hs
--- a/Monky/Outputs/Fallback.hs
+++ b/Monky/Outputs/Fallback.hs
@@ -52,6 +52,7 @@
   doLine (WO o) = doLine o
 
 
+-- |Lowerlevel access to guess which terminal out to use based on system encoding
 chooseTerminalOut :: IO WrapOuts
 chooseTerminalOut = do
   l <- getLocaleEncoding
diff --git a/Monky/Outputs/Guess.hs b/Monky/Outputs/Guess.hs
--- a/Monky/Outputs/Guess.hs
+++ b/Monky/Outputs/Guess.hs
@@ -1,6 +1,32 @@
+{-
+    Copyright 2016 Markus Ongyerth
+
+    This file is part of Monky.
+
+    Monky is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Monky 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with Monky.  If not, see <http://www.gnu.org/licenses/>.
+-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE ExistentialQuantification #-}
 {-# LANGUAGE CPP #-}
+{-|
+Module      : Monky.Outputs.Guess
+Description : Guess the output that should be used based on pipe
+Maintainer  : ongy
+Stability   : testing
+Portability : Linux
+
+-}
 module Monky.Outputs.Guess
   ( guessOutput
   , GuessOut
@@ -15,7 +41,6 @@
 import Data.Maybe (catMaybes)
 import System.Directory (getDirectoryContents)
 import System.IO (hIsTerminalDevice, stdout)
-import System.IO.Error (IOError)
 import System.Posix.Files (readSymbolicLink)
 
 import Monky.Modules
@@ -36,6 +61,7 @@
   | Other
   deriving (Eq, Ord, Show)
 
+-- | Type wrapper for this to work
 data GuessOut = forall a . MonkyOutput a => GO a
 
 instance MonkyOutput GuessOut where
@@ -100,10 +126,11 @@
   -> IO GuessOut
 chooseProcessOut height path x
   | x == "dzen2" = GO <$> getDzenOut height path
-  | x == "i3-bar" = GO <$> getI3Output
+  | x == "i3bar" = GO <$> getI3Output
   | x `elem`networkOuts = GO <$> getSerializeOut
   | otherwise = GO <$> getShowOut
 
+-- | Guess output based on isatty and other side of the stdout fd
 guessOutput
   :: Int -- ^Dzen height
   -> Text -- ^Dzen xbm path
diff --git a/Monky/Outputs/I3.hs b/Monky/Outputs/I3.hs
--- a/Monky/Outputs/I3.hs
+++ b/Monky/Outputs/I3.hs
@@ -24,7 +24,11 @@
 Stability   : testing
 Portability : Linux
 
-This module provides the output generation for i3-bar outputs
+This module provides the output generation for i3-bar outputs.
+Do note, if you are using this output, you have to compile monky
+once before you are piping it to i3-bar.
+GHC will output something during compilation step, this can't be avoided
+by monky, this will break the output.
 -}
 module Monky.Outputs.I3
   ( I3Output
diff --git a/Monky/Wifi.hs b/Monky/Wifi.hs
--- a/Monky/Wifi.hs
+++ b/Monky/Wifi.hs
@@ -34,12 +34,16 @@
   , Interface
   , SSIDSocket
   , getWifiFd
+  , prepareEvents
 
+  , Signal(..)
   , WifiStats(..)
   , WifiConn(..)
   )
 where
 
+import Debug.Trace
+
 import Data.Bits ((.&.))
 import Data.Word (Word8, Word32)
 import Data.Maybe (listToMaybe, fromMaybe)
@@ -75,13 +79,18 @@
   | WifiDisconnect -- ^The current network was disconnectd
   | WifiConnect WifiStats -- ^A new connection was established
 
+-- |Signal type: http://lxr.free-electrons.com/source/net/wireless/nl80211.c#L6944
+data Signal
+  = SigMBM Word32 -- ^Signal MBM
+  | SigUNSPEC Word8 -- ^Strength 0-100 http://lxr.mein.io/source/iwinfo/api/nl80211.h#L3388
+
 -- |Wifi network connection information
 data WifiStats = WifiStats
   { wifiChannel :: Word8
   , wifiRates :: [Word32]
   , wifiName :: String
   , wifiFreq :: Word32
-  , wifiMBM :: Word32
+  , wifiSig :: Signal
   }
 
 -- Unsafe decode, we rely on kernel to be sensible
@@ -98,7 +107,13 @@
     (Left _)  -> Nothing
     (Right x) -> return x
 
+-- |Convert raw values from netlink
+getSignal :: Maybe Word32 -> Maybe Word8 -> Signal
+getSignal Nothing    (Just unspec) = SigUNSPEC unspec
+getSignal (Just mbm) Nothing       = SigMBM mbm
+getSignal x          y             = error ("Wifi signal is weird, should be either, got: " ++ show x ++ " and " ++ show y)
 
+-- |Get WifiStats from netlink message
 attrToStat :: NL80211Packet -> Maybe WifiStats
 attrToStat pack = do
   pattrs <- getBssAttrs $ packetAttributes pack
@@ -109,19 +124,20 @@
   rate <- M.lookup eWLAN_EID_SUPP_RATES attrs
 
   freq <- uDecode . M.lookup eNL80211_BSS_FREQUENCY $ pattrs
-  mbm <- uDecode . M.lookup eNL80211_BSS_SIGNAL_MBM $ pattrs
+  let mbm = uGetWord32 . M.lookup eNL80211_BSS_SIGNAL_MBM $ pattrs
+  let sig = uDecode . M.lookup eNL80211_BSS_SIGNAL_UNSPEC $ pattrs
 
   let bs = M.lookup eWLAN_EID_EXT_SUPP_RATES attrs
   let ratL = rate `BS.append` fromMaybe BS.empty bs
   let rates = map (\y -> fromIntegral (y .&. 0x7F) * (500000 :: Word32)) . BS.unpack $ ratL
 
-  return $ WifiStats channel rates name freq mbm
+  return $ WifiStats channel rates name freq $getSignal mbm sig
 
 -- |Get the stats of a currently connected wifi network
 getCurrentWifiStats :: SSIDSocket -> Interface -> IO (Maybe WifiStats)
 getCurrentWifiStats s i = do
   wifis <- getConnectedWifi s i
-  return $ attrToStat =<< listToMaybe wifis
+  return $ attrToStat =<< listToMaybe (trace ("conn: " ++ show wifis) wifis)
 
 
 -- |Get only the name of the currently connected wifi
@@ -167,10 +183,13 @@
               else return WifiNone
           else return WifiNone
 
+-- |Subscribe to multicast group
+prepareEvents :: SSIDSocket -> IO ()
+prepareEvents s = joinMulticastByName s "mlme"
 
--- |Get a netlink socket bound to nl80211 mlme Group
+-- |Get a netlink socket bound to nl80211
+-- Before this is used event based, call 'prepareEvents'
 getSSIDSocket :: IO SSIDSocket
 getSSIDSocket = do
   s <- makeNL80211Socket
-  joinMulticastByName s "mlme"
   return s
diff --git a/bin/Main.hs b/bin/Main.hs
--- a/bin/Main.hs
+++ b/bin/Main.hs
@@ -51,6 +51,7 @@
 import System.IO (withFile, IOMode(..), hPutStr, hPutStrLn, stderr)
 import System.Posix.Process (executeFile)
 import System.Process (system)
+import Data.Monoid ((<>))
 
 import Options.Applicative
 
diff --git a/monky.cabal b/monky.cabal
--- a/monky.cabal
+++ b/monky.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             2.0.1.0
+version:             2.1.0.0
 
 -- The ABOVE LINE has to stay AS IS (except for version changes) for the
 -- template to work properly
@@ -96,6 +96,10 @@
   Description: enable ibus example
   Default: False
 
+Flag pulse
+  Description: enable pulse example (7.6 disabled because travis)
+  Default: True
+
 Source-repository head
   type:       git
   location:   https://github.com/monky-hs/monky
@@ -128,12 +132,13 @@
 
 library
   exposed-modules: Monky.Disk Monky.Modules Monky.Time Monky.CPU Monky.Memory Monky.Network Monky.Utility Monky.Alsa Monky.Battery Monky
-  exposed-modules: Monky.Examples.Alsa Monky.Examples.Battery Monky.Examples.CPU Monky.Examples.Disk Monky.Examples.Network Monky.Examples.Time Monky.Examples.Memory
+  exposed-modules: Monky.Examples.Battery Monky.Examples.CPU Monky.Examples.Disk Monky.Examples.Network Monky.Examples.Time Monky.Examples.Memory
   exposed-modules: Monky.Disk.Btrfs Monky.Disk.Device
   exposed-modules: Monky.Examples.Prepend Monky.Connectivity
   exposed-modules: Monky.Wifi Monky.Examples.Wifi
   exposed-modules: Monky.Examples.Connectivity Monky.Network.Dynamic
   exposed-modules: Monky.Network.Static Monky.Examples.File Monky.Examples.Utility
+  exposed-modules: Monky.Examples.Sound.Alsa  Monky.Examples.Alsa 
 
   exposed-modules: Monky.Version Monky.Examples.Combine
   exposed-modules: Monky.Examples.Plain Monky.Disk.Common Monky.Blkid
@@ -147,7 +152,7 @@
 
 
   build-depends:       base >=4.6.0.1 && <=5, directory, time
-  build-depends:       text, unix, network, mtl, transformers, text
+  build-depends:       text, unix, network, mtl, transformers
   build-depends:       template-haskell, containers, stm, statvfs
   build-depends:       bytestring, netlink, cereal, formatting, composition
   build-depends:       env-locale >= 1.0.0.1
@@ -165,6 +170,11 @@
   if flag(ibus)
     build-depends: ibus-hs, dbus
     exposed-modules: Monky.Examples.IBus
+
+  if impl(ghc >= 7.8)
+    if flag(pulse)
+      build-depends: pulseaudio
+      exposed-modules: Monky.Examples.Sound.Pulse
 
   ghc-options:         -Wall
   extra-libraries:     
