From 388393d4de6c93d12da5d1c84cb112126fa80c84 Mon Sep 17 00:00:00 2001 From: hanwen Date: Sat, 21 Feb 2004 01:05:31 +0000 Subject: [PATCH] * 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. --- ChangeLog | 9 + lily/my-lily-lexer.cc | 1 + lily/parser.yy | 8 + ...e-iterator.cc => part-combine-iterator.cc} | 42 ++--- lily/quote-iterator.cc | 173 ++++++++++++++++++ lily/sequential-iterator.cc | 8 +- ly/declarations-init.ly | 3 +- scm/define-context-properties.scm | 1 + scm/define-music-properties.scm | 1 + scm/define-music-types.scm | 11 +- scm/part-combiner.scm | 15 ++ 11 files changed, 245 insertions(+), 27 deletions(-) rename lily/{new-part-combine-iterator.cc => part-combine-iterator.cc} (88%) create mode 100644 lily/quote-iterator.cc diff --git a/ChangeLog b/ChangeLog index b8e7a5c27b..7d32442c92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-02-21 Han-Wen Nienhuys + + * 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 * lily/auto-beam-engraver.cc (try_music): accept and process diff --git a/lily/my-lily-lexer.cc b/lily/my-lily-lexer.cc index f412d4d2ba..cceb376a6f 100644 --- a/lily/my-lily-lexer.cc +++ b/lily/my-lily-lexer.cc @@ -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/parser.yy b/lily/parser.yy index f4998c7c6b..566af26bb6 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -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/new-part-combine-iterator.cc b/lily/part-combine-iterator.cc similarity index 88% rename from lily/new-part-combine-iterator.cc rename to lily/part-combine-iterator.cc index 79e3e7c889..600de9611e 100644 --- a/lily/new-part-combine-iterator.cc +++ b/lily/part-combine-iterator.cc @@ -1,5 +1,5 @@ /* - new-part-combine-music-iterator.cc -- implement New_pc_iterator + new-part-combine-music-iterator.cc -- implement Part_combine_iterator source file of the GNU LilyPond music typesetter @@ -14,16 +14,16 @@ #include "music-iterator.hh" #include "interpretation-context-handle.hh" -class New_pc_iterator : public Music_iterator +class Part_combine_iterator : public Music_iterator { public: - New_pc_iterator (); + Part_combine_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 &); + Part_combine_iterator (Part_combine_iterator const &); virtual void construct_children (); virtual Moment pending_moment () const; @@ -69,7 +69,7 @@ private: }; -New_pc_iterator::New_pc_iterator () +Part_combine_iterator::Part_combine_iterator () { first_iter_ = 0; second_iter_ = 0; @@ -79,7 +79,7 @@ New_pc_iterator::New_pc_iterator () } void -New_pc_iterator::derived_mark () const +Part_combine_iterator::derived_mark () const { if (first_iter_) scm_gc_mark (first_iter_->self_scm()); @@ -88,7 +88,7 @@ New_pc_iterator::derived_mark () const } void -New_pc_iterator::derived_substitute (Context *f, +Part_combine_iterator::derived_substitute (Context *f, Context *t) { if (first_iter_) @@ -98,7 +98,7 @@ New_pc_iterator::derived_substitute (Context *f, } void -New_pc_iterator::do_quit () +Part_combine_iterator::do_quit () { if (first_iter_) first_iter_->quit(); @@ -113,7 +113,7 @@ New_pc_iterator::do_quit () } Moment -New_pc_iterator::pending_moment () const +Part_combine_iterator::pending_moment () const { Moment p; p.set_infinite (1); @@ -126,13 +126,13 @@ New_pc_iterator::pending_moment () const } bool -New_pc_iterator::ok () const +Part_combine_iterator::ok () const { return first_iter_->ok () || second_iter_->ok (); } void -New_pc_iterator::chords_together () +Part_combine_iterator::chords_together () { if (state_ == TOGETHER) return; @@ -147,7 +147,7 @@ New_pc_iterator::chords_together () void -New_pc_iterator::kill_mmrest (Context * tg) +Part_combine_iterator::kill_mmrest (Context * tg) { static Music * mmrest; if (!mmrest) @@ -160,7 +160,7 @@ New_pc_iterator::kill_mmrest (Context * tg) } void -New_pc_iterator::solo1 () +Part_combine_iterator::solo1 () { if (state_ == SOLO1) return; @@ -186,7 +186,7 @@ New_pc_iterator::solo1 () } void -New_pc_iterator::substitute_both (Context * to1, +Part_combine_iterator::substitute_both (Context * to1, Context * to2) { Context *tos[] = {to1,to2}; @@ -215,7 +215,7 @@ New_pc_iterator::substitute_both (Context * to1, void -New_pc_iterator::unisono (bool silent) +Part_combine_iterator::unisono (bool silent) { Status newstate = (silent) ? UNISILENCE : UNISONO; @@ -243,7 +243,7 @@ New_pc_iterator::unisono (bool silent) } void -New_pc_iterator::solo2 () +Part_combine_iterator::solo2 () { if (state_ == SOLO2) return; @@ -266,7 +266,7 @@ New_pc_iterator::solo2 () } void -New_pc_iterator::apart (bool silent) +Part_combine_iterator::apart (bool silent) { if (!silent) playing_state_ = APART; @@ -282,7 +282,7 @@ New_pc_iterator::apart (bool silent) void -New_pc_iterator::construct_children () +Part_combine_iterator::construct_children () { split_list_ = get_music ()->get_mus_property ("split-list"); SCM lst = get_music ()->get_mus_property ("elements"); @@ -363,7 +363,7 @@ New_pc_iterator::construct_children () } void -New_pc_iterator::process (Moment m) +Part_combine_iterator::process (Moment m) { Moment now = get_outlet ()->now_mom (); Moment *splitm = 0; @@ -406,7 +406,7 @@ New_pc_iterator::process (Moment m) } Music_iterator* -New_pc_iterator::try_music_in_children (Music *m) const +Part_combine_iterator::try_music_in_children (Music *m) const { Music_iterator * i = first_iter_->try_music (m); if (i) @@ -415,4 +415,4 @@ New_pc_iterator::try_music_in_children (Music *m) const return second_iter_->try_music (m); } -IMPLEMENT_CTOR_CALLBACK (New_pc_iterator); +IMPLEMENT_CTOR_CALLBACK (Part_combine_iterator); diff --git a/lily/quote-iterator.cc b/lily/quote-iterator.cc new file mode 100644 index 0000000000..ed26decf3f --- /dev/null +++ b/lily/quote-iterator.cc @@ -0,0 +1,173 @@ +/* + quote-iterator.cc -- implement Quote_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 "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); diff --git a/lily/sequential-iterator.cc b/lily/sequential-iterator.cc index c63d812ccb..b7d733aa25 100644 --- a/lily/sequential-iterator.cc +++ b/lily/sequential-iterator.cc @@ -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 diff --git a/ly/declarations-init.ly b/ly/declarations-init.ly index 9405e8985c..ba75cb154e 100644 --- a/ly/declarations-init.ly +++ b/ly/declarations-init.ly @@ -130,5 +130,4 @@ partCombineListener = \paper { % reset default duration unusedEntry = \notes { c4 } -% music = "\melodic\relative c" - +#(define musicQuotes (make-hash-table)) diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index 23389f9cbf..22c2b77848 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -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.") ) diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm index 0c70e7a78e..f033680d3b 100644 --- a/scm/define-music-properties.scm +++ b/scm/define-music-properties.scm @@ -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 diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm index 5d7bb57b29..5cd4e91f45 100644 --- a/scm/define-music-types.scm +++ b/scm/define-music-types.scm @@ -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") diff --git a/scm/part-combiner.scm b/scm/part-combiner.scm index 297153fef4..16f5e0f5aa 100644 --- a/scm/part-combiner.scm +++ b/scm/part-combiner.scm @@ -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) '())))) + )) -- 2.39.5