{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE RecordWildCards #-}
module Reanimate.Driver
( reanimate
)
where
import Control.Applicative ((<|>))
import Control.Monad
import Data.Maybe
import Data.Either
import Reanimate.Animation (Animation)
import Reanimate.Driver.Check
import Reanimate.Driver.CLI
import Reanimate.Driver.Compile
import Reanimate.Driver.Server
import Reanimate.Parameters
import Reanimate.Render (render, renderSnippets, renderSvgs,
selectRaster)
import System.Directory
import System.Exit
import System.FilePath
import System.IO
import Text.Printf
presetFormat :: Preset -> Format
presetFormat Youtube = RenderMp4
presetFormat ExampleGif = RenderGif
presetFormat Quick = RenderMp4
presetFormat MediumQ = RenderMp4
presetFormat HighQ = RenderMp4
presetFormat LowFPS = RenderMp4
presetFPS :: Preset -> FPS
presetFPS Youtube = 60
presetFPS ExampleGif = 25
presetFPS Quick = 15
presetFPS MediumQ = 30
presetFPS HighQ = 30
presetFPS LowFPS = 10
presetWidth :: Preset -> Width
presetWidth Youtube = 2560
presetWidth ExampleGif = 320
presetWidth Quick = 320
presetWidth MediumQ = 800
presetWidth HighQ = 1920
presetWidth LowFPS = presetWidth HighQ
presetHeight :: Preset -> Height
presetHeight preset = presetWidth preset * 9 `div` 16
formatFPS :: Format -> FPS
formatFPS RenderMp4 = 60
formatFPS RenderGif = 25
formatFPS RenderWebm = 60
formatWidth :: Format -> Width
formatWidth RenderMp4 = 2560
formatWidth RenderGif = 320
formatWidth RenderWebm = 2560
formatHeight :: Format -> Height
formatHeight RenderMp4 = 1440
formatHeight RenderGif = 180
formatHeight RenderWebm = 1440
formatExtension :: Format -> String
formatExtension RenderMp4 = "mp4"
formatExtension RenderGif = "gif"
formatExtension RenderWebm = "webm"
reanimate :: Animation -> IO ()
reanimate animation = do
Options {..} <- getDriverOptions
case optsCommand of
Raw {..} -> do
setFPS 60
renderSvgs rawOutputFolder rawFrameOffset rawPrettyPrint animation
Test -> do
setNoExternals True
renderSnippets animation
Check -> checkEnvironment
View {..} -> serve viewVerbose viewGHCPath viewGHCOpts viewOrigin
Render {..} -> do
let fmt =
guessParameter renderFormat (fmap presetFormat renderPreset)
$ case renderTarget of
Just target -> case takeExtension target of
".mp4" -> RenderMp4
".gif" -> RenderGif
".webm" -> RenderWebm
_ -> RenderMp4
Nothing -> RenderMp4
target <- case renderTarget of
Nothing -> do
mbSelf <- findOwnSource
let ext = formatExtension fmt
self = fromMaybe "output" mbSelf
pure $ replaceExtension self ext
Just target -> makeAbsolute target
let
fps =
guessParameter renderFPS (fmap presetFPS renderPreset) $ formatFPS fmt
(width, height) = fromMaybe
( maybe (formatWidth fmt) presetWidth renderPreset
, maybe (formatHeight fmt) presetHeight renderPreset
)
(userPreferredDimensions renderWidth renderHeight)
raster <-
if renderRaster == RasterNone || renderRaster == RasterAuto then do
svgSupport <- hasFFmpegRSvg
if isRight svgSupport
then selectRaster renderRaster
else do
raster <- selectRaster RasterAuto
when (raster == RasterNone) $ do
hPutStrLn stderr $
"Error: your FFmpeg was built without SVG support and no raster engines \
\are available. Please install either inkscape, imagemagick, or rsvg."
exitWith (ExitFailure 1)
return raster
else selectRaster renderRaster
if renderCompile
then compile $
[ "render"
, "--fps"
, show fps
, "--width"
, show width
, "--height"
, show height
, "--format"
, showFormat fmt
, "--raster"
, showRaster raster
, "--target"
, target
, "+RTS"
, "-N"
, "-RTS"
] ++ [ "--partial" | renderPartial ]
else do
setRaster raster
setFPS fps
setWidth width
setHeight height
printf
"Animation options:\n\
\ fps: %d\n\
\ width: %d\n\
\ height: %d\n\
\ fmt: %s\n\
\ target: %s\n\
\ raster: %s\n"
fps
width
height
(showFormat fmt)
target
(show raster)
render animation target raster fmt width height fps renderPartial
guessParameter :: Maybe a -> Maybe a -> a -> a
guessParameter a b def = fromMaybe def (a <|> b)
userPreferredDimensions :: Maybe Width -> Maybe Height -> Maybe (Width, Height)
userPreferredDimensions (Just width) (Just height) = Just (width, height)
userPreferredDimensions (Just width) Nothing =
Just (width, makeEven $ width * 9 `div` 16)
userPreferredDimensions Nothing (Just height) =
Just (makeEven $ height * 16 `div` 9, height)
userPreferredDimensions Nothing Nothing = Nothing
makeEven :: Int -> Int
makeEven x | even x = x
| otherwise = x - 1