]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'issue4097' into HEAD
authorDavid Kastrup <dak@gnu.org>
Sun, 14 Sep 2014 05:49:03 +0000 (07:49 +0200)
committerDavid Kastrup <dak@gnu.org>
Sun, 14 Sep 2014 05:49:03 +0000 (07:49 +0200)
input/regression/addlyrics-to-staff-context.ly [new file with mode: 0644]
lily/context.cc
lily/lyric-combine-music-iterator.cc
lily/lyric-engraver.cc
lily/parser.yy
ly/engraver-init.ly
scm/define-context-properties.scm
scm/define-music-properties.scm
scm/ly-syntax-constructors.scm

diff --git a/input/regression/addlyrics-to-staff-context.ly b/input/regression/addlyrics-to-staff-context.ly
new file mode 100644 (file)
index 0000000..13b45ca
--- /dev/null
@@ -0,0 +1,22 @@
+\version "2.19.14"
+
+\header {
+  texidoc = "
+@code{\\addlyrics} may get used on a @code{Staff} context and will
+then consider all note events created below it for synchronization.
+"
+}
+
+\relative \new Staff {
+  \time 2/4
+  c''4 b8. a16 g4.
+  << { r8 a4( b) c2 } \\
+     { f,8 e4 d c2 }
+  >>
+}
+\addlyrics {
+  Life is __ _ love, _ live __ _ life.
+}
+\addlyrics {
+  No more let sins and sor -- rows grow.
+}
index 8a85165cfdde63d5aef1c665786d3196b3f6acb0..da1810240135ff030d5f419ef4ea33a479d4137a 100644 (file)
@@ -812,14 +812,29 @@ set_context_property_on_children (Context *trans, SCM sym, SCM val)
 bool
 melisma_busy (Context *tr)
 {
-  SCM melisma_properties = tr->get_property ("melismaBusyProperties");
-  bool busy = false;
+  // When there are subcontexts, they are responsible for maintaining
+  // melismata.
+  SCM ch = tr->children_contexts ();
+  if (scm_is_pair (ch))
+    {
+      // all contexts need to have a busy melisma for this to evaluate
+      // to true.
+
+      do {
+        if (!melisma_busy (Context::unsmob (scm_car (ch))))
+          return false;
+        ch = scm_cdr (ch);
+      } while (scm_is_pair (ch));
+      return true;
+    }
 
-  for (; !busy && scm_is_pair (melisma_properties);
+  for (SCM melisma_properties = tr->get_property ("melismaBusyProperties");
+       scm_is_pair (melisma_properties);
        melisma_properties = scm_cdr (melisma_properties))
-    busy = busy || to_boolean (tr->get_property (scm_car (melisma_properties)));
+    if (to_boolean (tr->get_property (scm_car (melisma_properties))))
+      return true;
 
-  return busy;
+  return false;
 }
 
 bool
index dfc616e0d5f00b8ab6fe91d06600e4ee6ddfd5c7..c0c1af5a61a3c1834618661e19747599056c1532 100644 (file)
@@ -67,6 +67,7 @@ private:
   Context *lyrics_context_;
   Context *music_context_;
   SCM lyricsto_voice_name_;
+  SCM lyricsto_voice_type_;
 
   Moment busy_moment_;
   Moment pending_grace_moment_;
@@ -83,6 +84,8 @@ Lyric_combine_music_iterator::Lyric_combine_music_iterator ()
   music_context_ = 0;
   lyrics_context_ = 0;
   busy_moment_.set_infinite (-1);
+  lyricsto_voice_name_ = SCM_UNDEFINED;
+  lyricsto_voice_type_ = SCM_UNDEFINED;
 }
 
 /*
@@ -109,14 +112,14 @@ Lyric_combine_music_iterator::set_music_context (Context *to)
 {
   if (music_context_)
     {
-      music_context_->event_source ()->
+      music_context_->events_below ()->
       remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("rhythmic-event"));
     }
 
   music_context_ = to;
   if (to)
     {
-      to->event_source ()->add_listener (GET_LISTENER (set_busy),
+      to->events_below ()->add_listener (GET_LISTENER (set_busy),
                                          ly_symbol2scm ("rhythmic-event"));
     }
 }
@@ -171,6 +174,8 @@ Lyric_combine_music_iterator::derived_mark ()const
     scm_gc_mark (lyrics_context_->self_scm ());
   if (music_context_)
     scm_gc_mark (music_context_->self_scm ());
+  scm_gc_mark (lyricsto_voice_name_);
+  scm_gc_mark (lyricsto_voice_type_);
 }
 
 void
@@ -200,6 +205,9 @@ Lyric_combine_music_iterator::construct_children ()
     }
 
   lyricsto_voice_name_ = get_music ()->get_property ("associated-context");
+  lyricsto_voice_type_ = get_music ()->get_property ("associated-context-type");
+  if (!scm_is_symbol (lyricsto_voice_type_))
+    lyricsto_voice_type_ = ly_symbol2scm ("Voice");
 
   Context *voice = find_voice ();
   if (voice)
@@ -249,19 +257,22 @@ Lyric_combine_music_iterator::find_voice ()
   SCM running = lyrics_context_
                 ? lyrics_context_->get_property ("associatedVoice")
                 : SCM_EOL;
-
-  if (scm_is_string (running))
+  SCM voice_type = lyricsto_voice_type_;
+  if (scm_is_string (running)) {
     voice_name = running;
+    voice_type = lyrics_context_->get_property ("associatedVoiceType");
+  }
 
   if (scm_is_string (voice_name)
-      && (!music_context_ || ly_scm2string (voice_name) != music_context_->id_string ()))
+      && (!music_context_ || ly_scm2string (voice_name) != music_context_->id_string ())
+      && scm_is_symbol (voice_type))
     {
       Context *t = get_outlet ();
       while (t && t->get_parent_context ())
         t = t->get_parent_context ();
 
       string name = ly_scm2string (voice_name);
-      return find_context_below (t, ly_symbol2scm ("Voice"), name);
+      return find_context_below (t, voice_type, name);
     }
 
   return 0;
@@ -327,15 +338,16 @@ Lyric_combine_music_iterator::do_quit ()
   if (!music_found_)
     {
       SCM voice_name = get_music ()->get_property ("associated-context");
-
-      string name;
+      SCM voice_type = get_music ()->get_property ("associated-context-type");
+      string name, type;
       if (scm_is_string (voice_name))
         name = ly_scm2string (voice_name);
+      type = robust_symbol2string (voice_type, "Voice");
       /* Don't print a warning for empty lyrics (in which case we don't try
          to find the proper voice, so it will not be found) */
       if (lyrics_found_)
