Safe Haskell | Safe-Inferred |
---|
This module manages the performance of music, specifically the creation of performance threads.
Performance is relative to a toplevel block, so each block has its own set of caches. Since performance is lazy, a separate thread will force it asynchronously.
Synopsis
- type SendStatus = BlockId -> Msg.DeriveStatus -> IO.IO ()
- update_performance :: SendStatus -> Ui.State -> Cmd.State -> ScoreDamage -> IO.IO Cmd.State
- derive_blocks :: Ui.State -> Set BlockId
- performance :: Ui.State -> Result -> Msg.Performance
- derive :: Ui.State -> Cmd.State -> BlockId -> (Msg.Performance, [Log.Msg])
- type Process = (IO.FilePath, [String])
- evaluate_im :: Config.Config -> (ScoreT.Instrument -> Maybe.Maybe Cmd.ResolvedInstrument) -> IO.FilePath -> RealTime.RealTime -> RealTime.RealTime -> BlockId -> Vector.Vector Score.Event -> IO.IO ([Process], Vector.Vector Score.Event)
- wait_for_subprocesses :: IO.IO () -> Set ScoreT.Instrument -> Set Process -> IO.IO Bool
Documentation
type SendStatus = BlockId -> Msg.DeriveStatus -> IO.IO () Source #
update_performance :: SendStatus -> Ui.State -> Cmd.State -> ScoreDamage -> IO.IO Cmd.State Source #
Update the performances by rederiving if necessary. This means figuring out ScoreDamage, and if there has been damage, killing any in-progress derivation and starting derivation. This updates performances for the root block and all visible blocks.
The majority of the calls here will bring neither score damage nor a changed view id, and thus this will do nothing.
This is tricky, and I've gotten it wrong in the past, so here's a detailed description:
Merge ui damage with each perf's damage. Then for each perf, if it's
Cmd.state_current_performance
has damage, kill its thread, and remove its
entry in Cmd.state_performance_threads
. The lack of a thread entry,
whether because was removed or never existed, means that a block should be
rederived. Derivation creates a new Msg.Performance
and an evaluate
thread, and puts them into Cmd.state_current_performance
and
Cmd.state_performance_threads
respectively, but due to laziness, no actual
derivation happens unless someone (like play) happens to look at the
performance. This all happens synchronously, so the next time
update_performance
is called, it sees a nice clean new Performance with
no damage.
Meanwhile, the evaluate thread asynchronously waits for a bit, then
forces the contents of the Performance, and then sends it back to the
responder so it can stash it in Cmd.state_performance
. If a new change
comes in while it's waiting it'll get killed off, and the out-of-date
derivation will never happen. Yay for laziness!
performance :: Ui.State -> Result -> Msg.Performance Source #
Constructor for Msg.Performance
.
type Process = (IO.FilePath, [String]) Source #
evaluate_im :: Config.Config -> (ScoreT.Instrument -> Maybe.Maybe Cmd.ResolvedInstrument) -> IO.FilePath -> RealTime.RealTime -> RealTime.RealTime -> BlockId -> Vector.Vector Score.Event -> IO.IO ([Process], Vector.Vector Score.Event) Source #
If there are im events, serialize them and return a Processes to render them, and the non-im events.
wait_for_subprocesses :: IO.IO () -> Set ScoreT.Instrument -> Set Process -> IO.IO Bool Source #
Like watch_subprocesses
, but notify the callback as soon as
they have all rendered enough audio.