]> git.donarmstrong.com Git - lilypond.git/commitdiff
* lily/sequential-iterator.cc (process): only process if moment >= 0.
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 21 Feb 2004 01:05:31 +0000 (01:05 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 21 Feb 2004 01:05:31 +0000 (01:05 +0000)
* lily/parser.yy (command_element): \quote DURATION NAME: support
cue notes.

* lily/quote-iterator.cc (class Quote_iterator): new file.

12 files changed:
ChangeLog
lily/my-lily-lexer.cc
lily/new-part-combine-iterator.cc [deleted file]
lily/parser.yy
lily/part-combine-iterator.cc [new file with mode: 0644]
lily/quote-iterator.cc [new file with mode: 0644]
lily/sequential-iterator.cc
ly/declarations-init.ly
scm/define-context-properties.scm
scm/define-music-properties.scm
scm/define-music-types.scm
scm/part-combiner.scm

index b8e7a5c27b6aefbf44e804a9e35fe2da3b8b3fda..7d32442c9273d1a0affb9040c39b4cb67e997a78 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-02-21  Han-Wen Nienhuys   <hanwen@xs4all.nl>
+
+       * lily/sequential-iterator.cc (process): only process if moment >= 0.
+
+       * lily/parser.yy (command_element): \quote DURATION NAME: support
+       cue notes. 
+
+       * lily/quote-iterator.cc (class Quote_iterator): new file.
+
 2004-02-20  Han-Wen Nienhuys   <hanwen@xs4all.nl>
 
        * lily/auto-beam-engraver.cc (try_music): accept and process
index f412d4d2bad57262756c013d2484d9bd942fda26..cceb376a6f4b2634e9dff47627ef1b190cd43828 100644 (file)
@@ -67,6 +67,7 @@ static Keyword_ent the_key_tab[]={
   {"paper", PAPER},
   {"partcombine", PARTCOMBINE},
   {"partial", PARTIAL},
+  {"quote", QUOTE},
   {"relative", RELATIVE},
   {"remove", REMOVE},
   {"repeat", REPEAT},
diff --git a/lily/new-part-combine-iterator.cc b/lily/new-part-combine-iterator.cc
deleted file mode 100644 (file)
index 79e3e7c..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-/*   
-     new-part-combine-music-iterator.cc -- implement New_pc_iterator
-
-     source file of the GNU LilyPond music typesetter
-  
-     (c) 2004 Han-Wen Nienhuys
-*/
-
-#include "context.hh"
-#include "event.hh"
-#include "music-sequence.hh"
-#include "lily-guile.hh"
-#include "warn.hh"
-#include "music-iterator.hh"
-#include "interpretation-context-handle.hh"
-
-class New_pc_iterator : public Music_iterator
-{
-public:
-  New_pc_iterator ();
-
-  DECLARE_SCHEME_CALLBACK(constructor, ()); 
-protected:
-  virtual void derived_substitute (Context *f, Context *t) ;
-  virtual void derived_mark () const;
-  New_pc_iterator (New_pc_iterator const &);
-
-  virtual void construct_children ();
-  virtual Moment pending_moment () const;
-  virtual void do_quit(); 
-  virtual void process (Moment);
-
-  virtual Music_iterator *try_music_in_children (Music *) const;
-
-  virtual bool ok () const;
-
-private:
-  Music_iterator * first_iter_;
-  Music_iterator * second_iter_;
-  
-  SCM split_list_;
-
-  enum Status  {
-    APART, TOGETHER,
-    SOLO1, SOLO2,
-    UNISONO, UNISILENCE,
-  };
-  Status state_;
-  Status playing_state_;
-
-  /*
-    TODO: this is getting of hand... 
-   */
-  Interpretation_context_handle one_;
-  Interpretation_context_handle two_;
-  Interpretation_context_handle null_;
-  Interpretation_context_handle shared_;
-  Interpretation_context_handle solo_;
-  
-  void substitute_both (Context * to1,
-                       Context * to2);
-
-  void kill_mmrest (Context *);
-  void chords_together ();
-  void solo1 ();
-  void solo2 ();
-  void apart (bool silent);
-  void unisono (bool silent);
-};
-
-
-New_pc_iterator::New_pc_iterator ()
-{
-  first_iter_ = 0;
-  second_iter_ = 0;
-  split_list_ = SCM_EOL;
-  state_ = APART;
-  playing_state_ = APART;
-}
-
-void
-New_pc_iterator::derived_mark () const
-{
-  if (first_iter_)
-    scm_gc_mark (first_iter_->self_scm());
-  if (second_iter_)
-    scm_gc_mark(second_iter_->self_scm());
-}
-
-void
-New_pc_iterator::derived_substitute (Context *f,
-                                    Context *t)
-{
-  if (first_iter_)
-    first_iter_->substitute_outlet (f,t);
-  if (second_iter_)
-    second_iter_->substitute_outlet (f,t);
-}
-
-void
-New_pc_iterator::do_quit ()
-{
-  if (first_iter_)
-    first_iter_->quit();
-  if (second_iter_)
-    second_iter_->quit();
-
-  null_.set_translator (0);
-  one_ .set_translator (0);
-  two_.set_translator (0);
-  shared_.set_translator (0);
-  solo_.set_translator (0);
-}
-
-Moment
-New_pc_iterator::pending_moment () const
-{
-  Moment p;
-  p.set_infinite (1);
-  if (first_iter_->ok ())
-    p = p <? first_iter_->pending_moment ();
-
-  if (second_iter_->ok ())
-    p = p <? second_iter_->pending_moment ();
-  return p;
-}
-
-bool
-New_pc_iterator::ok () const
-{
-  return first_iter_->ok () || second_iter_->ok ();
-}
-
-void
-New_pc_iterator::chords_together ()
-{
-  if (state_ == TOGETHER)
-    return;
-  else
-    {
-      playing_state_ = TOGETHER;
-      state_ = TOGETHER;
-
-      substitute_both (shared_.get_outlet (), shared_.get_outlet());
-    }
-}
-
-
-void
-New_pc_iterator::kill_mmrest (Context * tg)
-{
-  static Music * mmrest;
-  if (!mmrest)
-    {
-      mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent"));
-      mmrest->set_mus_property ("duration", SCM_EOL);
-    }
-
-  tg->try_music (mmrest);
-}
-
-void
-New_pc_iterator::solo1 ()
-{
-  if (state_ == SOLO1)
-    return;
-  else
-    {
-      state_ = SOLO1;
-      substitute_both (solo_.get_outlet (),
-                      null_.get_outlet ());
-      
-      kill_mmrest (two_.get_outlet ());
-      kill_mmrest (shared_.get_outlet ());
-
-      if (playing_state_ != SOLO1)
-       {
-         static Music* event;
-         if (!event)
-           event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
-
-         first_iter_-> try_music_in_children (event);
-       }
-      playing_state_ = SOLO1;
-    }
-}
-
-void
-New_pc_iterator::substitute_both (Context * to1,
-                                 Context * to2)
-{
-  Context *tos[]  = {to1,to2};
-  Music_iterator *mis[] = {first_iter_, second_iter_}; 
-  Interpretation_context_handle *hs[] = {
-    &null_,
-    &one_, &two_,
-    &shared_,  &solo_,
-    0
-  };
-  
-  for (int i = 0; i < 2 ; i++)
-    {
-      for (int j =  0; hs[j]; j++)
-       if (hs[j]->get_outlet () != tos[i])
-         mis[i]->substitute_outlet (hs[j]->get_outlet (), tos[i]); 
-    }
-
-  for (int j =  0; hs[j]; j++)
-    {
-      Context * t = hs[j]->get_outlet ();
-      if (t != to1 && t != to2)
-       kill_mmrest (t);
-    }
-}
-
-
-void
-New_pc_iterator::unisono (bool silent)
-{
-  Status newstate = (silent) ? UNISILENCE : UNISONO;
-  
-  if (newstate == state_)
-    return; 
-  else
-    {
-      substitute_both (shared_.get_outlet (), null_.get_outlet ());
-
-      kill_mmrest (two_.get_outlet ());
-      kill_mmrest (shared_.get_outlet ());
-
-      if (playing_state_ != UNISONO
-         && newstate == UNISONO)
-       {
-         static Music* event;
-         if (!event)
-           event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
-
-         first_iter_-> try_music_in_children (event);      
-         playing_state_ = UNISONO;
-       }
-      state_ = newstate;
-    }
-}
-
-void
-New_pc_iterator::solo2 ()
-{
-  if (state_ == SOLO2)
-    return;
-  else
-    {
-      state_ = SOLO2;
-      
-      substitute_both (null_.get_outlet (), solo_.get_outlet ());
-      
-      if (playing_state_ != SOLO2)
-       {
-         static Music* event;
-         if (!event)
-           event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
-
-         second_iter_-> try_music_in_children (event);
-         playing_state_ = SOLO2;
-       }
-    }
-}
-
-void
-New_pc_iterator::apart (bool silent)
-{
-  if (!silent)
-    playing_state_ = APART;
-
-  if (state_ == APART)
-    return;
-  else
-    {
-      state_ = APART;
-      substitute_both (one_.get_outlet (), two_.get_outlet ());
-    }
-}
-
-
-void
-New_pc_iterator::construct_children ()
-{
-  split_list_ =  get_music ()->get_mus_property ("split-list");
-  SCM lst =  get_music ()->get_mus_property ("elements");
-
-  SCM props = scm_list_n (/*
-                           used to have tweaks here.
-                          */
-                         
-                         SCM_UNDEFINED);
-
-  Context *tr
-    =  get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
-                                            "shared",props);
-
-  shared_.set_translator (tr);
-
-  /*
-    If we don't, we get a new staff for every Voice.
-   */
-  set_translator (tr);
-
-  Context *solo_tr
-    =  get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
-                                             "solo",props);
-
-  solo_ .set_translator (solo_tr);
-
-  Context *null
-    =  get_outlet ()->find_create_context (ly_symbol2scm ("Devnull"),
-                                            "", SCM_EOL);
-
-  if (!null)
-    programming_error ("No Devnull found?");
-  
-  null_.set_translator (null);
-
-  Context *one = tr->find_create_context (ly_symbol2scm ("Voice"),
-                                                     "one", props);
-
-  one_.set_translator (one);
-
-  set_translator (one);
-  first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
-
-
-  Context *two = tr->find_create_context (ly_symbol2scm ("Voice"),
-                                                     "two", props);
-  two_.set_translator (two);
-  set_translator (two);
-  second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
-
-
-  set_translator (tr);
-
-
-  char const * syms[] = {
-    "Stem",
-    "DynamicLineSpanner",
-    "Tie",
-    "Dots",
-    "Rest",
-    "Slur",
-    "TextScript",
-    "Script",
-    0
-  };
-  
-  for (char const**p = syms; *p; p++)
-    {
-      SCM sym = ly_symbol2scm (*p);
-      execute_pushpop_property (one, sym,
-                                    ly_symbol2scm ("direction"), gh_int2scm (1));
-
-      execute_pushpop_property (two, sym,
-                               ly_symbol2scm ("direction"), gh_int2scm (-1));
-    }
-
-}
-
-void
-New_pc_iterator::process (Moment m)
-{
-  Moment now = get_outlet ()->now_mom ();
-  Moment *splitm = 0;
-  
-  for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
-    {
-      splitm = unsmob_moment (gh_caar (split_list_));
-      if (*splitm > now)
-       break ;
-
-      SCM tag = gh_cdar (split_list_);
-      
-      if (tag == ly_symbol2scm ("chords"))
-       chords_together ();
-      else if (tag == ly_symbol2scm ("apart")
-              || tag == ly_symbol2scm ("apart-silence")
-              || tag == ly_symbol2scm ("apart-spanner"))
-       apart (tag == ly_symbol2scm ("apart-silence"));
-      else if (tag == ly_symbol2scm ("unisono"))
-       unisono (false);
-      else if (tag == ly_symbol2scm ("unisilence"))
-       unisono (true);
-      else if (tag == ly_symbol2scm ("solo1"))
-       solo1 ();
-      else if (tag == ly_symbol2scm ("solo2"))
-       solo2 ();
-      else if (gh_symbol_p (tag))
-       {
-         String s =  "Unknown split directive: "
-           + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol")); 
-         programming_error (s);
-       }
-    }
-  
-  if (first_iter_->ok ())
-    first_iter_->process (m);
-  
-  if (second_iter_->ok ())
-    second_iter_->process (m);
-}
-
-Music_iterator*
-New_pc_iterator::try_music_in_children (Music *m) const
-{
-  Music_iterator * i =  first_iter_->try_music (m);
-  if (i)
-    return i;
-  else
-    return second_iter_->try_music (m);
-}
-
-IMPLEMENT_CTOR_CALLBACK (New_pc_iterator);
index f4998c7c6b6a1df36ea42db93d1f95e101d46f36..566af26bb6b3d05915b8732b681af30ece516220 100644 (file)
@@ -283,6 +283,7 @@ yylex (YYSTYPE *s,  void * v)
 %token PAPER
 %token PARTCOMBINE
 %token PARTIAL