-        get_music ()->origin ()->warning (_f ("cannot find Voice `%s'",
-                                              name.c_str ()) + "\n");
+        get_music ()->origin ()->warning (_f ("cannot find %s `%s'",
+                                              type.c_str (), name.c_str ()) + "\n");
     }
 
   if (lyric_iter_)
index 100984062bcb28486e93fbc1cb3b8df90409dd4c..d4bbe64a988eef85e828ef9ad7625db61fd16afe 100644 (file)
@@ -112,11 +112,15 @@ get_voice_to_lyrics (Context *lyrics)
         nm = nm.substr (0, idx);
     }
 
+  SCM voice_type = lyrics->get_property ("associatedVoiceType");
+  if (!scm_is_symbol (voice_type))
+    return 0;
+
   Context *parent = lyrics;
   Context *voice = 0;
   while (parent && !voice)
     {
-      voice = find_context_below (parent, ly_symbol2scm ("Voice"), nm);
+      voice = find_context_below (parent, voice_type, nm);
       parent = parent->get_parent_context ();
     }
 
@@ -127,7 +131,7 @@ get_voice_to_lyrics (Context *lyrics)
   voice = 0;
   while (parent && !voice)
     {
-      voice = find_context_below (parent, ly_symbol2scm ("Voice"), "");
+      voice = find_context_below (parent, voice_type, "");
       parent = parent->get_parent_context ();
     }
 
index 645b35b6ee04147cbd31a545638ea5bcd8c93b9a..388ce46e51a58ba9e44c5f4c794e94df0dc59f26 100644 (file)
@@ -1455,7 +1455,11 @@ basic_music:
        | repeated_music
        | music_bare
        | LYRICSTO simple_string lyric_mode_music {
-               $$ = MAKE_SYNTAX ("lyric-combine", @$, $2, $3);
+               $$ = MAKE_SYNTAX ("lyric-combine", @$, $2, SCM_EOL, $3);
+       }
+       | LYRICSTO symbol '=' simple_string lyric_mode_music
+       {
+               $$ = MAKE_SYNTAX ("lyric_combine", @$, $3, $2, $4);
        }
        ;
 
