monky-2.0.0.0: Monky/Modules.hs
{-
Copyright 2015,2016 Markus Ongyerth, Stephan Guenther
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 ExistentialQuantification #-}
{-# LANGUAGE CPP #-}
{-|
Module : Monky.Modules
Description : The module definition used by 'startLoop'
Maintainer : ongy, moepi
Stability : experimental
Portability : Linux
The EvtModule and PollModule classes have to be implemented by monky compatible modules
-}
module Monky.Modules
( MonkyOut(..)
, MonkyOutput(..)
, PollModule(..)
, EvtModule(..)
, Modules(..)
, EvtModules(..)
, PollModules(..)
, pollPack
, evtPack
)
where
import Control.Arrow ((***))
import Data.Word (Word8)
import Data.Text (Text)
import qualified Data.Text.Encoding as E
import Data.Serialize
#if MIN_VERSION_base(4,8,0)
#else
import Control.Applicative ((<$>))
#endif
-- |A data type to encode general output types
data MonkyOut
= MonkyPlain Text -- ^Plaintext output
| MonkyBar Int -- ^A Vertical bar, in %
| MonkyHBar Int -- ^A horizontal bar, in pixel
-- Temporary (FG,BG)
-- Color format (and somewhat image) are not fix yet, so don't rely on them to much
| MonkyColor (Text, Text) MonkyOut -- ^Colorize the enclosed output TODO: Color format
| MonkyImage Text Char -- ^Path to an image to display (for icons), or Unicode glyph that should be used
deriving (Show, Read)
-- |Class that output converters have to implement
class MonkyOutput a where
-- |Create one tick of output from a list of collection module output
doLine
:: a -- ^The output handle, may have a connection handle
-> [[MonkyOut]] -- ^The outputs generated by collection modules
-> IO () -- ^IO() since the output module chooses how to transfer the data to the display client
-- |The "New" class for collection modules
class PollModule a where
-- |Get the current (new) output
getOutput
:: a -- ^The handle, may store data from previous calls
-> IO [MonkyOut] -- ^A list of outputs to build
-- |Initialize the module, this is called once before data collection starts
initialize
:: a -- ^The handle to initialize
-> IO ()
-- |Default implementation
initialize _ = return ()
-- |The class for eventing modules
class EvtModule a where
{- |Start your own event loop. The second argument is the consumer of your output.
Doing this in an opaque way gives a way to chain actions to your event handling
-}
startEvtLoop :: a -> ([MonkyOut] -> IO ()) -> IO ()
-- |A wrapper around module instances so they can be put into a list.
data PollModules = forall a . PollModule a => NMW a Int
-- |A wrapper around EvtModule for so they can be in a list
data EvtModules = forall a . EvtModule a => DW a
-- |Wrapper around 'PollModules' and 'EvtModules' so we can pass all modules in one list to 'startLoop'
data Modules
= Poll PollModules
| Evt EvtModules
-- |Function to make packaging modules easier
pollPack :: PollModule a
=> Int -- ^The refresh rate for this module
-> IO a -- ^The function to get a module (get??Handle)
-> IO Modules -- ^The packed module ready to be given to 'startLoop'
pollPack i = fmap (Poll . flip NMW i)
-- |'pollPack' for 'EvtModule's
evtPack :: EvtModule a
=> IO a
-> IO Modules
evtPack = fmap (Evt . DW)
-- "Official" Serialize instance for sending MonkyOuts over the network
instance Serialize MonkyOut where
put (MonkyPlain t) = do
put (1 :: Word8)
put $ E.encodeUtf8 t
put (MonkyBar i) = do
put (2 :: Word8)
put i
put (MonkyHBar i) = do
put (3 :: Word8)
put i
put (MonkyColor c out) = do
put (4 :: Word8)
put $ E.encodeUtf8 *** E.encodeUtf8 $ c
put out
put (MonkyImage t c) = do
put (5 :: Word8)
put $ E.encodeUtf8 t
put c
get = do
t <- get :: Get Word8
case t of
1 -> MonkyPlain . E.decodeUtf8 <$> get
2 -> MonkyBar <$> get
3 -> MonkyHBar <$> get
4 -> do
c <- get
out <- get
return $ MonkyColor (E.decodeUtf8 *** E.decodeUtf8 $ c) out
5 -> do
i <- E.decodeUtf8 <$> get
c <- get
return $ MonkyImage i c
_ -> fail ("Could not decode MonkyOut, got type: " ++ show t)