]> git.donarmstrong.com Git - lilypond.git/commitdiff
patch::: 1.3.141.jcn3
authorJan Nieuwenhuizen <janneke@gnu.org>
Sat, 24 Mar 2001 15:20:14 +0000 (16:20 +0100)
committerJan Nieuwenhuizen <janneke@gnu.org>
Sat, 24 Mar 2001 15:20:14 +0000 (16:20 +0100)
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.

35 files changed:
CHANGES
Documentation/regression-test.tely
Documentation/topdocs/INSTALL.texi
Documentation/user/lilypond.tely
Documentation/user/refman.itely
Documentation/user/tutorial.itely
VERSION
input/bugs/crescendo-squash.ly [new file with mode: 0644]
input/regression/dynamics-broken-hairpin.ly [new file with mode: 0644]
input/regression/dynamics-line.ly
input/regression/percent-repeat.ly [new file with mode: 0644]
input/star-spangled-banner.ly
input/test/test-german-chords.ly [new file with mode: 0644]
input/tricks/follow-thread.ly
lily/hairpin.cc
lily/include/lookup.hh
lily/include/percent-repeat-item.hh [new file with mode: 0644]
lily/lookup.cc
lily/multi-measure-rest.cc
lily/percent-repeat-engraver.cc
lily/percent-repeat-item.cc [new file with mode: 0644]
lily/system-start-delimiter-engraver.cc
lily/system-start-delimiter.cc
lily/tuplet-engraver.cc
ly/german-chords.ly [new file with mode: 0644]
mf/feta-schrift.mf
ps/lily.ps
scm/chord-name.scm
scm/grob-description.scm
scm/interface-description.scm
scm/ps.scm
scm/tex.scm
scripts/ly2dvi.py
scripts/mup2ly.py
scripts/pmx2ly.py

diff --git a/CHANGES b/CHANGES
index 2bb1994a46a46c4b5fdefe90bc2f41c8e69ed3e7..9996f1fa38b526e54f2b94dab4f42ff343f0abfa 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+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).
index 53d356514c7bc591b762ac621699a2572e50f74e..2b89bd8ab7c0d3356cb39cd0599243e201a2ed3f 100644 (file)
@@ -57,6 +57,8 @@ and documenting bugfixes.
 
 @lilypondfile[printfilename]{dynamics-line.ly}
 
+@lilypondfile[printfilename]{dynamics-broken-hairpin.ly}
+
 @lilypondfile[printfilename]{arpeggio.ly}
 
 @lilypondfile[printfilename]{glissando.ly}
index 9d7e01ad9d93ab4decb103739e63cf5a83c86dd2..66141d6c215c27e02c603c1d4fe65d60f2a9923b 100644 (file)
@@ -257,6 +257,27 @@ everything will be compiled, but nothing will be installed.  The
 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
@@ -330,6 +351,13 @@ in addition to the those needed for running:
 @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
index 25830f909d56b36a6ac929e8a031cc2314cc6b1b..d0034f88a75df8aaae3787d7bab65ccbc3c5b858 100644 (file)
@@ -15,7 +15,7 @@
 @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
@@ -33,7 +33,8 @@ 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
index 3ec63950395a5db5f5b6b27912795023b351a88a..ee400db07aa56a89ea7a4efbff59ea6bd58264d3 100644 (file)
@@ -41,7 +41,6 @@ revision of this document was for LilyPond 1.3.141.
 * Page layout::                 
 * Sound::                       
 * Music entry::                 
-* Using LilyPond::              
 * Interpretation context::      
 * Syntactic details::           
 * Lexical details::             
@@ -1367,11 +1366,9 @@ want to get several marks during one note, you must use spacer notes.
 
 @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:
 
@@ -1384,7 +1381,11 @@ 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.
 
 
 
@@ -1583,10 +1584,15 @@ In the @code{percent} style, a note pattern can be repeated. It is
 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
