-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathDvb.hs
56 lines (50 loc) · 2.05 KB
/
Dvb.hs
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
-- |Wrappers for libdvb. I'm not sure how it should be done so this
-- may contain fatal errors. Feel free to fix my code if it's broken.
{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
module Dvb where
import Control.Monad
import Foreign.C
import Foreign.Ptr
import Foreign.Marshal.Alloc
import System.IO
import System.Posix.IO (fdToHandle)
import System.Posix.Types
data DvbDeviceStruct
type DvbDevice = Ptr DvbDeviceStruct
foreign import ccall unsafe "new_dvb_device" new_dvb_device :: IO DvbDevice
foreign import ccall unsafe "dvb_open" dvb_open :: DvbDevice -> CInt -> CInt -> CInt -> IO CInt
foreign import ccall unsafe "dvb_get_error" dvb_get_error :: DvbDevice -> IO CString
foreign import ccall unsafe "dvb_tune" dvb_tune :: DvbDevice -> CSize -> IO CInt
foreign import ccall unsafe "dvb_init_pes_stream" dvb_init_pes_stream :: DvbDevice -> CInt -> CInt -> IO CInt
foreign import ccall unsafe "dvb_stop_stream" dvb_stop_stream :: DvbDevice -> IO CInt
foreign import ccall unsafe "dvb_get_demuxer_fd" dvb_get_demuxer_fd :: DvbDevice -> IO CInt
openDvb :: Int -> Int -> Int -> Int -> Int -> IO (Handle,DvbDevice)
openDvb devId frontendId demuxerId frequency pid = do
dev <- new_dvb_device
when (dev==nullPtr) $ fail "Unable to allocate memory"
openStatus <- dvb_open dev (fromIntegral devId) (fromIntegral frontendId) (fromIntegral demuxerId)
case openStatus of
0 -> do
tuneStatus <- dvb_tune dev (fromIntegral frequency)
case tuneStatus of
0 -> do
initStatus <- dvb_init_pes_stream dev (fromIntegral pid) 5
case initStatus of
0 -> do
fd <- dvb_get_demuxer_fd dev
h <- fdToHandle $ Fd fd
return (h,dev)
_ -> cleanupAndFail dev
_ -> cleanupAndFail dev
_ -> cleanupAndFail dev
cleanupAndFail :: DvbDevice -> IO a
cleanupAndFail dev = do
msg <- dvb_get_error dev >>= peekCString
free dev
error msg
closeDvb :: DvbDevice -> IO ()
closeDvb dev = do
status <- dvb_stop_stream dev
case status of
0 -> free dev
_ -> cleanupAndFail dev