source file of the GNU LilyPond music typesetter
- (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
-#include "grace-iterator.hh"
+
#include "translator-group.hh"
#include "debug.hh"
#include "sequential-music-iterator.hh"
#include "music-list.hh"
-#include "request-chord-iterator.hh"
+
+/*
+
+ TODO: handling of grace notes is exquisite pain. This handling
+ should be formally specified and then the implementation verified.
+
+*/
+
+/*
+
+ TODO: the grace note handling hasn't been done for skip() and
+ get_music(), meaning that staff-switching and partcombining will be
+ broken with grace notes.
+
+ */
+/*
+
+ TODO: the grace note handling hasn't been done for skip() and
+ get_music(), meaning that staff-switching and partcombining will be
+ broken with grace notes.
+
+ */
/*
Invariant for the data structure.
if (gh_pair_p (cursor_))
- iter_p_->music_l_ == unsmob_music (gh_car (cursor_))
+ iter_p_->music_l_ == unsmob_music (ly_car (cursor_))
else
iter_p_ == 0;
here_mom_ = sum (length (musiclist [start ... cursor>)) %)
*/
-
-
Sequential_music_iterator::Sequential_music_iterator ()
{
cursor_ = SCM_EOL;
here_mom_ = Moment (0);
-
+ grace_fixups_ = 0;
iter_p_ =0;
}
Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src)
: Music_iterator (src)
{
+ grace_fixups_ = src.grace_fixups_;
cursor_ = src.cursor_;
here_mom_ = src.here_mom_;
if (src.iter_p_)
delete iter_p_;
}
+
+/*
+
+
+ if (start_music.grace)
+ here.grace -= start_music.grace
+
+ last
+ if (len
+
+ */
+
+Grace_fixup *
+get_grace_fixups (SCM cursor)
+{
+ Moment here;
+ Moment last (-1);
+ Grace_fixup *head = 0;
+ Grace_fixup **tail = &head;
+
+ for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
+ {
+ Music * mus = unsmob_music (ly_car (cursor));
+ Moment s = mus->start_mom ();
+ Moment l =mus->length_mom () - s;
+
+ if (s.grace_part_)
+ {
+ if (last != Moment (-1))
+ {
+ Grace_fixup *p =new Grace_fixup;
+ p->start_ = last;
+ p->length_ = here - last;
+ p->grace_start_ = s.grace_part_;
+ p->next_ = 0;
+ *tail = p;
+ tail = &(*tail)->next_;
+ }
+
+ here.grace_part_ = s.grace_part_;
+ }
+
+ if (l.to_bool())
+ {
+ last = here;
+ here += l;
+ }
+ }
+ return head;
+}
+
void
Sequential_music_iterator::construct_children ()
{
- cursor_ = dynamic_cast<Music_sequence const*> (music_l_)->music_list ();
+ cursor_ = dynamic_cast<Music_sequence const*> (music_l ())->music_list ();
- iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (gh_car (cursor_))) : 0;
+ iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (ly_car (cursor_))) : 0;
while (iter_p_ && !iter_p_->ok ())
{
next_element ();
}
+ here_mom_ = music_l ()->start_mom ();
+ grace_fixups_ = get_grace_fixups (cursor_);
+
/*
iter_p_->ok () is tautology, but what the heck.
*/
if (iter_p_ && iter_p_->ok ())
descend_to_child ();
-
}
void
Sequential_music_iterator::next_element ()
{
- here_mom_ += iter_p_->music_length_mom ();
+ Moment len =iter_p_->music_length_mom () - iter_p_->music_start_mom ();
+ assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_);
+
+ if (len.main_part_ && grace_fixups_ &&
+ grace_fixups_->start_ == here_mom_)
+ {
+ here_mom_ += grace_fixups_->length_;
+ here_mom_.grace_part_ += grace_fixups_->grace_start_;
+
+ Grace_fixup * n =grace_fixups_->next_;
+ delete grace_fixups_;
+ grace_fixups_ = n;
+ }
+ else if (len.grace_part_ && !len.main_part_)
+ {
+ here_mom_.grace_part_ =0;
+ }
+ else
+ {
+ /*
+ !len.grace_part_ || len.main_part_
+
+ We skip over a big chunk (mainpart != 0). Any starting graces
+ in that chunk should be in len.grace_part_
+
+ */
+ here_mom_ += len;
+ }
+
delete iter_p_;
- cursor_ = gh_cdr (cursor_);
+ cursor_ = ly_cdr (cursor_);
if (gh_pair_p (cursor_))
- iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
+ iter_p_ = get_iterator_p (unsmob_music (ly_car (cursor_)));
else
iter_p_ = 0;
}
move to context of child iterator if it is deeper down in the
hierarchy.
*/
-
void
Sequential_music_iterator::descend_to_child ()
{
Translator_group * child_report = child_report = iter_p_->report_to_l ();
Translator_group * me_report = report_to_l ();
- if (dynamic_cast<Grace_iterator*> (iter_p_))
- child_report = child_report->daddy_trans_l_;
-
Translator_group * c = child_report;
while (c && c != me_report)
{
s = gh_append2 (nm, s);
Moment m = 0;
- for (SCM i = nm; gh_pair_p (i); i = gh_cdr (i))
- m = m >? unsmob_music (gh_car (i))->length_mom ();
-
+ for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
+ {
+ Music *mus=unsmob_music (ly_car (i));
+ m = m >? (mus->length_mom () - mus->start_mom ());
+ }
if (m > Moment (0))
break ;
else
return s;
}
+
+
/*
- Skip events till UNTIL. We don't do any other side effects (such as
- moving descending to child iterator contexts, because they might
- depend on \context specs and \translator changes being executed
-
+ Skip events till UNTIL. We don't do any other side effects such as
+ descending to child iterator contexts, because they might depend on
+ \context specs and \translator changes being executed
+
+ TODO: build support for grace notes here.
*/
void
Sequential_music_iterator::skip (Moment until)
{
while (iter_p_)
{
- iter_p_->process (until - here_mom_);
+ if (grace_fixups_ &&
+ grace_fixups_->start_ == here_mom_
+ && (grace_fixups_->start_ + grace_fixups_->length_
+ + Moment (Rational (0), grace_fixups_->grace_start_) == until))
+ {
+ /*
+ do the stuff/note/rest preceding a grace.
+ */
+ iter_p_->process (iter_p_->music_length_mom ());
+ }
+ else
+ iter_p_->process (until - here_mom_ + iter_p_->music_start_mom ());
/*
if the iter is still OK, there must be events left that have
Moment
Sequential_music_iterator::pending_moment () const
{
- return iter_p_->pending_moment () + here_mom_;
+ Moment cp = iter_p_->pending_moment ();
+
+ /*
+ Fix-up a grace note halfway in the music.
+ */
+ if (grace_fixups_ && here_mom_ == grace_fixups_->start_
+ && grace_fixups_->length_ + iter_p_->music_start_mom () == cp)
+ {
+ return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
+ }
+
+ /*
+ Fix-up a grace note at the start of the music.
+ */
+ return cp + here_mom_ - iter_p_->music_start_mom ();
}