@@ -2169,7 +2175,7 @@ scheme = \notes {
 
 \score {
   <
-    \context ChordNamesVoice \scheme
+    \context ChordNames \scheme
     \context Staff \scheme
   >
 }
@@ -2611,6 +2617,29 @@ Formally the syntax for these constructions is
 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.
@@ -3338,107 +3367,6 @@ will complain about not finding @code{src:X:Y} files. Those complaints are
 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
 
index 04265373c0636bf42f47df291438c9165c13aaeb..415d95ac8ceb5a59537c9d2ba4620cff276bf91c 100644 (file)
@@ -1827,3 +1827,40 @@ files in @file{input} and @file{input/test}.  You can also look at Real
 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}
+
diff --git a/VERSION b/VERSION
index 1eeef491e1fdc48b08dcfc889ac9a1b46ed2e133..959790eb7e6b05a69c8be442291184673db10d14 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond
 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.
diff --git a/input/bugs/crescendo-squash.ly b/input/bugs/crescendo-squash.ly
new file mode 100644 (file)
index 0000000..b143968
--- /dev/null
@@ -0,0 +1,9 @@
+
+
+ % < becomes | 
+\score {\notes { \context Staff < f''1
+   { s4 \< \! s4 } > }
+
+  \paper { linewidth = -1.;  }
+  }
+
diff --git a/input/regression/dynamics-broken-hairpin.ly b/input/regression/dynamics-broken-hairpin.ly
new file mode 100644 (file)
index 0000000..2aef249
--- /dev/null
@@ -0,0 +1,12 @@
+\header{
+texidoc = "Broken crescendi should look be open on one side.";
+}
+
+\score { \notes \relative c'' { 
+    c1 \< \break \! c1  \> \break \! c1 
+  }
+  \paper {
+    linewidth = 10.\cm;
+  }
+}
+  
index 95f6b6068c39edaa93c86f3fc5c7768880558079..9ab480cb625766396e4686941bd880b9384bfec4 100644 (file)
@@ -1,7 +1,8 @@
 \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.
+ ";
 }
 
 
diff --git a/input/regression/percent-repeat.ly b/input/regression/percent-repeat.ly
new file mode 100644 (file)
index 0000000..2080187
--- /dev/null
@@ -0,0 +1,18 @@
+\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 }
+   
+
+
+     }}
index c72646beff84e56c4be35d04cacef5282fb55884..4f79f9dafbb8b601e590221304eee0f719822045 100644 (file)
@@ -1,7 +1,7 @@
 %{
-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
 %}
 
 
diff --git a/input/test/test-german-chords.ly b/input/test/test-german-chords.ly
new file mode 100644 (file)
index 0000000..0df2a1a
--- /dev/null
@@ -0,0 +1,14 @@
+\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 {}
+}
+
index 30dfa9d1fc2a23c8ef9b23e47d7bd14b284e6a93..c09efe20756b2a460b640c3480f0c6996cc1ea0a 100644 (file)
@@ -2,14 +2,14 @@
 \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
index 23de3362d420e952b8e2c8f709a48a38c0ff8c8a..4fc4bce8d3c66538e5f19bf149cf1e0c15b31d75 100644 (file)
@@ -76,16 +76,33 @@ Hairpin::brew_molecule (SCM smob)
   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);
 
index 4a3dea7e0f9f343cb18e8e1f6d8769e82255b6de..8f954757dff970a0f38bf3d62cac647c5ba4c023 100644 (file)
@@ -24,7 +24,8 @@ struct Lookup
   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
diff --git a/lily/include/percent-repeat-item.hh b/lily/include/percent-repeat-item.hh
new file mode 100644 (file)
index 0000000..057144c
--- /dev/null
@@ -0,0 +1,25 @@
+/*   
+  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 */
+
index f2e89466b6d91c7a813b25465a36ab9052d10453..b01db45413ca14b3f931ec242ae3804dacf7dc76 100644 (file)
@@ -355,3 +355,21 @@ Lookup::accordion (SCM s, Real staff_space, Font_metric *fm)
   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);
