[cabalize and split into two packages (from gwern0@gmail) Evan Martin **20080331165651] { move ./README ./LICENSE adddir ./src move ./MPD.hs ./src/MPD.hs move ./PowerMate.hsc ./src/PowerMate.hsc adddir ./mpdmate hunk ./LICENSE 1 -PowerMate bindings for Haskell, -MPD bindings (barely) for Haskell. - addfile ./mpdmate/LICENSE hunk ./mpdmate/LICENSE 1 +Copyright (C) 2006 Evan Martin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + addfile ./mpdmate/MPDMate.hs hunk ./mpdmate/MPDMate.hs 1 +-- PowerMate+MPD utility. +-- Copyright (C) 2006 Evan Martin + +module Main where + +import qualified PowerMate +import qualified MPD +import System.IO + +debug :: Bool +debug = False + +ifDebug :: IO () -> IO () +ifDebug _ | debug = return () +ifDebug _ | otherwise = return () + +mpdAddress :: (String, Int) +mpdAddress = ("localhost", 6600) + +data State = State { + stConn :: MPD.ReconnectableConnection, + stPowerMate :: Handle, + stVolume :: Int +} + +processEvent :: State -> PowerMate.Event -> IO State +processEvent state (PowerMate.Button True) = do + MPD.rcDo (stConn state) $ \conn -> MPD.runCommand_ conn "pause" + return state +processEvent state (PowerMate.Button False) = return state + +processEvent state (PowerMate.Rotate dir) = do + let newvol = max 0 $ min 100 $ (stVolume state) + dir + ifDebug $ do + putStr (if dir > 0 then "+" else "-") + hFlush stdout + putStrLn $ show newvol + MPD.rcDo (stConn state) $ \conn -> MPD.setVolume conn newvol + updateBrightness state + return $ state { stVolume=newvol } + +processEvent state (PowerMate.StatusChange status) = do + ifDebug $ do + putStrLn "New status:" + putStrLn $ " Brightness: " ++ show (PowerMate.brightness status) + putStrLn $ " Pulse Speed: " ++ show (PowerMate.pulse_speed status) + putStrLn $ " Pulse Mode: " ++ show (PowerMate.pulse_mode status) + putStrLn $ " Pulse Asleep: " ++ show (PowerMate.pulse_asleep status) + putStrLn $ " Pulse Awake: " ++ show (PowerMate.pulse_awake status) + return state + +readMPDStatus :: State -> IO State +readMPDStatus state = do + volume <- MPD.rcDo (stConn state) $ MPD.getVolume + return $ state { stVolume=volume } + +updateBrightness :: State -> IO () +updateBrightness state = do + let brightness = (stVolume state)*255 `div` 100 + PowerMate.writeStatus (stPowerMate state) $ + PowerMate.statusInit { PowerMate.brightness=brightness } + +loop :: a -> (a -> IO a) -> IO () +loop state func = do + newstate <- func state + loop newstate func + return () -- never reached + +mainLoop :: FilePath -> IO () +mainLoop devname = do + pm <- PowerMate.openDevice devname + --PowerMate.writeStatus pm $ PowerMate.statusInit { PowerMate.brightness=100, PowerMate.pulse_asleep = True } + + conn <- MPD.rcConnect mpdAddress + state <- readMPDStatus $ State { stConn=conn, stPowerMate=pm, stVolume=0 } + updateBrightness state + + loop state $ \stat -> do + event <- PowerMate.readEventWithSkip pm Nothing + case event of + Nothing -> return stat + Just ev -> processEvent stat ev + +main :: IO () +main = do + powermate_device <- PowerMate.searchForDevice + case powermate_device of + Nothing -> return () + Just pmd -> do + mainLoop pmd + +-- vim: set ts=2 sw=2 et ft=haskell : addfile ./mpdmate/Setup.hs hunk ./mpdmate/Setup.hs 1 +#!/usr/bin/runhaskell + +import Distribution.Simple + +main = defaultMainWithHooks defaultUserHooks addfile ./mpdmate/mpdmate.cabal hunk ./mpdmate/mpdmate.cabal 1 +name: mpdmate +version: 0.1 +synopsis: MPD/PowerMate executable +description: This library exploits the PowerMate bindings + to provide PowerMate+MPD utility. +Stability: Experimental +category: System +license: BSD3 +license-file: LICENSE +author: Evan Martin +maintainer: Evan Martin +homepage: http://neugierig.org/software/darcs/powermate/ + +tested-with: GHC==6.8.2 +Cabal-Version: >= 1.2 +build-type: Simple + +Executable mpdmate + build-depends: powermate + build-depends: base>3, unix, directory, network + executable: mpdmate + main-is: MPDMate.hs + + ghc-options: -O2 -Wall -optl-Wl,-s + ghc-prof-options: -prof -auto-al hunk ./src/MPD.hs 15 -import List +import Data.List hunk ./src/MPD.hs 76 -rcDo :: ReconnectableConnection -> (Connection -> IO a) -> IO a +rcDo :: ReconnectableConnection -> (Connection -> IO a) -> IO a hunk ./src/PowerMate.hsc 1 -{-# OPTIONS -fffi #-} +{-# LANGUAGE ForeignFunctionInterface #-} hunk ./src/PowerMate.hsc 23 -import IO -import List (isPrefixOf, find) +import System.Environment +import Data.List (isPrefixOf, find) hunk ./src/PowerMate.hsc 26 +import Control.Exception (bracket) hunk ./src/PowerMate.hsc 28 -import CString (withCAString, peekCString) +import Foreign.C.String (withCAString, peekCString) hunk ./src/PowerMate.hsc 82 --- show (typ, code, value) = +-- show (typ, code, value) = }