+%token QUOTE
 %token RELATIVE
 %token REMOVE
 %token REPEAT
@@ -1347,6 +1348,13 @@ command_element:
 
                $$ = skip;
        }
+       | QUOTE duration_length STRING {
+               Music * quote = MY_MAKE_MUSIC("QuoteMusic");
+               quote->set_mus_property ("duration", $2);
+               quote->set_mus_property ("quoted-name", $3);
+               quote->set_spot (THIS->here_input ());
+               $$ = quote; 
+       }
        | OCTAVE { THIS->push_spot (); }
          pitch {
                Music *l = MY_MAKE_MUSIC("RelativeOctaveCheck");
diff --git a/lily/part-combine-iterator.cc b/lily/part-combine-iterator.cc
new file mode 100644 (file)
index 0000000..600de96
--- /dev/null
@@ -0,0 +1,418 @@
+/*   
+     new-part-combine-music-iterator.cc -- implement Part_combine_iterator
+
+     source file of the GNU LilyPond music typesetter
+  
+     (c) 2004 Han-Wen Nienhuys
+*/
+
+#include "context.hh"
+#include "event.hh"
+#include "music-sequence.hh"
+#include "lily-guile.hh"
+#include "warn.hh"
+#include "music-iterator.hh"
+#include "interpretation-context-handle.hh"
+
+class Part_combine_iterator : public Music_iterator
+{
+public:
+  Part_combine_iterator ();
+
+  DECLARE_SCHEME_CALLBACK(constructor, ()); 
+protected:
+  virtual void derived_substitute (Context *f, Context *t) ;
+  virtual void derived_mark () const;
+  Part_combine_iterator (Part_combine_iterator const &);
+
+  virtual void construct_children ();
+  virtual Moment pending_moment () const;
+  virtual void do_quit(); 
+  virtual void process (Moment);
+
+  virtual Music_iterator *try_music_in_children (Music *) const;
+
+  virtual bool ok () const;
+
+private:
+  Music_iterator * first_iter_;
+  Music_iterator * second_iter_;
+  
+  SCM split_list_;
+
+  enum Status  {
+    APART, TOGETHER,
+    SOLO1, SOLO2,
+    UNISONO, UNISILENCE,
+  };
+  Status state_;
+  Status playing_state_;
+
+  /*
+    TODO: this is getting of hand... 
+   */
+  Interpretation_context_handle one_;
+  Interpretation_context_handle two_;
+  Interpretation_context_handle null_;
+  Interpretation_context_handle shared_;
+  Interpretation_context_handle solo_;
+  
+  void substitute_both (Context * to1,
+                       Context * to2);
+
+  void kill_mmrest (Context *);
+  void chords_together ();
+  void solo1 ();
+  void solo2 ();
+  void apart (bool silent);
+  void unisono (bool silent);
+};
+
+
+Part_combine_iterator::Part_combine_iterator ()
+{
+  first_iter_ = 0;
+  second_iter_ = 0;
+  split_list_ = SCM_EOL;
+  state_ = APART;
+  playing_state_ = APART;
+}
+
+void
+Part_combine_iterator::derived_mark () const
+{
+  if (first_iter_)
+    scm_gc_mark (first_iter_->self_scm());
+  if (second_iter_)
+    scm_gc_mark(second_iter_->self_scm());
+}
+
+void
+Part_combine_iterator::derived_substitute (Context *f,
+                                    Context *t)
+{
+  if (first_iter_)
+    first_iter_->substitute_outlet (f,t);
+  if (second_iter_)
+    second_iter_->substitute_outlet (f,t);
+}
+
+void
+Part_combine_iterator::do_quit ()
+{
+  if (first_iter_)
+    first_iter_->quit();
+  if (second_iter_)
+    second_iter_->quit();
+
+  null_.set_translator (0);
+  one_ .set_translator (0);
+  two_.set_translator (0);
+  shared_.set_translator (0);
+  solo_.set_translator (0);
+}
+
+Moment
+Part_combine_iterator::pending_moment () const
+{
+  Moment p;
+  p.set_infinite (1);
+  if (first_iter_->ok ())
+    p = p <? first_iter_->pending_moment ();
+
+  if (second_iter_->ok ())
+    p = p <? second_iter_->pending_moment ();
+  return p;
+}
+
+bool
+Part_combine_iterator::ok () const
+{
+  return first_iter_->ok () || second_iter_->ok ();
+}
+
+void
+Part_combine_iterator::chords_together ()
+{
+  if (state_ == TOGETHER)
+    return;
+  else
+    {
+      playing_state_ = TOGETHER;
+      state_ = TOGETHER;
+
+      substitute_both (shared_.get_outlet (), shared_.get_outlet());
+    }
+}
+
+
+void
+Part_combine_iterator::kill_mmrest (Context * tg)
+{
+  static Music * mmrest;
+  if (!mmrest)
+    {
+      mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent"));
+      mmrest->set_mus_property ("duration", SCM_EOL);
+    }
+
+  tg->try_music (mmrest);
+}
+
+void
+Part_combine_iterator::solo1 ()
+{
+  if (state_ == SOLO1)
+    return;
+  else
+    {
+      state_ = SOLO1;
+      substitute_both (solo_.get_outlet (),
+                      null_.get_outlet ());
+      
+      kill_mmrest (two_.get_outlet ());
+      kill_mmrest (shared_.get_outlet ());
+
+      if (playing_state_ != SOLO1)
+       {
+         static Music* event;
+         if (!event)
+           event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
+
+         first_iter_-> try_music_in_children (event);
+       }
+      playing_state_ = SOLO1;
+    }
+}
+
+void
+Part_combine_iterator::substitute_both (Context * to1,
+                                 Context * to2)
+{
+  Context *tos[]  = {to1,to2};
+  Music_iterator *mis[] = {first_iter_, second_iter_}; 
+  Interpretation_context_handle *hs[] = {
+    &null_,
+    &one_, &two_,
+    &shared_,  &solo_,
+    0
+  };
+  
+  for (int i = 0; i < 2 ; i++)
+    {
+      for (int j =  0; hs[j]; j++)
+       if (hs[j]->get_outlet () != tos[i])
+         mis[i]->substitute_outlet (hs[j]->get_outlet (), tos[i]); 
+    }
+
+  for (int j =  0; hs[j]; j++)
+    {
+      Context * t = hs[j]->get_outlet ();
+      if (t != to1 && t != to2)
+       kill_mmrest (t);
+    }
+}
+
+
+void
+Part_combine_iterator::unisono (bool silent)
+{
+  Status newstate = (silent) ? UNISILENCE : UNISONO;
+  
+  if (newstate == state_)
+    return; 
+  else
+    {
+      substitute_both (shared_.get_outlet (), null_.get_outlet ());
+
+      kill_mmrest (two_.get_outlet ());
+      kill_mmrest (shared_.get_outlet ());
+
+      if (playing_state_ != UNISONO
+         && newstate == UNISONO)
+       {
+         static Music* event;
+         if (!event)
+           event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
+
+         first_iter_-> try_music_in_children (event);      
+         playing_state_ = UNISONO;
+       }
+      state_ = newstate;
+    }
+}
+
+void
+Part_combine_iterator::solo2 ()
+{
+  if (state_ == SOLO2)
+    return;
+  else
+    {
+      state_ = SOLO2;
+      
+      substitute_both (null_.get_outlet (), solo_.get_outlet ());
+      
+      if (playing_state_ != SOLO2)
+       {
+         static Music* event;
+         if (!event)
+           event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
+
+         second_iter_-> try_music_in_children (event);
+         playing_state_ = SOLO2;
+       }
+    }
+}
+
+void
+Part_combine_iterator::apart (bool silent)
+{
+  if (!silent)
+    playing_state_ = APART;
+
+  if (state_ == APART)
+    return;
+  else
+    {
+      state_ = APART;
+      substitute_both (one_.get_outlet (), two_.get_outlet ());
+    }
+}
+
+
+void
+Part_combine_iterator::construct_children ()
+{
+  split_list_ =  get_music ()->get_mus_property ("split-list");
+  SCM lst =  get_music ()->get_mus_property ("elements");
+
+  SCM props = scm_list_n (/*
+                           used to have tweaks here.
+                          */
+                         
+                         SCM_UNDEFINED);
+
+  Context *tr
+    =  get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
+                                            "shared",props);
+
+  shared_.set_translator (tr);
+
+  /*
+    If we don't, we get a new staff for every Voice.
+   */
+  set_translator (tr);
+
+  Context *solo_tr
+    =  get_outlet ()->find_create_context (ly_symbol2scm ("Voice"),
+                                             "solo",props);
+
+  solo_ .set_translator (solo_tr);
+
+  Context *null
+    =  get_outlet ()->find_create_context (ly_symbol2scm ("Devnull"),
+                                            "", SCM_EOL);
+
+  if (!null)
+    programming_error ("No Devnull found?");
+  
+  null_.set_translator (null);
+
+  Context *one = tr->find_create_context (ly_symbol2scm ("Voice"),
+                                                     "one", props);
+
+  one_.set_translator (one);
+
+  set_translator (one);
+  first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
+
+
+  Context *two = tr->find_create_context (ly_symbol2scm ("Voice"),
+                                                     "two", props);
+  two_.set_translator (two);
+  set_translator (two);
+  second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
+
+
+  set_translator (tr);
+
+
+  char const * syms[] = {
+    "Stem",
+    "DynamicLineSpanner",
+    "Tie",
+    "Dots",
+    "Rest",
+    "Slur",
+    "TextScript",
+    "Script",
+    0
+  };
+  
+  for (char const**p = syms; *p; p++)
+    {
+      SCM sym = ly_symbol2scm (*p);
+      execute_pushpop_property (one, sym,
+                                    ly_symbol2scm ("direction"), gh_int2scm (1));
+
+      execute_pushpop_property (two, sym,
+                               ly_symbol2scm ("direction"), gh_int2scm (-1));
+    }
+
+}
+
+void
+Part_combine_iterator::process (Moment m)
+{
+  Moment now = get_outlet ()->now_mom ();
+  Moment *splitm = 0;
+  
+  for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
+    {
+      splitm = unsmob_moment (gh_caar (split_list_));
+      if (*splitm > now)
+       break ;
+
+      SCM tag = gh_cdar (split_list_);
+      
+      if (tag == ly_symbol2scm ("chords"))
+       chords_together ();
+      else if (tag == ly_symbol2scm ("apart")
+              || tag == ly_symbol2scm ("apart-silence")
+              || tag == ly_symbol2scm ("apart-spanner"))
+       apart (tag == ly_symbol2scm ("apart-silence"));
+      else if (tag == ly_symbol2scm ("unisono"))
+       unisono (false);
+      else if (tag == ly_symbol2scm ("unisilence"))
+       unisono (true);
+      else if (tag == ly_symbol2scm ("solo1"))
+       solo1 ();
+      else if (tag == ly_symbol2scm ("solo2"))
+       solo2 ();
+      else if (gh_symbol_p (tag))
+       {
+         String s =  "Unknown split directive: "
+           + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol")); 
+         programming_error (s);
+       }
+    }
+  
+  if (first_iter_->ok ())
+    first_iter_->process (m);
+  
+  if (second_iter_->ok ())
+    second_iter_->process (m);
+}
+
+Music_iterator*
+Part_combine_iterator::try_music_in_children (Music *m) const
+{
+  Music_iterator * i =  first_iter_->try_music (m);
+  if (i)
+    return i;
+  else
+    return second_iter_->try_music (m);
+}
+
+IMPLEMENT_CTOR_CALLBACK (Part_combine_iterator);
diff --git a/lily/quote-iterator.cc b/lily/quote-iterator.cc
new file mode 100644 (file)
index 0000000..ed26dec
--- /dev/null
@@ -0,0 +1,173 @@
+/*   
+  quote-iterator.cc --  implement Quote_iterator
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#include "context.hh"
+#include "event.hh"
+#include "music-sequence.hh"
+#include "lily-guile.hh"
+#include "music-iterator.hh"
+#include "music.hh"
+#include "input.hh"
+#include "warn.hh"
+
+
+class Quote_iterator : public Music_iterator
+{
+public:
+  Quote_iterator ();
+  
+  Moment start_moment_;
+  SCM event_vector_;
+  int event_idx_;
+  int end_idx_ ;
+
+  DECLARE_SCHEME_CALLBACK(constructor, ()); 
+
+protected:
+  virtual void construct_children ();
+  virtual Moment pending_moment () const;
+  virtual void process (Moment);
+  virtual bool ok () const;
+};
+
+Quote_iterator::Quote_iterator ()
+{
+  event_vector_ = SCM_EOL;
+  event_idx_ = 0;
+  end_idx_ = 0;
+}
+
+bool
+moment_less (SCM a, SCM b)
+{
+  return  *unsmob_moment (a) < *unsmob_moment (b);
+}
+
+
+int
+binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
+{
+  int lo;
+  int hi;
+  lo = 0;
+  hi = SCM_VECTOR_LENGTH (vec);
+
+  /* binary search */
+  do
+  {
+    int cmp = (lo + hi) / 2;
+
+      SCM when = gh_car (SCM_VECTOR_REF(vec, cmp));
+      bool result =  (*is_less) (key, when);
+      if (result)
+          hi = cmp;
+      else
+          lo = cmp;
+    }
+  while (hi - lo > 1);
+
+  return lo;
+}
+
+
+void
+Quote_iterator::construct_children ()
+{
+  SCM tab = get_outlet()->get_property ("quotes");
+  if (scm_hash_table_p (tab) != SCM_BOOL_T)
+    {
+      get_music ()->origin ()->warning ("Context property `quotes' unset; cannot process quote.");
+      return ;
+    }
+
+  SCM name = get_music ()->get_mus_property ("quoted-name");
+  SCM dur = get_music ()->get_mus_property ("duration");
+
+  if (!unsmob_duration (dur))
+    return ;
+
+  set_translator (get_outlet ()->get_default_interpreter ());
+  
+  Moment now = get_outlet ()->now_mom ();
+  Moment stop = now + unsmob_duration (dur)->get_length ();
+
+  start_moment_ = now;
+  
+  event_vector_ = scm_hash_ref (tab, name, SCM_BOOL_F);
+
+  if (scm_vector_p (event_vector_) == SCM_BOOL_T)
+    {
+      event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
+      end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
+    }
+  else
+    get_music ()->origin ()->warning ("Can't find requested source");
+}
+
+
+bool
+Quote_iterator::ok () const
+{
+  return (event_idx_ <  end_idx_);
+}
+
+
+Moment
+Quote_iterator::pending_moment () const
+{
+  SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
+  return *unsmob_moment (gh_car (entry)) - start_moment_;
+}
+
+
+void
+Quote_iterator::process (Moment m)
+{
+  SCM entry = SCM_EOL;
+
+  m += start_moment_;
+  while (event_idx_ < end_idx_)
+    {
+      entry = SCM_VECTOR_REF (event_vector_, event_idx_);
+
+      Moment em = *unsmob_moment (gh_car (entry));
+
+      if (em > m)
+       return ;
+
+      if (em == m)
+       break ;
+
+      event_idx_++;
+    }
+
+  if (!gh_pair_p (entry))
+    return;
+  
+  for (SCM s = gh_cdr (entry); gh_pair_p (s); s = gh_cdr (s))
+    {
+      SCM ev_acc = gh_car (s);
+
+
+      Music * mus = unsmob_music (gh_car (ev_acc));
+      if (mus)
+       {
+         bool b = get_outlet ()->try_music (mus);
+      
+         if (!b)
+           mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name()));
+       }
+      else
+       programming_error ("need music in quote.");
+    }
+
+  event_idx_ ++; 
+}
+
+IMPLEMENT_CTOR_CALLBACK (Quote_iterator);
index c63d812ccb95b790fd7a7f54c7363555dac51997..b7d733aa252b0cc655cf3eb273de1d1501372410 100644 (file)
@@ -246,8 +246,12 @@ Sequential_iterator::process (Moment until)
          iter_->process (iter_->music_get_length ());
        }
       else
