+2006-05-16 Erik Sandberg <mandolaerik@gmail.com>
+ * lily/percent-repeat-engraver.cc, lily/parser.yy,
+ lily/define-music-types.cc, lily/percent-repeat-iterator.cc,
+ lily/slash-repeat-engraver.cc,
+ lily/include/percent-repeat-iterator.hh: Rework percent repeats:
+ iterator sends PercentEvents
+
+ * lily/time-scaled-music-iterator.cc, lily/tuplet-engraver.cc:
+ rework tuplets: send start/stop events to engraver
+
2006-05-15 Graham Percival <gpermus@gmail.com>
* Documentation/user/README.txt: update info for doc writers.
void
Folded_repeat_iterator::process (Moment m)
{
- if (!m.to_bool ())
- {
- bool success = try_music (get_music ());
- if (!success)
- get_music ()->origin ()->warning (_ ("no one to print a repeat brace"));
- }
-
if (main_iter_)
{
main_iter_->process (m);
#ifndef PERCENT_REPEAT_ITERATOR_HH
#define PERCENT_REPEAT_ITERATOR_HH
-#include "music-iterator.hh"
+#include "sequential-iterator.hh"
-class Percent_repeat_iterator : public Music_iterator
+class Percent_repeat_iterator : public Sequential_iterator
{
public:
DECLARE_CLASSNAME(Percent_repeat_iterator);
DECLARE_SCHEME_CALLBACK (constructor, ());
Percent_repeat_iterator ();
protected:
- virtual void derived_substitute (Context *f, Context *t);
-
+ virtual SCM get_music_list () const;
virtual void derived_mark () const;
- virtual Moment pending_moment () const;
- virtual void do_quit ();
virtual void construct_children ();
- virtual bool ok () const;
- virtual void process (Moment);
- virtual Music_iterator *try_music_in_children (Music *) const;
-
private:
- Music_iterator *child_iter_;
- Moment finish_mom_;
+ SCM child_list_;
};
#endif /* PERCENT_REPEAT_ITERATOR_HH */
source file of the GNU LilyPond music typesetter
- (c) 1998--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 1998--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>,
+ Erik Sandberg <mandolaerik@gmail.com>
*/
-#ifndef Time_scaled_music_ITERATOR_HH
-#define Time_scaled_music_ITERATOR_HH
+#ifndef TIME_SCALED_MUSIC_ITERATOR_HH
+#define TIME_SCALED_MUSIC_ITERATOR_HH
-#include "music-wrapper-iterator.hh"
+#include "sequential-iterator.hh"
-class Time_scaled_music_iterator : public Music_wrapper_iterator
+class Time_scaled_music_iterator : public Sequential_iterator
{
public:
DECLARE_SCHEME_CALLBACK (constructor, ());
/* construction */
DECLARE_CLASSNAME(Time_scaled_music_iterator);
+ Time_scaled_music_iterator ();
protected:
- virtual void process (Moment);
+ virtual SCM get_music_list () const;
+ virtual void derived_mark () const;
+ virtual void construct_children ();
+private:
+ SCM child_list_;
};
-#endif /* Time_scaled_music_ITERATOR_HH */
-
+#endif /* TIME_SCALED_MUSIC_ITERATOR_HH */
Repeated_music:
REPEAT simple_string bare_unsigned Music Alternative_music
{
- /*TODO: move to Scheme.*/
- Music *beg = $4;
- int times = $3;
+ SCM proc = ly_lily_module_constant ("make-repeat");
SCM alts = scm_is_pair ($5) ? scm_car ($5) : SCM_EOL;
- if (times < scm_ilength (alts)) {
- unsmob_music (scm_car (alts))
- ->origin ()->warning (
- _ ("more alternatives than repeats"));
- warning ("junking excess alternatives");
- alts = ly_truncate_list (times, alts);
- }
-
-
- SCM proc = ly_lily_module_constant ("make-repeated-music");
-
- SCM mus = scm_call_1 (proc, $2);
+ assert ($4);
+ SCM mus = scm_call_4 (proc, $2, scm_int2num ($3), $4->self_scm (), alts);
Music *r = unsmob_music (mus);
- r->protect ();
- if (beg)
- {
- r-> set_property ("element", beg->self_scm ());
- beg->unprotect ();
- }
- r->set_property ("repeat-count", scm_from_int (max (times, 1)));
-
- r-> set_property ("elements",alts);
- if (ly_is_equal ($2, scm_makfrom0str ("tremolo"))) {
- /*
- TODO: move this code to Scheme.
- */
-
- /* we cannot get durations and other stuff
- correct down the line,
- so we have to add to the duration log here. */
- SCM func = ly_lily_module_constant ("shift-duration-log");
-
- int dots = ($3 % 3) ? 0 : 1;
- int shift = -intlog2 ((dots) ? ($3*2/3) : $3);
-
- if ($4->is_mus_type ("sequential-music"))
- {
- int list_len = scm_ilength ($4->get_property ("elements"));
- if (list_len != 2)
- $4->origin ()->warning (_f ("expect 2 elements for Chord tremolo, found %d", list_len));
- shift -= 1;
- r->compress (Moment (Rational (1, list_len)));
- }
- scm_call_3 (func, r->self_scm (), scm_from_int (shift), scm_from_int (dots));
-
- }
+ r->protect ();
+ $4->unprotect ();
r->set_spot (*$4->origin ());
$$ = r;
| TIMES fraction Music
{
- int n = scm_to_int (scm_car ($2));
- int d = scm_to_int (scm_cdr ($2));
- Music *mp = $3;
-
- $$= MY_MAKE_MUSIC ("TimeScaledMusic");
- $$->set_spot (@$);
-
- $$->set_property ("element", mp->self_scm ());
- mp->unprotect();
- $$->set_property ("numerator", scm_from_int (n));
- $$->set_property ("denominator", scm_from_int (d));
- $$->compress (Moment (Rational (n,d)));
-
+ int n = scm_to_int (scm_car ($2));
+ int d = scm_to_int (scm_cdr ($2));
+ Music *mp = $3;
+
+ $$= MY_MAKE_MUSIC ("TimeScaledMusic");
+ $$->set_spot (@$);
+
+ $$->set_property ("element", mp->self_scm ());
+ mp->unprotect();
+ $$->set_property ("numerator", scm_from_int (n));
+ $$->set_property ("denominator", scm_from_int (d));
+ $$->compress (Moment (Rational (n,d)));
}
| Repeated_music { $$ = $1; }
| TRANSPOSE pitch_also_in_chords pitch_also_in_chords Music {
source file of the GNU LilyPond music typesetter
- (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>, Erik Sandberg <mandolaerik@gmail.com>
*/
#include "translator.icc"
+/*
+* TODO: Create separate Double_percent_repeat_engraver?
+* Or, at least move double percent handling to Slash_repeat_engraver
+*/
+
class Percent_repeat_engraver : public Engraver
{
void typeset_perc ();
TRANSLATOR_DECLARATIONS (Percent_repeat_engraver);
protected:
- Music *repeat_;
+ Music *percent_event_;
- /// moment (global time) where beam started.
- Moment start_mom_;
+ /// moment (global time) where percent started.
Moment stop_mom_;
-
- /// location within measure where beam started.
- Moment beam_start_location_;
- Moment next_moment_;
- Moment body_length_;
+ Moment start_mom_;
enum Repeat_sign_type
{
};
Repeat_sign_type repeat_sign_type_;
- Item *double_percent_;
- Item *double_percent_counter_;
-
Spanner *percent_;
Spanner *percent_counter_;
- Spanner *finished_percent_;
- Spanner *finished_percent_counter_;
- int count_;
- int total_count_;
protected:
virtual void finalize ();
virtual bool try_music (Music *);
percent_ = 0;
percent_counter_ = 0;
- finished_percent_ = 0;
- finished_percent_counter_ = 0;
-
- double_percent_ = 0;
- double_percent_counter_ = 0;
-
- repeat_ = 0;
- count_ = 0;
- total_count_ = 0;
+ percent_event_ = 0;
}
bool
Percent_repeat_engraver::try_music (Music *m)
{
- if (m->is_mus_type ("repeated-music")
- && m->get_property ("iterator-ctor")
- == Percent_repeat_iterator::constructor_proc
- && !repeat_)
+ if (m->is_mus_type ("percent-event")
+ && !percent_event_)
{
- body_length_ = Repeated_music::body_get_length (m);
- total_count_ = Repeated_music::repeat_count (m);
-
- Moment now = now_mom ();
- start_mom_ = now;
- stop_mom_ = start_mom_ + Moment (total_count_) * body_length_;
- next_moment_ = start_mom_;
- next_moment_ += body_length_;
-
+ Moment body_length = m->get_length ();
Moment meas_len (robust_scm2moment (get_property ("measureLength"),
Moment (1)));
-
- if (meas_len == body_length_)
+
+ if (meas_len == body_length)
+ {
repeat_sign_type_ = MEASURE;
- else if (Moment (2) * meas_len == body_length_)
+ start_mom_ = now_mom ();
+ stop_mom_ = now_mom () + body_length;
+ get_global_context ()->add_moment_to_process (stop_mom_);
+ }
+ else if (Moment (2) * meas_len == body_length)
+ {
repeat_sign_type_ = DOUBLE_MEASURE;
+ start_mom_ = now_mom () + meas_len;
+ stop_mom_ = now_mom () + body_length; /* never used */
+ get_global_context ()->add_moment_to_process (start_mom_);
+ }
else
return false;
-
-
- repeat_ = m;
-
- Global_context *global = get_global_context ();
- for (int i = 1; i < total_count_; i++)
- {
- Moment m = next_moment_ + Moment (i) * body_length_;
- global->add_moment_to_process (m);
-
- /* bars between % too. */
- if (repeat_sign_type_ == DOUBLE_MEASURE)
- global->add_moment_to_process (m - meas_len);
- }
- if (repeat_sign_type_ == DOUBLE_MEASURE)
- next_moment_ += meas_len;
+ percent_event_ = m;
- count_ = 1;
return true;
}
void
Percent_repeat_engraver::process_music ()
{
- if (repeat_ && now_mom ().main_part_ == next_moment_.main_part_)
+ if (percent_event_ && now_mom ().main_part_ == start_mom_.main_part_)
{
- count_ ++;
if (repeat_sign_type_ == MEASURE)
{
- finished_percent_ = percent_;
- finished_percent_counter_ = percent_counter_;
-
- typeset_perc ();
- percent_ = make_spanner ("PercentRepeat", repeat_->self_scm ());
+ if (percent_)
+ typeset_perc ();
+ percent_ = make_spanner ("PercentRepeat", percent_event_->self_scm ());
Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
percent_->set_bound (LEFT, col);
- if (total_count_ > 2
- && to_boolean (get_property ("countPercentRepeats")))
+ SCM count = percent_event_->get_property ("repeat-count");
+ if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats")))
{
percent_counter_
- = make_spanner ("PercentRepeatCounter", repeat_->self_scm ());
+ = make_spanner ("PercentRepeatCounter", percent_event_->self_scm ());
- SCM text = scm_number_to_string (scm_from_int (count_),
- scm_from_int (10));
+ SCM text = scm_number_to_string (count, scm_from_int (10));
percent_counter_->set_property ("text", text);
percent_counter_->set_bound (LEFT, col);
Side_position_interface::add_support (percent_counter_,
percent_);
percent_counter_->set_parent (percent_, Y_AXIS);
- }
+ }
+ else
+ percent_counter_ = 0;
}
else if (repeat_sign_type_ == DOUBLE_MEASURE)
{
- double_percent_ = make_item ("DoublePercentRepeat", repeat_->self_scm ());
+ Item *double_percent = make_item ("DoublePercentRepeat", percent_event_->self_scm ());
- if (total_count_ > 2
+ SCM count = percent_event_->get_property ("repeat-count");
+ if (count != SCM_EOL
&& to_boolean (get_property ("countPercentRepeats")))
{
- double_percent_counter_
- = make_item ("DoublePercentRepeatCounter",
- repeat_->self_scm());
+ Item *double_percent_counter = make_item ("DoublePercentRepeatCounter",
+ percent_event_->self_scm());
- SCM text = scm_number_to_string (scm_from_int (count_),
+ SCM text = scm_number_to_string (count,
scm_from_int (10));
- double_percent_counter_->set_property ("text", text);
+ double_percent_counter->set_property ("text", text);
- Side_position_interface::add_support (double_percent_counter_,
- double_percent_);
- double_percent_counter_->set_parent (double_percent_, Y_AXIS);
- double_percent_counter_->set_parent (double_percent_, X_AXIS);
+ Side_position_interface::add_support (double_percent_counter,
+ double_percent);
+ double_percent_counter->set_parent (double_percent, Y_AXIS);
+ double_percent_counter->set_parent (double_percent, X_AXIS);
}
/* forbid breaks on a % line. Should forbid all breaks, really. */
context ()->get_score_context ()->set_property ("forbidBreak", SCM_BOOL_T);
+
+ /* No more processing needed. */
+ repeat_sign_type_ = UNKNOWN;
}
- next_moment_ = next_moment_ + body_length_;
- next_moment_.grace_part_ = Rational (0);
}
}
void
Percent_repeat_engraver::finalize ()
{
- typeset_perc ();
if (percent_)
{
- repeat_->origin ()->warning (_ ("unterminated percent repeat"));
+ percent_event_->origin ()->warning (_ ("unterminated percent repeat"));
percent_->suicide ();
percent_counter_->suicide();
}
void
Percent_repeat_engraver::typeset_perc ()
{
- if (finished_percent_)
+ if (percent_)
{
Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
- finished_percent_->set_bound (RIGHT, col);
- finished_percent_ = 0;
+ percent_->set_bound (RIGHT, col);
+ percent_ = 0;
- if (finished_percent_counter_)
- finished_percent_counter_->set_bound (RIGHT, col);
-
- finished_percent_counter_ = 0;
+ if (percent_counter_)
+ percent_counter_->set_bound (RIGHT, col);
+ percent_counter_ = 0;
}
-
- double_percent_ = 0;
- double_percent_counter_ = 0;
}
void
if (stop_mom_.main_part_ == now_mom ().main_part_)
{
if (percent_)
- {
- finished_percent_ = percent_;
- finished_percent_counter_ = percent_counter_;
-
- typeset_perc ();
- }
- repeat_ = 0;
- percent_ = 0;
-
- percent_counter_ = 0;
+ typeset_perc ();
+ percent_event_ = 0;
repeat_sign_type_ = UNKNOWN;
}
}
void
Percent_repeat_engraver::stop_translation_timestep ()
{
- typeset_perc ();
}
ADD_TRANSLATOR (Percent_repeat_engraver,
"Make whole bar and double bar repeats.",
/* create */
- "PercentRepeat "
"DoublePercentRepeat "
- "PercentRepeatCounter "
- "DoublePercentRepeatCounter",
+ "DoublePercentRepeatCounter "
+ "PercentRepeat "
+ "PercentRepeatCounter ",
/* accept */
- "repeated-music",
+ "percent-event ",
/* read */
- "measureLength "
+ "countPercentRepeats "
"currentCommandColumn "
- "countPercentRepeats",
+ "measureLength ",
/* write */
"forbidBreak "
source file of the GNU LilyPond music typesetter
- (c) 2001--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 2001--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>, Erik Sandberg <mandolaerik@gmail.com>
*/
#include "percent-repeat-iterator.hh"
#include "input.hh"
#include "international.hh"
+#include "music.hh"
#include "repeated-music.hh"
IMPLEMENT_CTOR_CALLBACK (Percent_repeat_iterator);
Percent_repeat_iterator::Percent_repeat_iterator ()
{
- child_iter_ = 0;
-}
-
-void
-Percent_repeat_iterator::do_quit ()
-{
- if (child_iter_)
- child_iter_->quit ();
-}
-
-bool
-Percent_repeat_iterator::ok () const
-{
- return child_iter_;
+ child_list_ = SCM_EOL;
}
void
Percent_repeat_iterator::construct_children ()
{
+ /* TODO: Distinction between percent and slash */
Music *mus = get_music ();
- finish_mom_ = mus->get_length ();
- child_iter_ = unsmob_iterator (get_iterator (Repeated_music::body (mus)));
-}
-
-void
-Percent_repeat_iterator::process (Moment m)
-{
- if (!m.to_bool ())
- {
- Music_iterator *yeah = try_music (get_music ());
- if (yeah)
- set_context (yeah->get_outlet ());
- else
- get_music ()->origin ()->warning (_ ("no one to print a percent"));
- }
-
- if (child_iter_->ok ())
- child_iter_->process (m);
-
- if (finish_mom_ <= m)
- {
- child_iter_->quit ();
- child_iter_ = 0;
- }
-}
-
-Moment
-Percent_repeat_iterator::pending_moment ()const
-{
- if (child_iter_->ok ())
- return child_iter_->pending_moment ();
- else
- return finish_mom_;
-}
-
-Music_iterator *
-Percent_repeat_iterator::try_music_in_children (Music *m) const
-{
- return child_iter_->try_music (m);
-}
-
-void
-Percent_repeat_iterator::derived_mark ()const
-{
- if (child_iter_)
- scm_gc_mark (child_iter_->self_scm ());
+ Music *child = Repeated_music::body (mus);
+ SCM length = child->get_length ().smobbed_copy ();
+ child_list_ = SCM_EOL;
+
+ int repeats = scm_to_int (mus->get_property ("repeat-count"));
+ for (int i = repeats; i > 1; i--)
+ {
+ Music *percent = make_music_by_name (ly_symbol2scm ("PercentEvent"));
+ percent->set_spot (*mus->origin ());
+ percent->set_property ("length", length);
+ if (repeats > 1)
+ percent->set_property ("repeat-count", scm_int2num (i - 1));
+ Music *percent_chord = make_music_by_name (ly_symbol2scm ("EventChord"));
+ percent_chord->set_spot (*mus->origin ());
+ percent_chord->set_property ("elements", scm_list_1 (percent->self_scm ()));
+ child_list_ = scm_cons (percent_chord->self_scm (), child_list_);
+ percent->unprotect ();
+ percent_chord->unprotect ();
+ }
+ child_list_ = scm_cons (child->self_scm (), child_list_);
+
+ Sequential_iterator::construct_children ();
+}
+
+SCM
+Percent_repeat_iterator::get_music_list () const
+{
+ return child_list_;
}
void
-Percent_repeat_iterator::derived_substitute (Context *f, Context *t)
+Percent_repeat_iterator::derived_mark () const
{
- if (child_iter_)
- child_iter_->substitute_outlet (f, t);
+ scm_gc_mark (child_list_);
+ Sequential_iterator::derived_mark ();
}
source file of the GNU LilyPond music typesetter
- (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>, Erik Sandberg <mandolaerik@gmail.com>
*/
#include "repeated-music.hh"
/**
This acknowledges repeated music with "percent" style. It typesets
- a % sign.
-
- TODO:
-
- - BEAT case: Create items for single beat repeats, i.e. c4 / / /
-
- - DOUBLE_MEASURE case: attach a % to an appropriate barline.
+ a slash sign.
*/
class Slash_repeat_engraver : public Engraver
{
public:
TRANSLATOR_DECLARATIONS (Slash_repeat_engraver);
protected:
- Music *repeat_;
-
- /// moment (global time) where beam started.
- Moment start_mom_;
- Moment stop_mom_;
-
- /// location within measure where beam started.
- Moment beam_start_location_;
- Moment next_moment_;
- Moment body_length_;
-
- Item *beat_slash_;
- Item *double_percent_;
+ Music *slash_;
protected:
virtual bool try_music (Music *);
- void start_translation_timestep ();
void process_music ();
};
Slash_repeat_engraver::Slash_repeat_engraver ()
{
- repeat_ = 0;
- beat_slash_ = 0;
+ slash_ = 0;
}
bool
Slash_repeat_engraver::try_music (Music *m)
{
- if (m->is_mus_type ("repeated-music")
- && !repeat_
- && m->get_property ("iterator-ctor")
- == Percent_repeat_iterator::constructor_proc)
+ /*todo: separate events for percent and slash */
+ if (m->is_mus_type ("percent-event"))
{
- body_length_ = Repeated_music::body_get_length (m);
- int count = Repeated_music::repeat_count (m);
-
- Moment now = now_mom ();
- start_mom_ = now;
- stop_mom_ = start_mom_ + Moment (count) * body_length_;
- next_moment_ = start_mom_ + body_length_;
-
Moment meas_length
- = robust_scm2moment (get_property ("measureLength"), Moment (0));
- if (body_length_ < meas_length)
- repeat_ = m;
+ = robust_scm2moment (get_property ("measureLength"), Moment (0));
+
+ if (m->get_length () < meas_length)
+ slash_ = m;
else
return false;
- Global_context *global = get_global_context ();
- for (int i = 0; i < count; i++)
- global->add_moment_to_process (next_moment_ + Moment (i) * body_length_);
-
return true;
}
void
Slash_repeat_engraver::process_music ()
{
- if (repeat_ && now_mom () == next_moment_)
+ if (slash_)
{
- beat_slash_ = make_item ("RepeatSlash", repeat_->self_scm ());
- next_moment_ = next_moment_ + body_length_;
-
- get_global_context ()->add_moment_to_process (next_moment_);
+ make_item ("RepeatSlash", slash_->self_scm ());
+ slash_ = 0;
}
}
-void
-Slash_repeat_engraver::start_translation_timestep ()
-{
- if (stop_mom_ == now_mom ())
- repeat_ = 0;
- beat_slash_ = 0;
-}
-
#include "translator.icc"
ADD_TRANSLATOR (Slash_repeat_engraver,
/* doc */ "Make beat repeats.",
/* create */ "RepeatSlash",
- /* accept */ "repeated-music",
+ /* accept */ "percent-event",
/* read */ "measureLength",
/* write */ "");
source file of the GNU LilyPond music typesetter
- (c) 1998--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 1998--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>,
+ Erik Sandberg <mandolaerik@gmail.com>
*/
#include "time-scaled-music-iterator.hh"
#include "context.hh"
#include "input.hh"
#include "international.hh"
+#include "music.hh"
+
+Time_scaled_music_iterator::Time_scaled_music_iterator ()
+{
+ child_list_ = SCM_EOL;
+}
+
+void
+Time_scaled_music_iterator::construct_children ()
+{
+ Music *mus = get_music ();
+ Input *origin = mus->origin ();
+ Music *child = unsmob_music (mus->get_property ("element"));
+
+ /* Create tuplet start/stop span events before/after the music */
+ SCM tuplet_symbol = ly_symbol2scm ("TupletEvent");
+ SCM start_event = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (START));
+ Music *start = unsmob_music (start_event);
+ start->set_spot (*origin);
+ start->set_property ("numerator", mus->get_property ("numerator"));
+ start->set_property ("denominator", mus->get_property ("denominator"));
+ start_event = scm_call_1 (ly_lily_module_constant ("make-event-chord"), scm_list_1 (start_event));
+ unsmob_music (start_event)->set_spot (*origin);
+
+ SCM stop_event = scm_call_2 (ly_lily_module_constant ("make-span-event"), tuplet_symbol, scm_from_int (STOP));
+ unsmob_music (stop_event)->set_spot (*origin);
+ stop_event = scm_call_1 (ly_lily_module_constant ("make-event-chord"), scm_list_1 (stop_event));
+ unsmob_music (stop_event)->set_spot (*origin);
+
+ child_list_ = scm_list_3 (start_event, child->self_scm (), stop_event);
+
+ Sequential_iterator::construct_children ();
+}
+
+SCM
+Time_scaled_music_iterator::get_music_list () const
+{
+ return child_list_;
+}
void
-Time_scaled_music_iterator::process (Moment m)
+Time_scaled_music_iterator::derived_mark () const
{
- if (!m.to_bool ())
- {
- Music_iterator *yeah = try_music (get_music ());
- if (yeah)
- set_context (yeah->get_outlet ());
- else
- get_music ()->origin ()->warning (_ ("no one to print a tuplet start bracket"));
- }
-
- Music_wrapper_iterator::process (m);
+ scm_gc_mark (child_list_);
+ Sequential_iterator::derived_mark ();
}
IMPLEMENT_CTOR_CALLBACK (Time_scaled_music_iterator);
struct Tuplet_description
{
Music *music_;
- Rational stop_;
- Rational span_stop_;
- Rational length_;
Spanner *bracket_;
Spanner *number_;
Tuplet_description ()
bracket_ = 0;
number_ = 0;
}
- static int compare (Tuplet_description const &a, Tuplet_description const &b)
- {
- return ::compare (a.length_, b.length_);
- }
};
class Tuplet_engraver : public Engraver
protected:
vector<Tuplet_description> tuplets_;
+ vector<Tuplet_description> stopped_tuplets_;
vector<Spanner*> last_tuplets_;
DECLARE_ACKNOWLEDGER (note_column);
virtual bool try_music (Music *r);
bool
Tuplet_engraver::try_music (Music *music)
{
- if (music->is_mus_type ("time-scaled-music"))
+ if (music->is_mus_type ("tuplet-spanner-event"))
{
- Music *el = unsmob_music (music->get_property ("element"));
- if (el && !el->is_mus_type ("event-chord"))
+ Direction dir = to_dir (music->get_property ("span-direction"));
+ if (dir == START)
{
Tuplet_description d;
d.music_ = music;
- d.length_ = music->get_length ().main_part_;
- d.stop_ = now_mom ().main_part_ + d.length_;
- d.span_stop_ = d.stop_;
-
- SCM s = get_property ("tupletSpannerDuration");
- if (unsmob_moment (s))
- d.span_stop_ = min (d.span_stop_, (now_mom () + *unsmob_moment (s)).main_part_);
-
tuplets_.push_back (d);
}
+ if (dir == STOP)
+ {
+ stopped_tuplets_.push_back (tuplets_.back ());
+ tuplets_.pop_back ();
+ }
return true;
}
return false;
void
Tuplet_engraver::process_music ()
{
+ for (vsize i = 0; i < stopped_tuplets_.size (); i++)
+ {
+ bool full_length = to_boolean (get_property ("tupletFullLength"));
+ if (stopped_tuplets_[i].bracket_)
+ {
+ if (full_length)
+ {
+ Item *col = unsmob_item (get_property ("currentMusicalColumn"));
+
+ stopped_tuplets_[i].bracket_->set_bound (RIGHT, col);
+ stopped_tuplets_[i].number_->set_bound (RIGHT, col);
+ }
+ else if (!stopped_tuplets_[i].bracket_->get_bound (RIGHT))
+ {
+ stopped_tuplets_[i].bracket_->set_bound (RIGHT,
+ stopped_tuplets_[i].bracket_->get_bound (LEFT));
+ stopped_tuplets_[i].number_->set_bound (RIGHT,
+ stopped_tuplets_[i].bracket_->get_bound (LEFT));
+ }
+ // todo: scrap last_tuplets_, use stopped_tuplets_ only.
+ // clear stopped_tuplets_ at start_translation_timestep
+ last_tuplets_.push_back (tuplets_[i].bracket_);
+ last_tuplets_.push_back (tuplets_[i].number_);
+ }
+ }
+ stopped_tuplets_.clear ();
+
if (!tuplets_.size ())
return;
- vector_sort (tuplets_, Tuplet_description::compare);
for (vsize i = 0; i < tuplets_.size (); i++)
{
if (tuplets_[i].bracket_)
void
Tuplet_engraver::start_translation_timestep ()
{
- Moment now = now_mom ();
-
last_tuplets_.clear ();
- if (tuplets_.empty ())
- return;
-
- Moment tsdmom = robust_scm2moment (get_property ("tupletSpannerDuration"), Moment (0));
- bool full_length = to_boolean (get_property ("tupletFullLength"));
-
- for (vsize i = tuplets_.size (); i--;)
- {
- Rational tsd = tsdmom.main_part_;
-
- if (now.main_part_ >= tuplets_[i].span_stop_)
- {
- if (tuplets_[i].bracket_)
- {
- if (full_length)
- {
- Item *col = unsmob_item (get_property ("currentMusicalColumn"));
-
- tuplets_[i].bracket_->set_bound (RIGHT, col);
- tuplets_[i].number_->set_bound (RIGHT, col);
- }
- else if (!tuplets_[i].bracket_->get_bound (RIGHT))
- {
- tuplets_[i].bracket_->set_bound (RIGHT,
- tuplets_[i].bracket_->get_bound (LEFT));
- tuplets_[i].number_->set_bound (RIGHT,
- tuplets_[i].bracket_->get_bound (LEFT));
- }
- last_tuplets_.push_back (tuplets_[i].bracket_);
- last_tuplets_.push_back (tuplets_[i].number_);
-
- tuplets_[i].bracket_ = 0;
- tuplets_[i].number_ = 0;
- }
-
- if (tsd)
- tuplets_[i].span_stop_ += tsd;
- }
-
- if (now.main_part_ >= tuplets_[i].stop_)
- tuplets_.erase (tuplets_.begin () + i);
- }
}
void
ADD_ACKNOWLEDGER (Tuplet_engraver, note_column);
ADD_TRANSLATOR (Tuplet_engraver,
- /* doc */ "Catch Time_scaled_music and generate appropriate bracket ",
- /* create */ "TupletBracket TupletNumber",
- /* accept */ "time-scaled-music",
- /* read */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength",
+ /* doc */ "Catch TupletSpannerEvent and generate appropriate bracket ",
+ /* create */ "TupletBracket TupletNumber ",
+ /* accept */ "tuplet-spanner-event",
+ /* read */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength ",
/* write */ "");
/*
Create Volta spanners, by reading repeatCommands property, usually
- set by Unfolded_repeat_iterator.
+ set by Volta_repeat_iterator.
*/
class Volta_engraver : public Engraver
{
(types . (layout-instruction general-music))
(iterator-ctor . ,ly:property-unset-iterator::constructor)
))
-
+
+ (PercentEvent
+ . (
+ (description . "Used internally to signal percent repeats.")
+ (types . (general-music event percent-event))
+ ))
+
(PesOrFlexaEvent
. (
(description . "Within a ligature, mark the previous and the
(types . (general-music span-event event trill-span-event))
))
+ (TransposedMusic
+ . (
+ (description . "Music that has been transposed.")
+ (iterator-ctor . ,ly:music-wrapper-iterator::constructor)
+ (start-callback . ,ly:music-wrapper::start-callback)
+ (length-callback . ,ly:music-wrapper::length-callback)
+ (to-relative-callback . ,ly:relative-octave-music::no-relative-callback)
+ (types . (music-wrapper-music general-music transposed-music))
+ ))
+
(TimeScaledMusic
. (
(description . "Multiply durations, as in tuplets.
(iterator-ctor . ,ly:time-scaled-music-iterator::constructor)
(types . (time-scaled-music music-wrapper-music general-music))
))
-
- (TransposedMusic
+
+ (TupletEvent
. (
- (description . "Music that has been transposed.")
- (iterator-ctor . ,ly:music-wrapper-iterator::constructor)
- (start-callback . ,ly:music-wrapper::start-callback)
- (length-callback . ,ly:music-wrapper::length-callback)
- (to-relative-callback . ,ly:relative-octave-music::no-relative-callback)
- (types . (music-wrapper-music general-music transposed-music))
- ))
+ (description . "Used internally to signal where tuplet brackets start and stop.")
+ (types . (tuplet-spanner-event span-event event general-music))
+ ))
(UnrelativableMusic
. (
(music-map (lambda (x) (shift-one-duration-log x shift dot))
music))
+(define-public (make-repeat name times main alts)
+ "create a repeat music expression, with all properties initialized properly"
+ (let ((talts (if (< times (length alts))
+ (begin
+ (ly:warning (_ "More alternatives than repeats. Junking excess alternatives"))
+ (take alts times))
+ alts))
+ (r (make-repeated-music name)))
+ (set! (ly:music-property r 'element) main)
+ (set! (ly:music-property r 'repeat-count) (max times 1))
+ (set! (ly:music-property r 'elements) talts)
+ (if (equal? name "tremolo")
+ (let* ((dot? (zero? (modulo times 3)))
+ (dots (if dot? 1 0))
+ (mult (if dot?
+ (quotient (* times 2) 3)
+ times))
+ (shift (- (ly:intlog2 mult))))
+
+ (if (memq 'sequential-music (ly:music-property main 'types))
+ ;; \repeat "tremolo" { c4 d4 }
+ (let ((children (length (ly:music-property main 'elements))))
+ (if (not (= children 2))
+ (ly:warning (_ "expecting 2 elements for chord tremolo, found ~a") children))
+ (ly:music-compress r (ly:make-moment 1 children))
+ (shift-duration-log r (1- shift) dots))
+ ;; \repeat "tremolo" c4
+ (shift-duration-log r shift dots)))
+ r)))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; clusters.