+1.3.141.jcn3
+============
+
+* some mup2ly progress.
+
+* Bugfix: ly2dvi: don't include empty set fo latexheaders, don't use
+python-1.5.2 abspath func.
+
1.3.141.jcn2
============
* Bugfix: lilypond-book: accept \documentclass{article}.
-1.3.141.jcn1
-============
-
* scripts/update-lily.py: fancy source rebuild update tool that we're
probably not going to use on www.lilypond.org. Check it out!
* Bugfix: building of topdocs.
-1.3.140.jcn6
+1.3.141.hwn1
============
+* doco fixes.
+
+* Beat repeats, double measure repeats; removed repeat sign character
+from the font (WARNING: FONT CHANGED).
+
+* cleanups in (de)crescendo code, fixed continued (de)crescendi.
+
+* German chords (Rune Zedler)
+
+1.3.141
+=======
+
* po update.
* Renamed remaining mudela -> lilypond (except for old change logs).
@lilypondfile[printfilename]{dynamics-line.ly}
+@lilypondfile[printfilename]{dynamics-broken-hairpin.ly}
+
@lilypondfile[printfilename]{arpeggio.ly}
@lilypondfile[printfilename]{glissando.ly}
resulting binaries can be found in the subdirectories @file{out/} (which
contain all files generated during compilation).
+
+@section Emacs mode
+
+
+An emacs mode for LilyPond is included with the source archive as
+@file{lilypond-mode.el} and @file{lilypond-font-lock.el}. If you have
+an RPM, it is in @file{/usr/share/doc/lilypond-X/}. You have to install
+it yourself.
+
+Add this to your ~/.emacs or ~/.emacs.el:
+@example
+ (load-library "lilypond-mode.el")
+ (setq auto-mode-alist
+ (cons '("\\.ly$" . LilyPond-mode) auto-mode-alist))
+ (add-hook 'LilyPond-mode-hook (lambda () (turn-on-font-lock)))
+@end example
+
+If you have the latest LilyPond-1.3.x Debian package, LilyPond-mode
+is automatically loaded, so you need not modify your ~/.emacs file.
+
+
@section Configuring for multiple platforms
If you want to build multiple versions of LilyPond with different
@item tetex-devel
@end itemize
+@section SuSE
+
+[TODO: document this]
+
+Install @code{tetex}, @code{te_mpost}, @code{te_kpath}.
+
+
@section Debian GNU/Linux
A Debian package is also available. You may install it easily by using
@titlepage
@title GNU LilyPond
@subtitle The music typesetter
-@author Han-Wen Nienhuys, Jan Nieuwenhuizen, Adrian Mariano, Tom Cato Amundsen
+@author
Copyright @copyright{} 1999--2001 by the authors
@ifinfo
This file documents GNU LilyPond.
-Copyright 1999 Han-Wen Nienhuys, Jan Nieuwenhuizen and Adrian Mariano
+Copyright 1999 Han-Wen Nienhuys, Jan Nieuwenhuizen, Adrian Mariano
+Tom Cato Amundsen.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
* Page layout::
* Sound::
* Music entry::
-* Using LilyPond::
* Interpretation context::
* Syntactic details::
* Lexical details::
@lilypond[fragment,verbatim,center]
c'' \< \! c'' d'' \decr e'' \rced
- < f''1 { s4 \< \! s2 \> \! s4 } >
+ < f''1 { s4 s4 \< \! s4 \> \! s4 } >
@end lilypond
-[BUG in \> ! ]
-
You can also use a text saying @emph{cresc.} instead of hairpins. Here
is an example how to do it:
@end lilypond
+@refbugs
+When using spacer notes to subdivide note dynamics and @code{linewidth =
+-1}, starting a hairpin on the first spacer note (the one coinciding
+with the real note) exposes an embarassing bug.
printed once, and then the pattern is replaced with a special sign.
@lilypond[verbatim,singleline]
- \context Voice { \repeat "percent" 5 { c'1 } }
+ \context Voice { \repeat "percent" 4 { c'4 }
+ \repeat "percent" 2 { c'2 es'2 f'4 fis'4 g'4 c''4 }
+}
@end lilypond
-At present, only repeats of whole measures are supported.
+@refbugs
+
+You can not nest percent repeats, filling in the first measure with
+slashes, and repeating that measure with percents.
@node Rhythmic music
@section Rhythmic music
\score {
<
- \context ChordNamesVoice \scheme
+ \context ChordNames \scheme
\context Staff \scheme
>
}
Here @var{symbol} is a Scheme expression of symbol type, @var{context}
and @var{grobname} are strings and @var{value} is a Scheme expression.
+If you want to be
+Correct nesting of @code{\override}, @code{\set}, @code{\revert} is as
+follows
+
+@example
+\override \set \set \set \set
+\revert
+@end example
+
+This is always correct, but if you know the default value, you can also use
+@example
+\set \set \set \set
+\set @var{to default value}
+@end example
+
+If there is no default (i.e. by default, the grob property is unset),
+then you can use
+@example
+\set \set \set \set \set
+\revert
+@end example
+
+
@refbugs
LilyPond will hang or crash if @var{value} contains cyclic references.
harmless, and can be ignored.
-@c . {Using LilyPond}
-@node Using LilyPond
-@section Using LilyPond
-@cindex Using LilyPond
-@cindex Generating output
-
-@c slaat dit ergens op?
-
-@c direct postscript?
-
-@table @code
-@item plain lilypond
-@example
-lilypond foo.ly
-@end example
-For more information on how to use lilypond see
-@ifnottex
-@ref{Invoking LilyPond}.
-@end ifnottex
-@iftex
-the online manual.
-@end iftex
-
-@item ly2dvi
-Ly2dvi produces titling from @code{\header} fields.
-@example
-ly2dvi foo.ly
-@end example
-For more information on how to use ly2dvi see
-@ifnottex
-@ref{ly2dvi}.
-@end ifnottex
-@iftex
-the online manual.
-@end iftex
-
-@item lilypond-book
-Lilypond-book supports interleaving text and music.
-@example
-lilypond-book foo.doc
-@end example
-For more information on how to use lilypond-book see
-@ifnottex
-@ref{lilypond-book}.
-@end ifnottex
-@iftex
-the online manual.
-@end iftex
-@end table
-
-
-An emacs mode for LilyPond is included with the source archive as
-@file{lilypond-mode.el} and @file{lilypond-font-lock.el}. If you have
-an RPM, it is in @file{/usr/share/doc/lilypond-X/}. You have to install
-it yourself.
-
-Add this to your ~/.emacs or ~/.emacs.el:
-@example
- (load-library "lilypond-mode.el")
- (setq auto-mode-alist
- (cons '("\\.ly$" . LilyPond-mode) auto-mode-alist))
- (add-hook 'LilyPond-mode-hook (lambda () (turn-on-font-lock)))
-@end example
-
-If you have the latest LilyPond-1.3.x Debian package, LilyPond-mode
-is automatically loaded, so you need not modify your ~/.emacs file.
-
-@menu
-* Pre-cooked makefile::
-@end menu
-
-@node Pre-cooked makefile
-@subsection Pre-cooked makefile
-
-@c waar deze info? is uiteindelijk wel handig, schat ik.
-[TODO: cut blabla]
-If you have a big music project, or just a lot of LilyPond input files,
-all generated output from LilyPond, @TeX{} and metafont will clutter
-your working directory. LilyPond comes with a one-size-fits-all
-pre-cooked makefile that helps you manage producing ouptut. It will
-produce all output in @file{out}, generate and track dependencies.
-Also, it helps in preparing your submission to the @ref{Mutopia
-project}.
-
-@file{make/ly.make}
-@example
-mkdir my-project
-cd my-project
-cp /usr/share/lilypond/make/ly.make GNUmakefile
-cp /usr/share/doc/lilypond/examples/input/tutorial/menuet.ly .
-make menuet
-[..]
-Generated out/menuet.ps for target menuet.
-@end example
-
-Type @samp{make help} to see possible targets.
-
-[TODO]
-@file{/usr/share/lilypond/doc/lilypond/examples/input/mutopia-header.ly}
-
-
@node Interpretation context
@section Interpretation context
Music (TM), have a look at the @ref{Mutopia project}.
+
+[TODO figure out what to do with this: ]
+
+@menu
+* Pre-cooked makefile::
+@end menu
+
+@node Pre-cooked makefile
+@subsection Pre-cooked makefile
+
+@c waar deze info? is uiteindelijk wel handig, schat ik.
+[TODO: cut blabla]
+
+If you have a big music project, or just a lot of LilyPond input files,
+all generated output from LilyPond, @TeX{} and metafont will clutter
+your working directory. LilyPond comes with a one-size-fits-all
+pre-cooked makefile that helps you manage producing ouptut. It will
+produce all output in @file{out}, generate and track dependencies.
+Also, it helps in preparing your submission to the @ref{Mutopia
+project}.
+
+@file{make/ly.make}
+@example
+mkdir my-project
+cd my-project
+cp /usr/share/lilypond/make/ly.make GNUmakefile
+cp /usr/share/doc/lilypond/examples/input/tutorial/menuet.ly .
+make menuet
+[..]
+Generated out/menuet.ps for target menuet.
+@end example
+
+Type @samp{make help} to see possible targets.
+
+[TODO]
+@file{/usr/share/lilypond/doc/lilypond/examples/input/mutopia-header.ly}
+
MAJOR_VERSION=1
MINOR_VERSION=3
PATCH_LEVEL=141
-MY_PATCH_LEVEL=jcn2
+MY_PATCH_LEVEL=jcn3
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
--- /dev/null
+
+
+ % < becomes |
+\score {\notes { \context Staff < f''1
+ { s4 \< \! s4 } > }
+
+ \paper { linewidth = -1.; }
+ }
+
--- /dev/null
+\header{
+texidoc = "Broken crescendi should look be open on one side.";
+}
+
+\score { \notes \relative c'' {
+ c1 \< \break \! c1 \> \break \! c1
+ }
+ \paper {
+ linewidth = 10.\cm;
+ }
+}
+
\header{
texidoc=" Dynamics appear below or above the staff. If multiple
dynamics are linked with (de)crescendi, they should be on the same
-line. Isolated dynamics may be forced up or down. ";
+line. Isolated dynamics may be forced up or down.
+ ";
}
--- /dev/null
+\header {
+texidoc = "Measure and beat repeats are supported.";
+}
+
+\score { \notes \relative c' \context Voice { \time 4/4;
+ \repeat "percent" 2 { c2 }
+
+ % the chairman dances
+ \repeat "percent" 2 { g'8 g c, c }
+ \repeat "percent" 4 { b8 b8 }
+ \repeat "percent" 2 { c8 d es f g4 r4 }
+
+ % riff
+ \repeat "percent" 2 { r8. a16 g8. a16 bes8. a16 f8 d | a c8 ~ c8 d8 ~ d8 r8 r4 }
+
+
+
+ }}
%{
-Converted from star.mup with the aid of mup2ly.py
-http://www.Arkkra.com/doc/star.html
-http://www.Arkkra.com/doc/star.ps
+Converted from star.mup with the aid of the old mup2ly.py
+http://www.arkkra.com/doc/star.html
+http://www.arkkra.com/doc/star.ps
%}
--- /dev/null
+\include "german-chords.ly"
+% #(set! german-Bb #t)
+
+ch = \chords { beses1/+beses bes/+bes b/+b bis/+bis ases/+ases as/+as a/+a ais/+ais fisis/+fisis}
+
+
+\score {
+ <
+ \context ChordNames=ch {\ch}
+ \context Staff=st \chords {\ch}
+ >
+ \paper {}
+}
+
\header{
texidoc="
Theads can be traced automagically when they switch staffs by setting
-property @code{followThread}.
+property @code{followVoice}.
";
}
% followThread: connect note heads with line when thread switches staff
fragment = \notes {
\context PianoStaff <
- \property PianoStaff.followThread = ##t
+ \property PianoStaff.followVoice = ##t
\context Staff \context Voice {
c'1
\translator Staff=two
bool continued = broken[Direction (-grow_dir)];
Real height = gh_scm2double (me->get_grob_property ("height"));
Real thick = line * gh_scm2double (me->get_grob_property ("thickness"));
+
+ Real starth, endh;
+ if (grow_dir < 0)
+ {
+ starth = height;
+ endh = continued ? height/2 : 0.0;
+ }
+ else
+ {
+ starth = continued ? height/2 : 0.0;
+ endh = height;
+ }
- const char* type = (grow_dir < 0) ? "decrescendo" : "crescendo";
- SCM hairpin = gh_list (ly_symbol2scm (type),
- gh_double2scm (thick),
- gh_double2scm (width),
- gh_double2scm (height),
- gh_double2scm (continued ? height/2 : 0.0),
- SCM_UNDEFINED);
-
- Box b (Interval (0, width), Interval (-2*height, 2*height));
+ /*
+ TODO: junk this and, make a general
+
+ Lookup::line (XY1, XY2).
+ */
+ SCM hairpin = gh_list (ly_symbol2scm ("hairpin"),
+ gh_double2scm (thick),
+ gh_double2scm (width),
+ gh_double2scm (starth),
+ gh_double2scm (endh),
+ SCM_UNDEFINED);
+
+ Interval yext = 2* height * Interval (-1,1);
+ Box b (Interval (0, width), yext);
Molecule mol (b, hairpin);
mol.translate_axis (broken_left + extra_off[LEFT], X_AXIS);
static Molecule beam (Real, Real, Real) ;
static Molecule dashed_slur (Bezier, Real thick, Real dash) ;
static Molecule blank (Box b) ;
- static Molecule filledbox (Box b) ;
+ static Molecule filledbox (Box b) ;
+ static Molecule repeat_slash( Real w, Real slope, Real th);
};
#endif // LOOKUP_HH
--- /dev/null
+/*
+ percent-repeat-item.hh -- declare Percent_repeat_item_interface
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#ifndef PERCENT_REPEAT_ITEM_HH
+#define PERCENT_REPEAT_ITEM_HH
+
+#include "grob.hh"
+
+class Percent_repeat_item_interface
+{
+public:
+ DECLARE_SCHEME_CALLBACK (beat_slash, (SCM ));
+ DECLARE_SCHEME_CALLBACK (double_percent, (SCM ));
+ static Molecule x_percent (Grob*,int,Real,Real );
+ static Molecule brew_slash (Grob*);
+};
+
+#endif /* PERCENT_REPEAT_ITEM_HH */
+
return m;
}
+/*
+ TODO: should use slope instead? Angle gives nasty rad <-> degree
+ conversions.
+*/
+Molecule
+Lookup::repeat_slash (Real w, Real s, Real t)
+{
+ SCM wid = gh_double2scm (w);
+ SCM sl = gh_double2scm (s);
+ SCM thick = gh_double2scm (t);
+ SCM slashnodot = gh_list (ly_symbol2scm ("repeat-slash"),
+ wid, sl, thick, SCM_UNDEFINED);
+
+ Box b (Interval (0, w + sqrt (sqr(t/s) + sqr (t))),
+ Interval (0, w * s));
+
+ return Molecule (b, slashnodot);
+}
#include "spanner.hh"
#include "staff-symbol-referencer.hh"
#include "text-item.hh"
+#include "percent-repeat-item.hh"
+
void
Multi_measure_rest::set_interface (Grob*me)
SCM
Multi_measure_rest::percent (SCM smob)
{
+
Grob *me = unsmob_grob (smob);
Spanner *sp = dynamic_cast<Spanner*> (me);
Font_metric *musfont = Font_interface::get_default_font (me);
- Molecule r (musfont->find_by_name ("scripts-repeatsign"));
+ Molecule r = Percent_repeat_item_interface::x_percent (me, 1, 0.75, 1.6);
// ugh copy & paste.
#include "spanner.hh"
#include "item.hh"
#include "percent-repeat-iterator.hh"
+#include "bar.hh"
+
+#include "score-engraver.hh"
+#include "translator-group.hh"
/**
This acknowledges repeated music with "percent" style. It typesets
MEASURE,
DOUBLE_MEASURE,
} repeat_sign_type_ ;
-
+
+ Item * beat_slash_;
+ Item * double_percent_;
Spanner * perc_p_;
Spanner * finished_perc_p_;
Item * stem_tremolo_;
perc_p_ = finished_perc_p_ = 0;
repeat_ =0;
stem_tremolo_ = 0;
+
+ beat_slash_ = 0;
+ double_percent_ = 0;
}
bool
stop_mom_ = start_mom_ + Moment (count) * body_length_;
next_moment_ = start_mom_ + body_length_;
- SCM m = get_property ("timeSignatureFraction");
- Moment mlen (1,
- gh_scm2int (gh_cdr (m)));
+ SCM m = get_property ("measureLength");
+ Moment meas_len;
+ if (unsmob_moment (m))
+ meas_len = *unsmob_moment (m);
- if (mlen == body_length_)
+ if (body_length_ < meas_len &&
+ meas_len.mod_rat (body_length_) == Moment (0,0))
repeat_sign_type_ = BEAT;
+ else if (meas_len == body_length_)
+ repeat_sign_type_ = MEASURE;
+ else if (Moment (2)* meas_len == body_length_)
+ {
+ repeat_sign_type_ = DOUBLE_MEASURE;
+ next_moment_ += meas_len ;
+ }
else
{
- mlen *= gh_scm2int (gh_car (m));
- if (mlen == body_length_)
- repeat_sign_type_ = MEASURE;
- else if (Moment (2)* mlen == body_length_)
- repeat_sign_type_ = DOUBLE_MEASURE;
-
- if (repeat_sign_type_ != MEASURE)
- {
- warning (_ ("Don't know yet how to handle this percent repeat."));
- return false;
- }
+ warning (_ ("Don't know how to handle a percent repeat of this length."));
+ return false;
}
repeat_ = rp;
{
if (repeat_sign_type_ == BEAT)
{
- ;
+ beat_slash_ = new Item (get_property ("RepeatSlash"));
+ announce_grob (beat_slash_, repeat_);
}
else if (repeat_sign_type_ == MEASURE)
{
perc_p_->set_bound (LEFT, unsmob_grob (col));
announce_grob (perc_p_, repeat_);
}
+ else if (repeat_sign_type_ == DOUBLE_MEASURE)
+
+ {
+ double_percent_ = new Item (get_property ("DoublePercentRepeat"));
+ announce_grob (double_percent_, repeat_);
+
+ /*
+ forbid breaks on a % line. Should forbid all breaks, really.
+ */
+ Score_engraver * e = 0;
+ Translator * t = daddy_grav_l ();
+ for (; !e && t; t = t->daddy_trans_l_)
+ {
+ e = dynamic_cast<Score_engraver*> (t);
+ }
+ if (!e)
+ programming_error ("No score engraver!");
+ else
+ e->forbid_breaks (); // guh. Use properties!
+ }
next_moment_ = next_moment_ + body_length_;
}
}
+
void
Percent_repeat_engraver::finalize ()
{
typeset_grob (finished_perc_p_);
finished_perc_p_ = 0;
}
+
+ if (beat_slash_)
+ {
+ typeset_grob (beat_slash_);
+ beat_slash_ = 0;
+ }
+
+ if (double_percent_)
+ {
+ typeset_grob (double_percent_);
+ double_percent_ = 0;
+ }
}
void
Percent_repeat_engraver::acknowledge_grob (Grob_info info)
{
+
}
void
Percent_repeat_engraver::start_translation_timestep ()
{
- if (perc_p_ && stop_mom_ == now_mom ())
+ if (stop_mom_ == now_mom ())
{
- finished_perc_p_ = perc_p_;
- typeset_perc ();
+ if (perc_p_)
+ {
+ finished_perc_p_ = perc_p_;
+ typeset_perc ();
+ }
repeat_ = 0;
perc_p_ = 0;
repeat_sign_type_ = UNKNOWN;
--- /dev/null
+/*
+ percent-repeat-item.cc -- implement Percent_repeat_item_interface
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+#include <math.h>
+
+#include "grob.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+#include "font-interface.hh"
+#include "font-metric.hh"
+#include "percent-repeat-item.hh"
+
+
+Molecule
+Percent_repeat_item_interface::brew_slash ( Grob *me)
+{
+ Real slope = gh_scm2double (me->get_grob_property ("slope"));
+ Real wid = 2.0 / slope;
+
+ /*
+ todo: check out if in staff-rule thickness normally.
+ */
+ Real thick = gh_scm2double (me->get_grob_property ("thickness"));
+ Molecule m = Lookup::repeat_slash (wid, slope, thick);
+ m.translate_axis (-m.extent (Y_AXIS).center (), Y_AXIS);
+ return m;
+}
+
+/*
+ todo: use grob props for dot_neg_kern, slash_neg_kern?
+ */
+Molecule
+Percent_repeat_item_interface::x_percent (Grob *me, int count,
+ Real dot_neg_kern,
+ Real slash_neg_kern)
+{
+ Molecule m ;
+ Molecule s = brew_slash (me);
+
+ for (int i = count; i--;)
+ {
+ m.add_at_edge (X_AXIS, RIGHT, s, -slash_neg_kern);
+ }
+ Molecule d1 = Font_interface::get_default_font (me)->find_by_name ("dots-dot");
+ Molecule d2 = d1;
+ d1.translate_axis (0.5, Y_AXIS );
+ d2.translate_axis (-0.5, Y_AXIS);
+
+ m.add_at_edge (X_AXIS, LEFT, d1, -dot_neg_kern);
+ m.add_at_edge (X_AXIS, RIGHT, d2, -dot_neg_kern);
+
+ return m;
+}
+
+MAKE_SCHEME_CALLBACK(Percent_repeat_item_interface,double_percent,1);
+SCM
+Percent_repeat_item_interface::double_percent (SCM grob)
+{
+ Grob *me = unsmob_grob (grob);
+ Molecule m = x_percent (me, 2, 0.75, 1.6);
+ m.translate_axis (- m.extent (X_AXIS).center (), X_AXIS);
+ return m.smobbed_copy ();
+}
+
+MAKE_SCHEME_CALLBACK(Percent_repeat_item_interface,beat_slash,1);
+SCM
+Percent_repeat_item_interface::beat_slash (SCM grob)
+{
+ Grob *me = unsmob_grob (grob);
+ Molecule m = brew_slash (me);
+
+ return m.smobbed_copy ();
+}
+
+
+
+
+
+
+
if (gh_symbol_p (gl) && gl == ly_symbol2scm ("brace")
&& gh_symbol_p (my_gl) && my_gl == ly_symbol2scm ("bracket"))
inf.elem_l_->translate_axis (-1.0, X_AXIS); // ugh
+ else if (gh_symbol_p (gl) && gl == ly_symbol2scm ("bracket")
+ && gh_symbol_p (my_gl) && my_gl == ly_symbol2scm ("bracket"))
+ {
+ inf.elem_l_->translate_axis ( -0.8, X_AXIS); // ugh
+ inf.elem_l_->set_grob_property ("arch-height",
+ gh_double2scm(gh_scm2double(inf.elem_l_->get_grob_property
+ ("arch-height"))+0.5));
+ }
}
}
me->get_grob_property ("bracket-thick"),
SCM_UNDEFINED);
+ /*
+TODO: sort this out.
+
+Another thing:
+In system-start-delimiter.cc I see the line
+
+ Real h = height + 2 * arc_height;
+
+But I really think that you mean
+
+ Real h = height + 2 * arc_width;
+
+(arc_height changes the x-axis-size of arc ; arc_width changes the
+y-axis-size)
+Will not fix it since I'm not sure.
+
+-Rune
+
+ */
Real h = height + 2 * arc_height;
Box b (Interval (0, 1.5), Interval (-h/2, h/2));
Molecule mol (b, at);
}
else if (Beam::has_interface (i.elem_l_))
{
+ /*
+ TODO:
+
+ ugh, superfluous. Should look at
+
+ tuplet -> note-column -> stem -> beam
+
+ to find the beam(s) of a tuplet
+ */
+
for (int j = 0; j < started_span_p_arr_.size (); j++)
if (started_span_p_arr_[j])
Tuplet_bracket::add_beam (started_span_p_arr_[j],i.elem_l_);
--- /dev/null
+
+% german-chords.ly:
+% german/norwegian/danish?
+
+% To get Bb instead of B, use
+% \include "german-chords.ly"
+% #(set! german-Bb #t)
+
+#(define german-Bb #f)
+
+#(define (pitch->chord-name-text-banter pitch)
+ (if (equal? (cdr pitch) '(6 -1))
+ (if german-Bb
+ (cons "B" (accidental->text -1))
+ '("B")
+ )
+ (cons
+ (list-ref '("C" "D" "E" "F" "G" "A" "H") (cadr pitch))
+ (accidental->text (caddr pitch))
+ )
+ )
+ )
+
+
+#(define (pitch->note-name-text-banter pitch)
+ (if (equal? (cdr pitch) '(6 -1))
+ '("b")
+ (cons
+ (string-append
+ (list-ref '("c" "d" "e" "f" "g" "a" "h") (cadr pitch))
+ (if (or (equal? (cadr pitch) 2) (equal? (cadr pitch) 5))
+ (list-ref '( "ses" "s" "" "is" "isis") (+ 2 (caddr pitch)))
+ (list-ref '("eses" "es" "" "is" "isis") (+ 2 (caddr pitch)))
+ )
+ )
+ '()
+ )
+ )
+ )
draw z1..z2..z3..z4..cycle;
fet_endchar;
-fet_beginchar("Repeatsign", "repeatsign", "repeatsign")
- set_char_box(staff_space#, staff_space#, staff_space#, staff_space#);
-
- save dot_diam;
- 2 dot_diam# = staff_space# - stafflinethickness#;
- define_pixels(dot_diam);
-
- penpos1(dot_diam,0);
- z1l=(-b,-d);
- penpos2(dot_diam,0);
- z2r=(w,h);
- filldraw z1l--z2l{right}--z2r{down}--z1r{right}--cycle;
- penlabels (1,2);
-
- pickup pencircle scaled dot_diam;
- draw (-staff_space/2, staff_space/2);
- draw (staff_space/2, -staff_space/2);
-fet_endchar;
-
fet_beginchar("Segno", "segno", "segno")
save thin, thick, ball_diam, darkness, pointheight;
save wd, ht, thick_nibangle, ball_nib_thick;
% round cappings
1 setlinecap
+/euclidean_length
+{
+ 1 copy mul exch 1 copy mul add sqrt
+} bind def
+
/draw_beam % width slope thick
{
2 div /beam_thick exch def
closepath fill
} bind def
-/draw_decrescendo % width height cons thick
-{
- setlinewidth
- /cresc_cont exch def
- /cresc_ht exch def
- /cresc_wd exch def
-
- cresc_wd cresc_cont moveto
- 0 cresc_ht lineto
- stroke
- cresc_wd cresc_cont neg moveto
- 0 cresc_ht neg lineto
- stroke
-} bind def
-
-/draw_crescendo % width height cons thick
-{
- setlinewidth
- /cresc_cont exch def
- /cresc_ht exch def
- /cresc_wd exch def
-
- 0 cresc_cont moveto
- cresc_wd cresc_ht lineto
- stroke
- 0 cresc_cont neg moveto
- cresc_wd cresc_ht neg lineto
- stroke
-} bind def
+/draw_repeat_slash % width slope thick
+{
+ /beamthick exch def
+ /slope exch def
+ /width exch def
+ beamthick beamthick slope div euclidean_length
+ /xwid exch def
+ 0 0 moveto
+ xwid 0 rlineto
+ width slope width mul rlineto
+ xwid neg 0 rlineto
+% width neg width angle sin mul neg rlineto
+ closepath fill
+} bind def
-/lily_distance
-{
- 1 copy mul exch 1 copy mul add sqrt
-} bind def
+/draw_hairpin % width start_h end_h thick
+{
+ setlinewidth
+ /end_h exch def
+ /start_h exch def
+ /wid exch def
+ 0 start_h moveto
+ wid end_h lineto
+ stroke
+ 0 start_h neg moveto
+ wid end_h neg lineto
+ stroke
+} bind def
/draw_tuplet % height gap dx dy thick dir
{
} bind def
% simple, but does it work everywhere?
+% explain ? --hwn
/draw_ez_ball % ch letter_col ball_col font
{
% font
(define (pitch->note-name pitch)
(cons (cadr pitch) (caddr pitch)))
-
-(define (pitch->text pitch)
- (cons
- (make-string 1 (integer->char (+ (modulo (+ (cadr pitch) 2) 7) 65)))
- (if (= (caddr pitch) 0)
+
+(define (accidental->text acc)
+ (if (= acc 0)
'()
(list
(append '(music)
(list (append '((raise . 0.6))
(list
(string-append "accidentals-"
- (number->string (caddr pitch)))))))))))))))
+ (number->string acc))))))))))))
+)
+
+(define (pitch->text pitch)
+ (cons
+ (make-string 1 (integer->char (+ (modulo (+ (cadr pitch) 2) 7) 65)))
+ (accidental->text (caddr pitch))
+ )
+)
;;; Hooks to override chord names and note names,
;;; see input/tricks/german-chords.ly
; staffspace (distances)
(define all-grob-descriptions
- `((Arpeggio . (
+ `(
+ (Accidentals . (
+ (molecule-callback . ,Local_key_item::brew_molecule)
+ (X-offset-callbacks . (,Side_position_interface::aligned_side))
+ (after-line-breaking-callback . ,Local_key_item::after_line_breaking)
+ (direction . -1)
+ (left-padding . 0.2)
+ (right-padding . 0.4)
+ (meta . ,(grob-description "Accidentals" accidentals-interface font-interface side-position-interface))
+ ))
+
+ (Arpeggio . (
(X-extent-callback . ,Arpeggio::width_callback)
(Y-extent-callback . #f)
(molecule-callback . ,Arpeggio::brew_molecule)
(meta . ,(grob-description "Custos" custos-interface staff-symbol-referencer-interface break-aligned-interface) )
))
- (Hairpin . (
- (molecule-callback . ,Hairpin::brew_molecule)
- (thickness . 1.0)
- (height . 0.6666)
- (spacing-procedure . ,Spanner::set_spacing_rods)
- (minimum-length . 2.0)
- (if-text-padding . 1.0)
- (width-correct . -1.0)
-
- (dash-thickness . 1.2)
- (dash-length . 4.0)
- (self-alignment-Y . 0)
- (Y-offset-callbacks . (,Side_position_interface::aligned_on_self))
- (meta . ,(grob-description "Hairpin" hairpin-interface dynamic-interface))
- ))
(DotColumn . (
(axes 0 )
(Y-offset-callbacks . (,Dots::quantised_position_callback ,Staff_symbol_referencer::callback))
(meta . ,(grob-description "Dots" font-interface dots-interface ))
))
+ (DoublePercentRepeat
+ . ((molecule-callback . ,Percent_repeat_item_interface::double_percent)
+ (breakable . #t)
+ (slope . 1.0)
+ (font-family . music)
+ (width . 2.0)
+ (thickness . 0.48)
+ (break-align-symbol . Staff_bar)
+ (visibility-lambda . ,begin-of-line-invisible)
+ (meta . ,(grob-description "DoublePercentRepeat" font-interface percent-repeat-interface))
+ ))
(DynamicText . (
(Y-offset-callbacks . (,Side_position_interface::aligned_on_self))
(axes 1)
(meta . ,(grob-description "HaraKiriVerticalGroup" axis-group-interface hara-kiri-group-interface))
))
-
- (LyricHyphen . (
+ (Hairpin . (
+ (molecule-callback . ,Hairpin::brew_molecule)
(thickness . 1.0)
- (height . 0.4)
- (minimum-length . 0.5)
- (molecule-callback . ,Hyphen_spanner::brew_molecule)
- (Y-extent-callback . ,Grob::point_dimension_callback)
- (meta . ,(grob-description "LyricHyphen" lyric-hyphen-interface ))
+ (height . 0.6666)
+ (spacing-procedure . ,Spanner::set_spacing_rods)
+ (minimum-length . 2.0)
+ (if-text-padding . 1.0)
+ (width-correct . -1.0)
+
+ (dash-thickness . 1.2)
+ (dash-length . 4.0)
+ (self-alignment-Y . 0)
+ (Y-offset-callbacks . (,Side_position_interface::aligned_on_self))
+ (meta . ,(grob-description "Hairpin" hairpin-interface dynamic-interface))
))
(InstrumentName . (
(meta . ,(grob-description "KeySignature" key-signature-interface font-interface break-aligned-interface))
))
- (Accidentals . (
- (molecule-callback . ,Local_key_item::brew_molecule)
- (X-offset-callbacks . (,Side_position_interface::aligned_side))
- (after-line-breaking-callback . ,Local_key_item::after_line_breaking)
- (direction . -1)
- (left-padding . 0.2)
- (right-padding . 0.4)
- (meta . ,(grob-description "Accidentals" accidentals-interface font-interface side-position-interface))
+
+ (LyricHyphen . (
+ (thickness . 1.0)
+ (height . 0.4)
+ (minimum-length . 0.5)
+ (molecule-callback . ,Hyphen_spanner::brew_molecule)
+ (Y-extent-callback . ,Grob::point_dimension_callback)
+ (meta . ,(grob-description "LyricHyphen" lyric-hyphen-interface ))
))
(LineOfScore . (
(PercentRepeat . (
(spacing-procedure . ,Multi_measure_rest::set_spacing_rods)
(molecule-callback . ,Multi_measure_rest::percent)
- (staff-position . 0)
- (expand-limit . 10)
- (padding . 2.0) ; staffspace
+ (slope . 1.0)
+ (thickness . 0.48)
(minimum-width . 12.5) ; staffspace
(font-family . music)
- (meta . ,(grob-description "PercentRepeat" multi-measure-rest-interface font-interface))
+ (meta . ,(grob-description "PercentRepeat" multi-measure-rest-interface font-interface percent-repeat-interface))
))
+ (RepeatSlash . (
+ (molecule-callback . , Percent_repeat_item_interface::beat_slash)
+ (thickness . 0.48)
+ (slope . 1.7)
+ (meta . ,(grob-description "RepeatSlash" percent-repeat-interface))
+ ))
(Rest . (
(after-line-breaking-callback . ,Rest::after_line_breaking)
(X-extent-callback . ,Rest::extent_callback)
;;;; Jan Nieuwenhuizen <janneke@gnu.org>
-; should include default value?
+ ; should include default value?
;;; FIXME: naming.
(define (grob-description name . interfaces)
(let* ((ifs (cons general-grob-interface interfaces))
(props (map caddr ifs))
-; (prop-typep-pairs (map (lambda (x) (cons (car x) (cadr x)))
-; (apply append props)))
+ ; (prop-typep-pairs (map (lambda (x) (cons (car x) (cadr x)))
+ ; (apply append props)))
(syms (map car ifs))
- )
+ )
(list (cons 'separator "\n\n\n") ;easy printing.
(cons 'name name)
(cons 'interfaces syms)
(cons 'interface-descriptions ifs)
- ; (cons 'interface-descriptions (cadr merged))
+ ; (cons 'interface-descriptions (cadr merged))
;; description of the grob itself?
-; (cons 'properties prop-typep-pairs)
- )))
+ ; (cons 'properties prop-typep-pairs)
+ )))
(lily-interface
'(
left-padding
right-padding
- ))
+ ))
'(direction
))
+(lily-interface
+ 'percent-repeat-interface
+ "Repeats that look like percent signs"
+ '(angle thickness))
- (lily-interface
- 'volta-bracket-interface
- "Volta bracket with number"
- '(
- bars
- thickness
- height
- ))
+(lily-interface
+ 'volta-bracket-interface
+ "Volta bracket with number"
+ '(
+ bars
+ thickness
+ height
+ ))
- (lily-interface
- 'span-bar-interface
- "A bar line that spans other barlines (typically used to get cross-staff barlines."
- '(
- ))
+(lily-interface
+ 'span-bar-interface
+ "A bar line that spans other barlines (typically used to get cross-staff barlines."
+ '(
+ ))
(eval (cons
(define (interface-names) (map (lambda (x) (symbol->string (car x))) all-interfaces))
+
(define (char i)
(invoke-char " show" i))
- (define (crescendo thick w h cont )
- (string-append
- (numbers->string (list w h (inexact->exact cont) thick))
- " draw_crescendo"))
+ (define (hairpin thick width starth endh )
+ (string-append
+ (numbers->string (list width starth endh thick))
+ " draw_hairpin"))
+
;; what the heck is this interface ?
(define (dashed-slur thick dash l)
(string-append
" "
(ly-number->string off)
" ] 0 draw_dashed_line"))
-
- (define (decrescendo thick w h cont)
- (string-append
- (numbers->string (list w h (inexact->exact cont) thick))
- " draw_decrescendo"))
-
-
+
+ (define (repeat-slash wid slope thick)
+ (string-append (numbers->string (list wid slope thick))
+ " draw_repeat_slash"))
+
(define (end-output)
"\nshowpage\n")
(define tuplet ,tuplet)
(define bracket ,bracket)
(define char ,char)
- (define crescendo ,crescendo)
+ (define hairpin ,hairpin)
(define volta ,volta)
(define bezier-sandwich ,bezier-sandwich)
(define dashed-line ,dashed-line)
(define dashed-slur ,dashed-slur)
- (define decrescendo ,decrescendo)
(define end-output ,end-output)
(define experimental-on ,experimental-on)
(define filledbox ,filledbox)
(define stem ,stem)
(define stop-line ,stop-line)
(define stop-last-line ,stop-line)
+ (define repeat-slash ,repeat-slash)
(define text ,text)
(define no-origin ,no-origin)
(define define-origin ,define-origin)
(define ez-ball ,ez-ball)
))
+ ((eq? action-name 'repeat-slash) repeat-slash)
((eq? action-name 'tuplet) tuplet)
((eq? action-name 'beam) beam)
((eq? action-name 'bezier-sandwich) bezier-sandwich)
((eq? action-name 'bracket) bracket)
((eq? action-name 'char) char)
- ((eq? action-name 'crescendo) crescendo)
((eq? action-name 'dashed-line) dashed-line)
((eq? action-name 'dashed-slur) dashed-slur)
- ((eq? action-name 'decrescendo) decrescendo)
+ ((eq? action-name 'hairpin) hairpin)
((eq? action-name 'experimental-on) experimental-on)
((eq? action-name 'filledbox) filledbox)
((eq? action-name 'ez-ball) ez-ball)
(define (dashed-slur thick dash l)
(embedded-ps ((ps-scm 'dashed-slur) thick dash l)))
- (define (crescendo thick w h cont)
- (embedded-ps ((ps-scm 'crescendo) thick w h cont)))
+ (define (hairpin thick w sh eh)
+ (embedded-ps ((ps-scm 'hairpin) thick w sh eh)))
(define (char i)
(string-append "\\char" (inexact->string i 10) " "))
(define (dashed-line thick on off dx dy)
(embedded-ps ((ps-scm 'dashed-line) thick on off dx dy)))
- (define (decrescendo thick w h cont)
- (embedded-ps ((ps-scm 'decrescendo) thick w h cont)))
-
(define (font-load-command name-mag command)
(string-append
"\\font\\" command "="
(define (experimental-on)
"")
+ (define (repeat-slash w a t)
+ (embedded-ps ((ps-scm 'repeat-slash) w a t)))
+
(define (font-switch i)
(string-append
"\\" (font i) "\n"))
(define bezier-sandwich ,bezier-sandwich)
(define bracket ,bracket)
(define char ,char)
- (define crescendo ,crescendo)
(define dashed-line ,dashed-line)
(define dashed-slur ,dashed-slur)
- (define decrescendo ,decrescendo)
+ (define hairpin ,hairpin)
(define end-output ,end-output)
(define experimental-on ,experimental-on)
(define filledbox ,filledbox)
(define volta ,volta)
(define define-origin ,define-origin)
(define no-origin ,no-origin)
+ (define repeat-slash ,repeat-slash)
))
((eq? action-name 'beam) beam)
((eq? action-name 'tuplet) tuplet)
((eq? action-name 'bracket) bracket)
- ((eq? action-name 'crescendo) crescendo)
+ ((eq? action-name 'hairpin) hairpin)
((eq? action-name 'dashed-line) dashed-line)
((eq? action-name 'dashed-slur) dashed-slur)
- ((eq? action-name 'decrescendo) decrescendo)
((eq? action-name 'end-output) end-output)
((eq? action-name 'experimental-on) experimental-on)
((eq? action-name 'font-def) font-def)
* dvi from lilypond .tex output? This is hairy, because we create dvi
from lilypond .tex *and* header output.
+ * windows compatibility: rm -rf, cp file... dir
+
'''
os.mkdir (temp_dir, 0777)
except OSError:
pass
-
-
+ os.chdir (temp_dir)
+
+
def system (cmd, ignore_error = 0):
if verbose_p:
progress (_ ("Invoking `%s\'") % cmd)
option_definitions = [
('', 'h', 'help', _ ("this help")),
('KEY=VAL', 's', 'set', _ ("change global setting KEY to VAL")),
+ ('DIR', 'I', 'include', _ ("add DIR to LilyPond\'s search path")),
('', 'P', 'postscript', _ ("generate PostScript output")),
('', 'k', 'keep', _ ("keep all output, and name the directory ly2dvi.dir")),
('', '', 'no-lily', _ ("don't run LilyPond")),
s = s + '\\usepackage{%s}\n' \
% string.join (extra['latexpackages'], ',')
-
- s = s + string.join (extra['latexheaders'], ' ')
+
+ if extra['latexheaders']:
+ s = s + '\\include{%s}\n' \
+ % string.join (extra['latexheaders'], '}\n\\include{')
textheight = ''
if extra['textheight']:
elif o == '--warranty' or o == '-w':
warranty ()
sys.exit (0)
-
-
-include_path = map (os.path.abspath, include_path)
-files = map (os.path.abspath, files)
-outdir = os.path.abspath (outdir)
+
+# On most platforms, this is equivalent to
+#`normpath(join(os.getcwd()), PATH)'. *Added in Python version 1.5.2*
+def compat_abspath (path):
+ return os.path.normpath (os.path.join (os.getcwd (), path))
+
+include_path = map (compat_abspath, include_path)
+files = map (compat_abspath, files)
+outdir = compat_abspath (outdir)
def strip_ly_suffix (f):
(p, e) =os.path.splitext (f)
'''
TODO:
+
+ WIP:lots of stuff
+
'''
import os
sys.stdout.write ('\n')
def progress (s):
- sys.stderr.write (s + '\n')
+ if s[-1] != '\n':
+ s = s + '\n'
+ sys.stderr.write (s)
def warning (s):
sys.stderr.write (_ ("warning: ") + s)
#
def encodeint (i):
- return chr ( i + ord ('A'))
+ return chr (i + ord ('A'))
actab = {-2: 'eses', -1: 'es', 0 : '', 1: 'is', 2:'isis'}
def pitch_to_lily_string (tup):
(o,n,a) = tup
- nm = chr((n + 2) % 7 + ord ('a'))
+ nm = chr((n + 2) % 7 + ord ('a'))
nm = nm + actab[a]
if o > 0:
nm = nm + "'" * o
sys.stderr.write ("\nOrphaned slur")
class Voice:
- def __init__ (self):
+ def __init__ (self, n):
+ self.number = n
self.entries = []
self.chords = []
self.staff = None
self.current_slurs = []
self.slurs = []
+
def toggle_slur (self, id):
for s in self.current_slurs:
self.slurs.append (s)
def last_chord (self):
- return self.chords[-1]
+ if len (self.chords):
+ return self.chords[-1]
+ else:
+ ch = Chord ()
+ ch.basic_duration = 4
+ return ch
+
def add_chord (self, ch):
self.chords.append (ch)
self.entries.append (ch)
+
def add_nonchord (self, nch):
self.entries.append (nch)
def idstring (self):
return 'staff%svoice%s ' % (encodeint (self.staff.number) , encodeint(self.number))
+
def dump (self):
str = ''
- ln = ''
+ if not self.entries:
+ #return '\n'
+ #ugh ugh
+ return '\n%s = {}\n\n' % self.idstring ()
+ ln = ' '
+ one_two = ("One", "Two")
+ if self.staff.voices [1 - self.number].entries:
+ ln = ln + '\\voice%s\n ' % one_two[self.number]
for e in self.entries:
- next = ' ' + e.dump ()
+ next = e.dump ()
if next[-1] == '\n':
- str = str + ln + next
- ln = ''
+ str = str + ln + next + ' '
+ ln = ' '
continue
if len (ln) +len (next) > 72:
str = str+ ln + '\n'
- ln = ''
- ln = ln + next
+ ln = ' '
+ ln = ln + next + ' '
str = str + ln
id = self.idstring ()
- str = '%s = \\notes { \n %s }\n '% (id, str)
+ str = '''%s = \\notes {
+%s
+}
+
+'''% (id, str)
return str
+
def calculate_graces (self):
lastgr = 0
lastc = None
lastc.chord_suffix = lastc.chord_suffix + ' } '
lastgr = c.grace
lastc = c
+
def calculate (self):
self.calculate_graces ()
for s in self.slurs:
's':'soprano',
't':'treble',
'f':'frenchviolin',
- }
+ }
+
class Staff:
- def __init__ (self):
- self.voices = (Voice (), Voice())
+ def __init__ (self, n):
+ # ugh
+ self.voices = (Voice (0), Voice (1))
+
+ # self.voice_idx = 0
self.clef = None
self.instrument = 0
- self.voice_idx = 0
- self.number = None
+ self.number = n
i = 0
- for v in self.voices:
+ for v in self.voices:
v.staff = self
v.number = i
i = i+1
+
def set_clef (self, letter):
clstr = clef_table[letter]
self.voices[0].add_nonchord (Clef (clstr))
- def current_voice (self):
- return self.voices[self.voice_idx]
- def next_voice (self):
- self.voice_idx = (self.voice_idx + 1)%len (self.voices)
+ #def current_voice (self):
+ # return self.voices[self.voice_idx]
+ #
+ #def next_voice (self):
+ # self.voice_idx = (self.voice_idx + 1)%len (self.voices)
def calculate (self):
for v in self.voices:
v.calculate ()
+
def idstring (self):
return 'staff%s' % encodeint (self.number)
+
def dump (self):
str = ''
refs = ''
for v in self.voices:
str = str + v.dump()
- refs = refs + '\\' + v.idstring ()+ ' '
+ refs = refs + '\n \\' + v.idstring ()
- str = str + '\n\n%s = \\context Staff = %s \n < \n %s >\n\n\n'% (self.idstring (), self.idstring (), refs)
+ str = str + '''
+%s = \context Staff = %s <%s
+>
+
+''' % (self.idstring (), self.idstring (), refs)
return str
class Tuplet:
def __init__ (self, filename):
self.parse_function = self.parse_context_music
self.staffs = []
+ self.current_voices = []
self.forced_duration = None
self.last_name = 0
self.last_oct = 0
self.parse (filename)
- def set_staffs (self, number):
- self.staffs = map (lambda x: Staff (), range (0, number))
+ #def set_staffs (self, number):
+ # self.staffs = map (lambda x: Staff (x), range (0, number))
- self.staff_idx = 0
-
- i =0
- for s in self.staffs:
- s.number = i
- i = i+1
-
- def current_staff (self):
- return self.staffs[self.staff_idx]
+ #def current_staff (self):
+ # return self.staffs[self.staff_idx]
- def current_voice (self):
- return self.current_staff ().current_voice ()
+ #def current_voice (self):
+ # return self.current_staff ().current_voice ()
- def next_staff (self):
- self.staff_idx = (self.staff_idx + 1)% len (self.staffs)
+ #def next_staff (self):
+ # self.staff_idx = (self.staff_idx + 1)% len (self.staffs)
+ def parse_compound_location (self, line):
+ colon = string.index (line, ':')
+ s = line[:colon]
+ debug (s)
+ line = line[colon + 1:]
+ debug (line)
+ self.current_voices = []
+ ##self.current_staffs = []
+ map (self.parse_location, string.split (s, '&'))
+ return line
+
+ def parse_location (self, line):
+ m = re.match ('^([-,0-9]+) *([-,0-9]*)', string.lstrip (line))
+
+ def range_list_to_idxs (s):
+
+ # duh
+ def flatten (l):
+ f = []
+ for i in l:
+ for j in i:
+ f.append (j)
+ return f
+
+ def range_to_list (s):
+ if string.find (s, '-') >= 0:
+ debug ('s: ' + s)
+ l = map (string.lstrip,
+ string.split (s, '-'))
+ r = range (string.atoi (l[0]) - 1,
+ string.atoi (l[1]))
+ else:
+ r = (string.atoi (s) - 1,)
+ return r
+
+ ranges = string.split (s, ',')
+ l = flatten (map (range_to_list, ranges))
+ l.sort ()
+ return l
+
+ staff_idxs = range_list_to_idxs (m.group (1))
+ if m.group (2):
+ voice_idxs = range_list_to_idxs (m.group (2))
+ else:
+ voice_idxs = [0]
+ for s in staff_idxs:
+ while s > len (self.staffs) - 1:
+ self.staffs.append (Staff (s))
+ for v in voice_idxs:
+ self.current_voices.append (self.staffs[s].voices[v])
+
def parse_note (self, line):
- name = line[0]
+ # FIXME: 1?
+ oct = 1
+ name = (ord (line[0]) - ord ('a') + 5) % 7
+ # FIXME: does key play any role in this?
alteration = 0
- line = line[1:]
+ line = string.lstrip (line[1:])
while line:
- if line[0] == '#':
+ if len (line) > 1 and line[:2] == '//':
+ line = 0
+ break
+ elif line[0] == '#':
alteration = alteration + 1
elif line[0] == '&':
alteration = alteration - 1
- line = line[1:]
- # shortcut
- line = 0
+ elif line[0] == '+':
+ oct = oct + 1
+ elif line[0] == '-':
+ oct = oct - 1
+ else:
+ skipping (_ ("%s") % line[0])
+ line = string.lstrip (line[1:])
return (oct, name, alteration)
-
def parse_chord (self, line):
- line = string.strip (line)
+ line = string.lstrip (line)
ch = Chord ()
if not line:
- ch = self.current_voice ().last_chord ()
+ ch = self.current_voices[0].last_chord ()
else:
- m = re.match ('([0-9]+)([.]*)', line)
+ m = re.match ('^([0-9]+)([.]*)', line)
if m:
ch.basic_duration = string.atoi (m.group (1))
- line = line[len (m.group (1))-1:]
+ line = line[len (m.group (1)):]
if m.group (2):
ch.basic_duration = len (m.group (2))
- line = line[len (m.group (1))-1:]
- line = string.strip (line)
- m = re.match ('([0-9]+)([.]*)', line)
+ line = line[len (m.group (1)):]
+ else:
+ ch.basic_duration = self.current_voices[0].last_chord ().basic_duration
+
+ line = string.lstrip (line)
+ if len (line) > 1 and line[:2] == '//':
+ line = 0
+ #ugh
+ if not line:
+ duration = ch.basic_duration
+ ch = self.current_voices[0].last_chord ()
+ ch.basic_duration = duration
+
while line:
- c = line[0]
- if line[:1] == 'mr':
+ if len (line) > 1 and line[:2] == '//':
+ line = 0
+ break
+ elif line[:1] == 'mr':
+ ch.multimeasure = 1
+ line = line[1:]
+ elif line[:1] == 'ms':
ch.multimeasure = 1
- line = 0
- elif c in 'abcdefgrs':
- pitch = parse_note (line)
- ch.add_pitches (pitch)
- line = 0
+ line = line[1:]
+ elif line[0] in 'rs':
+ pass
+ elif line[0] in 'abcdefg':
+ pitch = self.parse_note (line)
+ debug ('PITCH: ' + `pitch`)
+ ch.pitches.append (pitch)
+ line = 0
+ break
else:
- progress ( _("skipping: %s") % line)
- line = 0
- self.current_voice ().add_chord (ch)
+ skipping (_ ("%s") % line[0])
+ line = string.lstrip (line[1:])
+ map (lambda x, ch=ch: x.add_chord (ch), self.current_voices)
def parse_voice (self, line):
chords = string.split (line, ';')
self.parse_function = self.parse_context_header
def parse_context_header (self, line):
- sys.stderr.write ('header: ' + line)
+ debug ('header: ' + line)
def init_context_footer (self, line):
self.parse_function = self.parse_context_footer
def parse_context_footer (self, line):
- sys.stderr.write ('footer: ' + line)
+ debug ('footer: ' + line)
def init_context_header2 (self, line):
self.parse_function = self.parse_context_header2
def parse_context_header2 (self, line):
- sys.stderr.write ('header2: ' + line)
+ debug ('header2: ' + line)
def init_context_footer2 (self, line):
self.parse_function = self.parse_context_footer2
def parse_context_footer2 (self, line):
- sys.stderr.write ('footer2: ' + line)
+ debug ('footer2: ' + line)
def init_context_score (self, line):
self.parse_function = self.parse_context_score
def parse_context_score (self, line):
- sys.stderr.write ('score: ' + line)
+ debug ('score: ' + line)
def init_context_staff (self, line):
self.parse_function = self.parse_context_staff
def parse_context_staff (self, line):
- sys.stderr.write ('staff: ' + line)
+ debug ('staff: ' + line)
def init_context_voice (self, line):
self.parse_function = self.parse_context_voice
def parse_context_voice (self, line):
- sys.stderr.write ('voice: ' + line)
+ debug ('voice: ' + line)
def init_context_grids (self, line):
self.parse_function = self.parse_context_line
def parse_context_grids (self, line):
- sys.stderr.write ('grids: ' + line)
+ debug ('grids: ' + line)
def init_context_music (self, line):
self.parse_function = self.parse_context_music
def parse_context_music (self, line):
- sys.stderr.write ('music: ' + line)
- m = re.match ('^([0-9]+):([0-9]*) ', line)
- if m:
- self.staff_idx = string.atoi (m.group (1))
- line = line[len (m.group (1)):]
- if m.group (2):
- self.current_staff ().voice_idx = string.atoi (m.group (2)) - 1
- line = line[len (m.group (2))-1:]
- else:
- self.current_staff ().voice_idx = 0
- self.parse_voice (line)
+ debug ('music: ' + line)
+ line = string.lstrip (line)
+ if line and line[0] in '0123456789':
+ line = string.lstrip (self.parse_compound_location (line))
+ self.parse_voice (line)
else:
- progress ( _("skipping: %s") % line)
+ skipping (_ ("%s") % line)
def parse (self, file):
# shortcut: set to official mup maximum (duh)
# self.set_staffs (40)
lines = open (file).readlines ()
for line in lines:
- m = re.match ('^([a-z2]+)', line)
+ debug ('LINE: ' + line)
+ m = re.match ('^([a-z]+2?)', line)
if m:
word = m.group (1)
if word in contexts:
eval ('self.init_context_%s (line)' % word)
continue
+ else:
+ warning (_ ("no such context: %s") % word)
+ skipping (line)
else:
+ debug ('FUNC: ' + `self.parse_function`)
self.parse_function (line)
for c in self.staffs:
refs = ''
for s in self.staffs:
str = str + s.dump ()
- refs = '\\' + s.idstring() + refs
+ refs = refs + '\n \\' + s.idstring ()
+
+ str = str + '''
- str = str + "\n\n\\score { <\n %s\n > }" % refs
+\score {
+ <%s
+ >
+}
+''' % refs
return str
option_definitions = [
+ ('', 'd', 'debug', _ ("debug")),
('', 'h', 'help', _ ("this help")),
('FILE', 'o', 'output', _ ("write output to FILE")),
('', 'V', 'verbose', _ ("verbose")),
('', 'w', 'warranty', _ ("show warranty and copyright")),
]
-
+debug_p = 0
+def debug (s):
+ if debug_p:
+ progress ('DEBUG: ' + s)
+def skipping (s):
+ if debug_p:
+ progress ('SKIPPING: ' + s)
(sh, long) = getopt_args (__main__.option_definitions)
try:
for opt in options:
o = opt[0]
a = opt[1]
- if o== '--help' or o == '-h':
+ if 0:
+ pass
+ elif o== '--debug' or o == '-d':
+ debug_p = 1
+ elif o== '--help' or o == '-h':
help ()
sys.exit (0)
- if o == '--version' or o == '-v':
+ elif o== '--verbose' or o == '-V':
+ verbose_p = 1
+ elif o == '--version' or o == '-v':
identify ()
sys.exit (0)
- if o == '--output' or o == '-o':
+ elif o == '--output' or o == '-o':
output = a
else:
print o
progress (_ ("Writing %s...") % output)
tag = '%% Lily was here -- automatically converted by %s from %s' % ( program_name, f)
- ly = tag + e.dump ()
+ ly = tag + '\n' + e.dump ()
o = open (output, 'w')
o.write (ly)
str = str[1:]
else:
ch = Chord ()
- self.current_voice().add_chord (ch)
+ self.current_voice().add_chord (ch)
+
+ # what about 's'?
if str[0] <> 'r':
name = (ord (str[0]) - ord('a') + 5) % 7