aboutsummaryrefslogtreecommitdiff
path: root/video/src/Video.hs
blob: 3a06a758dbec9ed110783a94d9ed5894936692ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
{-# LANGUAGE BinaryLiterals #-}
module Video (ConfigSocket(..), video) where

import Graphics.Gloss
import Graphics.Gloss.Interface.IO.Simulate
import Data.ByteString (ByteString, unpack, pack, hPut, hGetLine)
import Data.List (elemIndex, isPrefixOf)
import Data.Word
import Data.Char (chr)
import Data.Maybe
import Data.IORef
import Data.String
import Network.Socket
import System.IO
import Control.Monad


device_get_high_byte = "h"
device_get_low_byte  = "l"
device_get_word      = "w"

device_set_high_byte = "H"
device_set_low_byte  = "L"
device_set_word      = "W"

device_ok = "o"


data ConfigSocket = ConfigInet PortNumber | ConfigUnix String


makeSocket :: ConfigSocket -> IO Socket
makeSocket (ConfigUnix a) = do
    sock <- socket AF_UNIX Stream defaultProtocol
    Network.Socket.connect sock $ SockAddrUnix a
    return sock
makeSocket (ConfigInet p) = do
    sock <- socket AF_INET Stream defaultProtocol
    Network.Socket.connect sock $ SockAddrInet p 0x0100007f
    return sock


producePicture :: [Word8] -> IO Picture
producePicture pic = do
    return $ bitmapOfByteString 256 256 (BitmapFormat TopToBottom PxRGBA)
                                (pack pic) False


bsToStr :: ByteString -> String
bsToStr = map (chr . fromEnum) . unpack


toHex :: Word8 -> String
toHex n = ["0123456789abcdef" !! (fromIntegral n `div` 16 `mod` 16)] ++
          ["0123456789abcdef" !! (fromIntegral n `mod` 16)]

fromHex :: String -> Int -> Int -> Int -> Int
fromHex _ _ 0 a = a
fromHex s i n a = fromHex s (i + 1) (n - 1)
    (a * 16 + fromJust (Data.List.elemIndex (s !! i) "0123456789abcdef"))


replace :: Int -> Int -> [Word8] -> [Word8]
replace 0 v (_:t) = fromIntegral v : t
replace n v (h:t) = h : replace (n - 1) v t


doCommand :: Handle -> [Word8] -> IO [Word8]
doCommand h pic = do
    cmdbs <- Data.ByteString.hGetLine h
    let cmd = bsToStr cmdbs
    if device_get_high_byte `isPrefixOf` cmd
    then let i = fromHex cmd 2 5 0 in do
        hPut h $ fromString $ device_ok ++ " " ++ toHex (pic !! i) ++ "\n"
        return pic
    else if device_get_low_byte `isPrefixOf` cmd
    then let i = fromHex cmd 2 5 0 in do
        hPut h $ fromString $ device_ok ++ " " ++ toHex (pic!!(i+1)) ++ "\n"
        return pic
    else if device_get_word `isPrefixOf` cmd
    then let i = fromHex cmd 2 5 0 in do
        hPut h $ fromString $ device_ok ++ " "
            ++ toHex (pic !! i) ++ toHex (pic!!(i+1)) ++ "\n"
        return pic
    else if device_set_high_byte `isPrefixOf` cmd
    then let i = fromHex cmd 2 5 0
             v = fromHex cmd 8 2 0 in do
        hPut h $ fromString $ device_ok ++ "\n"
        return $ replace i v pic
    else if device_set_low_byte `isPrefixOf` cmd
    then let i = fromHex cmd 2 5 0
             v = fromHex cmd 8 2 0 in do
        hPut h $ fromString $ device_ok ++ "\n"
        return $ replace (i + 1) v pic
    else if device_set_word `isPrefixOf` cmd
    then let i = fromHex cmd 2 5 0
             vh = fromHex cmd 8 2 0
             vl = fromHex cmd 10 2 0 in do
        hPut h $ fromString $ device_ok ++ "\n"
        return $ replace i vh $ replace (i + 1) vl pic
    else error "Unknown Device Protocol Line"

control :: Handle -> ViewPort -> Float -> [Word8] -> IO [Word8]
control h _ _ pic = do
    cmd_ready <- hReady h
    if cmd_ready then doCommand h pic else return pic


video :: ConfigSocket -> IO ()
video sock = do
    s <- makeSocket sock
    h <- socketToHandle s ReadWriteMode
    let pic = replicate (256 * 256 * 4) 255
    simulateIO (InWindow "Suem Video" (256, 256) (0, 0)) black 60
               pic producePicture (control h)