hoovie-0.1.1: src/Hoovie/Stream.hs
{-# LANGUAGE OverloadedStrings #-}
module Hoovie.Stream (
streamHandler
) where
import Control.Monad (when)
import Control.Monad.IO.Class (liftIO)
import Data.Maybe (fromJust)
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC
import Snap.Core
import Debug.Trace
import Hoovie.Transcode
import Hoovie.Monitor
import Hoovie.Util
import Hoovie.Resource
streamHandler :: FilePath -> Snap ()
streamHandler db = do
request <- getRequest
rid <- getParam "id"
resource <- liftIO $ getResourceById db (maybe Nothing maybeReadBS rid)
if resource /= Nothing && getHeader "TransferMode.DLNA.org" request == Just "Streaming"
then streamResource $ fromJust resource
else pass
streamResource :: Resource -> Snap ()
streamResource resource = do
request <- getRequest
modifyResponse $ setHeader "TransferMode.DLNA.org" "Streaming"
. setHeader "Content-Type" "video/mpeg"
. setHeader "ContentFeatures.DLNA.ORG" "DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=10;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000"
. setHeader "Accept-Ranges" "bytes"
. setHeader "Connection" "keep-alive"
let timeRange = case getHeader "TimeSeekRange.dlna.org" request of
Nothing -> (Nothing, Nothing)
Just range -> parseTimeRange range
when (rqMethod request == HEAD) $ do
modifyResponse $ setContentLength 0
when (rqMethod request == GET) $ do
modifyResponse $ setResponseBody (transcode timeRange $ reFilename resource)
parseTimeRange :: B.ByteString -> (Maybe Double, Maybe Double)
parseTimeRange s = let (start, stop) = BC.break (== '-') $ BC.drop 1 $ BC.dropWhile (/= '=') s
in (parseTime start, parseTime $ BC.drop 1 stop)
parseTime :: B.ByteString -> Maybe Double
parseTime s = trace (show s) $ maybeRead (BC.unpack s)