+}
index f216aeac8a4988af1471d56d05778d38ec9afe95..890c0d1562901f24928140aea8ccd0361ce30ce0 100644 (file)
@@ -19,6 +19,8 @@
 #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)
@@ -36,12 +38,13 @@ MAKE_SCHEME_CALLBACK (Multi_measure_rest,percent,1);
 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.
   
index b063ad46603f8399b47daae86cc85f7023bae8d0..994288da6406d9f4def48db2467390392af9e4c0 100644 (file)
 #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
@@ -52,7 +56,9 @@ protected:
     MEASURE,
     DOUBLE_MEASURE,
   } repeat_sign_type_ ;
-  
+
+  Item * beat_slash_;
+  Item * double_percent_;
   Spanner * perc_p_;
   Spanner * finished_perc_p_;
   Item * stem_tremolo_;
@@ -70,6 +76,9 @@ Percent_repeat_engraver::Percent_repeat_engraver ()
   perc_p_  = finished_perc_p_ = 0;
   repeat_ =0;
   stem_tremolo_ = 0;
+
+  beat_slash_ = 0;
+  double_percent_ = 0;
 }
 
 bool
@@ -89,25 +98,25 @@ Percent_repeat_engraver::try_music (Music * m)
       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;
@@ -138,7 +147,8 @@ Percent_repeat_engraver::process_music ()
     {
       if (repeat_sign_type_ == BEAT)
        {
-         ;
+         beat_slash_ = new Item (get_property ("RepeatSlash"));
+         announce_grob (beat_slash_, repeat_);
        }
       else if (repeat_sign_type_ == MEASURE)
        {
@@ -149,10 +159,31 @@ Percent_repeat_engraver::process_music ()
          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 ()
 {
@@ -174,22 +205,38 @@ Percent_repeat_engraver::typeset_perc ()
       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;
diff --git a/lily/percent-repeat-item.cc b/lily/percent-repeat-item.cc
new file mode 100644 (file)
index 0000000..3734044
--- /dev/null
@@ -0,0 +1,85 @@
+/*   
+  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 ();
+}
+
+
+
+
+
+
+
index 1f4504a7338c9fa0e9bfc48c2051f94cfb2dba8c..27ee99dc86b22375148e2f4431a1cae7b99432bd 100644 (file)
@@ -53,6 +53,14 @@ System_start_delimiter_engraver::acknowledge_grob (Grob_info inf)
       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));
+        }
     }
 
 }
index 39bd68040ece1a7a93e956dfcb71acdb1cdd8000..5d4cb3d67a9aeac9c9803d150fecaf928e975db3 100644 (file)
@@ -32,6 +32,25 @@ System_start_delimiter::staff_bracket (Grob*me,Real height)
                    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);
index 7568a08679c7bffe6c4588c6a1f8b7b7be0b9376..0e7d238247e9a529c9ea35a334c7542ef9a36286 100644 (file)
@@ -110,6 +110,16 @@ Tuplet_engraver::acknowledge_grob (Grob_info i)
     }
   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_);
diff --git a/ly/german-chords.ly b/ly/german-chords.ly
new file mode 100644 (file)
index 0000000..e158592
--- /dev/null
@@ -0,0 +1,39 @@
+
+%  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)))
+         )
+       )
+       '()
+     )
+   )
+ )
index f4fc744a2792bd7579a8212ae00d70b89cfc325e..8ddcc5d1d658603c0088304c4825e99222d64581 100644 (file)
@@ -585,25 +585,6 @@ fet_beginchar("Flageolet", "flageolet", "flageolet")
        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;
index de0f845dd0f4d0d579ebbf49aac907269225b088..b5406ca0ac9089afe7a030e5ef7afe374e7b71d7 100644 (file)
@@ -5,6 +5,11 @@
 % 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
index bcdf7aaa1f928e754eb0020f261a770582fc97a8..5bbb2017e4d61f904725fb87163f1d1debe96661 100644 (file)
 
 (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
index d12715908cc50f8e577317c8a7bff11880242c8e..a1fdc784cf8f95a6ff418405c76c343fb053b63f 100644 (file)
@@ -9,7 +9,18 @@
 ; 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)
index 31160299533014fff2980acc01b497793dd09bc6..61f746d6f01b5ca0727a3ebd6894035c1f4263f6 100644 (file)
@@ -6,7 +6,7 @@
 ;;;;                 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 
- ))
  ))
 
 
 
@@ -758,22 +758,26 @@ direction = Forced direction for all ties"
    '(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
@@ -784,3 +788,4 @@ direction = Forced direction for all ties"
 
 (define (interface-names) (map (lambda (x) (symbol->string (car x))) all-interfaces))
 
+
index d17843731e1ae15371cef24c0f2658d18e842233..0f8011bf6d858406ca0f47f7f9a363c417352bb0 100644 (file)
   (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")
   
@@ -208,12 +207,11 @@ lilypondpaperoutputscale lilypondpaperoutputscale scale
            (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)
@@ -231,20 +229,21 @@ lilypondpaperoutputscale lilypondpaperoutputscale scale
            (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)    
index 6f0e0e69f6e5de44392d15ef2083ec7af1ff825f..5e358449f90b47f247d427acd6d339c8d175ad37 100644 (file)
@@ -47,8 +47,8 @@
   (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) " "))
@@ -56,9 +56,6 @@
   (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 "="
@@ -86,6 +83,9 @@
   (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)
index a29429947b7e50016a38f24c68ab94ebe2fbb8d9..bb9d97188c54fb728e172a46f7d31007c9864dc9 100644 (file)
@@ -21,6 +21,8 @@ TODO:
   * 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
+  
 '''
 
 
@@ -200,8 +202,9 @@ def setup_temp ():
                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)
@@ -241,6 +244,7 @@ def set_setting (dict, key, val):
 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")),
@@ -364,8 +368,10 @@ def global_latex_definition (tfiles, extra):
 
        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']:
@@ -505,11 +511,15 @@ for opt in options:
        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)
index 7011a7b1e459df15f33d7dad964a940885e67894..2808dc1b653f571ee803678ec8402998790d591d 100644 (file)
@@ -7,6 +7,9 @@
 
 '''
 TODO:
+
+   WIP:lots of stuff
+   
 '''
 
 import os
@@ -66,7 +69,9 @@ NO WARRANTY.'''))
        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)
@@ -199,7 +204,7 @@ def set_setting (dict, key, val):
 #
 
 def encodeint (i):
-       return chr ( i  + ord ('A'))
+       return chr (i  + ord ('A'))
 
        
 actab = {-2: 'eses', -1: 'es', 0 : '', 1: 'is', 2:'isis'}
@@ -207,7 +212,7 @@ 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
@@ -321,12 +326,14 @@ class Slur:
                        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:
@@ -340,36 +347,56 @@ class Voice:
                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
@@ -380,6 +407,7 @@ class Voice:
                                lastc.chord_suffix = lastc.chord_suffix + ' } '
                        lastgr = c.grace
                        lastc = c
+                        
        def calculate (self):
                self.calculate_graces ()
                for s in self.slurs:
@@ -400,43 +428,54 @@ clef_table = {
        '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:
@@ -564,6 +603,7 @@ class Parser:
        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               
@@ -573,68 +613,140 @@ class Parser:
 
                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, ';')
@@ -644,81 +756,80 @@ class Parser:
                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:
@@ -730,13 +841,20 @@ class Parser:
                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")),
@@ -744,7 +862,13 @@ option_definitions = [
        ('', '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:
@@ -757,13 +881,19 @@ except:
 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
@@ -793,7 +923,7 @@ for f in files:
        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)
index b8d289b861612497507797b70ed512dd57e8dc3c..c260b068195a68ea37feaf84962a02824476add4 100644 (file)
@@ -407,7 +407,9 @@ class Parser:
                        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