Safe Haskell | Safe-Inferred |
---|
This module is sister to Derive.Deriver.Lib, except that it contains functions which are normally only used by the built-in track derivation scheme, and are not used when writing most normal calls.
Synopsis
- get_dynamic :: (Dynamic -> a) -> Deriver a
- get_constant :: (Constant -> a) -> Deriver a
- local :: (Dynamic -> Dynamic) -> Deriver a -> Deriver a
- localm :: (Dynamic -> Deriver Dynamic) -> Deriver a -> Deriver a
- detached_local :: (Dynamic -> Dynamic) -> Deriver a -> Deriver (Either Error a)
- set_threaded :: Threaded -> Deriver ()
- merge_collect :: Collect -> Deriver ()
- local_collect :: Deriver a -> Deriver (a, Collect)
- trim_track_warps :: Maybe RealTime -> Maybe RealTime -> Deriver a -> Deriver a
- with_collect :: (Collect -> Collect) -> Deriver a -> Deriver a
- modify_collect :: (Collect -> Collect) -> Deriver ()
- get_environ :: Deriver DeriveT.Environ
- record_track_dynamic :: Dynamic -> Maybe TrackDynamic
- record_track_dynamic_for :: BlockId -> TrackId -> Deriver ()
- with_default_merge :: Map ScoreT.Control Merger -> Deriver a -> Deriver a
- with_control_damage :: ControlDamage -> Deriver derived -> Deriver derived
- add_block_dep :: BlockId -> Deriver ()
- get_ui_state :: (Ui.State -> a) -> Deriver a
- get_ui_config :: (UiConfig.Config -> a) -> Deriver a
- get_track :: TrackId -> Deriver Track.Track
- get_block :: BlockId -> Deriver Block.Block
- eval_ui :: CallStack.Stack => Ui.StateId a -> Deriver a
- lookup_id :: (Ord k, Show k) => k -> Map k a -> Deriver a
- lookup_current_block_id :: Deriver (Maybe BlockId)
- get_current_block_id :: Deriver BlockId
- lookup_current_tracknum :: Deriver (Maybe (BlockId, TrackNum))
- get_current_tracknum :: Deriver (BlockId, TrackNum)
- with_stack_block :: BlockId -> Deriver a -> Deriver a
- with_stack_track :: TrackId -> Deriver a -> Deriver a
- with_stack_region :: ScoreTime -> ScoreTime -> Deriver a -> Deriver a
- with_stack_call :: CallName -> Deriver a -> Deriver a
- with_stack_serial :: Int -> Deriver a -> Deriver a
- with_stack :: Stack.Frame -> Deriver a -> Deriver a
- add_stack_frame :: Stack.Frame -> Dynamic -> Dynamic
- get_stack :: Deriver Stack.Stack
- class Time a where
- real :: a -> Deriver RealTime
- score :: a -> Deriver ScoreTime
- to_duration :: a -> DeriveT.Duration
- in_real_time :: Deriver a -> Deriver a
- with_warp :: (Warp.Warp -> Warp.Warp) -> Deriver a -> Deriver a
- get_warp :: Deriver Warp.Warp
- at :: ScoreTime -> Deriver a -> Deriver a
- stretch :: ScoreTime -> Deriver a -> Deriver a
- place :: ScoreTime -> ScoreTime -> Deriver a -> Deriver a
- warp :: Warp.Warp -> Deriver a -> Deriver a
- add_new_track_warp :: Maybe TrackId -> Deriver ()
- block_logical_range :: BlockId -> Deriver (TrackTime, TrackTime)
- block_event_end :: BlockId -> Deriver ScoreTime
- record_empty_tracks :: [TrackId] -> Deriver ()
- record_empty_track :: BlockId -> TrackId -> Deriver ()
- get_control_function_dynamic :: Deriver DeriveT.Dynamic
- convert_dynamic :: Ruler.Marklists -> Dynamic -> Stack.Serial -> DeriveT.Dynamic
- get_ruler :: Deriver Ruler.Marklists
- modify_threaded :: (Threaded -> Threaded) -> Deriver ()
- increment_event_serial :: Deriver ()
- is_root_block :: Deriver Bool
generic state access
get_dynamic :: (Dynamic -> a) -> Deriver a Source #
get_constant :: (Constant -> a) -> Deriver a Source #
local :: (Dynamic -> Dynamic) -> Deriver a -> Deriver a Source #
This is a little different from Reader.local because only a portion of the state is used Reader-style.
Note that this doesn't restore the state on an exception. I think this is ok because exceptions are always "caught" at the event evaluation level since it runs each one separately. Since the state dynamic state (i.e. except Collect) from the sub derivation is discarded, whatever state it's in after the exception shouldn't matter.
detached_local :: (Dynamic -> Dynamic) -> Deriver a -> Deriver (Either Error a) Source #
A version of local
that catches exceptions and ignores any changes to
Collect. This is appropriate for sub-calls that are below normal track
derivation.
set_threaded :: Threaded -> Deriver () Source #
Collect
merge_collect :: Collect -> Deriver () Source #
Collect is only ever accumulated.
Direct modification would be potentially more efficient, but according to profiling it doesn't make a difference.
local_collect :: Deriver a -> Deriver (a, Collect) Source #
Run with an empty Collect, restore the original Collect, and return the sub-deriver's Collect.
trim_track_warps :: Maybe RealTime -> Maybe RealTime -> Deriver a -> Deriver a Source #
Modify the collect_warp_map
to reduce the start and end by the given
times. This is useful if you're going to clip off some events. The
TrackWarps, and hence playback cursor, can't know you're going to do this,
so you have to tell it.
with_collect :: (Collect -> Collect) -> Deriver a -> Deriver a Source #
Run the deriver and modify the Collect it returns.
modify_collect :: (Collect -> Collect) -> Deriver () Source #
TODO this is sketchy, you're supposed to use merge_collect
.
environ
record_track_dynamic :: Dynamic -> Maybe TrackDynamic Source #
Figure out the current block and track, and record the current environ in the Collect. It only needs to be recorded once per track.
record_track_dynamic_for :: BlockId -> TrackId -> Deriver () Source #
record_track_dynamic
for when I already know BlockId and TrackId.
misc Dynamic state
with_default_merge :: Map ScoreT.Control Merger -> Deriver a -> Deriver a Source #
cache
with_control_damage :: ControlDamage -> Deriver derived -> Deriver derived Source #
add_block_dep :: BlockId -> Deriver () Source #
ui state
get_ui_state :: (Ui.State -> a) -> Deriver a Source #
get_ui_config :: (UiConfig.Config -> a) -> Deriver a Source #
get_track :: TrackId -> Deriver Track.Track Source #
Because Deriver is not a UiStateMonad.
TODO I suppose it could be, but then I'd be tempted to make a ReadOnlyUiStateMonad. And I'd have to merge the exceptions. Or just rethrow, right?
eval_ui :: CallStack.Stack => Ui.StateId a -> Deriver a Source #
Evaluate a Ui.M computation, rethrowing any errors.
lookup_id :: (Ord k, Show k) => k -> Map k a -> Deriver a Source #
Lookup map!key
, throwing if it doesn't exist.
stack
with_stack :: Stack.Frame -> Deriver a -> Deriver a Source #
add_stack_frame :: Stack.Frame -> Dynamic -> Dynamic Source #
Add a new stack frame and hash it with the random seed.
I skip Stack.Call for seed changes. This is so I can use calls like log-seed to record the seed to hardcode it later, which is the whole point of doing this thing where I hash on every stack frame. Otherwise, the presence of the log-seed call itself would be enough to change the seed.
In addition, calculating the seed eagerly this way is actually pretty expensive, since the stack is constantly being updated, so updating it less frequently is good for performance. It's possible I could update the seed lazily to reduce this cost, but not doing something at all is still cheaper than lazy, and can't be accidentally forced.
The risk is that this makes the seed too stable, and things which should be randomized become identical.
time and duration
Times are types that can be converted to RealTime and ScoreTime.
real :: a -> Deriver RealTime Source #
score :: a -> Deriver ScoreTime Source #
to_duration :: a -> DeriveT.Duration Source #
Instances
Time DeriveT.Duration Source # | |
Defined in Derive.Deriver.Internal | |
Time DefaultReal Source # | |
Defined in Derive.Typecheck | |
Time DefaultScore Source # | |
Defined in Derive.Typecheck | |
Time RealTime Source # | |
Time ScoreTime Source # | |
warp
in_real_time :: Deriver a -> Deriver a Source #
track warp
add_new_track_warp :: Maybe TrackId -> Deriver () Source #
Start a new track warp for the current block_id.
This must be called for each block, and it must be called after the tempo is warped for that block so it can install the new warp.
block_logical_range :: BlockId -> Deriver (TrackTime, TrackTime) Source #
Sub-derived blocks are stretched according to their length, and this function defines the length of a block. This is therefore the logical duration of the block, which may be shorter or lorger than the end of the last event, or the ruler.
block_event_end :: BlockId -> Deriver ScoreTime Source #
Get the duration of the block according to the last event.
track
record_empty_tracks :: [TrackId] -> Deriver () Source #
The deriver strips out tracks that can't be derived because they have no notes. But that means the track warps and track dynamics aren't recorded, which means they don't have tempo or a playback monitor, which makes them annoying.
ControlFunction
convert_dynamic :: Ruler.Marklists -> Dynamic -> Stack.Serial -> DeriveT.Dynamic Source #
get_ruler :: Deriver Ruler.Marklists Source #
Get the meter
marklists, if there is a ruler track here. This
is called in all contexts, due to control_at
, so it has to be careful
to not require a ruler.
Threaded
increment_event_serial :: Deriver () Source #
Increment state_event_serial
.
misc
is_root_block :: Deriver Bool Source #
Am I deriving the toplevel block?