module Codec.Container.Ogg.RawPage (
OggRawPage (..),
pageMarker,
pageVersion,
rawPageScan,
rawPageBuild
) where
import Codec.Container.Ogg.ByteFields
import qualified Data.ByteString.Lazy as L
import Data.Int (Int64)
import Data.Word (Word8, Word32, Word64)
data OggRawPage =
OggRawPage {
rawPageVersion :: !Word8,
rawPageHType :: !Word8,
rawPageGranulepos :: !Word64,
rawPageSerialno :: !Word32,
rawPageSeqno :: !Word32,
rawPageCRC :: !Word32,
rawPageNumseg :: !Int,
rawPageSegtab :: !([Int]),
rawPageBody :: !L.ByteString
}
pageMarker :: L.ByteString
pageMarker = L.pack [0x4f, 0x67, 0x67, 0x53]
pageVersion :: Word8
pageVersion = 0x00
rawPageScan :: L.ByteString -> [OggRawPage]
rawPageScan input
| L.null input = []
| L.isPrefixOf pageMarker input = newPage : rawPageScan rest
| otherwise = rawPageScan (L.tail input)
where (newPage, pageLen) = rawPageBuild input
rest = L.drop pageLen input
rawPageBuild :: L.ByteString -> (OggRawPage, Int64)
rawPageBuild d = (newRawPage, pageLen) where
newRawPage = OggRawPage v htype gp serialno seqno crc numseg segtab body
v = u8At 4 d
htype = u8At 5 d
gp = le64At 6 d
serialno = le32At 14 d
seqno = le32At 18 d
crc = le32At 22 d
numseg64 = u8At 26 d
numseg = fromIntegral numseg64
st = L.unpack $ L.take numseg64 (L.drop 27 d)
segtab = map fromIntegral st
headerSize = 27 + numseg64
bodySize = fromIntegral $ sum segtab
body = L.take bodySize (L.drop headerSize d)
pageLen = fromIntegral $ headerSize + bodySize
instance Show OggRawPage where
show r =
"Version: " ++ show (rawPageVersion r) ++ "\n" ++
"HType: " ++ show (rawPageHType r) ++ "\n" ++
"Granulepos: " ++ show (rawPageGranulepos r) ++ "\n" ++
"Serialno: " ++ show (rawPageSerialno r) ++ "\n" ++
"Seqno: " ++ show (rawPageSeqno r) ++ "\n" ++
"CRC: " ++ show (rawPageCRC r) ++ "\n" ++
"Numseg: " ++ show (rawPageNumseg r) ++ "\n" ++
"Segtab: " ++ show (rawPageSegtab r) ++ "\n" ++ "\n"