]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 3966/2: Allows the user to override the text property of ChordName
authorDavid Kastrup <dak@gnu.org>
Tue, 24 Jun 2014 15:54:03 +0000 (17:54 +0200)
committerDavid Kastrup <dak@gnu.org>
Mon, 30 Jun 2014 08:14:55 +0000 (10:14 +0200)
This is a reimplementation of issue 2813.

input/regression/chord-name-override-text.ly [new file with mode: 0644]
lily/chord-name-engraver.cc
scm/define-context-properties.scm

diff --git a/input/regression/chord-name-override-text.ly b/input/regression/chord-name-override-text.ly
new file mode 100644 (file)
index 0000000..36b4795
--- /dev/null
@@ -0,0 +1,13 @@
+\version "2.17.6"
+
+\header {
+  texidoc = "Users can override the @code{text} property of
+@code{ChordName}.
+"
+}
+
+\new ChordNames \chordmode {
+  a b c:7
+  \once \override ChordName.text = #"foo"
+  d
+}
index 86d977cabef4db2c57bd9f0455797f7a8def4228..0ca322716fde1e8153034b99028feb95bd7d6257 100644 (file)
@@ -42,7 +42,6 @@ protected:
   DECLARE_TRANSLATOR_LISTENER (note);
   DECLARE_TRANSLATOR_LISTENER (rest);
 private:
-  Item *chord_name_;
   vector<Stream_event *> notes_;
 
   Stream_event *rest_event_;
@@ -55,86 +54,99 @@ Chord_name_engraver::finalize ()
 
 Chord_name_engraver::Chord_name_engraver ()
 {
-  chord_name_ = 0;
   rest_event_ = 0;
 }
 
 void
 Chord_name_engraver::process_music ()
 {
+  if (!rest_event_ && notes_.empty ())
+    return;
+
   SCM markup;
   SCM bass = SCM_EOL;
   SCM inversion = SCM_EOL;
   SCM pitches = SCM_EOL;
+  Item *chord_name = 0;
 
+  // rest events present a hen-and-egg problem with regard to
+  // overriding the text property of the ChordName grob since we
+  // cannot create a ChordName grob, look at its text property and, if
+  // not set, use noChordSymbol to decide whether we should not have
+  // created the grob in the first place.
   if (rest_event_)
     {
       SCM no_chord_markup = get_property ("noChordSymbol");
       if (!Text_interface::is_markup (no_chord_markup))
         return;
       markup = no_chord_markup;
+      chord_name = make_item ("ChordName", rest_event_->self_scm ());
+      chord_name->set_property ("text", markup);
     }
   else
     {
-      if (!notes_.size ())
-        return;
-
-      Stream_event *inversion_event = 0;
-      for (vsize i = 0; i < notes_.size (); i++)
+      chord_name = make_item ("ChordName", notes_[0]->self_scm ());
+      // We cannot actually delay fetching the text property in case
+      // it is a callback since we need to compare the generated
+      // markups for the sake of chordChanges
+      markup = chord_name->get_property ("text");
+      if (!Text_interface::is_markup (markup))
         {
-          Stream_event *n = notes_[i];
-          SCM p = n->get_property ("pitch");
-          if (!unsmob_pitch (p))
-            continue;
-
-          if (n->get_property ("inversion") == SCM_BOOL_T)
+          Stream_event *inversion_event = 0;
+          for (vsize i = 0; i < notes_.size (); i++)
             {
-              inversion_event = n;
-              inversion = p;
+              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;
+                }
+              else if (n->get_property ("bass") == SCM_BOOL_T)
+                bass = p;
+              else
+                pitches = scm_cons (p, pitches);
             }
-          else if (n->get_property ("bass") == SCM_BOOL_T)
-            bass = p;
-          else
-            pitches = scm_cons (p, pitches);
-        }
 
-      if (inversion_event)
-        {
-          SCM oct = inversion_event->get_property ("octavation");
-          if (scm_is_number (oct))
+          if (inversion_event)
             {
-              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);
+              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);
+                }
+              else
+                programming_error ("inversion does not have original pitch");
             }
-          else
-            programming_error ("inversion does not have original pitch");
-        }
 
-      pitches = scm_sort_list (pitches, Pitch::less_p_proc);
+          pitches = scm_sort_list (pitches, Pitch::less_p_proc);
 
-      SCM name_proc = get_property ("chordNameFunction");
-      markup = scm_call_4 (name_proc, pitches, bass, inversion,
-                           context ()->self_scm ());
+          SCM name_proc = get_property ("chordNameFunction");
+          markup = scm_call_4 (name_proc, pitches, bass, inversion,
+                               context ()->self_scm ());
+          if (!Text_interface::is_markup (markup))
+            {
+              // Ugh, we created a grob, now we better populate it.
+              // Use an empty string.
+              markup = scm_string (SCM_EOL);
+            }
+          chord_name->set_property ("text", markup);
+        }
     }
-  /*
-    Ugh.
-  */
-  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 ());
-  chord_name_->set_property ("text", markup);
 
   SCM chord_changes = get_property ("chordChanges");
   SCM last_chord = get_property ("lastChord");
-  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);
+  if (to_boolean (chord_changes) && ly_is_equal (markup, last_chord))
+    chord_name->set_property ("begin-of-line-visible", SCM_BOOL_T);
 
-  context ()->set_property ("lastChord", chord_as_scm);
+  context ()->set_property ("lastChord", markup);
 }
 
 IMPLEMENT_TRANSLATOR_LISTENER (Chord_name_engraver, note);
@@ -154,7 +166,6 @@ Chord_name_engraver::listen_rest (Stream_event *ev)
 void
 Chord_name_engraver::stop_translation_timestep ()
 {
-  chord_name_ = 0;
   notes_.clear ();
   rest_event_ = 0;
 }
index 66100915b4589997363cb9bd3569b499e4d7e18b..2d38188d29273c4ec114e94380f60e41e41b7af0 100644 (file)
@@ -709,7 +709,7 @@ in an axis group.")
 @code{CommandColumn} contains items that will affect spacing.")
 
 
-     (lastChord ,list? "Last chord, used for detecting chord changes.")
+     (lastChord ,markup? "Last chord, used for detecting chord changes.")
      (lastKeyAlterations ,list? "Last key signature before a key
 signature change.")
      (localAlterations ,list? "The key signature at this point in the