* lily/new-lyric-combine-music-iterator.cc (process): new file.
Add a single LyricsVoice to a melody. Melismata may be set
individually.
* input/regression/lyric-combine-new.ly: new file. Demo \newaddlyrics.
* lily/dot-column.cc: add stdio.h
+2004-01-13 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * mf/feta18.mf: design size is 18 not 22.5
+
+ * lily/new-lyric-combine-music-iterator.cc (process): new file.
+ Add a single LyricsVoice to a melody. Melismata may be set
+ individually.
+
+ * input/regression/lyric-combine-new.ly: new file. Demo \newaddlyrics.
+
+ * lily/dot-column.cc: add stdio.h
+
+2004-01-12 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * lily/item.cc: documentation for break-visibility (Thanks, John).
+
2004-01-11 Han-Wen Nienhuys <hanwen@xs4all.nl>
* lily/bar-line.cc (compound_barline): add bartype : (dotted).
\bar ":|" c
\bar ".|" c
\bar ".|." c
-\bar "|."
+\bar "|." c
+\bar ":" c
@end lilypond
For allowing linebreaks, there is a special command,
@example
In this manual: @ref{Repeats}.
-The bar line objects that are created at @internalsref{Staff} level
-are called @internalsref{BarLine}, the bar lines that span staves are
-@internalsref{SpanBar}s.
+Internals: the bar line objects that are created at
+@internalsref{Staff} level are called @internalsref{BarLine}, the bar
+lines that span staves are @internalsref{SpanBar}s.
@cindex bar lines at start of system
@cindex start of system
in every context, and that type is determined by the property
@code{systemStartDelimiter}.
+Examples: @inputfileref{input/test,bar-lines.ly},
+
@node Polyphony
@section Polyphony
@cindex polyphony
public:
void set_infinite (int sign);
- bool infty_b () const
- {
- return sign_ == 2 || sign_ == -2;
- }
+ bool is_infinity () const;
void invert ();
int num () const { return sign_ * num_; }
int den () const { return den_; }
return -1;
else if (r.sign_ > s.sign_)
return 1;
- else if (r.infty_b ())
+ else if (r.is_infinity ())
return 0;
else if (r.sign_ == 0)
return 0;
Rational &
Rational::operator += (Rational r)
{
- if (infty_b ())
+ if (is_infinity ())
;
- else if (r.infty_b ())
+ else if (r.is_infinity ())
{
*this = r;
}
Rational::operator *= (Rational r)
{
sign_ *= ::sign (r.sign_);
- if (r.infty_b ())
+ if (r.is_infinity ())
{
sign_ = sign () * 2;
goto exit_func;
String
Rational::to_string () const
{
- if (infty_b ())
+ if (is_infinity ())
{
String s (sign_ > 0 ? "" : "-" );
return String (s + "infinity");
{
return r.sign ();
}
+
+bool
+Rational::is_infinity () const
+{
+ return sign_ == 2 || sign_ == -2;
+}
--- /dev/null
+\header {
+
+ texidoc = "With the newaddlyrics mechanism, individual lyric lines
+ can be associated with one melody line. For each lyric line, can
+ be tuned whether to follow melismata or not."
+
+}
+
+\score {
+<<
+ \notes \context Voice = "bla" \relative c'' {
+ c2( d4) e4 ( c2 d4) e4
+ }
+ \newaddlyrics "bla" \lyrics \new LyricsVoice { bla ab blob blob }
+ \newaddlyrics "bla"
+ \lyrics \new LyricsVoice {
+ bla
+
+ \property LyricsVoice . ignoreMelismata = ##t
+
+ blob
+
+ %% note: effect of ignoreMelismata delayed one time step.
+ \property LyricsVoice . ignoreMelismata \unset
+ blob
+
+ blob
+ }
+ >>
+ }
"Construct a function that will do CALLBACK and add parentheses.
Example usage:
- \property Voice.NoteHead \\override #'molecule-callback
+ \\property Voice.NoteHead \\override #'molecule-callback
=
#(parenthesize-callback Note_head::brew_molecule)
(c) 1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
-#include <set>
+#include <stdio.h>
#include <map>
#include "dots.hh"
#include "axis-group-interface.hh"
#include "stem.hh"
-using std::set;
-
/*
TODO: let Dot_column communicate with stem via Note_column.
*/
void operator = (Interpretation_context_handle const&);
Interpretation_context_handle (Interpretation_context_handle const&);
Translator_group * report_to () const;
-
+ int get_count () const;
void quit ();
private:
Translator_group * report_to_;
virtual Moment pending_moment () const;
virtual bool ok () const;
+
+ virtual bool run_always () const;
virtual SCM get_pending_events (Moment until)const;
virtual void process (Moment until);
virtual void skip (Moment until);
void add_fresh_group_translator (Translator *trans);
void add_used_group_translator (Translator *trans);
- /// Score_register = 0, Staff_registers = 1, etc)
- Translator_group* get_ancestor (int l=1);
int get_depth () const;
bool is_bottom_translator_b () const;
bool is_removable () const;
void terminate_translator (Translator*r);
Translator *remove_translator (Translator*trans);
void check_removal ();
- // Translator *get_simple_translator (String) const;
Translator_group *find_existing_translator (SCM context_name, String id);
Translator_group *find_create_translator (SCM context_name, String id, SCM ops);
Link_array<Translator_group> path_to_acceptable_translator (SCM alias,
return report_to_;
}
-
+int
+Interpretation_context_handle::get_count ()const
+{
+ return report_to_->iterator_count_ ;
+}
"the outcome of the @code{break-visibility}. This grob property is a\n"
"function taking a direction (-1, 0 or 1) as argument. It returns a\n"
"cons of booleans, signifying whether this grob should be transparent\n"
- "and have no extent.\n",
+ "and have no extent.\n"
+ "\n"
+ "The following variables for break-visibility are predefined:\n"
+ "@example\n"
+ " grob will show: before no after\n"
+ " break break break\n"
+ " all-invisible no no no\n"
+ " begin-of-line-visible no no yes\n"
+ " end-of-line-visible yes no no\n"
+ " all-visible yes yes yes\n"
+ " begin-of-line-invisible yes yes no\n"
+ " end-of-line-invisible no yes yes\n"
+ "@end example\n"
+ ,
"no-spacing-rods break-visibility breakable")
String
Lyric_phrasing_engraver::get_voice_name_for_lyric (Translator_group*tr)
{
+ SCM voice_context = tr->get_property ("associatedVoiceContext");
+ if (Translator *vc = unsmob_translator (voice_context))
+ {
+ return dynamic_cast<Translator_group*> (vc)->id_string_;
+ }
+
SCM voice = tr->get_property ("associatedVoice");
String nm = tr->id_string_;
if (gh_string_p (voice))
Music_iterator::do_quit()
{
}
+
+bool
+Music_iterator::run_always ()const
+{
+ return false;
+}
{"midi", MIDI},
{"name", NAME},
{"new", NEWCONTEXT},
+ {"newaddlyrics", NEWADDLYRICS},
{"notes", NOTES},
{"octave", OCTAVE},
{"once", ONCE},
--- /dev/null
+/*
+new-lyric-combine-iterator.cc -- implement New_lyric_combine_music_iterator
+
+source file of the GNU LilyPond music typesetter
+
+(c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ */
+
+#include "translator-group.hh"
+#include "lyric-combine-music.hh"
+#include "event.hh"
+#include "grob.hh"
+#include "music-iterator.hh"
+
+
+class New_lyric_combine_music_iterator : public Music_iterator
+{
+public:
+ VIRTUAL_COPY_CONS (Music_iterator);
+ New_lyric_combine_music_iterator ();
+ New_lyric_combine_music_iterator (New_lyric_combine_music_iterator const&src);
+ DECLARE_SCHEME_CALLBACK(constructor, ());
+protected:
+ virtual void construct_children ();
+ virtual Moment pending_moment () const;
+ virtual void do_quit();
+ virtual void process (Moment);
+ virtual Music_iterator *try_music_in_children (Music *) const;
+ virtual bool run_always ()const;
+ virtual bool ok () const;
+ virtual void derived_mark () const;
+private:
+ bool start_new_syllable () ;
+
+ Translator_group * lyrics_context_;
+ Translator_group* music_context_;
+ Music_iterator * lyric_iter_;
+};
+
+/*
+ Ugh, why static?
+ */
+static Music *busy_ev;
+static Music *start_ev;
+static Music *melisma_playing_ev;
+
+New_lyric_combine_music_iterator::New_lyric_combine_music_iterator ()
+{
+ lyric_iter_ =0;
+ music_context_ =0;
+ lyrics_context_ = 0;
+ if (!busy_ev)
+ {
+ busy_ev
+ = make_music_by_name (ly_symbol2scm ("BusyPlayingEvent"));
+ start_ev
+ = make_music_by_name (ly_symbol2scm ("StartPlayingEvent"));
+ melisma_playing_ev
+ = make_music_by_name (ly_symbol2scm ("MelismaPlayingEvent"));
+ }
+}
+
+bool
+New_lyric_combine_music_iterator::start_new_syllable ()
+{
+ bool b = music_context_->try_music (busy_ev);
+
+ if (!b)
+ return false;
+
+ if (!to_boolean (lyrics_context_->get_property ("ignoreMelismata")))
+ {
+ bool m = music_context_->try_music (melisma_playing_ev);
+ if (m)
+ return false;
+ }
+
+ return true;
+}
+
+Moment
+New_lyric_combine_music_iterator::pending_moment () const
+{
+ Moment m;
+
+ m.set_infinite (1);
+
+ return m;
+}
+
+bool
+New_lyric_combine_music_iterator::run_always () const
+{
+ return true;
+}
+
+bool
+New_lyric_combine_music_iterator::ok () const
+{
+ return music_context_ && lyric_iter_->ok ();
+}
+
+void
+New_lyric_combine_music_iterator::derived_mark()const
+{
+ if (lyric_iter_)
+ scm_gc_mark (lyric_iter_->self_scm ());
+ if (lyrics_context_)
+ scm_gc_mark (lyrics_context_->self_scm ());
+ if (music_context_)
+ scm_gc_mark (music_context_->self_scm ());
+}
+
+/*
+ ID == "" means accept any ID.
+ */
+Translator_group *
+find_context_below (Translator_group * where,
+ String type, String id)
+{
+ if (where->context_name () == type)
+ {
+ if (id == "" || where->id_string_ == id)
+ return where;
+ }
+
+ Translator_group * found = 0;
+ for (SCM s = where->trans_group_list_;
+ !found && gh_pair_p (s); s = gh_cdr (s))
+ {
+ Translator_group * tr = dynamic_cast<Translator_group*> (unsmob_translator (gh_car (s)));
+
+
+ found = find_context_below (tr, type, id);
+ }
+
+ return found;
+}
+
+
+
+void
+New_lyric_combine_music_iterator::construct_children ()
+{
+ Music *m = unsmob_music (get_music ()->get_mus_property ("element"));
+ lyric_iter_ = unsmob_iterator (get_iterator (m));
+
+ SCM voice_name = get_music ()->get_mus_property ("associated-context");
+
+
+ Translator_group * thread = 0, *voice =0;
+
+ if (gh_string_p (voice_name))
+ {
+ Translator_group *t = report_to ();
+ while (t && t->daddy_trans_)
+ t = t->daddy_trans_;
+
+ voice = find_context_below (t, "Voice", ly_scm2string (voice_name));
+ if (voice)
+ thread = find_context_below (voice, "Thread", "");
+ }
+
+ if (thread)
+ {
+ music_context_ = thread;
+ lyrics_context_ = find_context_below (lyric_iter_->report_to (), "LyricsVoice", "");
+
+ if (lyrics_context_)
+ lyrics_context_->set_property ("associatedVoiceContext", voice->self_scm ());
+ }
+}
+
+void
+New_lyric_combine_music_iterator::process (Moment )
+{
+ if (!music_context_->daddy_trans_)
+ {
+ music_context_ = 0;
+ if (lyrics_context_)
+ lyrics_context_->unset_property (ly_symbol2scm ("associatedVoiceContext"));
+ }
+
+ if (music_context_
+ && start_new_syllable () && lyric_iter_->ok ())
+ {
+ Moment m= lyric_iter_->pending_moment ();
+ lyric_iter_->process (m);
+ }
+}
+
+void
+New_lyric_combine_music_iterator::do_quit ()
+{
+ if (lyric_iter_)
+ lyric_iter_->quit();
+}
+
+New_lyric_combine_music_iterator::New_lyric_combine_music_iterator (New_lyric_combine_music_iterator const & src)
+ : Music_iterator (src)
+{
+ lyric_iter_ = 0;
+
+ if (src.lyric_iter_)
+ lyric_iter_ = src.lyric_iter_->clone ();
+
+ if (lyric_iter_)
+ scm_gc_unprotect_object (lyric_iter_->self_scm());
+
+ music_context_ = src.music_context_;
+ lyric_iter_ = src.lyric_iter_;
+
+
+ assert (false); // shouldn't copy, really.
+}
+
+
+Music_iterator*
+New_lyric_combine_music_iterator::try_music_in_children (Music *m) const
+{
+ return lyric_iter_->try_music (m);
+}
+
+
+IMPLEMENT_CTOR_CALLBACK (New_lyric_combine_music_iterator);
}
else if (m->is_mus_type ("busy-playing-event"))
return note_reqs_.size ();
+ else if (m->is_mus_type ("start-playing-event"))
+ return note_reqs_.size ();
return false;
}
%token ACCEPTS
%token ADDLYRICS
+%token NEWADDLYRICS
%token ALIAS
%token ALTERNATIVE
%token APPLY
scm_gc_unprotect_object ($2->self_scm ());
$$ = l;
}
+ | NEWADDLYRICS string Music {
+ Music*l =MY_MAKE_MUSIC("NewLyricCombineMusic");
+ l->set_mus_property ("element", $3->self_scm ());
+ scm_gc_unprotect_object ($3->self_scm ());
+ $$ = l;
+ l->set_mus_property ("associated-context", $2);
+ }
;
part_combined_music:
while(gh_pair_p (*proc))
{
Music_iterator * i = unsmob_iterator (gh_car (*proc));
- if (i->pending_moment () == until)
+ if (i->run_always ()
+ || i->pending_moment () == until)
{
i->process (until);
}
next.set_infinite (1);
for (SCM s = children_list_; gh_pair_p (s); s = gh_cdr(s))
- next = next <? unsmob_iterator (gh_car (s))->pending_moment () ;
+ {
+ Music_iterator * it = unsmob_iterator (gh_car (s));
+ if (!it-> run_always ())
+ next = next <? it->pending_moment ();
+ }
return next;
}
-
-
bool
Simultaneous_music_iterator::ok () const
{
- return gh_pair_p (children_list_);
+ for (SCM s = children_list_; gh_pair_p (s); s = gh_cdr(s))
+ {
+ Music_iterator * it = unsmob_iterator (gh_car (s));
+ if (!it->run_always ())
+ return true;
+ }
+ return false;
}
Music_iterator*
assert (this_shortest.to_bool());
shortest_in_measure = shortest_in_measure <? this_shortest.main_part_;
}
- else if (!shortest_in_measure.infty_b()
+ else if (!shortest_in_measure.is_infinity ()
&& Item::breakable_b (cols[i]))
{
int j = 0;
programming_error ("Moving backwards in time");
dt = 0;
}
+ else if (dt.main_part_.is_infinity ())
+ {
+ programming_error ("Moving infinitely to future");
+ dt = 0;
+ }
if (!dt.to_bool ())
return;
return (daddy_trans_) ? daddy_trans_->get_depth () + 1 : 0;
}
-Translator_group*
-Translator_group::get_ancestor (int level)
-{
- if (!level || !daddy_trans_)
- return this;
-
- return daddy_trans_->get_ancestor (level-1);
-}
-
void
Translator_group::terminate_translator (Translator*r)
{
input feta-autometric;
% todo change file name
-fet_beginfont("feta", 22.5);
+fet_beginfont("feta", 18);
staffsize#:=17.82pt#;
test:=0;
(grob-property-description 'break-visibility procedure? "a function
that takes the break direction and returns a cons of booleans
containing (TRANSPARENT . EMPTY).
+The following variables are predefined: @code{all-visible},
+@code{begin-of-line-visible}, @code{end-of-line-visible},
+@code{begin-of-line-invisible}, @code{end-of-line-invisible},
+@code{all-invisible}.
")
(grob-property-description 'virga boolean? "is this neume a virga?.")
(internal-class-name . "Event")
(types . (general-music event busy-playing-event))
))
+ (StartPlayingEvent
+ . (
+ (description . "Used internally to signal beginning of notes.")
+
+ (internal-class-name . "Event")
+ (types . (general-music event start-playing-event))
+ ))
(ClusterNoteEvent
. (
(types . (general-music lyric-combine-music))
(iterator-ctor . ,Lyric_combine_music_iterator::constructor)
))
+
+ (NewLyricCombineMusic
+ . (
+ (description . "Align lyrics to the start of notes.
+Syntax @var{\\addlyrics }@var{music} @var{lyrics}.")
+ (internal-class-name . "Music")
+ (length . ,(ly:make-moment 0 1))
+ (types . (general-music lyric-combine-music))
+ (iterator-ctor . ,New_lyric_combine_music_iterator::constructor)
+ ))
(LyricEvent
. (
(translator-property-description 'highStringOne boolean? "Whether the
1st string is the string with highest pitch on the instrument (used by
the automatic string selector).")
+
+(translator-property-description 'ignoreMelismata boolean?
+ "Ignore melismata for this @ref{LyricsVoice}.")
(translator-property-description 'instr markup? "see @code{instrument}")
(translator-property-description 'instrument markup? " If @code{Instrument_name_engraver}
@cindex Instrument_name_engraver
if c == 'Score':
return ''
else:
- return r"\unset \property %s.melismaBusyProperties" % c
+ return r" \property %s.melismaBusyProperties \unset" % c
elif b == 'f':
return r"\property %s.melismaBusyProperties = #'(melismaBusy)" % c