-       iter_->process (until - here_mom_ + iter_->music_start_mom ());
-
+       {
+         Moment w = until - here_mom_ + iter_->music_start_mom ();
+         if (w >= Moment (0)) 
+           iter_->process (w);
+       }
+      
       /*
        if the iter is still OK, there must be events left that have
        
index 9405e8985c3e976554158f95befe4a139acf54d3..ba75cb154e7549f6acd609e73e206d170080145f 100644 (file)
@@ -130,5 +130,4 @@ partCombineListener = \paper {
 % reset default duration
 unusedEntry = \notes { c4 }
 
-% music = "\melodic\relative c"
-
+#(define musicQuotes (make-hash-table)) 
index 23389f9cbfeeee77cbfc7ae789706128960a19a5..22c2b77848842d501f708daf8061d3eb5b74365b 100644 (file)
@@ -437,6 +437,7 @@ signature change.")
 Script_engraver for typesetting note-super/subscripts. See
 @file{scm/script.scm} for more information
 ")
+     (quotes ,hash-table? "Hash table, mapping names to music-event vectors.")
      (stavesFound ,grob-list? "list of all staff-symbols found.")
      (tieMelismaBusy ,boolean? "Signal whether a tie is present.")
      )
index 0c70e7a78e34de627ce2cacbc81bf7bf7e253813..f033680d3b6d296960a13a80be52906263cab394 100644 (file)
@@ -81,6 +81,7 @@ For chord inversions, this is negative.")
      (property-operations ,list?
                          "Do these operations for instantiating the context.")
      (predicate ,procedure? "the predicate of a \\outputproperty")
+     (quoted-name ,string? "The name of the voice to be quoted")
      (type ,symbol? "The type of this music object. Determines iteration in some cases.")
      (types ,list? "The types of this music
 object; determines by what engraver this music expression is
index 5d7bb57b29d8fad338003b520c6f95f119d35aaa..5cd4e91f45527a8e580d24076950081db9e9caf6 100644 (file)
@@ -321,9 +321,8 @@ as separate voices.")
 
        (internal-class-name . "Simultaneous_music")
        (types . (general-music part-combine-music))
-       (iterator-ctor . ,New_pc_iterator::constructor)
+       (iterator-ctor . ,Part_combine_iterator::constructor)
        ))
-    
     (PhrasingSlurEvent
      . (
        (description . "Start or end phrasing slur. Syntax NOTE \\(  and \\) NOTE")
@@ -362,6 +361,14 @@ goes down).")
        (types . (general-music pes-or-flexa-event event))
        ))
 
+    (QuoteMusic
+     . (
+       (description . "Quote preprocessed snippets of music. ")
+       (internal-class-name . "Event") ;;  so we get Event::get_length ().
+       (iterator-ctor . ,Quote_iterator::constructor)
+       (types . (general-music))
+       ))
+    
     (RelativeOctaveCheck
      . ((description . "Check if a pitch is in the correct octave.")
        (internal-class-name . "Relative_octave_check")
index 297153fef465d84a131fd6e1a82c4961940a6494..16f5e0f5aa707cbf8636156c75f3ed1e83a37573 100644 (file)
@@ -625,3 +625,18 @@ the mark when there are no spanners active."
   ))
 
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-public (add-quotable name mus)
+  (set! noticed '())
+  (let*
+      ((tab (eval 'musicQuotes (current-module) ))
+       (context (ly:run-translator (context-spec-music mus 'Voice)
+                                  part-combine-listener))
+       (evs (last-pair noticed))
+       )
+
+    (if (pair? evs)
+       (hash-set! tab name
+                  (list->vector (reverse! (car evs) '()))))
+  ))