added pianobar control scripts
[powermate.git] / powermate.hs
1 module Main where
2
3 import PowerMate
4 import System.IO
5 import System.Process
6 import Control.Monad
7 import Text.Regex.Posix
8 import Data.Time
9
10 data State = State {
11   stPowerMate   :: Handle,
12   stVolume      :: Int,
13   stPrevDir     :: Int,
14   stPrevAction  :: Int,
15   stPressed     :: Bool,
16   stLastPress   :: UTCTime
17 }
18
19 processEvent :: State -> Event -> IO State
20 processEvent state (Button True) = do
21   time <- getCurrentTime
22   state <- updateLastPress state (time)
23   state <- updateButton state True
24   return state
25 processEvent state (Button False) = do
26   time <- getCurrentTime
27   if (diffUTCTime (time) (stLastPress state) > 0.8)
28     then ( do createProcess(proc "volume-toggle" []); return () )
29     else ( do runCommand "music-toggle"; return () )
30   state <- updateButton state False
31   return state
32
33 processEvent state (Rotate dir) = do
34   state <- (if (stPressed state) == False
35               && dir < 2
36               && (stPrevDir state) == 1
37               && (stPrevAction state) == 1
38                 then volumeUp
39               else return) state
40   state <- (if (stPressed state) == False
41               && dir > 2
42               && (stPrevDir state) == 0
43               && (stPrevAction state) == 0
44                 then volumeDown
45               else return) state
46   when ((stPressed state) == True && dir < 2) ( do runCommand "next"; return () )
47   when ((stPressed state) == True && dir > 2) ( do runCommand "back"; return () )
48   state <- updatePrevState state (if dir < 2 then 1 else 0)
49   updateBrightness state
50   state <- updatePrevAction state (if (stPrevAction state) == 1 then 0 else 1)
51   return state
52
53 readState :: State -> IO State
54 readState state = do
55   return state
56
57 next :: a -> (a -> IO a) -> IO ()
58 next state func = do
59   newstate <- func state
60   next newstate func
61   return ()
62
63 updateBrightness :: State -> IO ()
64 updateBrightness state = do
65   let brightness = (stVolume state)
66   writeStatus (stPowerMate state) $
67     statusInit { brightness=brightness }
68
69 volumeUp :: State -> IO State
70 volumeUp state = do
71   createProcess (proc "volume-up" [])
72   state <- readState $ State {
73     stPowerMate=(stPowerMate state),
74     stVolume=(max 0 $ 1+(stVolume state)),
75     stPrevAction=(stPrevAction state),
76     stPrevDir=(stPrevDir state),
77     stPressed=(stPressed state),
78     stLastPress=(stLastPress state) }
79   state <- updatePrevAction state 1
80   return state
81
82 volumeDown :: State -> IO State
83 volumeDown state = do
84   createProcess (proc "volume-down" [])
85   state <- readState $ State {
86     stPowerMate=(stPowerMate state),
87     stVolume=(max 0 $ (stVolume state)-1),
88     stPrevAction=(stPrevAction state),
89     stPrevDir=(stPrevDir state),
90     stPressed=(stPressed state),
91     stLastPress=(stLastPress state) }
92   state <- updatePrevAction state 0
93   return state
94
95 updatePrevState :: State -> Int -> IO State
96 updatePrevState state dir = do
97   state <- readState $ State {
98     stPowerMate=(stPowerMate state),
99     stVolume=(stVolume state),
100     stPrevAction=(stPrevAction state),
101     stPrevDir=dir,
102     stPressed=(stPressed state),
103     stLastPress=(stLastPress state) }
104   return state
105
106 updatePrevAction :: State -> Int -> IO State
107 updatePrevAction state action = do
108   state <- readState $ State {
109     stPowerMate=(stPowerMate state),
110     stVolume=(stVolume state),
111     stPrevAction=action,
112     stPrevDir=(stPrevDir state),
113     stPressed=(stPressed state),
114     stLastPress=(stLastPress state) }
115   return state
116
117 updateButton :: State -> Bool -> IO State
118 updateButton state button = do
119   state <- readState $ State {
120     stPowerMate=(stPowerMate state),
121     stVolume=(stVolume state),
122     stPrevAction=(stPrevAction state),
123     stPrevDir=(stPrevDir state),
124     stPressed=button,
125     stLastPress=(stLastPress state) }
126   return state
127
128 updateLastPress :: State -> UTCTime -> IO State
129 updateLastPress state lastPress = do
130   state <- readState $ State {
131     stPowerMate=(stPowerMate state),
132     stVolume=(stVolume state),
133     stPrevAction=(stPrevAction state),
134     stPrevDir=(stPrevDir state),
135     stPressed=(stPressed state),
136     stLastPress=lastPress }
137   return state
138
139 loop :: FilePath -> IO ()
140 loop devname = do
141   powermate <- openDevice devname
142
143   alsaMixers <- readProcess "amixer" ["get", "Master"] []
144   let alsaMaster = (alsaMixers =~ "\\[([0-9]{1,2})%\\]" :: String)
145   let volume = read (drop 1
146                       (take
147                         (subtract 2
148                           (length alsaMaster)) alsaMaster)) :: Int
149   time <- getCurrentTime
150   state <- readState $ State {
151     stPowerMate=powermate,
152     stVolume=volume,
153     stPrevAction=0,
154     stPrevDir=0,
155     stPressed=False,
156     stLastPress=time }
157   updateBrightness state
158
159   next state $ \call -> do
160     event <- readEventWithSkip powermate Nothing
161     case event of
162       Nothing -> return call
163       Just event -> processEvent call event
164
165 main :: IO ()
166 main = do
167   powermate <- searchForDevice
168   case powermate of
169     Nothing  -> return ()
170     Just work -> do
171       loop work