source file of the GNU LilyPond music typesetter
- (c) 1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ (c) 1999--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
-
+/*
+ This is too hairy. Maybe split into subclasses for volta and full
+ unfold?
+
+ */
+#include "music-iterator.hh"
#include "repeated-music.hh"
#include "music-list.hh"
-#include "unfolded-repeat-iterator.hh"
#include "debug.hh"
#include "translator-group.hh"
+/**
+ Iterate repeats. First do body, then alternatives one by one,
+ optionally interspersed by the body.
+ */
+class Unfolded_repeat_iterator : public Music_iterator
+{
+ void add_repeat_command (SCM);
+
+public:
+ VIRTUAL_COPY_CONS (Music_iterator);
+ /**
+ How often have we done the body (assuming bodies are interspersed.)?
+
+ In volta: the number to print in the bracket.
+ */
+ int done_count_;
+ static SCM constructor_cxx_function;
+
+ /*
+ are we now busy doing the body?
+
+ */
+ bool do_main_b_;
+
+ /*
+ are we doing volta's?
+ */
+ bool volta_b_;
+
+ /** How far have we progressed into the repeat.
+ This excludes the elt currently being iterated.
+ */
+ Moment here_mom_;
+ int alternative_count_i_;
+ Music_iterator * current_iter_p_;
+
+ /// pointer to the alternative that will be processed next.
+ SCM alternative_cons_;
+ ~Unfolded_repeat_iterator ();
+ Unfolded_repeat_iterator ();
+ Unfolded_repeat_iterator (Unfolded_repeat_iterator const &);
+protected:
+ virtual void construct_children ();
+ virtual Moment pending_moment () const;
+ virtual void process (Moment);
+ virtual Music_iterator *try_music_in_children (Music *) const;
+ virtual void skip (Moment);
+ virtual SCM get_music (Moment) const;
+
+ virtual bool ok () const;
+ virtual void next_element (bool side_effect);
+};
+
+class Volta_repeat_iterator : public Unfolded_repeat_iterator
+{
+public:
+ Volta_repeat_iterator ();
+ static SCM constructor_cxx_function;
+ VIRTUAL_COPY_CONS (Music_iterator);
+};
+
+
+
Unfolded_repeat_iterator::~Unfolded_repeat_iterator ()
{
delete current_iter_p_;
}
+Unfolded_repeat_iterator::Unfolded_repeat_iterator (Unfolded_repeat_iterator const &src)
+ : Music_iterator (src)
+{
+ done_count_ = src.done_count_;
+ current_iter_p_ = (src.current_iter_p_)? src.current_iter_p_->clone () : 0;
+ do_main_b_ = src.do_main_b_;
+ volta_b_ = src.volta_b_;
+ alternative_count_i_ = src.alternative_count_i_;
+ alternative_cons_ = src.alternative_cons_;
+}
+
Unfolded_repeat_iterator::Unfolded_repeat_iterator ()
{
done_count_ =0;
current_iter_p_ =0;
+ volta_b_ = false;
do_main_b_ = false;
alternative_count_i_ =0;
+ alternative_cons_ = SCM_EOL;
}
/**
*/
void
-Unfolded_repeat_iterator::next_element ()
+Unfolded_repeat_iterator::next_element (bool side_effect)
{
- Repeated_music const* mus =dynamic_cast<Repeated_music const*> (music_l_);
+ Repeated_music * repmus =dynamic_cast<Repeated_music *> (music_l ());
delete current_iter_p_;
current_iter_p_ =0;
-
+ bool do_repcommands = side_effect && volta_b_;
+
if (do_main_b_)
{
- done_mom_ += mus->repeat_body_p_->length_mom ();
+ /*
+ we were busy doing the main body, so
+
+ - go to alternative if we're a volta
- if (full_unfold_b_)
+ - make a :| if there are no alternatives
+
+ - do something intelligent when we're fully unfolding (fixcomment)
+ */
+
+ here_mom_ += repmus->body ()->length_mom ();
+
+ if (!volta_b_)
done_count_ ++;
- if (alternative_cons_l_)
+ if (gh_pair_p (alternative_cons_))
{
- current_iter_p_ = get_iterator_p (alternative_cons_l_->car_);
+ current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
do_main_b_ = false;
+
+ if (volta_b_)
+ {
+ String repstr = to_str (done_count_ + 1) + ".";
+
+ /*
+ we're coming in from main, so we're always on the first repeat.
+ */
+ assert (done_count_ == 0);
+
+ if (done_count_ == 0
+ && alternative_count_i_ < repmus->repeat_count ())
+ {
+ done_count_ += repmus->repeat_count () - alternative_count_i_;
+ repstr = "1.--" + to_str (done_count_ + 1) + ".";
+ }
+
+ if (do_repcommands)
+ add_repeat_command (scm_list_n (ly_symbol2scm ("volta"),
+ ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
+ }
}
- else if (done_count_ < mus->repeats_i_ && full_unfold_b_)
+ else if (volta_b_)
{
- current_iter_p_ = get_iterator_p (mus->repeat_body_p_);
+ add_repeat_command (ly_symbol2scm ("end-repeat"));
+ }
+ else if (done_count_ < repmus->repeat_count ())
+ {
+ current_iter_p_ = get_iterator_p (repmus->body ());
do_main_b_ = true;
}
}
we're not in the main part. So we're either in an alternative, or
we just finished.
*/
- if (alternative_cons_l_)
+
+ /*
+ we're in the alternatives. We move the pointer to the
+ next alternative.
+ */
+ if (alternative_cons_)
{
- done_mom_ += alternative_cons_l_->car_->length_mom ();
+ here_mom_ += unsmob_music (ly_car (alternative_cons_))->length_mom ();
+
+ if (volta_b_ ||
+ repmus->repeat_count () - done_count_ < alternative_count_i_)
+ alternative_cons_ = ly_cdr (alternative_cons_);
+
+ if (do_repcommands)
+ add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED));
- if (!full_unfold_b_ ||
- mus->repeats_i_ - done_count_ < alternative_count_i_)
- alternative_cons_l_ = alternative_cons_l_->next_;
+
/*
we've done the main body as well, but didn't go over the other
increment. */
- if (full_unfold_b_)
+ if (volta_b_)
done_count_ ++;
}
+
+ /*
+ We still have alternatives left, so
+
+ if we're volta: traverse them
+
+ if we're full unfold: go back to main body.
+ */
- if (done_count_ < mus->repeats_i_ && alternative_cons_l_)
+ if (done_count_ < repmus->repeat_count () && gh_pair_p (alternative_cons_))
{
- if (!full_unfold_b_)
- current_iter_p_ = get_iterator_p (alternative_cons_l_->car_);
+ if (do_repcommands)
+ {
+ String repstr = to_str (done_count_ + 1) + ".";
+ add_repeat_command (scm_list_n (ly_symbol2scm ("volta"),
+ ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
+ add_repeat_command (ly_symbol2scm ("end-repeat"));
+ }
+
+
+ if (volta_b_)
+ current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
else
{
- current_iter_p_ = get_iterator_p (mus->repeat_body_p_);
+ current_iter_p_ = get_iterator_p (repmus->body ());
do_main_b_ = true;
}
}
bool
Unfolded_repeat_iterator::ok () const
{
- return current_iter_p_ ;
+ return current_iter_p_;
}
Moment
-Unfolded_repeat_iterator::next_moment () const
+Unfolded_repeat_iterator::pending_moment () const
{
- return done_mom_ + current_iter_p_->next_moment ();
+ return here_mom_ + current_iter_p_->pending_moment ();
}
void
Unfolded_repeat_iterator::construct_children ()
{
- Repeated_music const* mus =dynamic_cast<Repeated_music const*> (music_l_);
- full_unfold_b_ = playback_b_ || (!mus->volta_fold_b_);
+ Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l ());
- alternative_cons_l_ = (mus->alternatives_p_)
- ? mus->alternatives_p_->music_p_list_p_->head_
- : 0;
+ alternative_cons_ = (mus->alternatives ())
+ ? mus->alternatives ()
+ : SCM_EOL;
- for (Cons<Music> *p = alternative_cons_l_; p; p = p->next_)
+ for (SCM p = alternative_cons_; gh_pair_p (p); p = ly_cdr (p))
alternative_count_i_ ++;
- if (mus->repeat_body_p_)
+ if (mus->body ())
{
- current_iter_p_ = get_iterator_p (mus->repeat_body_p_);
+ current_iter_p_ = get_iterator_p (mus->body ());
do_main_b_ = true;
}
- else if (alternative_cons_l_)
+ else if (gh_pair_p (alternative_cons_))
{
- current_iter_p_ = get_iterator_p (alternative_cons_l_->car_);
+ current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
do_main_b_ = false;
}
+
+ while (current_iter_p_ && !current_iter_p_-> ok ())
+ {
+ next_element (true);
+ }
}
+/*
+ TODO: add source information for debugging
+ */
void
-Unfolded_repeat_iterator::do_process_and_next (Moment m)
+Unfolded_repeat_iterator::add_repeat_command (SCM what)
{
- if (!m)
+ SCM reps = ly_symbol2scm ("repeatCommands");
+ SCM current_reps = report_to_l ()->internal_get_property (reps);
+
+ Translator_group * where = report_to_l ()->where_defined (reps);
+ if (where
+ && current_reps == SCM_EOL || gh_pair_p (current_reps))
{
- Music_iterator *yeah = try_music (music_l_);
- if (yeah)
- set_translator (yeah->report_to_l ());
- else
- music_l_->warning ( _("no one to print a volta bracket"));
+ current_reps = gh_cons (what, current_reps);
+ where->internal_set_property (reps, current_reps);
+ }
+}
+
+void
+Unfolded_repeat_iterator::process (Moment m)
+{
+ if (!m.to_bool ())
+ {
+ if (volta_b_)
+ add_repeat_command (ly_symbol2scm ("start-repeat"));
}
while (1)
{
while (!current_iter_p_->ok ())
{
- next_element();
+ next_element (true);
if (!current_iter_p_)
return;
}
- if (m - done_mom_ >= current_iter_p_->next_moment ())
- current_iter_p_->process_and_next (m - done_mom_);
+ if (m - here_mom_ >= current_iter_p_->pending_moment ())
+ current_iter_p_->process (m - here_mom_);
else
return;
}
}
-
+
void
-Unfolded_repeat_iterator::do_print () const
+Unfolded_repeat_iterator::skip (Moment until)
+{
+ while (current_iter_p_)
+ {
+ Moment l =current_iter_p_->music_length_mom ();
+ if (l >= until - here_mom_)
+ current_iter_p_->skip (until - here_mom_);
+
+ if (current_iter_p_->ok ())
+ return ;
+
+ next_element (false);
+ }
+}
+
+SCM
+Unfolded_repeat_iterator::get_music (Moment until)const
{
-#ifndef NPRINT
- DEBUG_OUT << "count " << done_count_ << "done time " << done_mom_ << '\n';
- DEBUG_OUT << "current: ";
- current_iter_p_->print();
-#endif
+ SCM s = SCM_EOL;
+ if (until < pending_moment ())
+ return s;
+
+
+ Unfolded_repeat_iterator * me
+ = dynamic_cast<Unfolded_repeat_iterator*> (this->clone ());
+
+ while (me->ok ())
+ {
+ SCM nm = me->current_iter_p_->get_music (until -
+ me->here_mom_);
+
+ s = gh_append2 (nm, s);
+
+ Moment m = 0;
+ for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
+ m = m >? unsmob_music (ly_car (i))->length_mom ();
+
+ if (m > Moment (0))
+ break ;
+ else
+ me->next_element (false);
+ }
+
+ delete me;
+
+ return s;
}
+
Music_iterator*
-Unfolded_repeat_iterator::try_music_in_children (Music const * m) const
+Unfolded_repeat_iterator::try_music_in_children (Music * m) const
{
return current_iter_p_->try_music (m);
}
+
+IMPLEMENT_CTOR_CALLBACK (Unfolded_repeat_iterator);
+IMPLEMENT_CTOR_CALLBACK (Volta_repeat_iterator);
+
+Volta_repeat_iterator::Volta_repeat_iterator ()
+{
+ volta_b_ = true;
+}