+
+score_staff_t *
+score_add_staff (score_t *score, score_clef_t clef)
+{
+ score_staff_t *staff;
+
+ staff = talloc (score, score_staff_t);
+ if (staff == NULL)
+ return NULL;
+
+ staff->clef = clef;
+
+ staff->notes = NULL;
+ staff->num_notes = 0;
+
+ staff->chords = NULL;
+ staff->num_chords = 0;
+
+ staff->upper_ledger_lines = 0;
+ staff->lower_ledger_lines = 0;
+
+ score->num_staves++;
+ score->staves = talloc_realloc (score,
+ score->staves,
+ score_staff_t*,
+ score->num_staves);
+ if (score->staves == NULL) {
+ score->num_staves = 0;
+ return NULL;
+ }
+
+ score->staves[score->num_staves - 1] = staff;
+
+ return staff;
+}
+
+score_chord_t *
+score_add_chord (score_staff_t *staff,
+ const char *name)
+{
+ score_chord_t *chord;
+
+ chord = talloc (staff, score_chord_t);
+ if (chord == NULL)
+ return NULL;
+
+ chord->staff = staff;
+ chord->name = talloc_strdup (chord, name);
+
+ /* The width will get set correctly the first time _draw_chord is
+ * called. */
+ chord->width = 0.0;
+
+ staff->num_chords++;
+ staff->chords = talloc_realloc (staff,
+ staff->chords,
+ score_chord_t*,
+ staff->num_chords);
+ if (staff->chords == NULL) {
+ staff->num_chords = 0;
+ return NULL;
+ }
+
+ staff->chords[staff->num_chords - 1] = chord;
+
+ return chord;
+}
+
+void
+score_remove_chord (score_chord_t *chord)
+{
+ score_staff_t *staff = chord->staff;
+ int i;
+
+ for (i = 0; i < staff->num_chords; i++)
+ if (staff->chords[i] == chord)
+ break;
+
+ if (i == staff->num_chords)
+ return;
+
+ if (i < staff->num_chords - 1)
+ {
+ memmove (staff->chords + i,
+ staff->chords + i + 1,
+ (staff->num_chords - 1 - i) * sizeof (score_chord_t *));
+ }
+
+ staff->num_chords -= 1;
+}
+
+score_note_t *
+score_add_note (score_staff_t *staff,
+ score_pitch_t pitch,
+ int octave,
+ score_duration_t duration)
+{
+ score_note_t *note;
+ double line;
+
+ note = talloc (staff, score_note_t);
+ if (note == NULL)
+ return NULL;
+
+ note->staff = staff;
+ note->pitch = pitch;
+ note->octave = octave;
+ note->duration = duration;
+
+ note->color.r = 0.0;
+ note->color.g = 0.0;
+ note->color.b = 0.0;
+
+ line = _score_note_to_line (staff, note);
+ if (line < 0) {
+ int lines = (int) (- line);
+ if (lines > staff->upper_ledger_lines)
+ staff->upper_ledger_lines = lines;
+ } else {
+ int lines = (int) (line - 4);
+ if (lines > staff->lower_ledger_lines)
+ staff->lower_ledger_lines = lines;
+ }
+
+ staff->num_notes++;
+ staff->notes = talloc_realloc (staff,
+ staff->notes,
+ score_note_t*,
+ staff->num_notes);
+ if (staff->notes == NULL) {
+ staff->num_notes = 0;
+ return NULL;
+ }
+
+ staff->notes[staff->num_notes - 1] = note;
+
+ return note;
+}
+
+void
+score_remove_note (score_note_t *note)
+{
+ score_staff_t *staff = note->staff;
+ int i;
+
+ for (i = 0; i < staff->num_notes; i++)
+ if (staff->notes[i] == note)
+ break;
+
+ if (i == staff->num_notes)
+ return;
+
+ if (i < staff->num_notes - 1)
+ {
+ memmove (staff->notes + i,
+ staff->notes + i + 1,
+ (staff->num_notes - 1 - i) * sizeof (score_note_t *));
+ }
+
+ staff->num_notes -= 1;
+
+ if (staff->num_notes == 0) {
+ staff->upper_ledger_lines = 0;
+ staff->lower_ledger_lines = 0;
+ }
+}
+
+void
+score_set_note_color_rgb (score_note_t *note,
+ double r,
+ double g,
+ double b)
+{
+ note->color.r = r;
+ note->color.g = g;
+ note->color.b = b;
+}
+
+score_note_t *
+score_staff_find_note (score_staff_t *staff,
+ score_pitch_t pitch,
+ int octave,
+ score_duration_t duration)
+{
+ int i;
+ score_note_t *note;
+
+ for (i = 0; i < staff->num_notes; i++) {
+ note = staff->notes[i];
+ if (note->pitch == pitch &&
+ note->octave == octave &&
+ note->duration == duration)
+ {
+ return note;
+ }
+ }
+
+ return NULL;
+}
+