Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::timeline_editor Namespace Reference

ScriptedUiHost is a SequencerUiHost whose playhead is written by the caller instead of an engine, and which keeps what a view emitted so a test can read it back. More...

Namespaces

namespace  detail
namespace  hit_test_detail

Classes

struct  EditIntent
 One editing step expressed without reference to the device that produced it. More...
struct  NoteEditIntent
 One validated note editing step, independent of pointer or view geometry. More...
class  ValidatedNoteEditIntent
 A note intent that passed validate_note_edit_intent and may cross a host seam. More...
struct  EditIntentIdentity
 Identities a lowered transaction needs and an intent deliberately does not carry. More...
struct  EditGestureSubmitOutcome
 Result of submitting one issued gesture transaction through its allocator. More...
struct  EditGestureSubmitError
 A refusal before submission, or an inconsistent successful session result. More...
class  EditGestureIdentityIssue
 One opaque, single-owner identity issue awaiting a submission outcome. More...
class  EditGestureIdentityAllocator
 Allocates one undo group and submits a construction-safe stream of gesture identities. More...
struct  UndoGestureBudget
 What one open gesture may spend against the undo budget. More...
struct  GridLine
 Describes one visible musical boundary in projected screen coordinates. More...
struct  GridLineResult
 Carries the generation status and the number of lines written. More...
struct  ProjectedHitCandidate
 One timeline item after a front-end projects it into pixel space. More...
struct  ProjectedHit
 The identity and region selected from a projected candidate set. More...
struct  ScriptedProgram
 What the caller scripts. Held by value inside the host's current program. More...
class  ScriptedUiHost
class  Selection
 Identity-only editor state that never enters the document or its undo history. More...
struct  UiPlayhead
 One complete reading of where playback is. More...
struct  AuditionRequest
 What a view asks to hear, in document terms only. More...
struct  AuditionHandle
 Names a sustained audition so it can be ended. More...
struct  AuditionResult
 Returned by value so a view driven by a host that cannot audition is observable in a test without a mock — the same reason StepGridViewBase returns PumpResult rather than relying on an unobservable side effect. More...
struct  IntentResult
class  SequencerUiHost
 The vocabulary-independent half of the seam: where playback is, and asking to hear something. More...
class  SequencerUiHostT
 Adds intent submission for one intent vocabulary. More...
class  SnapGrid
 A validated musical grid whose phase restarts at every authored bar. More...
struct  TimePitchQueryResult
 Notes intersecting one time-and-pitch query, plus structural work diagnostics. More...
class  TimePitchIndex
 Immutable index for visible-note and marquee queries. More...
struct  TrackEditIntent
 One track-arrangement step expressed without reference to the device that produced it. More...
struct  TrackCreateIntent
 One complete track insertion expressed without device coordinates. More...
class  TrackHeaderProjection
 Maps authored track order to header rows and reorder insertion neighbors. More...
struct  PixelSpan
 A one-dimensional pixel range owned by the editor kernel. More...
class  TickProjection
 Projects a visible musical-time range onto a horizontal pixel span. More...
class  PitchProjection
 Projects an inclusive MIDI pitch range onto piano-roll rows. More...

Typedefs

using NoteEditIntentHost = SequencerUiHostT<ValidatedNoteEditIntent>
 Host binding used by a piano-roll front-end before command lowering.
using EditIntentHost = SequencerUiHostT<EditIntent>
 The host an editor submits its intents to.
using TrackArrangementIntent = std::variant<TrackEditIntent, TrackCreateIntent>
 Reorder or create vocabulary for controls that offer both operations.
using TrackEditIntentHost = SequencerUiHostT<TrackEditIntent>
 The host an arranger submits track intents to.
using TrackArrangementIntentHost = SequencerUiHostT<TrackArrangementIntent>
 The host an arranger offering reorder and creation submits intents to.

Enumerations

