Karya, built on Sun Nov 26 01:04:37 PST 2017 (patch 0a920b2bde70c0cbac8ee09d158064798b61bbe5)

Derive.Deriver.Internal

Description

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

# generic state access

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.

# Collect

Collect is only ever accumulated.

Direct modification would be potentially more efficient, but according to profiling it doesn't make a difference.

Run with an empty Collect, restore the original Collect, and return the sub-deriver's Collect.

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

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 when I already know BlockId and TrackId.

# ui state

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 :: Text -> 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

Make a quick trick block stack.

Make a quick trick track stack.

Add a new stack frame and hash it with the random seed.

# warp

## time and duration

class Time a where Source #

Times are types that can be converted to RealTime and ScoreTime.

Minimal complete definition

Methods

score :: a -> Deriver ScoreTime Source #

Instances

 # Methods # Methods # Methods # Methods # Methods

## warp

place :: ScoreTime -> ScoreTime -> Deriver a -> Deriver a Source #

at and stretch in one. It's a little faster than using them separately. The order is stretch, then shift, as documented by Score.Warp. TODO shouldn't the arguments go in the other order then?

warp :: Score.Warp -> Deriver a -> Deriver a Source #

Low level warp function.

Previously, this would disallow <=0 stretch, but it turns out to be useful to stretch events to 0, and to negative durations.

Am I deriving the toplevel block?

## track warp

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.

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.

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

Get the Ruler.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.

Increment state_event_serial.