index 4c61334d4033ff5245816d22e5a9d7978284528e..a222e6a7bae768bce128a57c74dac0322df5e2a9 100644 (file)
@@ -592,6 +592,7 @@ automatically when an output definition (a @code{\\score} or
 
   drumStyleTable = #drums-style
 
+  associatedVoiceType = #'Voice
   melismaBusyProperties = #default-melisma-properties
   tieWaitForNote = ##f
   clefGlyph = #"clefs.G"
index 5f92397dca3bbe9ad206af59cd302dd9aed82c71..f694a677785e161377c386b352eac6d764918acb 100644 (file)
@@ -63,7 +63,10 @@ suffixes.  No setting will not go back in measure-number time.")
      (alternativeRestores ,symbol-list? "Timing variables that are
 restored to their value at the end of the first alternative in
 subsequent alternatives.")
-     (associatedVoice ,string? "Name of the @code{Voice} that has the
+     (associatedVoice ,string? "Name of the context (see
+@code{associatedVoiceType} for its type, usually @code{Voice}) that
+has the melody for this @code{Lyrics} line.")
+     (associatedVoiceType ,symbol? "Type of the context that has the
 melody for this @code{Lyrics} line.")
      (autoAccidentals ,list? "List of different ways to typeset an
 accidental.
index 42525bb8b290165191918a0b638aa5699d291174..f20952b56fe75bb926df362d80b14e68c24237cf 100644 (file)
@@ -39,7 +39,9 @@ lettering should be incremented.")
 TODO: Consider making type into symbol.")
      (articulations ,ly:music-list?
                     "Articulation events specifically for this note.")
-     (associated-context ,string? "Name of the Voice context associated with
+     (associated-context ,string? "Name of the context associated with
+this @code{\\lyricsto} section.")
+     (associated-context-type ,symbol? "Type of the context associated with
 this @code{\\lyricsto} section.")
      (augmented ,boolean? "This figure is for an augmented figured
 bass (with @code{+} sign).")
index 68bfb1f9f163361ada22655459bd303ea0f96395..a427daadcca376d5e8dda561daf7c804dadc50ba 100644 (file)
@@ -207,11 +207,10 @@ into a @code{MultiMeasureTextEvent}."
                 'context-type ctx
                 'origin location)))
 
-(define (get-first-context-id! type mus)
-  "Find the name of a ContextSpeccedMusic with given type, possibly naming it"
+(define (get-first-context-id! mus)
+  "Find the name of a ContextSpeccedMusic, possibly naming it"
   (let ((id (ly:music-property mus 'context-id)))
-    (if (and (eq? (ly:music-property mus 'name) 'ContextSpeccedMusic)
-             (eq? (ly:music-property mus 'context-type) type))
+    (if (eq? (ly:music-property mus 'name) 'ContextSpeccedMusic)
         (if (and (string? id)
                  (not (string-null? id)))
             id
@@ -232,7 +231,7 @@ into a @code{MultiMeasureTextEvent}."
 (define-ly-syntax-simple (lyric-event text duration)
   (make-lyric-event text duration))
 
-(define (lyric-combine-music sync music loc)
+(define (lyric-combine-music sync sync-type music loc)
   ;; CompletizeExtenderEvent is added following the last lyric in MUSIC
   ;; to signal to the Extender_engraver that any pending extender should
   ;; be completed if the lyrics end before the associated voice.
@@ -241,35 +240,29 @@ into a @code{MultiMeasureTextEvent}."
   (make-music 'LyricCombineMusic
               'element music
               'associated-context sync
+              'associated-context-type sync-type
               'origin loc))
 
-(define-ly-syntax (lyric-combine parser location voice music)
-  (lyric-combine-music voice music location))
+(define-ly-syntax (lyric-combine parser location voice typ music)
+  (lyric-combine-music voice typ music location))
 
 (define-ly-syntax (add-lyrics parser location music addlyrics-list)
-  (let* ((existing-voice-name (get-first-context-id! 'Voice music))
+  (let* ((existing-voice-name (get-first-context-id! music))
          (voice-name (if (string? existing-voice-name)
                          existing-voice-name
                          (get-next-unique-voice-name)))
          (voice (if (string? existing-voice-name)
                     music
-                    (if (eq? (ly:music-property music 'name) 'ContextSpeccedMusic)
-                        (begin
-                          (set! (ly:music-property music 'element)
-                                (make-music 'ContextSpeccedMusic
-                                            'element (ly:music-property music 'element)
-                                            'context-type 'Voice
-                                            'context-id voice-name
-                                            'origin (ly:music-property music 'origin)))
-                          music)
-                        (make-music 'ContextSpeccedMusic
-                                    'element music
-                                    'context-type 'Voice
-                                    'context-id voice-name
-                                    'origin (ly:music-property music 'origin)))))
+                    (make-music 'ContextSpeccedMusic
+                                'element music
+                                'context-type 'Voice
+                                'context-id voice-name
+                                'origin (ly:music-property music 'origin))))
+         (voice-type (ly:music-property voice 'context-type))
          (lyricstos (map (lambda (mus)
                            (let* ((loc (ly:music-property mus 'origin))
-                                  (lyr (lyric-combine-music voice-name mus loc)))
+                                  (lyr (lyric-combine-music
+                                        voice-name voice-type mus loc)))
                              (make-music 'ContextSpeccedMusic
                                          'create-new #t
                                          'context-type 'Lyrics