enum class  EditIntentKind : std::uint8_t { EditIntentKind::Draw , EditIntentKind::Erase , EditIntentKind::Move , EditIntentKind::Resize }
 What an editing gesture does to the document. More...
enum class  NoteEditIntentKind : std::uint8_t {
  NoteEditIntentKind::Insert , NoteEditIntentKind::Erase , NoteEditIntentKind::Move , NoteEditIntentKind::Resize ,
  NoteEditIntentKind::SetVelocity
}
 What a piano-roll gesture does to one note. More...
enum class  EditGestureIdentityState : std::uint8_t { EditGestureIdentityState::AwaitingBegin , EditGestureIdentityState::Open , EditGestureIdentityState::Closed , EditGestureIdentityState::Exhausted }
 Confirmed lifecycle state of one continuous edit gesture. More...
enum class  EditGestureIdentityError : std::uint8_t {
  EditGestureIdentityError::InvalidWriter , EditGestureIdentityError::WriterMismatch , EditGestureIdentityError::InvalidPhase , EditGestureIdentityError::GestureClosed ,
  EditGestureIdentityError::IdentityExhausted , EditGestureIdentityError::IdentityPending , EditGestureIdentityError::ForeignOrStaleIssue , EditGestureIdentityError::IntentLoweringFailed ,
  EditGestureIdentityError::SubmissionResultMismatch
}
 Why an edit-gesture identity operation was refused. More...
enum class  NoteLoweringError : std::uint8_t {
  NoteLoweringError::ContinuousGestureUnsupported , NoteLoweringError::DuplicateNoteIdentity , NoteLoweringError::NoteNotInClip , NoteLoweringError::ExpectedNoteMismatch ,
  NoteLoweringError::InvalidIdentity
}
 Why a note intent could not be lowered to a transaction. More...
enum class  GridLineLevel : std::uint8_t { Bar , Beat }
 Identifies the musical boundary represented by a grid line. More...
enum class  GridLineError : std::uint8_t {
  None , NonFiniteSpacing , NonPositiveSpacing , RangeOverflow ,
  OutputTooSmall
}
 Reports why grid-line generation stopped. More...
enum class  ProjectedHitRegion : std::uint8_t { ProjectedHitRegion::Body , ProjectedHitRegion::LeadingEdge , ProjectedHitRegion::TrailingEdge }
 The horizontal part of a projected item selected by a hit test. More...
enum class  LoopRangeError : std::uint8_t { LoopRangeError::CollapsedSpan }
 Why an already-snapped loop range could not be constructed. More...
enum class  UiTransportState : std::uint8_t { Stopped , Playing , Scrubbing }
 Whether the playhead is moving, and why. More...
enum class  AuditionStatus : std::uint8_t { Started , Unsupported , Busy , Rejected }
enum class  IntentStatus : std::uint8_t { Accepted , Deferred , Rejected }
enum class  SnapDirection : std::uint8_t { SnapDirection::AtOrBefore , SnapDirection::Nearest , SnapDirection::AtOrAfter }
 Which inclusive grid boundary a gesture requests. More...
enum class  SnapGridError : std::uint8_t { SnapGridError::InvalidInterval , SnapGridError::InvalidSwingRatio }
enum class  TrackEditIntentKind : std::uint8_t { TrackEditIntentKind::Reorder }
 What a track-arrangement gesture does to the document. More...
enum class  TrackHeaderProjectionError : std::uint8_t {
  EmptyTrackOrder , InvalidTrackId , DuplicateTrackId , NonFiniteGeometry ,
  NonPositiveRowHeight , NonFiniteCoordinate , MissingMovingTrack
}
 Construction and query failures for track-header projection. More...
enum class  ViewportProjectionError : std::uint8_t {
  NonFinitePixelSpan , NonPositivePixelExtent , NonPositiveTickDuration , TickRangeOverflow ,
  InvalidPitchRange
}

Functions

