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

Safe HaskellNone




type TrackTree = [Tree.Tree Ui.TrackInfo] Source #

A TrackTree is the Skeleton resolved to the tracks it references.

parents_children_of :: Ui.M m => BlockId -> TrackId -> m (Maybe ([Ui.TrackInfo], [Ui.TrackInfo])) Source #

Return (parents, self : children).

get_children_of :: Ui.M m => BlockId -> TrackId -> m [Ui.TrackInfo] Source #

This is like parents_children_of, but only the children, and it doesn't include the given TrackId.

track_tree_of :: Ui.M m => BlockId -> m TrackTree Source #

Combine the skeleton with the tracks to create a TrackTree.

TODO this is pretty complicated. If I stored the tracks as a tree in the first place and generated the skeleton from that then this would all go away. But that would mean redoing all the Ui.Skeleton operations for trees. And the reason I didn't do it in the first place was the hassle of graph operations on a Data.Tree.

resolve_track_tree Source #


:: Map TrackNum a 
-> [Tree.Tree TrackNum] 
-> ([Tree.Tree a], [TrackNum])

resolved tree, and missing TrackNums

Resolve the TrackNum indices in a tree into whatever values as given by a map.

data Track Source #




  • track_title :: !Text
  • track_events :: !Events.Events

    Events on this track. These are shifted by slice_notes, so they are in ScoreTime, not TrackTime.

  • track_id :: !(Maybe TrackId)

    This goes into the stack when the track is evaluated. Inverted tracks will carry the TrackId of the track they were inverted from, so they'll show up in the stack twice. This means they can record their environ as it actually is when the notes are evaluated, rather than its pre-invert value, which is likely to not have the right scale.

  • track_block_id :: !(Maybe BlockId)

    The block these events came from. A track can appear in multiple blocks, but can only appear once in each block.

  • track_start :: !ScoreTime

    The relative start and end of this slice of track. Like track_events, this is in ScoreTime, not TrackTime.

  • track_end :: !ScoreTime
  • track_sliced :: !Sliced

    True if this is a sliced track. That means it's a fragment of a track and certain track-level things should be skipped.

  • track_around :: !([Event.Event], [Event.Event])

    These events are not evaluated, but go in ctx_prev_events and ctx_next_events. This is so that sliced calls (such as inverting calls) can see previous and following events. Shifted along with track_events.

  • track_shifted :: !TrackTime

    If the events have been shifted from their original positions on the track, add this to them to put them back in TrackTime.

  • track_voice :: !(Maybe Int)

    This is the track's track voice, as defined in track_voices. Originally I tried to keep it all within Derive.Call.BlockUtil, but it gets complicated with child tracks and slicing. Putting it in Track ensures it can't get lost.

data Sliced Source #



An intact track, unchanged from the score.

It's confusing to say track_sliced track == NotSliced, and I could pick something like Intact, but there's no precedent for that terminology.

Sliced !Event.Orientation

A Derive.Sliced fragment, and certain track-level things should be skipped.


Set on the fake track created by inversion.

block_events_tree :: Ui.M m => BlockId -> m EventsTree Source #

Get the EventsTree of a block. Strip disabled tracks.

track_children :: EventsNode -> Set TrackId Source #

All the children of this EventsNode with TrackIds.

track_voices :: [Tree.Tree Ui.TrackInfo] -> [Tree.Tree (Ui.TrackInfo, Maybe Int)] Source #

Each note track with an instrument gets a count and maximum count, so they can go in track_voice and track_voices.

count_occurrences :: (Traversable.Traversable f, Traversable.Traversable g, Ord k) => (a -> k) -> f (g a) -> f (g (a, Int)) Source #

For each element, give its index amount its equals, and the total number of elements equal to it.