X-Git-Url: https://disinclined.org/git/?a=blobdiff_plain;f=powermate.hs;h=22b41fcf0133bd4c87ca1132a7b91a48d9ca7002;hb=86d37eb6d13abcaa358e51556876afa0d44fbede;hp=16a783ffa26bdd70b596df8ab306ab034c0e0d75;hpb=58b20da5d6cbf502cef3c31f0c6491e81a0772e6;p=powermate.git diff --git a/powermate.hs b/powermate.hs index 16a783f..22b41fc 100755 --- a/powermate.hs +++ b/powermate.hs @@ -3,24 +3,50 @@ module Main where import PowerMate import System.IO import System.Process +import Control.Monad +import Text.Regex.Posix +import Data.Time data State = State { - stPowerMate :: Handle, - stVolume :: Int + stPowerMate :: Handle, + stVolume :: Int, + stPrevDir :: Int, + stPrevAction :: Int, + stPressed :: Bool, + stLastPress :: UTCTime } processEvent :: State -> Event -> IO State processEvent state (Button True) = do - createProcess (proc "music-toggle" []) + time <- getCurrentTime + state <- updateLastPress state (time) + state <- updateButton state True return state -processEvent state (Button False) = return state - -processEvent state (Rotate dir) = do - if dir < 2 then createProcess (proc "volume-up" []) - else createProcess (proc "volume-down" []) +processEvent state (Button False) = do + time <- getCurrentTime + if (diffUTCTime (time) (stLastPress state) > 0.8) + then ( do runCommand "amixer set Master toggle"; return () ) + else ( do runCommand "music-toggle"; return () ) + state <- updateButton state False return state -processEvent state (StatusChange status) = do +processEvent state (Rotate dir) = do + state <- (if (stPressed state) == False + && dir < 2 + && (stPrevDir state) == 1 + && (stPrevAction state) == 1 + then volumeUp + else return) state + state <- (if (stPressed state) == False + && dir > 2 + && (stPrevDir state) == 0 + && (stPrevAction state) == 0 + then volumeDown + else return) state + when ((stPressed state) == True && dir < 2) ( do runCommand "next"; return () ) + state <- updatePrevState state (if dir < 2 then 1 else 0) + updateBrightness state + state <- updatePrevAction state (if (stPrevAction state) == 1 then 0 else 1) return state readState :: State -> IO State @@ -33,12 +59,101 @@ next state func = do next newstate func return () +updateBrightness :: State -> IO () +updateBrightness state = do + let brightness = (stVolume state) + writeStatus (stPowerMate state) $ + statusInit { brightness=brightness } + +volumeUp :: State -> IO State +volumeUp state = do + createProcess (proc "volume-up" []) + state <- readState $ State { + stPowerMate=(stPowerMate state), + stVolume=(max 0 $ 1+(stVolume state)), + stPrevAction=(stPrevAction state), + stPrevDir=(stPrevDir state), + stPressed=(stPressed state), + stLastPress=(stLastPress state) } + state <- updatePrevAction state 1 + return state + +volumeDown :: State -> IO State +volumeDown state = do + createProcess (proc "volume-down" []) + state <- readState $ State { + stPowerMate=(stPowerMate state), + stVolume=(max 0 $ (stVolume state)-1), + stPrevAction=(stPrevAction state), + stPrevDir=(stPrevDir state), + stPressed=(stPressed state), + stLastPress=(stLastPress state) } + state <- updatePrevAction state 0 + return state + +updatePrevState :: State -> Int -> IO State +updatePrevState state dir = do + state <- readState $ State { + stPowerMate=(stPowerMate state), + stVolume=(stVolume state), + stPrevAction=(stPrevAction state), + stPrevDir=dir, + stPressed=(stPressed state), + stLastPress=(stLastPress state) } + return state + +updatePrevAction :: State -> Int -> IO State +updatePrevAction state action = do + state <- readState $ State { + stPowerMate=(stPowerMate state), + stVolume=(stVolume state), + stPrevAction=action, + stPrevDir=(stPrevDir state), + stPressed=(stPressed state), + stLastPress=(stLastPress state) } + return state + +updateButton :: State -> Bool -> IO State +updateButton state button = do + state <- readState $ State { + stPowerMate=(stPowerMate state), + stVolume=(stVolume state), + stPrevAction=(stPrevAction state), + stPrevDir=(stPrevDir state), + stPressed=button, + stLastPress=(stLastPress state) } + return state + +updateLastPress :: State -> UTCTime -> IO State +updateLastPress state lastPress = do + state <- readState $ State { + stPowerMate=(stPowerMate state), + stVolume=(stVolume state), + stPrevAction=(stPrevAction state), + stPrevDir=(stPrevDir state), + stPressed=(stPressed state), + stLastPress=lastPress } + return state loop :: FilePath -> IO () loop devname = do powermate <- openDevice devname - state <- readState $ State { stPowerMate=powermate, stVolume=0 } + alsaMixers <- readProcess "amixer" ["get", "Master"] [] + let alsaMaster = (alsaMixers =~ "\\[([0-9]{1,2})%\\]" :: String) + let volume = read (drop 1 + (take + (subtract 2 + (length alsaMaster)) alsaMaster)) :: Int + time <- getCurrentTime + state <- readState $ State { + stPowerMate=powermate, + stVolume=volume, + stPrevAction=0, + stPrevDir=0, + stPressed=False, + stLastPress=time } + updateBrightness state next state $ \call -> do event <- readEventWithSkip powermate Nothing