From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Wed, 24 Nov 2010 23:40:17 +0000 (+0100)
Subject: PartCombine: part-combine texts on first real note rather than rests
X-Git-Tag: release/2.13.41-1~3^2~1
X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=f0f0f0648b63a1ce156cf9634f043a046384a182;p=lilypond.git

PartCombine: part-combine texts on first real note rather than rests

-) If the context property partCombineTextsOnNote is set, the part-combine
   texts are not printed immediately if there is a rest or skip, but on
	 the next following note. If the voice contains a note, they are printed
	 immediately.
	 This is needed if one voice has a full measure rest and the other e.g.
	 r2 r4 c4.
-) The event triggering the part-combine text is cached in that case
   and the Part_combine_engraver now also listens to note events. The
	 texts are then created at the first moment when a note is encountered.
---

diff --git a/input/regression/part-combine-text-wait.ly b/input/regression/part-combine-text-wait.ly
new file mode 100644
index 0000000000..73260661a1
--- /dev/null
+++ b/input/regression/part-combine-text-wait.ly
@@ -0,0 +1,26 @@
+\version "2.13.41"
+
+
+\header {
+  texidoc ="Wait for the next real note for part-combine texts (i.e. don't
+print part-combine texts on rests). This is needed because the part-combiner
+needs an override if one voice has a full-bar rest while the other has some
+rests and then a solo."
+}
+
+\layout { ragged-right = ##t }
+
+mI = \relative c'' {
+  \set Score.partCombineTextsOnNote = ##t
+  g4 \partcombineSoloI r4 c2 |
+  \partcombineSoloII R1*2 |
+}
+mII = \relative c' {
+  c4 r2. |
+  r2 r4 c4 |
+  R1 |
+}
+
+\score {
+  \new Staff \partcombine \mI \mII
+}
diff --git a/lily/part-combine-engraver.cc b/lily/part-combine-engraver.cc
index bbc0d059e5..59a818952c 100644
--- a/lily/part-combine-engraver.cc
+++ b/lily/part-combine-engraver.cc
@@ -38,46 +38,74 @@ protected:
   DECLARE_ACKNOWLEDGER (stem);
 
   DECLARE_TRANSLATOR_LISTENER (part_combine);
+  DECLARE_TRANSLATOR_LISTENER (note);
   void process_music ();
   void stop_translation_timestep ();
+  void create_item (Stream_event *ev);
+
 private:
   Item *text_;
-  Stream_event *event_;
+  Stream_event *new_event_; // Event happened at this moment
+  bool note_found_;
+  // Event possibly from an earlier moment waiting to create a text:
+  Stream_event *waiting_event_;
 };
 
 IMPLEMENT_TRANSLATOR_LISTENER (Part_combine_engraver, part_combine);
 void
 Part_combine_engraver::listen_part_combine (Stream_event *ev)
 {
-  ASSIGN_EVENT_ONCE (event_, ev);
+  ASSIGN_EVENT_ONCE (new_event_, ev);
+  // If two events occur at the same moment, discard the second as the
+  // warning indicates:
+  waiting_event_ = new_event_;
+}
+
+IMPLEMENT_TRANSLATOR_LISTENER (Part_combine_engraver, note);
+void
+Part_combine_engraver::listen_note (Stream_event *)
+{
+  note_found_ = true;
 }
 
 Part_combine_engraver::Part_combine_engraver ()
 {
   text_ = 0;
-  event_ = 0;
+  new_event_ = 0;
+  waiting_event_ = 0;
+  note_found_ = false;
+}
+
+void
+Part_combine_engraver::create_item (Stream_event *ev)
+{
+  SCM what = ev->get_property ("class");
+  SCM text = SCM_EOL;
+  if (what == ly_symbol2scm ("solo-one-event"))
+    text = get_property ("soloText");
+  else if (what == ly_symbol2scm ("solo-two-event"))
+    text = get_property ("soloIIText");
+  else if (what == ly_symbol2scm ("unisono-event"))
+    text = get_property ("aDueText");
+
+  if (Text_interface::is_markup (text))
+    {
+      text_ = make_item ("CombineTextScript", ev->self_scm ());
+      text_->set_property ("text", text);
+    }
 }
 
 void
 Part_combine_engraver::process_music ()
 {
-  if (event_
+  if (waiting_event_
       && to_boolean (get_property ("printPartCombineTexts")))
     {
-      SCM what = event_->get_property ("class");
-      SCM text = SCM_EOL;
-      if (what == ly_symbol2scm ("solo-one-event"))
-	text = get_property ("soloText");
-      else if (what == ly_symbol2scm ("solo-two-event"))
-	text = get_property ("soloIIText");
-      else if (what == ly_symbol2scm ("unisono-event"))
-	text = get_property ("aDueText");
-
-      if (Text_interface::is_markup (text))
-	{
-	  text_ = make_item ("CombineTextScript", event_->self_scm ());
-	  text_->set_property ("text", text);
-	}
+      if (note_found_ || !to_boolean (get_property ("partCombineTextsOnNote")))
+        {
+          create_item (waiting_event_);
+          waiting_event_ = 0;
+        }
     }
 }
 
@@ -105,7 +133,8 @@ void
 Part_combine_engraver::stop_translation_timestep ()
 {
   text_ = 0;
-  event_ = 0;
+  new_event_ = 0;
+  note_found_ = false;
 }
 
 ADD_ACKNOWLEDGER (Part_combine_engraver, note_head);
@@ -120,6 +149,7 @@ ADD_TRANSLATOR (Part_combine_engraver,
 
 		/* read */
 		"printPartCombineTexts "
+		"partCombineTextsOnNote "
 		"soloText "
 		"soloIIText "
 		"aDueText ",
diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly
index 515c1cd3bb..f2ca7c3e46 100644
--- a/ly/engraver-init.ly
+++ b/ly/engraver-init.ly
@@ -531,6 +531,7 @@ automatically when an output definition (a @code{\score} or
   soloIIText = #"Solo II"
   aDueText = #"a2"
   printPartCombineTexts = ##t
+  partCombineTextsOnNote = ##t
   systemStartDelimiter =#'SystemStartBar
 
   drumStyleTable = #drums-style
diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm
index 4a2a6736f2..8a22e2d36a 100644
--- a/scm/define-context-properties.scm
+++ b/scm/define-context-properties.scm
@@ -361,6 +361,8 @@ Changing this creates a new text spanner.")
 translator during music interpretation.")
 
 
+     (partCombineTextsOnNote ,boolean? "Print part-combine texts only on
+the next note rather than immediately on rests or skips.")
      (pedalSostenutoStrings ,list? "See @code{pedalSustainStrings}.")
      (pedalSostenutoStyle ,symbol? "See @code{pedalSustainStyle}.")
      (pedalSustainStrings ,list? "A list of strings to print for