module Data.MediaBus.StreamSegment
( segmentC
, segmentC'
) where
import Conduit
import Data.Monoid
import Data.MediaBus.Stream
import Data.MediaBus.Ticks
import Data.MediaBus.Segment
import Control.Lens
import Data.Default
import Data.MediaBus.Series
import Data.Proxy
import GHC.TypeLits
segmentC :: (Num s, Monad m, HasDuration c, CanSegment c, Monoid c, Default i, KnownNat r, Integral t, HasStaticDuration d)
=> Conduit (Stream i s (Ticks r t) p c) m (Stream i s (Ticks r t) p (Segment d c))
segmentC = segmentC' Proxy
segmentC' :: (Num s, Monad m, HasDuration c, CanSegment c, Monoid c, Default i, KnownNat r, Integral t, HasStaticDuration d)
=> proxy d
-> Conduit (Stream i s (Ticks r t) p c) m (Stream i s (Ticks r t) p (Segment d c))
segmentC' dpx = evalStateC (0, Nothing) $ awaitForever go
where
segmentDurationInTicks =
nominalDiffTime # segmentDuration
segmentDuration = getStaticDuration dpx
go (MkStream (Next (MkFrame !t !s !cIn))) = do
!cRest <- _2 <<.= Nothing
let tsOffset = negate (getDurationTicks cRest)
!cRest' <- yieldLoop (maybe cIn (<> cIn) cRest) tsOffset
_2 .= cRest'
where
yieldLoop !c !timeOffset =
if getDuration c == segmentDuration
then do
yieldWithAdaptedSeqNumAndTimestamp (MkSegment c)
return Nothing
else case splitAfterDuration dpx c of
Just (!packet, !rest) -> do
yieldWithAdaptedSeqNumAndTimestamp packet
_1 += 1
yieldLoop rest (timeOffset + segmentDurationInTicks)
Nothing -> do
_1 -=
1
return (Just c)
where
yieldWithAdaptedSeqNumAndTimestamp !p = do
!seqNumOffset <- use _1
yieldNextFrame (MkFrame (t + timeOffset) (s + seqNumOffset) p)
go (MkStream (Start !frmCtx)) =
yieldStartFrameCtx frmCtx