std::optional< timeline::ModelError > validate_note_edit_intent (const NoteEditIntent &intent) noexcept
 Returns the first structural or note-domain error, or nullopt when valid.
runtime::Result< timeline::Transaction, NoteLoweringError > lower_note_edit_intent (const ValidatedNoteEditIntent &intent, std::span< const timeline::NoteEvent > current_notes, const EditIntentIdentity &identity)
 Lowers one note intent to the granular transaction that performs it.
runtime::Result< timeline::Transaction, timeline::ModelError > lower_edit_intent (const EditIntent &intent, const EditIntentIdentity &identity)
 Lowers one intent to the ordinary transaction that performs it.
UndoGestureBudget undo_gesture_budget (const timeline::UndoLimits &limits, std::span< const timeline::Command > step_forward, std::span< const timeline::Command > step_inverse) noexcept
 Returns what one open gesture of uniform per-step cost may spend.
GridLineResult generate_grid_lines (const TickProjection &projection, const timebase::CompiledMeterMap &meter, float minimum_spacing_px, std::span< GridLine > output) noexcept
 Emits visible bar lines and beat lines that are at least minimum_spacing_px from their enclosing bar line.
std::optional< ProjectedHit > hit_test_projected_items (std::span< const ProjectedHitCandidate > back_to_front, float x_px, float y_px, float tolerance_px) noexcept
 Selects one projected timeline item using already-resolved pixel tolerance.
runtime::Result< timebase::LoopRegion, LoopRangeError > loop_region_from_snapped_endpoints (timebase::TickPosition first, timebase::TickPosition second) noexcept
 Build an enabled, structurally canonical loop candidate.
constexpr timebase::LoopRegion with_loop_enabled (timebase::LoopRegion loop, bool enabled) noexcept
 Return loop with only its enabled state changed.
runtime::Result< timeline::Transaction, timeline::ModelError > lower_track_edit_intent (const TrackEditIntent &intent, const EditIntentIdentity &identity)
 Lowers one track intent to the ordinary transaction that performs it.
runtime::Result< timeline::Transaction, timeline::ModelError > lower_track_create_intent (const TrackCreateIntent &intent, const EditIntentIdentity &identity)
 Lowers one complete track-creation intent to InsertTrack.
runtime::Result< timeline::Transaction, timeline::ModelError > lower_track_arrangement_intent (const TrackArrangementIntent &intent, const EditIntentIdentity &identity)
 Lowers either complete track-arrangement alternative.

Detailed Description

ScriptedUiHost is a SequencerUiHost whose playhead is written by the caller instead of an engine, and which keeps what a view emitted so a test can read it back.

SequencerUiHost is the whole coupling a timeline editor view has toward playback.

It is the seam that makes an editor view testable with no audio, no transport, and no mocking framework — the same job PumpResult does for a hostless StepGridView, done from the other side of the interface.

It is not only a test fixture. A host that has no audio yet is a legitimate deployment: an editor embedded in a tool that only writes files gets a stopped playhead and Unsupported auditions, and stays fully usable.

The scripted program is deliberately heap-owned and genuinely replaced by swap_program(). A UiPlayhead is required to be a self-contained value, and that requirement is only worth stating if something can catch a violation: after a swap the previous program's storage is freed, so a reading that borrowed from it reads freed memory rather than quietly disagreeing.

A view reads where the playhead is, asks to hear something, and hands out the intents a gesture produced; it never links, includes, or names a playback type to do any of it. The interface is declared here, beside the editor, and implemented by whoever owns audio — the product shell, or a plugin that drives its own engine and wants a piano roll over it.

Two properties carry the contract, and both are mechanically checked:

  • EVERYTHING CROSSES BY VALUE. A playhead reading is a self-contained value with no pointer into engine-owned storage, so a program swap on the audio side cannot dangle or tear a reading the view already holds. TransportSnapshot is the counterexample this exists to avoid: it carries a const CompiledTempoMap* borrowed from the compiled program, which is correct for a block renderer and fatal for a view that keeps a copy across a frame.
  • THE VOCABULARY IS DOCUMENT-SIDE. Positions are timebase ticks and subjects are timeline::ItemIds — the same identities the document model and the edit commands already use. Nothing here describes how audio is produced.

