module EventLoop.Output.Single (outSingle) where
import qualified Network.Socket as S
import qualified Network.WebSockets as WS
import qualified Data.Text as T
import Control.Exception (catch, SomeException, throw)
import EventLoop.EventProcessor (IOMessage)
import EventLoop.Output.OutputEvent
import EventLoop.Output.Graphical
import EventLoop.Output.SystemMessage
import EventLoop.Config
import EventLoop.Json
import EventLoop.CommonTypes
outSingle :: OutputEvent -> IO ()
outSingle out = S.withSocketsDo $ do
sock <- WS.makeSocket ipadres (fromIntegral port)
pendingConn <- WS.makePendingConnection sock
conn <- WS.acceptRequest pendingConn
let
close = catched sock conn
func = do
sendResponse conn setup
sendResponse conn out'
sendResponse conn closeMsg
WS.sendClose conn (T.pack "")
WS.closeSocket sock
catch func close
where
setup = toIOMessage (setupMessage out)
out' = toIOMessage out
closeMsg = toIOMessage closeMessage
catched :: S.Socket -> WS.Connection -> SomeException -> IO ()
catched sock conn e = do
WS.sendClose conn (T.pack "")
WS.closeSocket sock
throw e
setupMessage :: OutputEvent -> OutputEvent
setupMessage (OutGraphical (Draw g _)) = OutSysMessage [CanvasSetup dim]
where
dim = maxDimensions g
setupMessage _ = OutSysMessage [CanvasSetup (512, 512)]
closeMessage :: OutputEvent
closeMessage = OutSysMessage [Close]
toIOMessage :: OutputEvent -> IOMessage
toIOMessage = toJsonMessage
sendResponse :: WS.Connection -> IOMessage -> IO ()
sendResponse conn response = do
let
string = show response
text = T.pack string
WS.sendTextData conn text
maxDimensions :: GObject -> Dimension
maxDimensions (GObject _ prim []) = maxDimensionsPrim prim
maxDimensions (GObject n prim (c:cs)) = (max w w', max h h')
where
(w, h) = maxDimensions c
(w', h') = maxDimensions (GObject n prim cs)
maxDimensions (Container []) = (0, 0)
maxDimensions (Container (c:cs)) = (max w w', max h h')
where
(w, h) = maxDimensions c
(w', h') = maxDimensions (Container cs)
maxDimensionsPrim :: Primitive -> Dimension
maxDimensionsPrim (Text _ _ _ (x, y) size _ str fromCenter) | fromCenter = (x + (fromIntegral $ length str * 10) / 2, y + size / 2)
| otherwise = (x + (fromIntegral $ length str * 10), y + size)
maxDimensionsPrim (Line _ _ []) = (0, 0)
maxDimensionsPrim (Line _ _ [(x, y)]) = (x, y)
maxDimensionsPrim (Line ec et ((x, y):xs)) = (max x x', max y y')
where
(x', y') = maxDimensionsPrim (Line ec et xs)
maxDimensionsPrim (Rect _ _ _ (x, y) (w, h)) = (x + w / 2, y + h / 2)
maxDimensionsPrim (Arc _ _ _ (x, y) r _ _) = (x + r, y + r)