-1.3.90.jcn1
+1.3.91.uu1
+==========
+
+* RPM .spec fixes.
+
+* italiano.ly
+
+* mudela-book updates by Tom Cato Amundsen.
+
+* Allow lyric hara kiri as well.
+
+* Bugfix: left/right mixup in Side_position_interface::aligned_on_self ()
+
+* rest collision of differing rests.
+
+* Cleanup of Sequential_music_iterator, Simple_music_iterator.
+
+* Unfolded_repeat_iterator now signals repeats using \property
+ repeatCommands. You could override this, eg.
+
+ \property Score.repeatCommands = #'((volta "X") start-repeat)
+
+ will print a |: and a volta bracket saying X. See also
+ input/test/manual-volta.ly
+
+* Volta_engraver, Repeat_acknowledge_engraver: new engravers that are
+controlled by repeatCommands; much cleaner than the Repeat_engraver.
+
+* Junked Repeat_engraver.
+
+1.3.91.jcn1
===========
+* Abort all running spanners when part-combiner combines voices.
+
+1.3.91
+======
* Use S_ISDIR () and check for stat.h.
<tr><td><font size=-1>
<a href="@TOP@Documentation/out-www/NEWS.html">NEWS</a><br>
<a href="@TOP@Documentation/out-www/CHANGES.html">Change Log</a><br>
- <a href="@TOP@Documentation/out-www/faq.html">FAQ</a><br>
+ <a href="http://appel.lilypond.org/wiki/index.php3?LilyPondFaqs">FAQ</a><br>
<a href="@TOP@Documentation/user/out-www/lilypond.html">User manual</a><br>
<a href="@TOP@Documentation/out-www/regression-test.html">Features</a><br>
<a href="http://appel.lilypond.org/lilypond/todo.html">Todo</a><br>
@title LilyPond Regression test
@end ignore
-@node Top, , ,
+@node Top, , , (dir)
@section Introduction
Officially BugFree (tm). This document is intended for finding bugs,
and documenting bugfixes.
+[TODO: revise and completize this. ]
+
+[TODO: should generate out of header fields using ly2dvi?]
+
+
+
@section Notes and rests
Rests. Note that the dot of 8th, 16th and 32nd rests rest should be
@mudelafile{repeat-line-break.ly}
+Auto change piano staff switches voices between up and down staffs
+automatically; rests are switched along with the coming note.
+@mudelafile{auto-change.ly}
@section Lyrics
@mudelafile{non-empty-text.ly}
+
+
+
+@section PianoStaff
+
+
+
@section Global stuff
Breaks can be encouraged and discouraged using @code{\break} and
@mudelafile{break.ly}
-
Markings that are attached to (invisible) barlines are
delicate: the are attached to the rest of the score without the score
knowing it. Consequently, they fall over often.
Rests are entered like notes, with note name `@code{r}@indexcode{r}',
-or `@code{R}@indexcode{R}'. There is also a note name `@code{s}@indexcode{s}',
-which produces a space of the specified duration.
-`@code{R}' is specifically meant for entering parts: the @code{R} rest
-can expand to fill a score with rests, or it can be printed as a
-single multimeasure rest.
+or `@code{R}@indexcode{R}'. There is also a note name
+`@code{s}@indexcode{s}', which produces a space of the specified
+duration. `@code{R}' is specifically meant for entering parts: the
+@code{R} rest can expand to fill a score with rests, or it can be
+printed as a single multimeasure rest.
+
+You can control the expansion by setting the property
+@code{Score.skipBars}. If this is set to true, Lily will not expand
+empty measures, and the multimeasure rests automatically adds the
+appropriate number.
@cindex lyrics expressions
--- /dev/null
+
+\score { \notes {
+ c4
+ \property Score.repeatCommands = #'((volta "93") end-repeat)
+ c4 c4
+ \property Score.repeatCommands = #'((volta #f))
+ c4 c4
+}
+}
}
-Real
-Align_interface::center_on_element (Score_element *me, Axis a)
-{
- Score_element *cent = unsmob_element (me->get_elt_property ("group-center-element"));
-
- if (cent)
- {
- Real r = cent->relative_coordinate (me, a);
- return -r;
- }
- return 0;
-}
-
/*
Hairy function to put elements where they should be. Can be tweaked
from the outside by setting minimum-space and extra-space in its
#include "bar.hh"
#include "score-engraver.hh"
-#include "bar-engraver.hh"
#include "musical-request.hh"
#include "multi-measure-rest.hh"
#include "command-request.hh"
#include "engraver-group-engraver.hh"
#include "warn.hh"
#include "item.hh"
+#include "engraver.hh"
+
+/**
+ generate bars. Either user ("|:"), or default (new measure)
+ */
+class Bar_engraver : public Engraver
+{
+public:
+ Bar_engraver();
+ VIRTUAL_COPY_CONS(Translator);
+ void request_bar (String type_str);
+
+protected:
+ virtual void do_creation_processing ();
+ virtual void do_removal_processing ();
+ virtual void do_process_music();
+ virtual void do_pre_move_processing();
+
+private:
+ void typeset_bar ();
+ void create_bar ();
+
+ Item * bar_p_;
+};
Bar_engraver::Bar_engraver()
{
if (!bar_p_)
{
bar_p_ = new Item (get_property ("basicBarProperties"));
+
+ SCM gl = get_property ("whichBar");
+ if (scm_equal_p (gl, bar_p_->get_elt_property ("glyph")) != SCM_BOOL_T)
+ bar_p_->set_elt_property ("glyph", gl);
+
announce_element (bar_p_, 0);
}
}
{
if (bar_p_)
{
- SCM gl = get_property ("whichBar");
- if (scm_equal_p (gl, bar_p_->get_elt_property ("glyph")) != SCM_BOOL_T)
- bar_p_->set_elt_property ("glyph", gl);
typeset_element (bar_p_);
bar_p_ =0;
}
}
ADD_THIS_TRANSLATOR(Bar_engraver);
-
-
-
{
if (Span_req * c = dynamic_cast<Span_req*>(m))
{
- if (c->span_type_str_ != "beam")
- return false;
-
- Direction d =c->span_dir_;
-
- if (d == STOP && !beam_p_)
+ if (c->span_type_str_ == "abort")
{
- m->origin ()->warning (_ ("can't find start of beam"));
- return false;
+ reqs_drul_[START] = 0;
+ reqs_drul_[STOP] = 0;
+ if (beam_p_)
+ beam_p_->suicide ();
+ beam_p_ = 0;
}
-
- if(d == STOP)
+ else if (c->span_type_str_ == "beam")
{
- SCM m = get_property ("automaticMelismata");
- SCM b = get_property("noAutoBeaming");
- if (to_boolean (m) && to_boolean(b))
+
+ Direction d =c->span_dir_;
+
+ if (d == STOP && !beam_p_)
{
- set_melisma (false);
+ m->origin ()->warning (_ ("can't find start of beam"));
+ return false;
}
- }
- reqs_drul_[d ] = c;
- return true;
+ if(d == STOP)
+ {
+ SCM m = get_property ("automaticMelismata");
+ SCM b = get_property("noAutoBeaming");
+ if (to_boolean (m) && to_boolean(b))
+ {
+ set_melisma (false);
+ }
+ }
+
+ reqs_drul_[d ] = c;
+ return true;
+ }
}
return false;
}
Break_align_engraver::add_column (SCM smob)
{
Score_element * e = unsmob_element (smob);
- Break_align_item::add_element (align_l_,e);
+ Break_align_interface::add_element (align_l_,e);
typeset_element (e);
}
if (!align_l_)
{
align_l_ = new Item (get_property ("basicBreakAlignProperties"));
- Break_align_item::set_interface (align_l_);
+ Break_align_interface::set_interface (align_l_);
announce_element (align_l_,0);
SCM edge_sym = ly_symbol2scm ("Left_edge_item");
Item * edge = new Item (get_property ("leftEdgeBasicProperties"));
+ /*
+ We must have left-edge in the middle. Instrument-names
+ are left to left-edge, so they don't enter the staff.
+ */
+ align_l_->set_elt_property ("self-alignment-X", edge->self_scm ());
+
+
/*
If the element is empty, it will be ignored in the break
alignment stuff.
group->set_parent (align_l_, Y_AXIS);
announce_element (group, 0);
column_alist_ = scm_assoc_set_x (column_alist_, align_name, group->self_scm ());
+
}
Axis_group_interface::add_element (group, item_l);
}
/*
- break-align-item.cc -- implement Break_align_item
+ break-align-item.cc -- implement Break_align_interface
source file of the GNU LilyPond music typesetter
#include "group-interface.hh"
#include "align-interface.hh"
-MAKE_SCHEME_CALLBACK(Break_align_item,before_line_breaking);
+MAKE_SCHEME_CALLBACK(Break_align_interface,before_line_breaking);
SCM
-Break_align_item::before_line_breaking (SCM smob)
+Break_align_interface::before_line_breaking (SCM smob)
{
Score_element* me = unsmob_element (smob);
do_alignment (me);
}
Real
-Break_align_item::alignment_callback (Score_element*c, Axis a)
+Break_align_interface::alignment_callback (Score_element*c, Axis a)
{
assert (a == X_AXIS);
Score_element *par = c->parent_l (a);
if (par && !to_boolean (par->get_elt_property ("break-alignment-done")))\
{
par->set_elt_property ("break-alignment-done", SCM_BOOL_T);
- Break_align_item::do_alignment (par);
+ Break_align_interface::do_alignment (par);
}
return 0.0;
}
+Real
+Break_align_interface::self_align_callback (Score_element *me, Axis a)
+{
+ assert (a == X_AXIS);
+
+ Item* item = dynamic_cast<Item*> (me);
+ Direction bsd = item->break_status_dir();
+ if (bsd == LEFT)
+ {
+ me->set_elt_property ("self-alignment-X", gh_int2scm (RIGHT));
+ }
+
+ return Side_position::aligned_on_self (me, a);
+}
+
void
-Break_align_item::add_element (Score_element*me, Score_element *toadd)
+Break_align_interface::add_element (Score_element*me, Score_element *toadd)
{
toadd->add_offset_callback (alignment_callback, X_AXIS);
Axis_group_interface::add_element (me, toadd);
}
void
-Break_align_item::do_alignment (Score_element *me)
+Break_align_interface::do_alignment (Score_element *me)
{
Item * item = dynamic_cast<Item*> (me);
Item *column = item->column_l ();
- if (item->break_status_dir() == LEFT)
- {
- me->set_elt_property ("self-alignment-X", gh_int2scm (RIGHT));
- }
- else
- {
- me->add_offset_callback (Align_interface::center_on_element, X_AXIS);
- }
Real interline= me->paper_l ()->get_var ("staffspace");
Link_array<Score_element> elems;
void
-Break_align_item::set_interface (Score_element*me)
+Break_align_interface::set_interface (Score_element*me)
{
Align_interface::set_interface (me);
Align_interface::set_axis (me,X_AXIS);
- me->add_offset_callback (Side_position::aligned_on_self, X_AXIS);
+ me->add_offset_callback (Break_align_interface::self_align_callback, X_AXIS);
}
}
else if (Span_req* s = dynamic_cast <Span_req*> (m))
{
- if ((s->span_type_str_ == "crescendo"
+ if (s->span_type_str_ == "abort")
+ {
+ accepted_spanreqs_drul_[LEFT] = 0;
+ accepted_spanreqs_drul_[RIGHT] = 0;
+ if (line_spanner_)
+ line_spanner_->suicide ();
+ line_spanner_ = 0;
+ }
+ else if ((s->span_type_str_ == "crescendo"
|| s->span_type_str_ == "decrescendo"))
{
accepted_spanreqs_drul_[s->span_dir_] = s;
*/
+
+/*
+ Folded repeats are a stupid idea at this point, so we refrain from
+ implementing get_music () and skip ().
+*/
+
#include "folded-repeat-iterator.hh"
#include "repeated-music.hh"
#include "music-list.hh"
alignment-done -- boolean to administrate whether we've done the alignment already (to ensure that the process is done only once)
- group-center-element -- element which will be at the center of the group
- after aligning (when using Align_interface::center_on_element)
+ center-element -- element which will be at the center of the group
+ after aligning (when using
+ Align_interface::center_on_element). The center element should
+ have this object as a reference point.
elements -- to be aligned elements
break-align-symbol -- the index in the spacing table (symbol) of
the to be aligned item.
-
- TODO: remove this as a class, and make interface.
- */
-
-class Break_align_item
+*/
+class Break_align_interface
{
public:
static SCM before_line_breaking (SCM);
static bool has_interface (Score_element*);
static void add_element (Score_element*me, Score_element*add);
static Real alignment_callback (Score_element*, Axis);
+ static Real self_align_callback (Score_element*, Axis);
};
#endif // BREAK_ALIGN_ITEM_HH
#include "lily-proto.hh"
#include "lily-guile.hh"
+
+
+
/*
+ Move rests in note-columns so that they do not collide.
+
properties:
+ read-only
+
+ maximum-rest-count -- kill off rests so we don't more than this
+ number left.
+
+ minimum-distance -- minimum distance between notes and rests.
+
+ read/write
+
elements -- list of elts (both rests and notes) participating in the
collision.
+
+ sets in elements:
+
+ rest-collision -- pointer to self.
+
+
+
+
*/
class Rest_collision // interface
private:
Moment here_mom_;
-
SCM cursor_;
Music_iterator * iter_p_;
+ void next_element ();
void descend_to_child ();
};
self-alignment-X -- real number: -1 = left aligned, 0 = center, 1
right-aligned in X direction.
+
+ Set to an element pointer, if you want that element to be the center.
self-alignment-Y -- like self-alignment-X but for Y axis
*/
class Unfolded_repeat_iterator : public Music_iterator
{
+ void add_repeat_command (SCM);
+
public:
VIRTUAL_COPY_CONS (Music_iterator);
/**
*/
int done_count_;
+ /*
+ are we now busy doing the body?
- /// unfold everything, or do volta?
- bool full_unfold_b_;
-
- /// are we busy doing the body?
+ */
bool do_main_b_;
/** How far have we progressed into the repeat.
This excludes the elt currently being iterated.
*/
- Moment done_mom_;
+ Moment here_mom_;
int alternative_count_i_;
Music_iterator * current_iter_p_;
~Unfolded_repeat_iterator();
Unfolded_repeat_iterator ();
-
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 ();
+ virtual void next_element (bool side_effect);
};
#endif /* UNFOLDED_REPEAT_ITERATOR_HH */
} else if (gh_number_p (sid)) {
yylval.scm = sid;
return NUMBER_IDENTIFIER;
- } else if (Translator_def* tr = unsmob_translator_def (sid)) {
+ } else if (unsmob_translator_def (sid)) {
yylval.scm = sid;
return TRANSLATOR_IDENTIFIER;
} else if (Music * mus =unsmob_music (sid)) {
/**
The name says it all: make multi measure rests
- */
+
+FIXME? The MM rest engraver must be able to see bar lines, so it won't
+work at Voice level. Not a problem in practice, but aesthetically pleasing?
+
+*/
class Multi_measure_rest_engraver : public Engraver
{
public:
else if (state & (UNIRHYTHM | UNISILENCE))
combine_b = true;
+ /*
+ When combining, abort all running spanners
+ */
+ if (combine_b && combine_b != previously_combined_b)
+ {
+#if 0
+ // Urg: Error in unknown function during GC: rogue pointer in heap
+ // Who deletes this 'pointer'?
+ Span_req abort;
+ abort.span_type_str_ = "abort";
+ if (second_iter_p_ && second_iter_p_->ok ())
+ second_translator->try_music (&abort);
+#else
+ Span_req* abort = new Span_req;
+ abort->span_type_str_ = "abort";
+ if (second_iter_p_ && second_iter_p_->ok ())
+ second_iter_p_->try_music (abort);
+#endif
+ }
+
if (combine_b != previously_combined_b)
change_to (second_iter_p_, p->what_str_, (combine_b ? "one" : "two")
+ suffix_);
--- /dev/null
+/*
+ repeat-acknowledge-engraver.cc -- implement Repeat_acknowledge_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+#include "engraver.hh"
+#include "translator-group.hh"
+#include "repeated-music.hh"
+
+
+/*
+ Objective:
+
+ -- set and reset repeatCommands, so Unfolded_repeat_iterator knows
+ where to set variables.
+
+ -- collect information passed by Unfolded_repeat_iterator for
+ Bar_engraver: writes whichBar property. (TODO: check for
+ interactions with timing engraver.)
+
+ */
+class Repeat_acknowledge_engraver : public Engraver
+{
+public:
+ VIRTUAL_COPY_CONS (Translator);
+ Repeat_acknowledge_engraver();
+
+ virtual void do_post_move_processing ();
+ virtual void do_process_music ();
+ virtual void do_creation_processing ();
+};
+
+void
+Repeat_acknowledge_engraver::do_creation_processing ()
+{
+ daddy_trans_l_->set_property ("repeatCommands", SCM_EOL);
+}
+
+
+Repeat_acknowledge_engraver::Repeat_acknowledge_engraver()
+{
+}
+
+void
+Repeat_acknowledge_engraver::do_post_move_processing ()
+{
+ Translator_group * tr = daddy_trans_l_->where_defined (ly_symbol2scm ("repeatCommands"));
+ if (!tr)
+ tr = daddy_trans_l_;
+
+ tr->set_property ("repeatCommands", SCM_EOL);
+}
+
+void
+Repeat_acknowledge_engraver::do_process_music ()
+{
+ SCM cs = get_property ("repeatCommands");
+
+ String s = "";
+ bool start = false;
+ bool end = false;
+ while (gh_pair_p (cs))
+ {
+ SCM command = gh_car (cs);
+ if (command == ly_symbol2scm ("start-repeat"))
+ start = true;
+ else if (command == ly_symbol2scm ("end-repeat"))
+ end = true;
+ cs = gh_cdr (cs);
+ }
+
+ if ( start && end )
+ s = ":|:";
+ else if (start)
+ s = "|:";
+ else if (end)
+ s = ":|";
+
+ if (s != "")
+ {
+ daddy_trans_l_->set_property ("whichBar", ly_str02scm(s.ch_C()));
+ }
+}
+
+
+ADD_THIS_TRANSLATOR(Repeat_acknowledge_engraver);
Request_chord_iterator::get_music (Moment) const
{
SCM s = SCM_EOL;
- if (music_l_)
+ if (last_processed_mom_ < Moment (0))
{
Music_sequence * ms = dynamic_cast<Music_sequence*> (music_l_);
void
Request_chord_iterator::process (Moment m)
{
- if (music_l_)
+ if (last_processed_mom_ < Moment (0))
{
for (SCM s = dynamic_cast<Music_sequence *> (music_l_)->music_list ();
gh_pair_p (s); s = gh_cdr (s))
#include "music-list.hh"
#include "request-chord-iterator.hh"
+/*
+ Invariant for the data structure.
+
+
+ if (gh_pair_p (cursor_))
+ iter_p_->music_l_ == unsmob_music (gh_car (cursor_))
+ else
+ iter_p_ == 0;
+
+ The length of musiclist from start to up to cursor_ (cursor_ not
+ including), is summed
+
+ here_mom_ = sum (length (musiclist [start ... cursor> )) %)
+
+ */
+
+
Sequential_music_iterator::Sequential_music_iterator ()
{
- cursor_ = 0;
- here_mom_ = 0;
+ cursor_ = SCM_EOL;
+ here_mom_ = Moment (0);
+
iter_p_ =0;
}
Sequential_music_iterator::construct_children()
{
cursor_ = dynamic_cast<Music_sequence const*> (music_l_)->music_list ();
-
- while (gh_pair_p (cursor_ ))
+
+ iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (gh_car (cursor_))) : 0;
+ while (iter_p_ && !iter_p_->ok ())
{
- iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
-
- if (iter_p_->ok())
- {
- descend_to_child ();
- return;
- }
-
- delete iter_p_ ;
- iter_p_ =0;
- cursor_ = gh_cdr (cursor_);
+ next_element ();
}
+
+ /*
+ iter_p_->ok () is tautology, but what the heck.
+ */
+ if (iter_p_ && iter_p_->ok())
+ descend_to_child ();
+
+}
+
+
+/*
+ maintain invariants: change cursor, iter and here_mom_ in one fell
+ swoop.
+*/
+void
+Sequential_music_iterator::next_element ()
+{
+ here_mom_ += iter_p_->music_length_mom ();
+ delete iter_p_;
+ cursor_ = gh_cdr (cursor_);
+
+ if (gh_pair_p (cursor_))
+ iter_p_ = get_iterator_p (unsmob_music (gh_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 ();
if (dynamic_cast<Grace_iterator*> (iter_p_))
child_report = child_report->daddy_trans_l_;
if (until < pending_moment ())
return s;
- SCM curs = cursor_;
- Music_iterator * iter = iter_p_->clone ();
- while (1)
+ Sequential_music_iterator * me =
+ dynamic_cast<Sequential_music_iterator*> (clone ());
+ while (me->ok ())
{
- SCM nm = iter->get_music (until - here_mom_);
+ SCM nm = me->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 = gh_cdr (i))
m = m >? unsmob_music (gh_car (i))->length_mom ();
- delete iter;
-
- curs = gh_cdr (curs);
-
- if (!gh_pair_p (curs) || m > Moment (0))
- return s;
+ if (m > Moment (0))
+ break ;
else
- {
- iter = get_iterator_p (unsmob_music (gh_car (curs)));
- }
+ me->next_element ();
}
+ delete me;
+
return s;
}
/*
void
Sequential_music_iterator::skip (Moment until)
{
- while (1)
+ while (ok ())
{
Moment l =iter_p_->music_length_mom ();
if (l >= until - here_mom_)
if (iter_p_->ok ())
return ;
-
- here_mom_ = here_mom_ + l;
- delete iter_p_;
- iter_p_ =0;
-
- cursor_ = gh_cdr (cursor_);
- if (!gh_pair_p (cursor_))
- return ;
- else
- iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
+ next_element ();
}
}
void
Sequential_music_iterator::process (Moment until)
{
- while (1)
+ while (iter_p_)
{
iter_p_->process (until - here_mom_);
if (iter_p_->ok ())
return ;
- here_mom_ += iter_p_->music_length_mom ();
-
descend_to_child ();
- delete iter_p_;
- iter_p_ =0;
-
- cursor_ = gh_cdr (cursor_);
-
- if (!gh_pair_p (cursor_))
- return ;
- else
- {
- delete iter_p_;
- iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
- }
+ next_element ();
}
-
}
Moment
callback that centers the element on itself
*/
Real
-Side_position::aligned_on_self (Score_element *elm, Axis ax)
+Side_position::aligned_on_self (Score_element *me, Axis ax)
{
String s ("self-alignment-");
s += (ax == X_AXIS) ? "X" : "Y";
- SCM align (elm->get_elt_property (s.ch_C()));
+ SCM align (me->get_elt_property (s.ch_C()));
if (gh_number_p (align))
{
- Interval ext(elm->extent (ax));
+ Interval ext(me->extent (ax));
if (ext.empty_b ())
{
}
else
{
- Real lambda = (0.5 + gh_scm2double (align) / 2.0);
+ Real lambda = (0.5 - gh_scm2double (align) / 2.0);
return - (lambda * ext[LEFT] + (1 - lambda) * ext[RIGHT]);
}
}
- else
+ else if (unsmob_element (align))
+ {
+ return - unsmob_element (align)->relative_coordinate (me, ax);
+ }
return 0.0;
}
Moment
Simple_music_iterator::pending_moment ()const
{
- if (music_l_)
+ if (last_processed_mom_ < Moment (0))
return Moment (0);
else
return music_length_mom ();
void
Simple_music_iterator::process (Moment m)
{
-#if 0
/*
- try_music () causes trouble for base classes
- */
- if (music_l_)
- {
- bool b = try_music (music_l_);
- if (!b)
- music_l_->origin ()->warning (_f ("Junking music: `%s'",
- classname (music_l_)));
- }
-#endif
+ don't do try_music (), since it would make the function useless for
+ base classes */
+
skip (m);
}
#include "engraver.hh"
#include "spanner.hh"
-class Slur_engraver :public Engraver {
+class Slur_engraver : public Engraver
+{
Link_array<Span_req> requests_arr_;
Link_array<Span_req> new_slur_req_l_arr_;
Link_array<Score_element> slur_l_stack_;
Link_array<Score_element> end_slur_l_arr_;
void set_melisma (bool);
+
protected:
virtual bool do_try_music (Music*);
virtual void do_process_music ();
public:
VIRTUAL_COPY_CONS (Translator);
-
};
bool
{
if (Span_req *sl = dynamic_cast <Span_req *> (req_l))
{
- if (sl->span_type_str_ != "slur")
- return false;
- new_slur_req_l_arr_.push (sl);
-
- return true;
+ if (sl->span_type_str_ == "abort")
+ {
+ for (int i = 0; i < slur_l_stack_.size (); i++)
+ {
+ slur_l_stack_[i]->suicide ();
+ }
+ slur_l_stack_.clear ();
+ for (int i = 0; i < end_slur_l_arr_.size (); i++)
+ {
+ end_slur_l_arr_[i]->suicide ();
+ }
+ end_slur_l_arr_.clear ();
+ requests_arr_.clear ();
+ new_slur_req_l_arr_.clear ();
+ }
+ else if (sl->span_type_str_ == "slur")
+ {
+ new_slur_req_l_arr_.push (sl);
+ return true;
+ }
}
return false;
}
void
Slur_engraver::do_process_music ()
{
- Link_array<Score_element> start_slur_l_arr_;
+ Link_array<Score_element> start_slur_l_arr;
for (int i=0; i< new_slur_req_l_arr_.size (); i++)
{
Span_req* slur_req_l = new_slur_req_l_arr_[i];
{
index_set_cell (slur->get_elt_property ("attachment"), START, s);
}
- start_slur_l_arr_.push (slur);
+ start_slur_l_arr.push (slur);
requests_arr_.push (slur_req_l);
announce_element (slur, slur_req_l);
}
}
- for (int i=0; i < start_slur_l_arr_.size (); i++)
- slur_l_stack_.push (start_slur_l_arr_[i]);
+ for (int i=0; i < start_slur_l_arr.size (); i++)
+ slur_l_stack_.push (start_slur_l_arr[i]);
}
void
void
Stem_tremolo::set_interface (Score_element *me)
{
+ me->set_interface (ly_symbol2scm ("stem-tremolo"));
+}
+
+bool
+Stem_tremolo::has_interface (Score_element *me)
+{
+ return me->has_interface (ly_symbol2scm ("stem-tremolo"));
}
(c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
+#include <iostream.h>
#include "translator-group.hh"
#include "command-request.hh"
virtual bool do_try_music (Music * );
virtual void do_post_move_processing ();
virtual void do_process_music ();
+ virtual void do_pre_move_processing ();
public:
- String which_bar ();
VIRTUAL_COPY_CONS(Translator);
};
Timing_translator::do_post_move_processing ();
SCM nonauto = get_property ("barNonAuto");
- SCM which = now_mom () ? SCM_UNDEFINED : ly_str02scm ("|");
+
+ SCM which = get_property ("whichBar");
+ if (!gh_string_p (which))
+ which = now_mom () ? SCM_EOL : ly_str02scm ("|");
- if (which == SCM_UNDEFINED && !to_boolean (nonauto))
+ if (!gh_string_p (which) && !to_boolean (nonauto))
{
SCM always = get_property ("barAlways");
if (!measure_position ()
daddy_trans_l_->set_property ("whichBar", which);
}
+void
+Timing_engraver::do_pre_move_processing ()
+{
+ Timing_translator::do_pre_move_processing ();
+ daddy_trans_l_->set_property ("whichBar", SCM_EOL);
+}
+
bool
Timing_engraver::do_try_music (Music*m)
{
*/
void
-Unfolded_repeat_iterator::next_element ()
+Unfolded_repeat_iterator::next_element (bool side_effect)
{
- Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l_);
+ Repeated_music * repmus =dynamic_cast<Repeated_music *> (music_l_);
delete current_iter_p_;
current_iter_p_ =0;
-
+ bool do_repcommands = side_effect && repmus->volta_fold_b_;
+
if (do_main_b_)
{
- done_mom_ += mus->body ()->length_mom ();
+ /*
+ we were busy doing the main body, so
+
+ - go to alternative if we're a volta
+
+ - do something intelligent when we're fully unfolding (fixcomment)
+ */
+
+ here_mom_ += repmus->body ()->length_mom ();
- if (!mus->volta_fold_b_)
+ if (!repmus->volta_fold_b_)
done_count_ ++;
if (gh_pair_p (alternative_cons_))
{
current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
do_main_b_ = false;
+
+ if (repmus->volta_fold_b_)
+ {
+ String repstr = to_str (done_count_ + 1);
+ if (do_repcommands)
+ add_repeat_command (gh_list (ly_symbol2scm ("volta"),
+ gh_str02scm (repstr.ch_C()), SCM_UNDEFINED));
+ }
}
- else if (done_count_ < mus->repeats_i_ && !mus->volta_fold_b_)
+ else if (done_count_ < repmus->repeats_i_ && !repmus->volta_fold_b_)
{
- current_iter_p_ = get_iterator_p (mus->body ());
+ 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.
*/
+
+ /*
+ we're in the alternatives. We move the pointer to the
+ next alternative.
+ */
if (alternative_cons_)
{
- done_mom_ += unsmob_music (gh_car (alternative_cons_))->length_mom ();
+ here_mom_ += unsmob_music (gh_car (alternative_cons_))->length_mom ();
- if (mus->volta_fold_b_ ||
- mus->repeats_i_ - done_count_ < alternative_count_i_)
+ if (repmus->volta_fold_b_ ||
+ repmus->repeats_i_ - done_count_ < alternative_count_i_)
alternative_cons_ = gh_cdr (alternative_cons_);
+ if (do_repcommands)
+ add_repeat_command (gh_list (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED));
+
+
+
/*
we've done the main body as well, but didn't go over the other
increment. */
- if (mus->volta_fold_b_)
+ if (repmus->volta_fold_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_ && gh_pair_p (alternative_cons_))
+ if (done_count_ < repmus->repeats_i_ && gh_pair_p (alternative_cons_))
{
- if (mus->volta_fold_b_)
+ if (do_repcommands)
+ {
+ String repstr = to_str (done_count_ + 1);
+ add_repeat_command (gh_list (ly_symbol2scm ("volta"),
+ gh_str02scm (repstr.ch_C()), SCM_UNDEFINED));
+ add_repeat_command (ly_symbol2scm ("end-repeat"));
+ }
+
+
+ if (repmus->volta_fold_b_)
current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
else
{
- current_iter_p_ = get_iterator_p (mus->body ());
+ current_iter_p_ = get_iterator_p (repmus->body ());
do_main_b_ = true;
}
}
Moment
Unfolded_repeat_iterator::pending_moment () const
{
- return done_mom_ + current_iter_p_->pending_moment ();
+ return here_mom_ + current_iter_p_->pending_moment ();
}
void
}
}
+void
+Unfolded_repeat_iterator::add_repeat_command (SCM what)
+{
+ SCM reps = ly_symbol2scm ("repeatCommands");
+ SCM current_reps = report_to_l ()->get_property(reps);
+
+ Translator_group * where = report_to_l ()->where_defined (reps);
+ if (where
+ && current_reps == SCM_EOL || gh_pair_p (current_reps))
+ {
+ current_reps = gh_cons (what, current_reps);
+ where->set_property (reps, current_reps);
+ }
+}
+
void
Unfolded_repeat_iterator::process (Moment m)
{
if (!m)
{
- Music_iterator *yeah = try_music (music_l_);
- if (yeah)
- set_translator (yeah->report_to_l ());
- else
- music_l_->origin ()->warning ( _("no one to print a volta bracket"));
+ if (dynamic_cast<Repeated_music*> (music_l_)->volta_fold_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_->pending_moment ())
- current_iter_p_->process (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::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
+{
+ 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 = gh_cdr (i))
+ m = m >? unsmob_music (gh_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 * m) const
--- /dev/null
+/*
+ volta-engraver.cc -- implement Volta_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#include "engraver.hh"
+#include "translator-group.hh"
+#include "volta-spanner.hh"
+#include "item.hh"
+#include "note-column.hh"
+#include "bar.hh"
+#include "side-position-interface.hh"
+
+/*
+ Create Volta spanners, by reading repeatCommands property, usually
+ set by Unfolded_repeat_iterator.
+ */
+class Volta_engraver : public Engraver
+{
+public:
+ Volta_engraver();
+ VIRTUAL_COPY_CONS(Translator);
+protected:
+
+ virtual void acknowledge_element (Score_element_info);
+ virtual void do_removal_processing ();
+ virtual void do_pre_move_processing ();
+ virtual void do_process_music ();
+
+ Moment started_mom_;
+ Spanner * volta_span_p_;
+ Spanner* end_volta_span_p_;
+};
+
+ADD_THIS_TRANSLATOR(Volta_engraver);
+
+Volta_engraver::Volta_engraver ()
+{
+ volta_span_p_ = 0;
+ end_volta_span_p_ = 0;
+}
+
+void
+Volta_engraver::do_process_music ()
+{
+ SCM cs = get_property ("repeatCommands");
+
+ SCM str = SCM_EOL;
+ bool end = false;
+ while (gh_pair_p (cs))
+ {
+ SCM c = gh_car (cs);
+
+ if (gh_pair_p (c) && gh_car (c) == ly_symbol2scm ("volta"))
+ {
+ if (gh_cadr (c) == SCM_BOOL_F)
+ end = true;
+ else
+ str = gh_cadr (c);
+ }
+
+ cs = gh_cdr (cs);
+ }
+
+ SCM l (get_property ("voltaSpannerDuration"));
+ Moment now = now_mom ();
+
+ bool early_stop = volta_span_p_ && unsmob_moment (l)
+ &&*unsmob_moment (l) <= now - started_mom_;
+
+ if (end || early_stop)
+ {
+ end_volta_span_p_ = volta_span_p_;
+ volta_span_p_ =0;
+
+ /*
+ maybe do typeset_element () directly?
+ */
+
+ if (!gh_string_p (str))
+ end_volta_span_p_->set_elt_property ("last-volta", SCM_BOOL_T);
+ }
+
+ if (gh_string_p (str))
+ {
+ started_mom_ = now;
+ if (volta_span_p_)
+ {
+ warning (_ ("Already have a volta spanner. Stopping that one prematurely."));
+
+ if (end_volta_span_p_)
+ {
+ warning (_("Also have a stopped spanner. Giving up."));
+
+ return ;
+
+ }
+
+
+ end_volta_span_p_ = volta_span_p_;
+ volta_span_p_ = 0;
+ }
+
+ volta_span_p_ = new Spanner (get_property ("basicVoltaSpannerProperties"));
+ Volta_spanner::set_interface (volta_span_p_);
+ announce_element (volta_span_p_,0);
+ volta_span_p_->set_elt_property ("text", str);
+ }
+}
+
+void
+Volta_engraver::acknowledge_element (Score_element_info i)
+{
+ if (Item* item = dynamic_cast<Item*> (i.elem_l_))
+ {
+ if (Note_column::has_interface (item))
+ {
+ if (volta_span_p_)
+ Volta_spanner::add_column (volta_span_p_,item);
+ if (end_volta_span_p_)
+ Volta_spanner::add_column (end_volta_span_p_,item);
+ }
+ if (Bar::has_interface (item))
+ {
+ if (volta_span_p_)
+ Volta_spanner::add_bar (volta_span_p_, item);
+ if (end_volta_span_p_)
+ Volta_spanner::add_bar(end_volta_span_p_ , item);
+ }
+ }
+}
+
+void
+Volta_engraver::do_removal_processing ()
+{
+ if (volta_span_p_)
+ {
+ typeset_element(volta_span_p_);
+ }
+ if (end_volta_span_p_)
+ {
+ typeset_element (end_volta_span_p_);
+ }
+}
+
+void
+Volta_engraver::do_pre_move_processing ()
+{
+ if (end_volta_span_p_)
+ {
+ Side_position::add_staff_support (end_volta_span_p_);
+
+ typeset_element (end_volta_span_p_ );
+ end_volta_span_p_ =0;
+ }
+}
% with empty ones.
- \consists "Repeat_engraver";
+% \consists "Repeat_engraver";
+ \consists "Volta_engraver";
\consists "Separating_line_group_engraver";
basicVoltaSpannerProperties \push #'padding = #5 % urg, in \pt
basicStaffSymbolProperties \push #'line-count = #1
- \consists "Repeat_engraver";
+% \consists "Repeat_engraver";
+ \consists "Volta_engraver";
\consists "Bar_engraver";
\consists "Time_signature_engraver";
\consists "Staff_symbol_engraver";
\name Score;
+ \consists "Repeat_acknowledge_engraver";
\consists "Timing_engraver";
\consists "Output_property_engraver";
\consists "System_start_delimiter_engraver";
\consists "Mark_engraver";
\consists "Break_align_engraver";
\consists "Spacing_engraver";
-
\consists "Vertical_align_engraver";
\consists "Lyric_phrasing_engraver";
%}
+
+papersizename = \papersize ;
+
paperfile = \papersize + ".ly";
% paperfile = "a4.ly";
\include \paperfile;
#
SCRIPTS = configure aclocal.m4
-README_FILES = DEDICATION COPYING NEWS TODO CHANGES ROADMAP
+README_FILES = DEDICATION COPYING NEWS CHANGES ROADMAP
README_TXT_FILES = AUTHORS.txt README.txt INSTALL.txt
IN_FILES := $(wildcard *.in)
EXTRA_DIST_FILES = dstreamrc lilypond-mode.el vimrc VERSION $(README_FILES) $(SCRIPTS) $(IN_FILES)
MODULE_NAME = midi2ly
SUBDIRS = include
-EXTRA_DIST_FILES += TODO
MODULE_LIBS=$(depth)/flower
HELP2MAN_EXECS = midi2ly
STEPMAKE_TEMPLATES=c++ executable po help2man