-- -- Module : Sort -- Copyright : (c) Conrad Parker 2008 -- License : BSD-style -- Maintainer : conradp@cse.unsw.edu.au -- Stability : experimental -- Portability : portable module Codec.Container.Ogg.Sort ( merge, sort, --, sortHeaders ) where import Codec.Container.Ogg.ContentType import Codec.Container.Ogg.List import Codec.Container.Ogg.Headers import Codec.Container.Ogg.Page import Codec.Container.Ogg.Serial import Codec.Container.Ogg.Track ------------------------------------------------------------ -- Exposed functions -- merge :: [[OggPage]] -> [OggPage] merge = sortHeaders . mergeSkeleton . listMerge sort :: [OggPage] -> [OggPage] sort = sortHeaders . listMerge . demux ------------------------------------------------------------ -- sortHeaders -- -- | Ensure the header pages of each track are in the correct order -- relative to each other. sortHeaders :: [OggPage] -> [OggPage] sortHeaders = processHeaders (sortHeaders' [] [] [] [] []) sortHeaders' :: [OggPage] -- skeleton bos -> [OggPage] -- theora bos -> [OggPage] -- other bos -> [OggPage] -- other headers -> [OggPage] -- skeleton eos -> [OggPage] -- input -> [OggPage] -- output sortHeaders' sb tb ob oh se [] = sb ++ tb ++ ob ++ oh ++ se sortHeaders' sb tb ob oh se (g:gs) | contentTypeIs skeleton g = case (pageBOS g, pageEOS g) of (True, False) -> sortHeaders' (sb++[g]) tb ob oh se gs (False, True) -> sortHeaders' sb tb ob oh (se++[g]) gs _ -> sortHeaders' sb tb ob (oh++[g]) se gs | contentTypeIs theora g = case (pageBOS g) of True -> sortHeaders' sb (tb++[g]) ob oh se gs False -> sortHeaders' sb tb ob (oh++[g]) se gs | otherwise = case (pageBOS g) of True -> sortHeaders' sb tb (ob++[g]) oh se gs False -> sortHeaders' sb tb ob (oh++[g]) se gs ------------------------------------------------------------ -- mergeSkeleton -- -- | When merging multiple files together, ensure that the resulting file -- contains only one Skeleton track mergeSkeleton :: [OggPage] -> [OggPage] mergeSkeleton [] = [] mergeSkeleton (g:gs) | contentTypeIs skeleton g = g : mergeSkeleton' (pageTrack g) gs | otherwise = g : mergeSkeleton gs mergeSkeleton' :: OggTrack -> [OggPage] -> [OggPage] mergeSkeleton' _ [] = [] mergeSkeleton' t' (g:gs) | contentTypeIs skeleton g = case (t == t', pageBOS g, pageEOS g) of (True, _, _) -> g:gs' -- Include known Skeleton pages (False, True, _) -> gs' -- Drop other Skeleton BOS pages (False, _, True) -> gs' -- Drop other Skeleton EOS pages (False, _, _) -> g':gs' -- Fix serialno of other Skeleton pages | otherwise = g : gs' -- Pass non-Skeleton pages through where t = pageTrack g g' = g{pageTrack = t'} gs' = mergeSkeleton' t' gs