mirror of
https://github.com/reanimate/reanimate.git
synced 2026-09-18 03:12:40 +00:00
Fix race condition issues on Windows.
Former-commit-id: 970a6f8c92ba8cab41053cb7a933a45f416e8696
This commit is contained in:
parent
9d5002e869
commit
158d79a9e7
6 changed files with 58 additions and 57 deletions
|
|
@ -15,10 +15,10 @@ import Reanimate.Raster
|
||||||
import Codec.Picture
|
import Codec.Picture
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = reanimate $ repeatAnimation 6 $ mkAnimation 5 $ do
|
main = reanimate $ mkAnimation 5 $ do
|
||||||
s <- getSignal signalLinear
|
s <- getSignal signalLinear
|
||||||
emit $ mkGroup
|
emit $ mkGroup
|
||||||
[ mkBackground "black"
|
[ mkBackground "grey"
|
||||||
, rotate (s*360) $ center $ scale 0.5 $ embedImage img ]
|
, rotate (s*360) $ center $ scale 0.5 $ embedImage img ]
|
||||||
where
|
where
|
||||||
img = generateImage pixelRenderer 255 255
|
img = generateImage pixelRenderer 255 255
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ library
|
||||||
diagrams-core, diagrams-lib, diagrams-contrib,
|
diagrams-core, diagrams-lib, diagrams-contrib,
|
||||||
svg-builder, matrices, cubicbezier, palette, websockets,
|
svg-builder, matrices, cubicbezier, palette, websockets,
|
||||||
hashable, fsnotify, open-browser, random-shuffle, base64-bytestring,
|
hashable, fsnotify, open-browser, random-shuffle, base64-bytestring,
|
||||||
vector, colour, cassava, ansi-wl-pprint, here
|
vector, colour, cassava, ansi-wl-pprint, here, temporary
|
||||||
|
|
||||||
Flag server
|
Flag server
|
||||||
Description: Enable rendering server
|
Description: Enable rendering server
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ module Reanimate.Driver ( reanimate ) where
|
||||||
|
|
||||||
import Control.Concurrent (MVar, forkIO, killThread,
|
import Control.Concurrent (MVar, forkIO, killThread,
|
||||||
modifyMVar_, newEmptyMVar,
|
modifyMVar_, newEmptyMVar,
|
||||||
putMVar, takeMVar)
|
putMVar, takeMVar, forkOS)
|
||||||
import Control.Exception (SomeException, finally, handle)
|
import Control.Exception (SomeException, finally, handle)
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Monad.Fix (fix)
|
import Control.Monad.Fix (fix)
|
||||||
|
|
@ -13,8 +13,7 @@ import qualified Data.Text.Read as T
|
||||||
import Data.Version
|
import Data.Version
|
||||||
import Network.WebSockets
|
import Network.WebSockets
|
||||||
import Paths_reanimate
|
import Paths_reanimate
|
||||||
import Reanimate.Misc (runCmdLazy, runCmd_, withTempDir,
|
import Reanimate.Misc (runCmdLazy, runCmd_)
|
||||||
withTempFile)
|
|
||||||
import Reanimate.Monad (Animation)
|
import Reanimate.Monad (Animation)
|
||||||
import Reanimate.Render (render, renderSnippets,
|
import Reanimate.Render (render, renderSnippets,
|
||||||
renderSvgs)
|
renderSvgs)
|
||||||
|
|
@ -24,8 +23,8 @@ import System.Environment (getArgs, getProgName)
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import System.FSNotify
|
import System.FSNotify
|
||||||
import System.IO (BufferMode (..), hPutStrLn,
|
import System.IO.Temp
|
||||||
hSetBuffering, stderr, stdin)
|
import System.IO
|
||||||
import Text.ParserCombinators.ReadP
|
import Text.ParserCombinators.ReadP
|
||||||
import qualified Text.PrettyPrint.ANSI.Leijen as Doc
|
import qualified Text.PrettyPrint.ANSI.Leijen as Doc
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
|
@ -45,44 +44,48 @@ reanimate animation = do
|
||||||
["check"] -> checkEnvironment
|
["check"] -> checkEnvironment
|
||||||
["render", target] ->
|
["render", target] ->
|
||||||
render animation target
|
render animation target
|
||||||
_ -> withTempDir $ \tmpDir -> do
|
_ -> do
|
||||||
|
prog <- getProgName
|
||||||
|
lst <- listDirectory "."
|
||||||
|
mbSelf <- findFile ("." : lst) prog
|
||||||
|
case mbSelf of
|
||||||
|
Nothing -> do
|
||||||
|
hPutStrLn stderr "Failed to find own source code."
|
||||||
|
exitWith (ExitFailure 1)
|
||||||
|
Just self -> do
|
||||||
url <- getDataFileName "viewer/build/index.html"
|
url <- getDataFileName "viewer/build/index.html"
|
||||||
putStrLn "Opening browser..."
|
putStrLn "Opening browser..."
|
||||||
bSucc <- openBrowser url
|
bSucc <- openBrowser url
|
||||||
if bSucc
|
if bSucc
|
||||||
then putStrLn "Browser opened."
|
then putStrLn "Browser opened."
|
||||||
else hPutStrLn stderr $ "Failed to open browser. Manually visit: " ++ url
|
else hPutStrLn stderr $ "Failed to open browser. Manually visit: " ++ url
|
||||||
|
putStrLn "Listening..."
|
||||||
runServerWith "127.0.0.1" 9161 opts $ \pending -> do
|
runServerWith "127.0.0.1" 9161 opts $ \pending -> do
|
||||||
putStrLn "Server pending..."
|
putStrLn "New connection received."
|
||||||
prog <- getProgName
|
|
||||||
lst <- listDirectory "."
|
|
||||||
mbSelf <- findFile ("." : lst) prog
|
|
||||||
blocker <- newEmptyMVar :: IO (MVar ())
|
|
||||||
case mbSelf of
|
|
||||||
Nothing -> do
|
|
||||||
hPutStrLn stderr "Failed to find own source code."
|
|
||||||
Just self -> do
|
|
||||||
conn <- acceptRequest pending
|
conn <- acceptRequest pending
|
||||||
slave <- newEmptyMVar
|
slave <- newEmptyMVar
|
||||||
let handler = modifyMVar_ slave $ \tid -> do
|
let handler = modifyMVar_ slave $ \tid -> do
|
||||||
sendTextData conn (T.pack "Compiling")
|
|
||||||
putStrLn "Killing and respawning..."
|
putStrLn "Reloading code..."
|
||||||
killThread tid
|
killThread tid
|
||||||
tid <- forkIO $ slaveHandler conn self tmpDir
|
tid <- forkOS $ slaveHandler conn self
|
||||||
return tid
|
return tid
|
||||||
killSlave = do
|
killSlave = do
|
||||||
tid <- takeMVar slave
|
tid <- takeMVar slave
|
||||||
killThread tid
|
killThread tid
|
||||||
putStrLn "Found self. Listening..."
|
|
||||||
stop <- watchFile watch self handler
|
stop <- watchFile watch self handler
|
||||||
putMVar slave =<< forkIO (return ())
|
putMVar slave =<< forkIO (return ())
|
||||||
let loop = do
|
let loop = do
|
||||||
fps <- receiveData conn :: IO T.Text
|
fps <- receiveData conn :: IO T.Text
|
||||||
handler
|
handler
|
||||||
loop
|
loop
|
||||||
loop `finally` (killSlave >> stop)
|
loop `finally` (stop >> killSlave)
|
||||||
|
|
||||||
slaveHandler conn self tmpDir = withTempFile ".exe" $ \tmpExecutable -> do
|
slaveHandler conn self =
|
||||||
|
withSystemTempDirectory "reanimate" $ \tmpDir ->
|
||||||
|
withTempFile tmpDir "reanimate.exe" $ \tmpExecutable handle -> do
|
||||||
|
hClose handle
|
||||||
|
sendTextData conn (T.pack "Compiling")
|
||||||
ret <- runCmd_ "stack" $ ["ghc", "--"] ++ ghcOptions tmpDir ++ [self, "-o", tmpExecutable]
|
ret <- runCmd_ "stack" $ ["ghc", "--"] ++ ghcOptions tmpDir ++ [self, "-o", tmpExecutable]
|
||||||
case ret of
|
case ret of
|
||||||
Left err ->
|
Left err ->
|
||||||
|
|
@ -90,7 +93,6 @@ slaveHandler conn self tmpDir = withTempFile ".exe" $ \tmpExecutable -> do
|
||||||
Right{} -> do
|
Right{} -> do
|
||||||
getFrame <- runCmdLazy tmpExecutable ["once", "+RTS", "-N", "-M1G", "-RTS"]
|
getFrame <- runCmdLazy tmpExecutable ["once", "+RTS", "-N", "-M1G", "-RTS"]
|
||||||
(frameCount,_) <- expectFrame =<< getFrame
|
(frameCount,_) <- expectFrame =<< getFrame
|
||||||
-- sendTextData conn (T.pack "Compiled")
|
|
||||||
sendTextData conn (T.pack $ show frameCount)
|
sendTextData conn (T.pack $ show frameCount)
|
||||||
fix $ \loop -> do
|
fix $ \loop -> do
|
||||||
(frameIdx, frame) <- expectFrame =<< getFrame
|
(frameIdx, frame) <- expectFrame =<< getFrame
|
||||||
|
|
@ -213,14 +215,13 @@ ffmpegVersion = do
|
||||||
|
|
||||||
hasTeXPackage :: FilePath -> String -> IO (Either String String)
|
hasTeXPackage :: FilePath -> String -> IO (Either String String)
|
||||||
hasTeXPackage exec pkg = handle (\(e::SomeException) -> return $ Left "n/a") $
|
hasTeXPackage exec pkg = handle (\(e::SomeException) -> return $ Left "n/a") $
|
||||||
withTempDir $ \tmp_dir -> withTempFile "tex" $ \tex_file -> do
|
withSystemTempDirectory "reanimate" $ \tmp_dir -> withTempFile tmp_dir "test.tex" $ \tex_file tex_handle -> do
|
||||||
let tmp_dir = "."
|
hPutStr tex_handle tex_document
|
||||||
tex_file = "test.tex"
|
hPutStr tex_handle $ "\\usepackage" ++ pkg ++ "\n"
|
||||||
writeFile tex_file tex_document
|
hPutStr tex_handle "\\begin{document}\n"
|
||||||
appendFile tex_file $ "\\usepackage" ++ pkg ++ "\n"
|
hPutStr tex_handle "blah\n"
|
||||||
appendFile tex_file "\\begin{document}\n"
|
hPutStr tex_handle tex_epilogue
|
||||||
appendFile tex_file "blah\n"
|
hClose tex_handle
|
||||||
appendFile tex_file tex_epilogue
|
|
||||||
ret <- runCmd_ exec ["-interaction=batchmode", "-halt-on-error", "-output-directory="++tmp_dir, tex_file]
|
ret <- runCmd_ exec ["-interaction=batchmode", "-halt-on-error", "-output-directory="++tmp_dir, tex_file]
|
||||||
return $ case ret of
|
return $ case ret of
|
||||||
Right{} -> Right "OK"
|
Right{} -> Right "OK"
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ runCmdLazy exec args = do
|
||||||
withTempDir :: (FilePath -> IO a) -> IO a
|
withTempDir :: (FilePath -> IO a) -> IO a
|
||||||
withTempDir action = do
|
withTempDir action = do
|
||||||
dir <- getTemporaryDirectory
|
dir <- getTemporaryDirectory
|
||||||
(path, handle) <- openTempFile dir "reanimate-XXXXXX"
|
(path, handle) <- openTempFile dir "reanimate"
|
||||||
hClose handle
|
hClose handle
|
||||||
removeFile path
|
removeFile path
|
||||||
createDirectory (dir </> path)
|
createDirectory (dir </> path)
|
||||||
|
|
@ -78,6 +78,6 @@ withTempDir action = do
|
||||||
withTempFile :: String -> (FilePath -> IO a) -> IO a
|
withTempFile :: String -> (FilePath -> IO a) -> IO a
|
||||||
withTempFile ext action = do
|
withTempFile ext action = do
|
||||||
dir <- getTemporaryDirectory
|
dir <- getTemporaryDirectory
|
||||||
(path, handle) <- openTempFile dir ("reanimate-XXXXXX" <.> ext)
|
(path, handle) <- openTempFile dir ("reanimate" <.> ext)
|
||||||
hClose handle
|
hClose handle
|
||||||
action path -- `finally` removeFile path
|
action path -- `finally` removeFile path
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
resolver: lts-13.14
|
resolver: lts-11.14
|
||||||
|
|
||||||
allow-newer: false
|
allow-newer: false
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue