[frogs] chord name engraver plus capo |
[ Thread Index |
Date Index
| More lilynet.net/frogs Archives
]
At last :-)
I've managed to work my way through (having lost my first attempt), and
here's my crack at doing the engraver. I've just done process_music in
this mail, since it's the only thing I've really changed.
I've added the capo variables, filled them in, and got down almost to
the bottom. There's just a couple of things to fix before I can try a
"compile and test". How do I actually get hold of the property capoFret?
And how do I combine the markups? I'm not going to bother with vertical
markup at the moment. That'll be easier once I've got to grips with the
rest of it.
Note that all my added comments are C++ style - // - and I tend to mark
"to dos" in my code with a triple bang !!!
So how do I fix those two issues? and then you'll probably hear the
screaming as it blows up (or hopefully the cheering as it works :-)
Cheers,
Wol
------------------------------------------------------
void
Chord_name_engraver::process_music ()
// This is called for each note or rest.
// It is called as a result of being registered with
IMPLEMENT_TRANSLATOR_LISTENER
{
SCM markup; // to store markup in
SCM bass = SCM_EOL; // remember notes to create chord
SCM inversion = SCM_EOL;
SCM pitches = SCM_EOL;
SCM capo_markup; // and transposed notes for capo chord
SCM capo_bass = SCM_EOL;
SCM capo_inversion = SCM_EOL;
SCM capo_pitches = SCM_EOL;
if (rest_event_)
{ // process a rest
SCM no_chord_markup = get_property ("noChordSymbol");
if (!Text_interface::is_markup (no_chord_markup))
return;
markup = no_chord_markup;
}
else
{ // process a note event
if (!notes_.size ())
return;
// get capo fret !!!
// This is set by "\set ChordNames.capoFret = #3" in the lily
source file
SCM capofret = whatever->get_property ("capoFret");
int capo = 0;
if (scm_is_number (capofret))
capo = scm_to_int (capofret);
Stream_event *inversion_event = 0;
for (vsize i = 0; i < notes_.size (); i++)
{ // step through each note in turn
Stream_event *n = notes_[i];
SCM p = n->get_property ("pitch");
if (!unsmob_pitch (p))
continue;
if (n->get_property ("inversion") == SCM_BOOL_T)
{
inversion_event = n;
inversion = p;
if (capo)
capo_inversion = p->transposed (Pitch (-capo, 0, 0));
}
else if (n->get_property ("bass") == SCM_BOOL_T)
bass = p;
if (capo)
capo_bass = p->transposed (Pitch (-capo, 0, 0));
else
pitches = scm_cons (p, pitches);
if (capo)
capo_pitches = scm_cons ( p->transposed (Pitch (-capo, 0, 0)),
capo_pitches);
}
if (inversion_event)
{
SCM oct = inversion_event->get_property ("octavation");
if (scm_is_number (oct))
{
Pitch *p = unsmob_pitch (inversion_event->get_property ("pitch"));
int octavation = scm_to_int (oct);
Pitch orig = p->transposed (Pitch (-octavation, 0, 0));
pitches = scm_cons (orig.smobbed_copy (), pitches);
// if capo sort this out later !!!
}
else
programming_error ("inversion does not have original pitch");
}
pitches = scm_sort_list (pitches, Pitch::less_p_proc);
if (capo)
capo_pitches = scm_sort_list (capo_pitches, Pitch::less_p_proc);
SCM name_proc = get_property ("chordNameFunction");
markup = scm_call_4 (name_proc, pitches, bass, inversion,
context ()->self_scm ());
if (capo)
capo_markup = scm_call_4 (name_proc, capo_pitches, capo_bass,
capo_inversion,
context ()->self_scm ());
}
/*
Ugh. // Why's this ughly?
*/
// do we need any more capo stuff here beyond setting the chord name text?
SCM chord_as_scm = scm_cons (pitches, scm_cons (bass, inversion));
chord_name_ = make_item ("ChordName",
rest_event_ ? rest_event_->self_scm () : notes_[0]->self_scm ());
if (!capo)
chord_name_->set_property ("text", markup);
else
// how do I combine text and markup to get "markup (capo_markup)" !!!
SCM chord_changes = get_property("chordChanges");
if (to_boolean (chord_changes) && scm_is_pair (last_chord_)
&& ly_is_equal (chord_as_scm, last_chord_))
chord_name_->set_property ("begin-of-line-visible", SCM_BOOL_T);
last_chord_ = chord_as_scm;
}
---
----
Join the Frogs!