Cursor API

The Cursor is the primary interface for navigating within a score and adding notes/rests. It represents a position within the score and provides methods for note input.

Source File

src/engraving/api/v1/cursor.h

Creating a Cursor

var cursor = curScore.newCursor();

Properties

PropertyTypeDescription
trackintCurrent track (staffIdx * 4 + voice). Read/write.
staffIdxintCurrent staff number (track / 4). Read/write.
staffStaffCurrent Staff object. Read/write. (Since 4.6)
voiceintCurrent voice (track % 4, range 0-3). Read/write.
filterintSegment type filter bitmask. Determines which segments cursor moves to.
tickintMIDI tick position (read only). Deprecated in 4.6, use fraction.
utickintMIDI tick position accounting for repeats (read only). Since 4.6.
fractionFractionWrapperTime position as fraction of whole note. Since 4.6.
tempoqrealTempo at current tick (read only).
keySignatureintKey signature of current staff at tick (read only).
scoreScoreAssociated score. Read/write.
elementEngravingItemCurrent element at track (read only).
segmentSegmentCurrent segment (read only).
measureMeasureCurrent measure (read only).
stringNumberintPhysical string number for tablature. Since 3.5.
inputStateModeInputStateModeCursor input state behavior. Since 3.5.

Rewind Modes

Cursor.SCORE_START // 0 - Rewind to start of score Cursor.SELECTION_START // 1 - Rewind to start of selection Cursor.SELECTION_END // 2 - Rewind to end of selection

Input State Modes

Cursor.INPUT_STATE_INDEPENDENT // Default - cursor independent of score Cursor.INPUT_STATE_SYNC_WITH_SCORE // Cursor synced with score input state

Navigation Methods

rewind(mode)

Move cursor to beginning of score or selection.

cursor.rewind(Cursor.SCORE_START); // Go to beginning cursor.rewind(Cursor.SELECTION_START); // Go to selection start cursor.rewind(Cursor.SELECTION_END); // Go to selection end

rewindToTick(tick)

Move cursor to specific tick position.

cursor.rewindToTick(480); // Move to tick 480

rewindToFraction(fraction)

Move cursor to specific time position.

var f = fraction(1, 1); // Create fraction for 1 whole note cursor.rewindToFraction(f);

next()

Move to next segment (returns false if at end).

while (cursor.next()) { // Process each segment var el = cursor.element; }

nextMeasure()

Move to next measure (returns false if at end).

while (cursor.nextMeasure()) { // Process each measure }

prev()

Move to previous segment (returns false if at start).

cursor.prev();

time(includeRepeats)

Get time position in seconds.

var timeInSeconds = cursor.time(false); var timeWithRepeats = cursor.time(true);

Note Input Methods

setDuration(z, n)

Set the duration for subsequent notes/rests as a fraction z/n.

// Common durations: cursor.setDuration(1, 1); // Whole note cursor.setDuration(1, 2); // Half note cursor.setDuration(1, 4); // Quarter note cursor.setDuration(1, 8); // Eighth note cursor.setDuration(1, 16); // Sixteenth note cursor.setDuration(1, 32); // 32nd note cursor.setDuration(1, 64); // 64th note // Dotted notes (multiply by 3/2): cursor.setDuration(3, 8); // Dotted quarter (3/8 = 1/4 * 3/2) cursor.setDuration(3, 16); // Dotted eighth

addNote(pitch, addToChord)

Add a note at the cursor position.

Parameters:

  • pitch (int): MIDI pitch value (0-127). Middle C = 60.
  • addToChord (bool, optional): If true, add to existing chord. Default: false.
// Add single notes cursor.addNote(60); // Add Middle C cursor.addNote(64); // Add E above middle C cursor.addNote(67); // Add G // Build a chord cursor.addNote(60, false); // C (new chord) cursor.addNote(64, true); // Add E to chord cursor.addNote(67, true); // Add G to chord (C major chord)

addRest()

Add a rest at the cursor position with the current duration.

cursor.setDuration(1, 4); cursor.addRest(); // Quarter rest

addTuplet(ratio, duration)

Add a tuplet at the cursor position.

Parameters:

  • ratio: FractionWrapper - The tuplet ratio (e.g., 3/2 for triplet)
  • duration: FractionWrapper - The total duration
var ratio = fraction(3, 2); // Triplet: 3 notes in space of 2 var duration = fraction(1, 4); // Quarter note duration cursor.addTuplet(ratio, duration);

add(element)

Add an arbitrary element at the cursor position.

var text = newElement(Element.STAFF_TEXT); text.text = "Hello"; cursor.add(text);

Complete Example: Adding a C Major Scale

function addCMajorScale() { var cursor = curScore.newCursor(); cursor.rewind(Cursor.SCORE_START); cursor.voice = 0; cursor.staffIdx = 0; curScore.startCmd("Add C Major Scale"); cursor.setDuration(1, 4); // Quarter notes // C Major scale: C D E F G A B C var pitches = [60, 62, 64, 65, 67, 69, 71, 72]; for (var i = 0; i < pitches.length; i++) { cursor.addNote(pitches[i]); } curScore.endCmd(); }

Complete Example: Adding a Chord Progression

function addChordProgression() { var cursor = curScore.newCursor(); cursor.rewind(Cursor.SCORE_START); curScore.startCmd("Add Chord Progression"); cursor.setDuration(1, 1); // Whole notes // C major chord cursor.addNote(60, false); // C cursor.addNote(64, true); // E cursor.addNote(67, true); // G // F major chord cursor.addNote(65, false); // F cursor.addNote(69, true); // A cursor.addNote(72, true); // C // G major chord cursor.addNote(67, false); // G cursor.addNote(71, true); // B cursor.addNote(74, true); // D // C major chord (return) cursor.addNote(60, false); // C cursor.addNote(64, true); // E cursor.addNote(67, true); // G curScore.endCmd(); }

Iterating Through Score Elements

function iterateScore() { var cursor = curScore.newCursor(); cursor.rewind(Cursor.SCORE_START); while (cursor.segment) { var element = cursor.element; if (element) { if (element.type == Element.CHORD) { var chord = element; var notes = chord.notes; for (var i = 0; i < notes.length; i++) { console.log("Note pitch: " + notes[i].pitch); } } else if (element.type == Element.REST) { console.log("Found rest"); } } cursor.next(); } }