chalkboard-1.9.0.15: Graphics/ChalkBoard/Main.hs
module Graphics.ChalkBoard.Main
( ChalkBoard
, drawChalkBoard
, writeChalkBoard
, updateChalkBoard
, drawRawChalkBoard
, exitChalkBoard
, startChalkBoard
, openChalkBoard
, chalkBoardServer
) where
import System.Process
import System.Environment
import System.IO
import System.Exit
import Control.Concurrent
import Graphics.ChalkBoard.Core
import Graphics.ChalkBoard.Types
import Graphics.ChalkBoard.Board
import Graphics.ChalkBoard.CBIR
import Graphics.ChalkBoard.CBIR.Compiler
import Graphics.ChalkBoard.OpenGL.CBBE
import Graphics.ChalkBoard.O
import Graphics.ChalkBoard.Options
import Codec.Image.DevIL
import Data.Word
import Control.Concurrent.MVar
import Control.Concurrent
import System.Cmd
import Data.Binary as Bin
import qualified Data.ByteString.Lazy as B
data ChalkBoardCommand
= DrawChalkBoard (Board RGB)
| UpdateChalkBoard (Board RGB -> Board RGB)
| WriteChalkBoard FilePath
| ExitChalkBoard
| DrawRawChalkBoard [Inst BufferId]
data ChalkBoard = ChalkBoard (MVar ChalkBoardCommand) (MVar ())
-- | Draw a board onto the ChalkBoard.
drawChalkBoard :: ChalkBoard -> Board RGB -> IO ()
drawChalkBoard (ChalkBoard var _) brd = putMVar var (DrawChalkBoard brd)
-- | Write the contents of a ChalkBoard into a File.
writeChalkBoard :: ChalkBoard -> FilePath -> IO ()
writeChalkBoard (ChalkBoard var _) nm = putMVar var (WriteChalkBoard nm)
-- | modify the current ChalkBoard.
updateChalkBoard :: ChalkBoard -> (Board RGB -> Board RGB) -> IO ()
updateChalkBoard (ChalkBoard var _) brd = putMVar var (UpdateChalkBoard brd)
-- | Debugging hook for writing raw CBIR code.
drawRawChalkBoard :: ChalkBoard -> [Inst BufferId] -> IO ()
drawRawChalkBoard (ChalkBoard var _) cmds = putMVar var (DrawRawChalkBoard cmds)
-- | pause for this many seconds, since the last redraw *started*.
pauseChalkBoard :: ChalkBoard -> Double -> IO ()
pauseChalkBoard _ n = do
threadDelay (fromInteger (floor (n * 1000000)))
-- | quit ChalkBoard.
exitChalkBoard :: ChalkBoard -> IO ()
exitChalkBoard (ChalkBoard var end) = do
putMVar var ExitChalkBoard
takeMVar end
return ()
-- | Start, in this process, a ChalkBoard window, and run some commands on it.
startChalkBoard :: [Options] -> (ChalkBoard -> IO ()) -> IO ()
startChalkBoard options cont = do
putStrLn "[Starting ChalkBoard]"
ilInit
v0 <- newEmptyMVar
v1 <- newEmptyMVar
v2 <- newEmptyMVar
vEnd <- newEmptyMVar
forkIO $ compiler options v1 v2
forkIO $ do
() <- takeMVar v0
cont (ChalkBoard v1 vEnd)
print "[Done]"
startRendering viewBoard v0 v2 options
return ()
-- | Open, remotely, a ChalkBoard windown, and return a handle to it.
-- Needs "CHALKBOARD_SERVER" set to the location of the ChalkBoard server.
openChalkBoard :: [Options] -> IO ChalkBoard
openChalkBoard args = do
putStrLn "[Opening Channel to ChalkBoard Server]"
ilInit
v0 <- newEmptyMVar
v1 <- newEmptyMVar
v2 <- newEmptyMVar
vEnd <- newEmptyMVar
(ein,eout,err,pid) <- openServerStream
let options = encode (args :: [Options])
B.hPut ein (encode (fromIntegral (B.length options) :: Word32))
B.hPut ein options
hFlush ein
forkIO $ compiler args v1 v2
forkIO $ do
let loop n = do
v <- takeMVar v2
let code = encode v
B.hPut ein (encode (fromIntegral (B.length code) :: Word32))
B.hPut ein code
hFlush ein
case v of
[Exit] -> putMVar vEnd ()
_ -> loop $! (n+1)
loop 0
return (ChalkBoard v1 vEnd)
viewBoard :: Int
viewBoard = 0
compiler :: [Options] -> MVar ChalkBoardCommand -> MVar [Inst Int] -> IO ()
compiler options v1 v2 = do
putMVar v2 [Allocate viewBoard (x,y) RGB24Depth (BackgroundRGB24Depth (RGB 1 1 1))]
loop (0::Integer) (boardOf (o (RGB 1 1 1)))
where
(x,y) = head ([ (x,y) | BoardSize x y <- options ] ++ [(400,400)])
loop n old_brd = do
cmd <- takeMVar v1
case cmd of
DrawChalkBoard brd -> do
cmds <- compile (x,y) viewBoard (move (0.5,0.5) brd)
-- putStrLn $ showCBIRs cmds
putMVar v2 cmds
loop (n+1) brd
UpdateChalkBoard fn -> do
let brd = fn old_brd
cmds <- compile (x,y) viewBoard (move (0.5,0.5) brd)
-- putStrLn $ showCBIRs cmds
putMVar v2 cmds
loop (n+1) brd
DrawRawChalkBoard cmds -> do
putMVar v2 cmds
loop (n+1) (error "Board in an unknown state")
WriteChalkBoard filename -> do
putMVar v2 [SaveImage viewBoard filename]
loop (n+1) old_brd
ExitChalkBoard -> putMVar v2 [Exit]
openServerStream :: IO (Handle,Handle,Handle,ProcessHandle)
openServerStream = do
server <- getEnv "CHALKBOARD_SERVER" `catch` (\ _ -> return "chalkboard-server-1_9_0_14")
runInteractiveProcess server [] Nothing Nothing `catch` (\ _ -> do print "DOOL" ; error "")
-- | create an instance of the ChalkBoard. Only used by the server binary.
chalkBoardServer :: IO ()
chalkBoardServer = do
v0 <- newEmptyMVar
v2 <- newEmptyMVar
bs <- B.hGet stdin 4
let n :: Word32
n = Bin.decode bs
options <- B.hGet stdin (fromIntegral n)
forkIO $ do
let loop = do
bs <- B.hGet stdin 4
let n :: Word32
n = Bin.decode bs
packet <- B.hGet stdin (fromIntegral n)
putMVar v2 (decode packet :: [Inst BufferId])
loop
loop
appendFile ("xx.txt") (show (decode options :: [Options]))
startRendering viewBoard v0 v2 (decode options :: [Options])
return ()