Structure, following the StepGridViewBase/StepGridViewT split:

  • SequencerUiHost — non-template. Playhead snapshots and audition, both independent of how edits are expressed.
  • SequencerUiHostT<Intent> — thin templated shim adding intent submission for one intent vocabulary. Edit intents are the editor's own type; the host is only their destination, so parameterizing here keeps the intent vocabulary and the playback seam free to evolve apart.

A host is driven from the UI/message thread. Implementations bridge to the audio thread themselves (SeqLock for the playhead, an SPSC queue for audition and intents is the shape that already works elsewhere); this interface deliberately says nothing about that bridge, so a host backed by a real transport and a host backed by a scripted value are interchangeable.

Enumeration Type Documentation

◆ AuditionStatus

enum class pulp::timeline_editor::AuditionStatus : std::uint8_t
strong
Enumerator
Started 

The host is sounding it. A sustained request also yields a valid handle.

Unsupported 

This host does not audition at all. A view must stay fully usable.

Busy 

The host is at its audition capacity and dropped this one.

Rejected 

The request named something the host could not route or sound.

◆ GridLineError

enum class pulp::timeline_editor::GridLineError : std::uint8_t
strong

Reports why grid-line generation stopped.

Enumerator
None 

Generation completed successfully.

NonFiniteSpacing 

The requested minimum pixel spacing is not finite.

NonPositiveSpacing 

The requested minimum pixel spacing is zero or negative.

RangeOverflow 

Meter or tick arithmetic could not advance safely through the range.

OutputTooSmall 

The output span filled before generation completed.

◆ GridLineLevel

enum class pulp::timeline_editor::GridLineLevel : std::uint8_t
strong

Identifies the musical boundary represented by a grid line.

Enumerator
Bar 

Marks the first tick of a bar.

Beat 

Marks a beat subdivision after the bar boundary.

◆ IntentStatus

enum class pulp::timeline_editor::IntentStatus : std::uint8_t
strong
Enumerator
Accepted 

The host took the intent and will apply it.

Deferred 

The host is not accepting intents right now — mid-adoption, or read only.

A view retries or drops; it never treats this as an error.

Rejected 

The host understood the intent and refused it.

◆ TrackHeaderProjectionError

enum class pulp::timeline_editor::TrackHeaderProjectionError : std::uint8_t
strong

Construction and query failures for track-header projection.

Enumerator
EmptyTrackOrder 
InvalidTrackId 
DuplicateTrackId 
NonFiniteGeometry 
NonPositiveRowHeight 
NonFiniteCoordinate 
MissingMovingTrack 

◆ UiTransportState

enum class pulp::timeline_editor::UiTransportState : std::uint8_t
strong

Whether the playhead is moving, and why.

A scrub moves the playhead while the musical transport is stopped, so a view that only asks "does the ruler need repainting" reads moving() rather than branching on the state.

Enumerator
Stopped 
Playing 
Scrubbing 

◆ ViewportProjectionError

enum class pulp::timeline_editor::ViewportProjectionError : std::uint8_t
strong
Enumerator
NonFinitePixelSpan 
NonPositivePixelExtent 
NonPositiveTickDuration 
TickRangeOverflow 
InvalidPitchRange 

Function Documentation

◆ generate_grid_lines()

GridLineResult pulp::timeline_editor::generate_grid_lines ( const TickProjection & projection,
const timebase::CompiledMeterMap & meter,
float minimum_spacing_px,
std::span< GridLine > output )
noexcept

Emits visible bar lines and beat lines that are at least minimum_spacing_px from their enclosing bar line.

The kernel deliberately returns screen coordinates but knows nothing about a view, canvas, or rendering policy.