+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
{"paper", PAPER},
{"partcombine", PARTCOMBINE},
{"partial", PARTIAL},
+ {"quote", QUOTE},
{"relative", RELATIVE},
{"remove", REMOVE},
{"repeat", REPEAT},
+++ /dev/null
-/*
- 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);
%token PAPER
%token PARTCOMBINE
%token PARTIAL
+%token QUOTE
%token RELATIVE
%token REMOVE
%token REPEAT
$$ = 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");
--- /dev/null
+/*
+ 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);
--- /dev/null
+/*
+ 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);
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
% reset default duration
unusedEntry = \notes { c4 }
-% music = "\melodic\relative c"
-
+#(define musicQuotes (make-hash-table))
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.")
)
(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
(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")
(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")
))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(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) '()))))
+ ))