-1.3.122.mb2
+1.3.123.hwn1
+============
+
+* Tutorial fragment on ly2dvi.
+
+* Bugfix: also print path of mismatched .TFM file.
+
+* Some callbacks to allow manipulation of fonts and molecules from
+Scheme. See input/test/molecule-hacking.ly ; allows for a kludged
+"parenthesize notehead" command.
+
+
+1.3.123.mb1
===========
+* Added percussion clef. Note: font updated!
+
+* Bugfix: font style Large works regardless of font-shape.
+
+
+
+1.3.123
+=======
+
* Added macro \turnOff to remove volta brackets or any other
graphical objects, see input/test/volta.ly or mutopia/J.S.Bach/pa.ly
cd $(outdir) && rm -f lilypond && ln -s . lilypond
cd $(outdir) && rm -f lilypond-internals && ln -s . lilypond-internals
cd $(outdir) && $(foreach i, $(LILYPOND_LINKS),\
- rm -f $(i) && ln -s lilypond.html $(i) &&) true
+ rm -f $(i) && ln -s $(i) lilypond.html &&) true
endif
}
@end lilypond
-
-LilyPond is more flexible than some users realise. Han-Wen could be
-very rich.
-
-Just too funny not to include.
-
@example
-@quotation
- I've just entered a request on cosource.com :
-@quotation
- http://www.cosource.com/cgi-bin/cos.pl/wish/info/387
-@end quotation
Here's a copy of my feature request :
@quotation
Your task, if you accept it is to implement a \smarttranspose
notations. Double accidentals should be removed, as well as #E
(-> F), bC (-> B), bF (-> E), #B (-> C).
@end quotation
-@end quotation
-You mean like this. (Sorry 'bout the nuked indentation.)
-Add IMPLEMENT_TYPE_P(Music, "music?"); to music.cc, and presto, done.
-
-That's an easy $ 100; if I'd make $ 200/hour for every hour I worked
-on Lily, I'd be very rich :)
+You mean like this. (Sorry 'bout the nuked indentation.)
@end example
* Introduction:: Introduction
* The first tune:: The first tune
* Lyrics and chords:: Lyrics and chords
+* More movements:: More than one movement in a file
* Piano music:: Piano music
* end of tutorial:: The end
@end menu
There are two things to note here. The format contains musical
concepts like pitches and durations, instead of symbols and positions:
the input format tries to capture the meaning of @emph{music}, and not
-notation. Therefore Second, the format tries to be @emph{context-free}:
+notation. Second, the format tries to be @emph{context-free}:
a note will sound the same regardless of the current time signature,
the key, etc.
description. In other words, LilyPond would be best
described by `music compiler' or `music to notation compiler'.
+
+
+
@node Lyrics and chords
@section Lyrics and chords
@end example
End the score block.
+@node More movements
+@section More movements
+
+You probably ran @file{ly2dvi} on the last example, and ended up with a
+viewable @file{.dvi} file. However, between there are a few steps of
+which LilyPond is only one. To enhance your understanding of what's
+happening under the hood when you run ly2dvi, we explain what programs
+are run.
+
+@code{ly2dvi} is a program that calls a number of programs in sequence.
+The first thing it does, is running LilyPond on the input file. After
+some calculations, lily comes up with a @file{.tex} file. The contents
+of this file are very low-level instructions.
+
+For example, if you'd put the following in a file called
+@file{layout.ly},
+
+@example
+ \header @{ title = "Two miniatures"; @}
+
+ #(set point-and-click #t)
+
+ \paper @{
+ linewidth = -1.0; @}
+
+ \score @{
+ \notes @{ c'4 d'4 @}
+ \header @{
+ opus = "Opus 1.";
+ piece = "Up"; @}
+ @}
+ \score @{
+ \notes @{ d'4 c'4 @}
+ \header @{
+ opus = "Opus 2.";
+ piece = "Down"; @}
+ @}
+@end example
+
+The result should look somewhat like this@footnote{The titling in this
+manual was not generated by ly2dvi, so details will differ.}
+
+@center @strong{Two miniatures}
+@flushright
+ Opus 1.
+@end flushright
+@flushleft
+@var{Up}
+@end flushleft
+@lilypond
+ \score {
+ \notes { c'4 d'4 }
+ \paper {
+ linewidth = -1.0; }
+ }
+@end lilypond
+@flushright
+ Opus 2.
+@end flushright
+@flushleft
+@var{Down}
+@end flushleft
+@lilypond
+ \score {
+ \notes { d'4 c'4 }
+ \paper {
+ linewidth = -1.0; }
+ }
+@end lilypond
+
+This file is produced by ly2dvi in a few stages, with the help of text
+formatting tools. LilyPond produces two output files, @file{layout.tex}
+and @file{layout-1.tex}. They both look like this:
+
+@example
+ ...
+ \placebox@{-5 \outputscale @}%
+ @{ 8.7229 \outputscale @}%
+ @{\magfontWXGEomMMBo\char90 @}%
+
+ \placebox@{-4 \outputscale @}%
+ @{ 81.0647 \outputscale @}%
+ ...
+@end example
+
+@file{ly2dvi} analyses the progress indication that LilyPond spews out,
+and generates a file called @file{layout_ly1.tex}. This file contains
+formatting instructions for the title and page layout. A fragment might
+look like
+@example
+
+ \geometry@{width=540.602362pt,headheight=2mm, ...
+ \renewcommand@{\@@oddfoot@}@{\parbox@{\textwidth@}@{\mbox@{@} ...
+ \begin@{document@}
+ \lilypondtitle@{foo@}%
+ \makelilytitle
+ \input@{ly2dvi.tex@}
+
+@end example
+
+@file{ly2dvi} runs it through LaTeX. LaTeX is a text-formatting system
+built on top of @TeX. It's very popular in the academic world. If LaTeX
+is successful, this will produce a @file{.dvi} file, containing both the
+titling and notes. @code{ly2dvi} completes its task by deleting the two
+temporary files, leaving only @file{layout.dvi}.
+
+@example
+ #(set point-and-click #t)
+@end example
+
+Editing input files can be quite complicated if you're working with
+large files: if you're digitizing existing music, you have to
+synchronize the .ly file, the sheet music on your lap and the sheet
+music on the screen. The point-and-click mechanism makes it easy to
+find the origin of an error in the .ly file: @footnote{This feature is
+presently only available on X-windows using a patched version of xdvi
+and emacs} when you view the file with Xdvi and click on a note using
+control-right button, [checkme], you editor will jump to the spot where
+that note was entered.
+
+More information is in in @ref{Point and click}
+
+@example
+ \paper @{
+@end example
+
+The @code{\score} blocks that follow in the file, don't have
+@code{\paper} sections, so the settings of this block are substituted: A
+paper block, at top-level, i.e. not in a @code{\score} block sets the
+default page layout.
+
+@example
+ linewidth = -1.0; @}
+@end example
+
+
+
+The variable @code{linewidth} normally sets the length of the systems on
+the page. However, a negative value has a special meaning here. If
+@code{linewidth} is less than 0, no line breaks are inserted into the
+score, and the spacing is set to natural length: a short phrase takes up
+little space, a longer phrase more space.
+
+@example
+ \score @{
+ \notes @{ c'4 d'4 @}
+@end example
+
+In previous examples, notes were specified in relative octaves,
+i.e. each note was put in the octave that would put it closest to its
+predecessor. Besides relative, there is also absolute octave
+specification, and it is turned on by default. In this input mode, the
+central C is denoted by @code{c'}. Going down, you get @code{c}
+@code{c,} @code{c,,} etc. Going up, you get @code{c''} @code{c'''} etc.
+
+When you're copying music from existing sheet music, relative octaves
+are probably the easiest to use: it's less typing work and errors are
+easily spotted. However, if you write LilyPond input, either by hand
+(ie. composing) or by computer, absolute octaves is probably less work.
+
+
+@example
+ \header @{
+@end example
+
+The @code{\header} is normally at the top of the file, where it sets
+values for the rest of the file. If you want to typeset different pieces
+from one file (eg. if there are multiple movements, or if you're making
+a etude-book), you can put different @code{\score}
+blocks into the input file. ly2dvi will assemble all LilyPond
+output files into a big document. The contents of \header blocks
+specified within each score, are used for the titling of each movement.
+@example
+ opus = "Opus 1.";
+ piece = "Up"; @}
+@end example
+For example, the Opus number is put at the right, and the piece string
+will be at the left.
+
+
+
@node Piano music
@section Piano music
PACKAGE_NAME=LilyPond
MAJOR_VERSION=1
MINOR_VERSION=3
-PATCH_LEVEL=123
-MY_PATCH_LEVEL=jcn1
+PATCH_LEVEL=124
+MY_PATCH_LEVEL=
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
\notes\relative c''{
\stemUp
a-"text"
- b-\textscript #"texta"
- c-\textscript #'(bold "textb")
+ b-#"texta"
+ c-#'(bold "textb")
- d-\textscript #'(lines "one" "two" "three")
- e-\textscript #'(lines (bold "one")
+ d-#'(lines "one" "two" "three")
+ e-#'(lines (bold "one")
(rows "and" "there" "is" ((font-family . number) "2"))
(italic "three"))
- f-\textscript #'(finger "3")
- g-\textscript #'(music (named "noteheads-2" "flags-u3"))
+ f-#'(finger "3")
+ g-#'(music (named "noteheads-2" "flags-u3"))
b-#'(rows "a" ((kern . 3) ((raise . 2) "b")) "c")
c-#'(rows "1" ((kern . -3) ((raise . -2) "2")) "3")
--- /dev/null
+
+\header { texidoc=" You can write molecule callbacks in Scheme, thus
+providing custom glyphs for notation elements. A simple example is
+adding parentheses to existing molecule callbacks.
+
+The parenthesized beam is less successful due to implementation of the
+Beam.
+";
+
+ }
+
+#(define (parenthesize-callback callback)
+ "Construct a function that will do CALLBACK and add parentheses.
+Example usage:
+
+ \property Voice.NoteHead \\override #'molecule-callback
+ =
+ #(parenthesize-callback Note_head::brew_molecule)
+
+"
+
+
+ (define (parenthesize-molecule grob)
+ "This function adds parentheses to the original callback for
+GROB. The dimensions of the molecule is not affected.
+"
+
+ (let* (
+ (fn (ly-get-default-font grob))
+ (pclose (ly-find-glyph-by-name fn "accidentals-)"))
+ (popen (ly-find-glyph-by-name fn "accidentals-("))
+ (subject (callback grob))
+
+ ;; remember old size
+ (subject-dims (ly-get-molecule-extent subject 0))
+ )
+
+ ;; add parens
+ (set! subject
+ (ly-combine-molecule-at-edge
+ (ly-combine-molecule-at-edge subject 0 1 pclose 0.2)
+ 0 -1 popen 0.2))
+
+ ;; revert old size.
+ (ly-set-molecule-extent! subject 0 subject-dims)
+ subject
+ )
+ )
+ parenthesize-molecule
+ )
+
+
+
+\score {
+ \notes \relative c' { c4 e
+
+ \property Voice.NoteHead \override #'molecule-callback
+ =
+ #(parenthesize-callback Note_head::brew_molecule)
+ g bes
+ \property Voice.NoteHead \revert #'molecule-callback
+ \property Voice.Beam \override #'molecule-callback
+ =
+ #(parenthesize-callback Beam::brew_molecule)
+
+ a8 gis8 a2.
+
+ }
+
+ \paper { linewidth = -1.; }
+ }
+
\score{
\context RhythmicStaff {
\notes\relative c''{
+ \clef percussion;
\time 4/4;
r4 r g2 | r4 g r2 | g1:32 | r1 |
}
}
+ \paper{
+ \translator{
+ \RhythmicStaffContext
+ \consists "Clef_engraver"; % Doesn't work!?
+ }
+ }
}
--- /dev/null
+\version "1.3.123";
+
+%
+% Test font selection and scm text markup
+%
+
+\score{
+ \notes\relative c''{
+ c'1^#'(rows (dynamic "p") " ma sosten.")
+ c^#'(bold "ABCD")
+ c^#'(rows "Dal " (music "scripts-segno"))
+ c^#'(Large "ABCD")
+ \break
+ \property Voice . TextScript \override #'font-shape = #'upright
+ c1^#'(rows (dynamic "p") " ma sosten.")
+ c^#'(bold "ABCD")
+ \property Voice . TextScript \override #'font-series = #'bold
+ c^#'(rows "Dal " (music "scripts-segno"))
+ c^#'(Large "ABCD")
+ }
+}
--- /dev/null
+
+voltaCommands = \notes {
+ s1 \property Staff.repeatCommands = #((volta . "1"))
+ c4 c4 c4 c4
+ s1
title = "The river is flowing";
composer = "Traditonal (?)";
}
+
\include "paper16.ly"
+
melody = \notes \relative c' {
\partial 8;
g8 |
--- /dev/null
+ \header {
+ title = "Two miniatures";
+ }
+
+ #(set point-and-click #t)
+
+ \paper { linewidth = -1.0; }
+
+ \score {
+ \notes { c'4 d'4 }
+ \header {
+ opus = "Opus 1.";
+ piece = "Up";
+ }
+ }
+
+ \score {
+ \notes { d'4 c'4 }
+ \header {
+ opus = "Opus 2.";
+ piece = "Down";
+ }
+ }
if (tfm->info_.checksum != afm->checksum_)
{
- String s = _f ("checksum mismatch for font file: `%s'", path.ch_C ());
- s += _f ("does not match: `%s'", tfm->path_.ch_C()); // FIXME
+ String s = _f ("checksum mismatch for font file:\n`%s'", path.ch_C ());
+ s += " " + _f ("does not match: `%s'", tfm->path_.ch_C()); // FIXME
s += "\n";
s += " TFM: " + to_str ((int) tfm->info_.checksum);
s += " AFM: " + to_str ((int) afm->checksum_);
scm_unprotect_object (val);
}
-
+
return
dynamic_cast<Tex_font_metric*> (unsmob_metrics (val));
}
return leftbeams;
}
+/*
+ TODO: it would be nice to introduce y-position via callbacks.
+ */
+
MAKE_SCHEME_CALLBACK(Beam,brew_molecule,1);
SCM
Beam::brew_molecule (SCM smob)
return fm;
}
+
+SCM
+ly_font_interface_get_default_font (SCM grob)
+{
+ Grob * gr = unsmob_grob (grob);
+
+ if (!gr)
+ {
+ warning ("ly_font_interface_get_default_font (): invalid argument");
+ return SCM_UNDEFINED;
+ }
+
+ return Font_interface::get_default_font (gr)->self_scm ();
+}
+
Font_metric *
Font_interface::get_font (Grob *me, SCM chain)
{
SCM font_name = gh_call2 (proc, fonts, chain);
Font_metric *fm = me->paper_l ()->find_font (font_name, 1.0);
-
return fm;
}
rel_sz_sym = scm_permanent_object (ly_symbol2scm ("font-relative-size"));
pt_sz_sym = scm_permanent_object (ly_symbol2scm ("font-point-size"));
wild_sym = scm_permanent_object (ly_symbol2scm ("*"));
+
+ scm_make_gsubr ("ly-get-default-font", 1 , 0, 0, (Scheme_function_unknown) ly_font_interface_get_default_font);
}
+
bool
Font_interface::wild_compare(SCM field_val, SCM val)
{
#include <math.h>
#include <ctype.h>
+#include "warn.hh"
#include "molecule.hh"
#include "ly-smobs.icc"
#include "font-metric.hh"
}
+SCM
+ly_find_glyph_by_name (SCM font, SCM name)
+{
+ if (!unsmob_metrics (font) || !gh_string_p (name))
+ {
+ warning ("ly-find-glyph-by-name: invalid argument.");
+ Molecule m;
+ return m.smobbed_copy ();
+ }
+
+ return unsmob_metrics (font)->find_by_name (ly_scm2string (name)).smobbed_copy ();
+}
+
+
+static void
+font_metric_init ()
+{
+ scm_make_gsubr ("ly-find-glyph-by-name", 2 , 0, 0, (Scheme_function_unknown) ly_find_glyph_by_name);
+}
+ADD_SCM_INIT_FUNC(font_metric_init, font_metric_init);
*/
SCM create_scheme () const;
bool empty_b() const;
+
+
+ static SCM ly_get_molecule_extent (SCM mol, SCM axis);
+ static SCM ly_set_molecule_extent_x (SCM,SCM,SCM);
+ static SCM ly_molecule_combined_at_edge (SCM,SCM,SCM,SCM,SCM);
};
Tfm_header header_;
Array<Tex_font_char_metric> char_metrics_;
Array<int> ascii_to_metric_idx_;
-
- String path_;
private:
Tex_font_metric ();
};
}
+
+
bool
to_boolean (SCM s)
{
add_molecule (toadd);
}
+
+
+
+bool
+number_pair_p (SCM p)
+{
+ return gh_pair_p (p) && gh_number_p (gh_car (p)) && gh_number_p (gh_cdr (p));
+}
+
+bool
+axis_p (SCM a)
+{
+ return gh_number_p (a) && (gh_scm2int (a) == 0 || gh_scm2int (a) == 1);
+}
+
+SCM
+Molecule::ly_set_molecule_extent_x (SCM mol, SCM axis, SCM np)
+{
+ Molecule* m = unsmob_molecule (mol);
+ if (m && axis_p (axis) && number_pair_p (np))
+ {
+ Interval iv = ly_scm2interval (np);
+ m->dim_[Axis(gh_scm2int (axis))] = ly_scm2interval (np);
+ }
+ else
+ warning ("ly-set-molecule-extent!: invalid arguments");
+ return SCM_UNDEFINED;
+}
+
+SCM
+Molecule::ly_get_molecule_extent (SCM mol, SCM axis)
+{
+ Molecule *m = unsmob_molecule (mol);
+
+ if (!m || !axis_p (axis))
+ {
+ warning ("ly-get-molecule-extent: invalid arguments");
+ return ly_interval2scm (Interval (0,0));
+ }
+
+ return ly_interval2scm (m->extent (Axis (gh_scm2int (axis))));
+}
+
+
+SCM
+Molecule::ly_molecule_combined_at_edge (SCM first, SCM axis, SCM direction,
+ SCM second, SCM padding)
+
+{
+ Molecule * m1 = unsmob_molecule (first);
+ Molecule * m2 = unsmob_molecule (second);
+ Molecule result;
+
+ if (!m1 || !m2 || !isdir_b (direction) || !axis_p (axis) || !gh_number_p (padding))
+ {
+ warning ("ly-combine-molecule-at-edge: invalid arguments");
+ Molecule r;
+ return r.smobbed_copy ();
+ }
+
+ result = *m1;
+
+ result.add_at_edge (Axis (gh_scm2int (axis)), Direction (gh_scm2int (direction)),
+ *m2, gh_scm2double (padding));
+
+ return result.smobbed_copy ();
+}
+
+
+static void
+molecule_init ()
+{
+ scm_make_gsubr ("ly-combine-molecule-at-edge", 5 , 0, 0, (Scheme_function_unknown) Molecule::ly_molecule_combined_at_edge);
+ scm_make_gsubr ("ly-set-molecule-extent!", 3 , 0, 0, (Scheme_function_unknown) Molecule::ly_set_molecule_extent_x);
+ scm_make_gsubr ("ly-get-molecule-extent", 2 , 0, 0, (Scheme_function_unknown) Molecule::ly_get_molecule_extent);
+}
+ADD_SCM_INIT_FUNC(molecule,molecule_init);
+
+
bool
Molecule::empty_b () const
{
Begin3
Title: LilyPond
-Version: 1.3.123
-Entered-date: 17JAN01
+Version: 1.3.124
+Entered-date: 18JAN01
Description:
Keywords: music notation typesetting midi fonts engraving
Author: hanwen@cs.uu.nl (Han-Wen Nienhuys)
janneke@gnu.org (Jan Nieuwenhuizen)
Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys)
Primary-site: sunsite.unc.edu /pub/Linux/apps/sound/convert
- 1000k lilypond-1.3.123.tar.gz
+ 1000k lilypond-1.3.124.tar.gz
Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/
- 1000k lilypond-1.3.123.tar.gz
+ 1000k lilypond-1.3.124.tar.gz
Copying-policy: GPL
End
%define info yes
Name: lilypond
-Version: 1.3.123
+Version: 1.3.124
Release: 1
License: GPL
Group: Applications/Publishing
-Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.123.tar.gz
+Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.124.tar.gz
Summary: A program for printing sheet music.
URL: http://www.cs.uu.nl/~hanwen/lilypond
# Icon: lilypond-icon.gif
draw_hufnagel_do_fa_clef((0,0), .8);
fet_endchar;
+def draw_percussion_clef(expr reduction) =
+ save reduced_il;
+ reduced_il# = staff_space# * reduction;
+ define_pixels(reduced_il);
+ set_char_box(0,.6reduced_il#,reduced_il#,reduced_il#);
+ pickup pencircle scaled 1.5 stafflinethickness;
+ draw (b,h) -- (b,-d);
+ draw (w,h) -- (w,-d);
+enddef;
+
+fet_beginchar("percussion clef", "percussion", "percussionclef")
+ draw_percussion_clef(1.0);
+fet_endchar;
+
+fet_beginchar("percussion clef", "percussion_change", "cpercussionclef")
+ draw_percussion_clef(.8);
+fet_endchar;
fet_endgroup("clefs");
("bass" . ("clefs-F" 2 0))
("F" . ( "clefs-F" 2 0))
("subbass" . ("clefs-F" 4 0))
+ ("percussion" . ("clefs-percussion" 0 0))
;; should move mensural stuff to separate file?
("vaticana_do1" . ("clefs-vaticana_do" -1 0))
(mark . ((font-family . number) (font-relative-size . 1)))
(script . ((font-family . roman) (font-relative-size . -1)))
(large . ((font-family . roman) (font-relative-size . 1)))
- (Large . ((font-series . bold) (font-family . roman) (font-relative-size . 2)))
+ (Large . ((font-series . bold) (font-shape . upright)
+ (font-family . roman) (font-relative-size . 2)))
(dynamic . ((font-family . dynamic) (font-relative-size . 0)))
))
(properties-to-font .