]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge http://git.sv.gnu.org/r/lilypond
authorNicolas Sceaux <nicolas.sceaux@free.fr>
Mon, 22 Jan 2007 21:14:50 +0000 (22:14 +0100)
committerNicolas Sceaux <nicolas.sceaux@free.fr>
Mon, 22 Jan 2007 21:14:50 +0000 (22:14 +0100)
130 files changed:
Documentation/topdocs/NEWS.tely
Documentation/user/basic-notation.itely
Documentation/user/instrument-notation.itely
Documentation/user/introduction.itely
Documentation/user/lilypond.tely
Documentation/user/macros.itexi
Documentation/user/non-music.itely
Documentation/user/putting.itely
Documentation/user/running.itely
Documentation/user/templates.itely
Documentation/user/tutorial.itely
THANKS
VERSION
buildscripts/build-profile.sh
buildscripts/coverage.py
buildscripts/output-distance.py
input/GNUmakefile
input/lsr/GNUmakefile [new file with mode: 0644]
input/lsr/advanced/+.ly [new file with mode: 0644]
input/lsr/advanced/Alternating-beam-directions.ly [new file with mode: 0644]
input/lsr/advanced/GNUmakefile [new file with mode: 0644]
input/lsr/advanced/SConscript [new file with mode: 0644]
input/lsr/trick/+.ly [new file with mode: 0644]
input/lsr/trick/Adding-ambiti-per-voice.ly [new file with mode: 0644]
input/lsr/trick/Caesura-railtracks-with-fermata.ly [new file with mode: 0644]
input/lsr/trick/GNUmakefile [new file with mode: 0644]
input/lsr/trick/SConscript [new file with mode: 0644]
input/lsr/trick/Tramlines-and-Feta-font-caesurae.ly [new file with mode: 0644]
input/makelsr.py [new file with mode: 0755]
input/regression/auto-beam-beaming-override.ly [new file with mode: 0644]
input/regression/collision-manual.ly
input/regression/hairpin-to-barline-mark.ly [new file with mode: 0644]
input/regression/hara-kiri-stanza-number.ly [new file with mode: 0644]
input/regression/lyric-combine-switch-voice-2.ly [new file with mode: 0644]
input/test/engraver-one-by-one.ly
lily/accidental-placement.cc
lily/accidental.cc
lily/all-font-metrics.cc
lily/ambitus-engraver.cc
lily/arpeggio.cc
lily/audio-element.cc
lily/audio-staff.cc
lily/auto-beam-engraver.cc
lily/axis-group-interface.cc
lily/bar-line.cc
lily/beam-engraver.cc
lily/beam.cc
lily/beaming-pattern.cc
lily/constrained-breaking.cc
lily/dots.cc
lily/dynamic-engraver.cc
lily/general-scheme.cc
lily/grob-smob.cc
lily/hairpin.cc
lily/includable-lexer.cc
lily/include/accidental-interface.hh
lily/include/all-font-metrics.hh
lily/include/beaming-pattern.hh
lily/include/lily-guile.hh
lily/include/lily-proto.hh
lily/include/midi-chunk.hh [new file with mode: 0644]
lily/include/midi-item.hh
lily/include/midi-stream.hh
lily/include/midi-walker.hh
lily/include/pango-font.hh
lily/include/smobs.hh
lily/include/source.hh
lily/include/sources.hh [new file with mode: 0644]
lily/include/stencil.hh
lily/include/tie-formatting-problem.hh
lily/input.cc
lily/key-engraver.cc
lily/key-signature-interface.cc
lily/lily-guile.cc
lily/lily-parser-scheme.cc
lily/lily-parser.cc
lily/line-spanner.cc
lily/lyric-combine-music-iterator.cc
lily/lyric-engraver.cc
lily/midi-chunk.cc [new file with mode: 0644]
lily/midi-item.cc
lily/midi-stream.cc
lily/midi-walker.cc
lily/multi-measure-rest.cc
lily/note-spacing.cc
lily/ottava-engraver.cc
lily/pango-font.cc
lily/pango-select.cc
lily/paper-column.cc
lily/paper-def.cc
lily/parse-scm.cc
lily/percent-repeat-item.cc
lily/performance.cc
lily/program-option.cc
lily/relocate.cc
lily/skyline.cc
lily/slur.cc
lily/source.cc
lily/sources.cc [new file with mode: 0644]
lily/stanza-number-align-engraver.cc
lily/stem.cc
lily/stencil-scheme.cc
lily/stencil.cc
lily/sustain-pedal.cc
lily/system-start-delimiter-engraver.cc
lily/system-start-delimiter.cc
lily/time-signature.cc
lily/volta-bracket.cc
ly/engraver-init.ly
ly/music-functions-init.ly
python/convertrules.py
python/midi.c
scm/coverage.scm [new file with mode: 0644]
scm/define-context-properties.scm
scm/define-grob-properties.scm
scm/define-grobs.scm
scm/define-markup-commands.scm
scm/framework-ps.scm
scm/fret-diagrams.scm
scm/layout-page-layout.scm
scm/lily-library.scm
scm/lily.scm
scm/memory-trace.scm [new file with mode: 0644]
scm/music-functions.scm
scm/output-ps.scm
scm/page.scm
scm/safe-lily.scm
scm/script.scm
scm/standalone.scm
scm/stencil.scm

index 4769d08c7adabf9dfe1c8f741112a7ad4fe64912..e7b58fc71fc819d53308b8d610700ff3e77da124 100644 (file)
@@ -20,7 +20,6 @@ See user manual, \NAME\
 @end macro
 @end ifnothtml
 
-
 @macro textanchor{NAME}
 @html
 <a name="\NAME\"></a>
@@ -65,12 +64,13 @@ which scares away people.
 * only show user-visible changes. 
 
 @end ignore
+
 @item
 Notes or rests, such as a typical end note, that fill an entire
 measure are preceded by some more space.
 
-@lilypond[ragged-right,relative=1]
-{
+@lilypond[ragged-right]
+\relative c' {
   \time 4/4
   s1
   c2. c4
index b4e36e8655209fe1d54b68178c1e446dee4d4447..da60b0e06cc876bc33edbfe50d74a0d53935c4be 100644 (file)
@@ -20,7 +20,7 @@ This chapter explains how to use basic notation features.
 @menu
 * Pitches::                     
 * Rhythms::                     
-* Multiple notes at once::      
+* Polyphony::                   
 * Staff notation::              
 * Connecting notes::            
 * Expressive marks::            
@@ -39,7 +39,7 @@ This section discusses how to specify the pitch of notes.
 * Accidentals::                 
 * Cautionary accidentals::      
 * Micro tones::                 
-* Notes names in other languages::  
+* Note names in other languages::  
 * Relative octaves::            
 * Octave check::                
 * Transpose::                   
@@ -128,7 +128,7 @@ The input @code{d e f} is interpreted as @q{print a D-natural,
 E-natural, and an F-natural,} regardless of the key
 signature.  For more information about the distinction between
 musical content and the presentation of that content, see
-@ref{More about pitches}.
+@ref{Accidentals and key signatures}.
 
 @lilypond[fragment,quote,ragged-right,verbatim,relative]
 \key d \major
@@ -212,8 +212,8 @@ three-quarter flats, so LilyPond's symbol does not conform to any
 standard.
 
 
-@node Notes names in other languages
-@subsection Notes names in other languages
+@node Note names in other languages
+@subsection Note names in other languages
 
 There are predefined sets of note names for various other languages.
 To use them, include the language specific init file.  For
@@ -884,8 +884,8 @@ Examples: @inputfileref{input/@/regression,completion@/-heads@/.ly}.
 Program reference: @internalsref{Completion_heads_engraver}.
 
 
-@node Multiple notes at once
-@section Multiple notes at once
+@node Polyphony
+@section Polyphony
 
 Polyphony in music refers to having more than one voice occurring in
 a piece of music.  Polyphony in LilyPond refers to having more than
@@ -1394,7 +1394,7 @@ can be specified by setting this property directly.
 
 Accidentals and key signatures often confuse new users, because
 unaltered notes get natural signs depending on the key signature.  For
-more information, see @ref{Accidentals} or @ref{More about pitches}.
+more information, see @ref{Accidentals} or @ref{Accidentals and key signatures}.
 
 @lilypond[quote,ragged-right,verbatim,relative=2,fragment]
 \key g \major
index fdd4d5ca41399ca49c3971f611ae2c82eb398ff6..b36de05bb4f47e92b3f83c2937c1c4ae266bae4d 100644 (file)
@@ -1381,12 +1381,11 @@ layout.
 @node More about stanzas
 @subsection More about stanzas
 
+@c what's this doing here?
 @cindex phrasing, in lyrics
 
-
 @cindex stanza number
-@cindex singer's names
-@cindex name of singer
+@subsubsection Adding stanza numbers 
 
 Stanza numbers can be added by setting @code{stanza}, e.g.,
 
@@ -1402,7 +1401,57 @@ Stanza numbers can be added by setting @code{stanza}, e.g.,
 }
 @end lilypond
 
-These numbers are put just before the start of first syllable.
+@noindent
+These numbers are put just before the start of the first syllable.
+
+
+@subsubsection Adding dynamics marks
+
+Stanzas differing in loudness may be indicated by putting a
+dynamics mark before each stanza.  In Lilypond, everthing coming in
+front of a stanza goes into the @code{StanzaNumber} object; dynamics marks
+are no different.  For technical reasons, you have to set the stanza
+outside @code{\lyricmode}:
+
+@lilypond[quote,ragged-right,verbatim]
+text = {
+  \set stanza = \markup { \dynamic "ff" "1. " }
+  \lyricmode {
+    Big bang
+  }
+}
+
+<<
+  \new Voice = "tune" {
+    \time 3/4
+    g'4 c'2
+  }
+\new Lyrics \lyricsto "tune" \text
+>>
+@end lilypond
+
+@cindex singer name
+@cindex name of singer
+@subsubsection Adding singer names
+
+Names of singers can also be added.  They are printed at the start of
+the line, just like instrument names.  They are created by setting
+@code{vocalName}.  A short version may be entered as @code{shortVocalName}.
+
+@lilypond[fragment,ragged-right,quote,verbatim,relative=2]
+\new Voice {
+  \time 3/4 g2 e4 a2 f4 g2.
+} \addlyrics {
+  \set vocalName = "Bert "
+  Hi, my name is Bert.
+} \addlyrics {
+  \set vocalName = "Ernie "
+  Oh, che -- ri, je t'aime
+}
+@end lilypond
+
+
+@subsubsection Printing stanzas at the end 
 
 Sometimes it is appropriate to have one stanza set
 to the music, and the rest added in verse form at
@@ -1448,23 +1497,7 @@ its fleece was white as snow.
 @end lilypond
 
 
-Names of singers can also be added.  They are printed at the start of
-the line, just like instrument names.  They are created by setting
-@code{vocalName}.  A short version may be entered as @code{shortVocalName}.
-
-
-@lilypond[fragment,ragged-right,quote,verbatim,relative=2]
-\new Voice {
-  \time 3/4 g2 e4 a2 f4 g2.
-} \addlyrics {
-  \set vocalName = "Bert "
-  Hi, my name is Bert.
-} \addlyrics {
-  \set vocalName = "Ernie "
-  Oh, che -- ri, je t'aime
-}
-@end lilypond
-
+@subsubsection Printing stanzas at the end in multiple columns 
 
 When a piece of music has many verses, they are often printed in
 multiple columns across the page. An outdented verse number often
index 33a62a44b8d15f7b6b921a150ee76821116cba7b..101772c95d26e26fb6bd44e299f2b3df01a73517 100644 (file)
@@ -787,8 +787,8 @@ are a set of tables showing the chord names, MIDI instruments,
 a list of color names, and the Feta font.
 
 @item
-@emph{@ref{Example templates}}
-provides templates of LilyPond pieces.  Just cut and paste a
+@emph{@ref{Templates}}
+of LilyPond pieces.  Just cut and paste a
 template into a file, add notes, and you're done!
 
 @item
index 3bd4ca5623de61e964933a32c1d4e141207978cb..7e5f04918588b0ece6e36d7d8edad6288f3684a3 100644 (file)
@@ -184,7 +184,7 @@ Appendices
 * Literature list::                Reference works about music notation.
 * Scheme tutorial::                Programming inside LilyPond.
 * Notation manual tables::         Tables and charts.
-* Example templates::              Ready-made templates.
+* Templates::                      Ready-made templates.
 * Cheat sheet::                    Summary of LilyPond syntax.
 * GNU Free Documentation License:: License of this document.
 * LilyPond command index::
index 0a85e749dce08303ba67f09e8b9f8b61e94eed9d..0274641da2e0b1e0f1d2244653c7f27ef3ae4632 100644 (file)
@@ -217,6 +217,11 @@ user manual, @internalsref{\NAME\}
 
 @end macro
 
+@macro moreinfo
+@subheading More information
+
+@end macro
+
 @macro seealso
 @noindent
 @subsubheading See also
index 365cfa9c2d19301b7da03f6ab68acc4354aeac35..f167c6cb2248b80d291d730529a0442d51d3dc28 100644 (file)
@@ -844,7 +844,6 @@ in the @code{\midi@{@}} section.
   \context @{
     \Voice
     \remove "Dynamic_performer"
-    \remove "Span_dynamic_performer"
   @}
 @}
 @end example
index af557788fc89bced9da052e525d55b4955d98325..1dd8222330d718ae29cb41d2a95ca9a61d8fdc43 100644 (file)
@@ -18,6 +18,7 @@ create @code{\score} blocks.
 * Extending the templates::     
 * How LilyPond files work::     
 * Score is a single musical expression::  
+* An orchestral part::          
 @end menu
 
 
@@ -458,3 +459,136 @@ layer starts on the same horizontal position in your
 text editor!
 
 
+
+
+
+
+@node An orchestral part
+@section An orchestral part
+
+In orchestral music, all notes are printed twice.  Once in a part for
+the musicians, and once in a full score for the conductor.  Identifiers can
+be used to avoid double work.  The music is entered once, and stored in
+a variable.  The contents of that variable is then used to generate
+both the part and the full score.
+
+It is convenient to define the notes in a special file.  For example,
+suppose that the file @file{horn-music.ly} contains the following part
+of a horn/@/bassoon duo
+
+@example
+hornNotes = \relative c @{
+  \time 2/4
+  r4 f8 a cis4 f e d
+@}
+@end example
+
+@noindent
+Then, an individual part is made by putting the following in a file
+
+@example
+\include "horn-music.ly"
+\header @{
+  instrument = "Horn in F"
+@}
+
+@{
+ \transpose f c' \hornNotes
+@}
+@end example
+
+The line
+
+@example
+\include "horn-music.ly"
+@end example
+
+@noindent
+substitutes the contents of @file{horn-music.ly} at this position in
+the file, so @code{hornNotes} is defined afterwards.  The command
+@code{\transpose f@tie{}c'} indicates that the argument, being
+@code{\hornNotes}, should be transposed by a fifth upwards.  Sounding
+@samp{f} is denoted by notated @code{c'}, which corresponds with the
+tuning of a normal French Horn in@tie{}F.  The transposition can be seen
+in the following output
+
+@lilypond[quote,ragged-right]
+\transpose f c' \relative c {
+  \time 2/4
+  r4 f8 a cis4 f e d
+}
+@end lilypond
+
+In ensemble pieces, one of the voices often does not play for many
+measures.  This is denoted by a special rest, the multi-measure
+rest.  It is entered with a capital @samp{R} followed by a duration
+(@code{1}@tie{}for a whole note, @code{2}@tie{}for a half note,
+etc.).  By multiplying the
+duration, longer rests can be constructed.  For example, this rest
+takes 3@tie{}measures in 2/4 time
+
+@example
+R2*3
+@end example
+
+When printing the part, multi-rests
+must be condensed.  This is done by setting a run-time variable
+
+@example
+\set Score.skipBars = ##t
+@end example
+
+@noindent
+This command sets the property @code{skipBars} in the
+@code{Score} context to true (@code{##t}).  Prepending the rest and
+this option to the music above, leads to the following result
+
+@lilypond[quote,ragged-right]
+\transpose f c' \relative c {
+  \time 2/4
+  \set Score.skipBars = ##t
+  R2*3
+  r4 f8 a cis4 f e d
+}
+@end lilypond
+
+
+The score is made by combining all of the music together.  Assuming
+that the other voice is in @code{bassoonNotes} in the file
+@file{bassoon-music.ly}, a score is made with
+
+@example
+\include "bassoon-music.ly"
+\include "horn-music.ly"
+
+<<
+  \new Staff \hornNotes
+  \new Staff \bassoonNotes
+>>
+@end example
+
+@noindent
+leading to
+
+@lilypond[quote,ragged-right]
+\relative c <<
+  \new Staff {
+    \time 2/4 R2*3
+    r4 f8 a cis4 f e d
+  }
+  \new Staff {
+    \clef bass
+    r4 d,8 f | gis4 c | b bes |
+    a8 e f4 | g d | gis f
+  }
+>>
+@end lilypond
+
+More in-depth information on preparing parts and scores can be found
+in the notation manual; see @ref{Orchestral music}.
+
+Setting run-time variables (@q{properties}) is discussed in
+@ref{Changing context properties on the fly}.
+
+
+
index ff4af0cf17153f077c7cf1110e8985767336a29f..738bf68759f9742004f017ae7bf35e5cf9b2dcf7 100644 (file)
@@ -378,7 +378,7 @@ cd ~/bin
 Create a file called @code{lilypond} which contains
 
 @example
-exec @var{path/to}/LilyPond.app/Contents/Resources/bin/lilypond "$@"
+exec @var{path/to}/LilyPond.app/Contents/Resources/bin/lilypond "$@@"
 @end example
 
 Create similar files @code{lilypond-book}, @code{convert-ly}, and
@@ -692,12 +692,14 @@ installation instructions.
 @end ifnothtml
 
 
-@item JEdit
+@item LilyPondTool
 
-The @uref{http://@/www@/.jedit@/.org@/,jEdit} editor has a LilyPond plugin.
-This plugin includes a DVI viewer, integrated help and viewing via
-GhostScript.  It can be installed by doing @key{Plugins > Plugin
-Manager}, and selecting @code{LilyTool} from the @key{Install} tab.
+Created as a plugin for the @uref{http://@/www@/.jedit@/.org@/,jEdit} text
+editor, LilyPondTool is the most feature-rich text-based tool for editing
+LilyPond scores.  Its features include a Document Wizard with lyrics
+support to set up documents easier, and embedded PDF viewer with advanced
+point-and-click support.  For screenshots, demos and installation
+instructions, visit @uref{http://lilypondtool@/.organum@/.hu}
 
 @end table
 
index fca2900d655f1b1cc9d53a332f37c7e448032f58..bc41f8d617e53657dfbbb0e69c9cdd9192ce2dd2 100644 (file)
@@ -7,8 +7,8 @@
     version that you are working on.  See TRANSLATION for details.
 @end ignore
 
-@node Example templates
-@appendix Example templates
+@node Templates
+@appendix Templates
 
 This section of the manual contains templates with the LilyPond score
 already set up for you.  Just add notes, run LilyPond, and enjoy
index ee0ee87abe533fe4a032da4def61b059b6bfe5e3..566a5db8d74ffd482abb4fdb5e001f1df98c4ccd 100644 (file)
@@ -7,6 +7,23 @@
     version that you are working on.  See TRANSLATION for details.
 @end ignore
 
+@ignore
+Tutorial guidelines:
+- unless you have a really good reason, use either
+    @l ilypond[quote,ragged-right,verbatim]
+  or
+    @l ilypond[quote,ragged-right,verbatim,fragment,relative=2]
+  (without spaces)
+  Don't use any other relative=X commands (make it a non-fragment
+  example), and don't use fragment without relative=2.
+- use "aes" and "ees" instead of "as" and "aes".  I know it's not
+  correct Dutch naming, but let's not confuse people with this until
+  we get to the Basic notation chapter.
+@end ignore
+
+
+
+@c   old info that will probably be removed.
 @c TODO:
 @c   * more details about running lilypond; error messages,
 @c     compiling/viewing (emacs?)
@@ -34,81 +51,77 @@ Try it on this image
 @lilypond[fragment,quote,ragged-right,relative=2]
 c-\markup { \bold \huge { Click here.  } }
 @end lilypond
-@end ifhtml
 
-By cutting and pasting the full input into a test file, you have a
+By cutting and pasting everything from the @qq{Start cut-&-pastable-section}
+to the end of the file, you have a
 starting template for experiments.  If you like learning in this way,
-you will probably want to print out or bookmark
-@ifhtml
-the
-@end ifhtml
+you will probably want to print out or bookmark the
 @ref{Cheat sheet}, which is a table listing of the most common
 commands for quick reference.
+@end ifhtml
 
 @menu
 * First steps::                 
-* Second steps::                
-* More about pitches::          
-* Entering ties::               
-* Automatic and manual beams::  
-* Octave entry::                
-* Music expressions explained::  
-* More staves::                 
-* Adding articulation marks to notes::  
-* Combining notes into chords::  
-* Advanced rhythmic commands::  
-* Commenting input files::      
-* Printing lyrics::             
-* A lead sheet::                
-* Adding titles::               
-* Single staff polyphony::      
-* Piano staves::                
-* Organizing larger pieces::    
-* An orchestral part::          
-* After the tutorial::          
+* Single staff notation::       
+* Multiple notes at once::      
+* Songs::                       
+* Final touches::               
 @end menu
 
 
 @node First steps
 @section First steps
 
-The first example demonstrates how to enter the most elementary piece
-of music, a @rglos{scale}.  A @rglos{note} can be entered by typing
-its name, from @samp{a} through @samp{g}.  So, if you enter
+This section gives a basic introduction to working with LilyPond.
+
+@menu
+* Compiling a file::            
+* Simple notation::             
+* Working on text files::       
+* How to read the tutorial::    
+@end menu
+
+
+@node Compiling a file
+@subsection Compiling a file
+
+The first example demonstrates how to start working with LilyPond.  To
+create sheet music, we write a text file that specifies the
+notation.  For example, if we write
 
 @example
 @{
-c' d' e' f' g' a' b' c''
+  c' e' g' e'
 @}
 @end example
 
 @noindent
 the result looks like this
 
-@lilypond[quote]
+@lilypond[quote,ragged-right]
 {
-c' d' e' f' g' a' b' c''
+  c' e' g' e'
 }
 @end lilypond
 
-@emph{Warning:} Every piece of LilyPond input needs to have @{curly
-braces@} placed around the input.  The braces should be also be
+@strong{Warning:} Every piece of LilyPond input needs to have @strong{@{ curly
+braces @}} placed around the input.  The braces should be also be
 surrounded by a space unless they are at the beginning or end of a
-line to avoid ambiguities.  These may be omitted in examples in this
+line to avoid ambiguities.  These may be omitted in some examples in this
 manual, but don't forget them in your own music!
 
 @cindex Case sensitive
-In addition, LilyPond input is case sensitive.  @code{ @{ c d e @} } is
-valid input; @code{ @{ C D E @} } will produce an error message.
+In addition, LilyPond input is @strong{case sensitive}.  @code{ @{ c d e @} }
+is valid input; @code{ @{ C D E @} } will produce an error message.
 
+@sp 1
 
-
-@unnumberedsubsec Entering music and viewing output
+@subheading Entering music and viewing output
 
 In this section we will explain what commands to run
 and how to view or print the output.
 
-@unnumberedsubsubsec MacOS X
+@subsubheading MacOS X
 
 If you double click LilyPond.app, it will open with an example
 file. Save it, for example, to @file{test.ly} on your Desktop, and
@@ -116,12 +129,12 @@ then process it with the menu command @samp{Compile > Typeset File}.
 The resulting PDF file will be displayed on your screen.
 
 Be warned that the first time you ever run lilypond will take a minute
-or two, because all of the system fonts have to be analyzed first.
+or two because all of the system fonts have to be analyzed first.
 
 For future use of LilyPond, you should begin by selecting "New"
 or "Open".
 
-@unnumberedsubsubsec Windows
+@subsubheading Windows
 
 On Windows, start up a text-editor@footnote{Any simple or
 programmer-oriented editor with UTF-8 support will do, for example
@@ -129,7 +142,9 @@ Notepad.  Do not use a word processor, since these insert formatting
 codes that will confuse LilyPond.} and enter
 
 @verbatim
-{ c' e' g' c'' }
+{
+  c' e' g' e'
+}
 @end verbatim
 
 Save it on the desktop as @file{test.ly} and make sure that it is not
@@ -137,18 +152,22 @@ called @file{test.ly.TXT}.  Double clicking @file{test.ly} will process
 the file and show the resulting PDF file.
 
 
-@unnumberedsubsubsec Unix
+@subsubheading Unix
 
 Begin by opening a terminal window and starting a text editor.  For
 example, you could open an xterm and execute
 @code{joe}@footnote{There are macro files for VIM addicts, and there
 is a @code{LilyPond-mode} for Emacs addicts.  If they have not been
-installed already, refer to the file @file{INSTALL.txt}.}.  In your
+installed already, refer to the file @file{INSTALL.txt}.  These
+easiest editing environment is @file{LilyPondTool}.  See
+@ref{Editor support} for more information.}.  In your
 text editor, enter the following input and save the file as
 @file{test.ly}
 
 @verbatim
-{ c' e' g' c'' }
+{
+  c' e' g' e'
+}
 @end verbatim
 
 @noindent
@@ -184,193 +203,376 @@ your system does not have any tools installed, you can try
 available package for viewing and printing PDF and PostScript files.}
 
 
-@node Second steps
-@section Second steps
+@node Simple notation
+@subsection Simple notation
+
+LilyPond will add some notation elements automatically.  In the next
+example, we have only specified four pitches, but LilyPond has
+added a clef, time signature, and rhythms.
 
-@emph{Remember:} Every piece of LilyPond input needs to have @{curly
-braces@} placed around the input.  The braces should be surrounded by
-a space unless they are at the beginning or end of a line to avoid
-ambiguities.  For the rest of this manual, most examples will omit
-these braces, but don't forget them in your own music!
+@lilypond[quote,ragged-right,verbatim]
+{
+  c' e' g' e'
+}
+@end lilypond
 
-@c will be removed once the tutorial either explains \relative or
-@c examples are fixed so they don't use it.  -gp
-In addition, many examples use @code{relative} mode.  This is explained
-in @ref{Octave entry}; for now simply be aware that some examples
-should be placed inside @code{\relative @{ @emph{...music...} @}}.
-Many example have also been compressed horizontally to save
-space, using @code{\paper @{ ragged-right = ##t @}}.
+@noindent
+This behavior may be altered, but in most cases these automatic values
+are useful.
 
-@cindex Case sensitive
-Finally, LilyPond input is case sensitive.  @code{ @{ c d e @} } is
-valid input; @code{ @{ C D E @} } will produce an error message.
 
-@c  End of latest re-write.  Since I have no life, I may do more
-@c  work on this, but I'd really like to have a Doc Helper take
-@c  over this task.  -gp
+@subheading Pitches
 
+The easiest way to enter notes is by using @code{\relative} mode.  In
+this mode, the @rglos{interval} between the previous note and the
+current note is assumed to be within a @rglos{fourth}.  We begin by
+entering the most elementary piece of music, a @rglos{scale}.
 
-The @rglos{duration} of a note is specified by a number after the note
-name.  @samp{1} for a @rglos{whole note}, @samp{2} for a @rglos{half note},
-@samp{4} for a @rglos{quarter note} and so on
+@lilypond[quote,ragged-right,verbatim]
+\relative c' {
+  c d e f
+  g a b c
+}
+@end lilypond
 
-@example
-a1 a2 a4 a16 a32
-@end example
+The initial note is @rglos{middle C}.  Each successive note
+is within a fourth of the previous note -- in other words, the first
+@samp{c} is the closest C to middle C.  This is followed by the closest
+D to the previous note.  We can create melodies which have larger intervals:
 
-@lilypond[fragment,quote,notime,relative=2]
-\set Staff.autoBeaming = ##f
-{ a1 a2 a4 a16 a32 s16_" " }
+@lilypond[quote,ragged-right,verbatim]
+\relative c' {
+  d f a g
+  c b f d
+}
 @end lilypond
 
-If you do not specify a duration, the duration last entered is used
-for the next notes.  The duration of the first note in input defaults
-to a quarter
+@noindent
+As you may notice, this example does not start on middle C.  The first
+note -- the @samp{d} -- is the closest D to middle C.
 
-@example
-a a8 a a2 a
-@end example
+To add intervals that are larger than a fourth, we can raise the octave
+by adding a single quote @code{'} (or apostrophe) to the note name.  We can
+lower the octave by adding a comma @code{,} to the note name.
 
-@lilypond[fragment,quote,notime,relative=2]
-{ a a8 a a2 a s16_" " }
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  a a, c' f,
+  g g'' a,, f'
+}
 @end lilypond
 
+@noindent
+To change a note by two (or more!) octaves, we use multiple @code{''} or
+@code{,,} -- but be careful that you use two single quotes @code{''} and
+not one double quote @code{"}@tie{}!  The initial value in
+@code{\relative c'} may also be modified like this.
 
-A @rglos{rest} is entered just like a note, but with the name @samp{r}
 
-@example
-r2 r4 r8 r16
-@end example
+@subheading Durations (rhythms)
 
-@lilypond[fragment,quote,notime]
-r2 r4 r8 r16 s16_" "
+The @rglos{duration} of a note is specified by a number after the note
+name.  @samp{1} for a @rglos{whole note}, @samp{2} for a @rglos{half note},
+@samp{4} for a @rglos{quarter note} and so on.  Beams are added
+automatically.
+
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  a1
+  a2 a4 a8 a
+  a16 a a a a32 a a a a64 a a a a a a a a2
+}
 @end lilypond
 
-Add a dot @samp{.} after the duration to get a @rglos{dotted note}
+@noindent
+If you do not specify a duration, the previous duration is used
+for the next note.  The duration of the first note defaults to a quarter.
 
-@example
-a2. a4 a8. a16
-@end example
+To create @rglos{dotted notes}, add a dot @samp{.} to the duration number.
 
-@lilypond[fragment,quote,notime,relative=1]
-{ a2. a4 a8. a16 s16_" " }
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  a a a4. a8
+  a8. a16 a a8. a8 a4.
+}
 @end lilypond
 
-The (or @rglos{time signature}) can be set with the @code{\time}
-command
 
-@example
-\time 3/4
-\time 6/8
-\time 4/4
-@end example
+@subheading Rests
 
-@c A clef here may lead to confusion, remove it.
-@lilypond[fragment,quote]
-\override Staff.Clef #'transparent = ##t
-\time 3/4
-s4_" "
-\time 6/8
-s4_" "
-\time 4/4
-s16_" "
+A @rglos{rest} is entered just like a note with the name @samp{r}:
+
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  a r r2
+  r8 a r4 r4. r8
+}
 @end lilypond
 
-The @rglos{clef} can be set using the @code{\clef} command
 
-@example
-\clef treble
-\clef bass
-\clef alto
-\clef tenor
-@end example
+@subheading Time signature
 
-@lilypond[fragment,quote,notime]
-\clef treble
-s4_" "
-\clef bass
-s4_" "
-\clef alto
-s4_" "
-\clef tenor
-s16_" "
+The @rglos{time signature}) can be set with the @code{\time} command:
+
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  \time 3/4
+  a4 a a
+  \time 6/8
+  a4. a
+  \time 4/4
+  a4 a a a
+}
 @end lilypond
 
-Remember to enclose the notes and commands in curly braces
-@code{@{@tie{}@dots{}@tie{}@}} to convert it to printable output.
 
-@lilypond[fragment,quote,noindent,verbatim]
-\time 3/4
-\clef bass
-c2 e4 g2.
-f4 e d c2 r4
+@subheading Clef
+
+The @rglos{clef} can be set using the @code{\clef} command:
+
+@lilypond[quote,ragged-right,verbatim]
+\relative c' {
+  \clef treble
+  c1
+  \clef alto
+       c1
+  \clef tenor
+  c1
+  \clef bass
+  c1
+}
 @end lilypond
 
-For more information on
 
+@subheading All together
+
+Here is a small example showing all these elements together:
+
+@lilypond[quote,ragged-right,verbatim]
+\relative c, {
+  \time 3/4
+  \clef bass
+  c2 e8 c' g'2.
+  f4 e d c4 c, r4
+}
+@end lilypond
+
+@moreinfo
 @quotation
 @table @asis
 @item Entering pitches and durations
-see
-@ref{Pitches}, and @ref{Durations}.
-@item Clefs
-see @ref{Clef}.
+see @ref{Pitches} and @ref{Durations}.
 @item Rests
 see @ref{Rests}.
 @item Time signatures and other timing commands
 see @ref{Time signature}.
+@item Clefs
+see @ref{Clef}.
+@end table
+@end quotation
+
+
+@node Working on text files
+@subsection Working on text files
+
+LilyPond input files are treated like files in most programming languages:
+they are case sensitive, white-space insensitive, expressions are
+formed with curly braces @{ @}, and comments are denoted with @code{%} or
+@code{%@{ .. %@}}.
+
+If the previous sentence sounds like nonsense, don't worry!  We'll explain
+what all these terms mean:
+
+@itemize
+
+@cindex Case sensitive
+@item @strong{Case sensitive}:
+it matters whether you enter a letter
+in lower case (i.e. @code{a, b, s, t}) or upper case (i.e.
+@code{A, B, S, T}).  Notes are lower case: @code{ @{ c d e @} }
+is valid input; @code{ @{ C D E @} } will produce an error message.
+
+@item @strong{Whitespace insensitive}:
+it does not matter how many
+spaces (or new lines) you add.  @code{ @{ c d e @}} means the same thing
+as @code{ @{ c @ @ @ @ @  d e @} } and
+@example
+          @{
+c                        d
+  e @}
+@end example
+
+@noindent
+Of course, the previous example is hard to read.  A good rule of thumb
+is to indent code blocks with either a tab or two spaces:
+@example
+@{
+  c d e
+@}
+@end example
+
+@item @strong{Expressions:}
+Every piece of LilyPond input needs to have
+@strong{@{ curly braces @}} placed around the input.  These braces tell
+LilyPond that the input is a single music expression, just like
+parenthesis @samp{()} in mathematics.  The braces should
+be surrounded by a space unless they are at the beginning or end of a
+line to avoid ambiguities.
+
+A function (such as @code{\relative @{ @}} ) also counts as a single
+music expression.
+
+@cindex comments
+@cindex line comment
+@cindex block comment
+@item @strong{Comments}:
+A comment is a remark for the human reader of the music input; it is
+ignored while parsing, so it has no effect on the printed output.
+There are two types of comments.  The percent symbol @samp{%}
+introduces a line comment; anything after @samp{%} on that line is
+ignored.  A block comment marks a whole section of music
+input as a comment.  Anything that is enclosed in @code{%@{} and @code{%@}} is
+ignored.  The following fragment shows possible uses for comments
+
+@example
+% notes for twinkle twinkle follow
+  c4 c g' g a a g2
+
+%@{
+    This line, and the notes below
+    are ignored, since they are in a
+    block comment.
+
+    g g f f e e d d c2
+%@}
+@end example
+
+@end itemize
+
+There are more tips for constructing input files in
+@ref{Suggestions for writing LilyPond files}.
+
+
+@node How to read the tutorial
+@subsection How to read the tutorial
+
+As we saw in @ref{Working on text files}, LilyPond input must be
+surrounded by @{ @} marks or a @code{\relative c'' @{ ... @}}.  For the
+rest of this manual, most examples will omit this.
+
+If you are reading the HTML documentation and wish to see the exact
+exact LilyPond code that was used to create the example, simply click
+on the picture.  If you are not reading the HTML version, you could
+copy and paste the displayed input, but you @strong{must} add the
+@code{\relative c'' @{ @}} like this:
+
+@example
+\relative c'' @{
+  ... example goes here...
+@}
+@end example
+
+Why omit the braces?  Most examples
+in this manual can be inserted into the middle of a longer piece of
+music.  For these examples, it does not make sense to add
+@code{\relative c'' @{ @}} -- you should not place a @code{\relative}
+inside another @code{\relative}, so you would not be able to copy
+a small documentation example and paste it inside a longer piece
+of your own.
+
+
+@node Single staff notation
+@section Single staff notation
+
+This section introduces common notation that is used for one voice
+on one staff.
+
+@menu
+* Relative note names::         
+* Accidentals and key signatures::  
+* Ties and slurs::              
+* Articulation and dynamics::   
+* Automatic and manual beams::  
+* Advanced rhythmic commands::  
+@end menu
+
+
+@node Relative note names
+@subsection Relative note names
+
+As we saw in @ref{Simple notation}, LilyPond calculates the pitch of
+each note relative to the previous one@footnote{There is another mode of
+entering pitches, @ref{Absolute note names}, but in practice relative
+mode is much easier and safer to use.}.  If no extra octave marks
+(@code{'} and @code{,}) are added, it assumes that each pitch is within
+a fourth of the previous note.
+
+LilyPond examines pitches based on the note names -- in other words,
+an augmented fourth is @emph{not} the same as a diminished fifth.  If we
+begin at a C, then an F-sharp will be placed a higher than the C, while
+a G-flat will be placed lower than the C.
+
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c2 fis
+c2 ges
+@end lilypond
+
+@moreinfo
+@quotation
+@table @asis
+@item Relative octaves
+see @ref{Relative octaves}.
+@item Octave check
+see @ref{Octave check}.
 @end table
 @end quotation
 
 
-@node More about pitches
-@section More about pitches
+
+@node Accidentals and key signatures
+@subsection Accidentals and key signatures
+
+@subheading Accidentals
 
 A @rglos{sharp} pitch is made by adding @samp{is} to
-the name, a @rglos{flat} pitch by adding @samp{es}.  As
+the name, and a @rglos{flat} pitch by adding @samp{es}.  As
 you might expect, a @rglos{double sharp} or @rglos{double flat} is
 made by adding @samp{isis} or @samp{eses}@footnote{This syntax
 derived from note naming conventions in Nordic and Germanic languages,
-like German and Dutch.}
+like German and Dutch.  To use other names for accidentals, see
+@ref{Note names in other languages}.}
 
-@example
-cis1 ees fisis aeses
-@end example
-
-@lilypond[fragment,quote,notime]
-\set Score.timing = ##f
-\transpose c c' { cis1 ees fisis aeses s16_" " }
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+cis1 ees fisis, aeses
 @end lilypond
 
 @cindex key signature, setting
-The key signature is set with the command @code{\key}, followed by
-a pitch and @code{\major} or @code{\minor}
+@subheading Key signatures
 
-@example
-\key d \major
-g1
-\key c \minor
-g
-@end example
+The key signature is set with the command @code{\key} followed by
+a pitch and @code{\major} or @code{\minor}.
 
-@lilypond[fragment,quote,notime,fragment]
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
 \key d \major
-g'1
+a1
 \key c \minor
-g'
+a
 @end lilypond
 
-@noindent
-Key signatures together with the pitches (including alterations) are
-used to determine when to print accidentals.  This is a
+@sp 1
+
+@subheading Warning: key signatures and pitches
+
+To determine whether to print an accidental, LilyPond examines the
+pitches and the key signature.  The key signature only effects
+the @emph{printed} accidentals, not the actual pitches!  This is a
 feature that often causes confusion to newcomers, so let us explain it
 in more detail.
 
-
 LilyPond makes a sharp distinction between musical content and
 layout.  The alteration (flat, natural or sharp) of a note is part of
 the pitch, and is therefore musical content.  Whether an accidental (a
-flat, natural or sharp @emph{sign}) is printed in front of the
+@emph{printed} flat, natural or sharp sign) is printed in front of the
 corresponding note is a question of layout.  Layout is something that
 follows rules, so accidentals are printed automatically according to
 those rules.  The pitches in your music are works of art, so they will
@@ -378,246 +580,356 @@ not be added automatically, and you must enter what you want to hear.
 
 In this example
 
-@lilypond[quote,notime,fragment]
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
 \key d \major
-d' cis' fis'
+d cis fis
 @end lilypond
 
 @noindent
-no note has an explicit accidental, but you still must enter
-
-@example
-\key d \major
-d cis fis
-@end example
+No note has a printed accidental, but you must still add the @samp{is} to
+@code{cis} and @code{fis}.
 
-@noindent
-The code @samp{d} does not mean @qq{print a black dot just below the
-staff.}  Rather, it means: @qq{a note with pitch D-natural.}  In the key
-of A-flat major, it does get an accidental
+The code @samp{e} does not mean @qq{print a black dot just below the
+first line of the staff.}  Rather, it means: @qq{there is a note with
+pitch E-natural.}  In the key of A-flat major, it @emph{does} get an
+accidental:
 
-@lilypond[quote,notime,fragment,relative=1,verbatim]
-\key as \major
-d
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+\key aes \major
+e
 @end lilypond
 
 Adding all alterations explicitly might require a little more effort
 when typing, but the advantage is that transposing is easier, and
 accidentals can be printed according to different conventions.  See
-@ref{Automatic accidentals}, for some examples how accidentals can be printed
+@ref{Automatic accidentals} for some examples how accidentals can be printed
 according to different rules.
 
-
-For more information on
-
+@moreinfo
 @quotation
 @table @asis
 @item Accidentals
-see @ref{Automatic accidentals}.
-
+see @ref{Accidentals} and @ref{Automatic accidentals}.
 @item Key signature
 see @ref{Key signature}.
 @end table
 @end quotation
 
-@node Entering ties
-@section Entering ties
 
-@cindex tie
+@node Ties and slurs
+@subsection Ties and slurs
+
+@cindex ties
+@subheading Ties
 A @rglos{tie} is created by appending a tilde @samp{~} to the first
 note being tied
 
-@lilypond[quote,notime,fragment,verbatim,relative=3]
-g4~ g a2~ a4
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+g4~ g c2~
+c4 ~ c8 a8 ~ a2
 @end lilypond
 
-For more information on Ties see @ref{Ties}.
-
-
+@cindex slurs
+@subheading Slurs
 
-@node Automatic and manual beams
-@section Automatic and manual beams
-
-@cindex beams, by hand
-All @rglos{beam}s are drawn automatically
+A @rglos{slur} is a curve drawn across many notes.  The starting note
+and ending note are marked with @samp{(} and @samp{)} respectively.
 
-@lilypond[quote,fragment,relative=2,verbatim]
-a8 ais d es r d
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+d4( c16) cis( d e c cis d) e( d4)
 @end lilypond
 
-@noindent
-If you do not like where beams are put, they can be entered by
-hand.  Mark the first note to be beamed with @samp{[} and the last one
-with @samp{]}.
+@cindex slurs, phrasing
+@cindex phrasing slurs
+@subheading Phrasing slurs
+
+@cindex phrasing slurs
+Slurs to indicate longer phrasing can be entered with @code{\(} and
+@code{\)}.  You can have both legato slurs and phrasing slurs at the
+same time, but you cannot have simultaneous slurs or simultaneous
+phrasing slurs.
 
-@lilypond[quote,fragment,relative=2,verbatim]
-a8[ ais] d[ es r d]
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+a8(\( ais b c) cis2 b'2 a4 cis,\)
 @end lilypond
 
-For more information on beams, see @ref{Manual beams}.
+@sp 1
 
+@cindex slurs versus ties
+@subheading Warnings: slurs vs. ties
 
-Here are key signatures, accidentals and ties in action
+A slur looks like a @rglos{tie}, but it has a different meaning.  A
+tie simply makes the first note longer, and can only be used on
+pairs of notes with the same pitch.  Slurs indicate the articulations
+of notes, and can be used on larger groups of notes.  Slurs and ties
+can be nested.
 
-@lilypond[fragment,quote,noindent,line-width=50\staff-space,verbatim]
-\relative c'' {
-  \time 4/4
-  \key g \minor
-  \clef treble
-  r4 r8 a8 gis4 b
-  a8 d4.~ d e,8
-  fis4 fis8 fis8 eis4 a8 gis~
-  gis2 r2
-}
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c2~( c8 fis fis4 ~ fis2 g2)
 @end lilypond
 
-@cindex accidentals
-
-
-@noindent
-There are some interesting points to note in this example.  Bar lines
-and beams are drawn automatically.  Line breaks are calculated
-automatically; it does not matter where the line breaks are in the
-source file.  Finally, the order in which time, key, and clef changes
-are entered is not relevant: in the printout, these are ordered
-according to standard notation conventions.
+@moreinfo
+@quotation
+@table @asis
+@item Ties
+see @ref{Ties}.
+@item Slurs
+see @ref{Slurs}.
+@item Phrasing slurs
+see @ref{Phrasing slurs}.
+@end table
+@end quotation
 
 
+@node Articulation and dynamics
+@subsection Articulation and dynamics
 
-@node Octave entry
-@section Octave entry
+@cindex articulation
+@cindex accents
+@cindex staccato
+@subheading Articulations
 
+@c  FIXME: change to @rglos once the term is added  (articulations)
+Common articulations can be added to a note using a dash (@samp{-}) and a
+single character:
 
-@c Tim wants to move this quotes example just before the: quotes-do not-work
-@c score, but we'd need to remove quotes from the other two (key and
-@c tie) examples...
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c-. c-- c-> c-^ c-+ c-_
+@end lilypond
 
-@c better to have this just before the `octaves are bad' snipped
-@c but we'd need to remove the ', from \key and tie
-To raise a note by an octave, add a high quote @samp{'} (apostrophe) to
-the note name, to lower a note one octave, add a @q{low quote} @samp{,}
-(comma).  Middle C is @code{c'}
+@cindex fingering
+@subheading Fingerings
+Similarly, fingering indications can be added to a note using a dash
+(@samp{-}) and the digit to be printed:
 
-@lilypond[quote,notime,fragment,verbatim]
-c'4 c'' c''' \clef bass c c,
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c-3 e-5 b-2 a-1
 @end lilypond
 
-An example of the use of quotes is in the following Mozart fragment
+Articulations and fingerings are usually placed automatically, but you
+can specify a direction using @samp{^} (up) or @samp{_} (down).  You can
+also use multiple articulations on the same note.  However, in most cases
+it is best to let LilyPond determine the articulation directions.
 
-@lilypond[quote,ragged-right,fragment,verbatim]
-\key a \major
-\time 6/8
-cis''8. d''16 cis''8 e''4 e''8
-b'8. cis''16 b'8 d''4 d''8
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c_-^1 d^. f^4_2-> e^-_+
 @end lilypond
 
-@noindent
-This example shows that music in a high register needs lots of quotes.
-This makes the input less readable, and it is a source of errors.  The
-solution is to use @q{relative octave} mode.   This is the
-most convenient way to copy existing music.
-
-In relative mode, a note without octavation quotes (i.e., the @samp{'}
-or @samp{,} after a note) is chosen so that it is closest to the
-previous one.  For example, @samp{c f} goes up while @samp{c g} goes
-down.
+@subheading Dynamics
+Dynamic signs are made by adding the markings (with a backslash) to
+the note
 
-To use relative mode, add @code{\relative} before the piece of
-music.  The first note is taken relative to the middle C
-@c no , for this sentence
-(i.e., @code{c'})
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c\ff c\mf c\p c\pp
+@end lilypond
 
+@cindex dynamics
+@cindex decrescendo
+@cindex crescendo
 
+Crescendi and decrescendi are started with the commands @code{\<} and
+@code{\>}.  An ending dynamic, for example @code{\f}, will finish the
+(de)crescendo, or the command @code{\!} can be used
 
-@lilypond[quote,notime,fragment,verbatim]
-\relative {
-  c' f c g c
-}
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c2\< c2\ff\> c2 c2\!
 @end lilypond
 
+@moreinfo
+@quotation
+@table @asis
+@item Articulations
+see @ref{Articulations}.
+@item Fingering
+see @ref{Fingering instructions}.
+@item Dynamics
+see @ref{Dynamics}.
+@end table
+@end quotation
 
-Since most music has small intervals, pieces can be written almost
-without octavation quotes in relative mode.  The previous example is
-entered as
 
-@lilypond[quote,ragged-right,verbatim]
-\relative {
-  \key a \major
-  \time 6/8
-  cis'8. d16 cis8 e4 e8
-  b8. cis16 b8 d4 d8
-}
+@node Automatic and manual beams
+@subsection Automatic and manual beams
+
+@cindex beams, by hand
+All @rglos{beam}s are drawn automatically:
+
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+a8 ais d ees r d c16 b a8
 @end lilypond
 
-@c needed better, maybe even redundant explanation
-@c   added another example below.
-@c grappig: Pa vond het heel logies, en slim toen-i eenmaal begreep.
-@c in eerste instantie drong het `relative' niet door zonder extra uitleg.
-Larger intervals are made by adding octavation quotes.
+@noindent
+If you do not like the automatic beams, they may be overridden
+manually.  Mark the first note to be beamed with @samp{[} and the last one
+with @samp{]}.
 
-@lilypond[quote,notime,verbatim,fragment]
-\relative c {
-  c'' f, f c' c g' c,
-}
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+a8[ ais] d[ ees r d] a b
 @end lilypond
 
-In summary, quotes or commas no longer determine the absolute height
-of a note in @code{\relative} mode.  Rather, the height of a note is
-relative to the previous one, and changing the octave of a single note
-shifts all following notes an octave up or down.
+@moreinfo
+@quotation
+@table @asis
+@item Automatic beams
+see @ref{Automatic beams}.
+@item Manual beams
+see @ref{Manual beams}.
+@end table
+@end quotation
+
+
+@node Advanced rhythmic commands
+@subsection Advanced rhythmic commands
 
-For more information on relative octaves see @ref{Relative octaves},
-and @ref{Octave check}.
+@cindex pickup
+@cindex anacruse
+@cindex partial measure
+@subheading Partial measure
 
+@c FIXME: glossary "anacrusis".
+A pickup (or @q{anacrusis}) is entered with the keyword @code{\partial}.  It
+is followed by a duration: @code{\partial 4} is a quarter note pickup
+and @code{\partial 8} an eighth note.
 
-@node Music expressions explained
-@section Music expressions explained
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+\partial 8
+f8 c2 d
+@end lilypond
 
+@cindex tuplets
+@cindex triplets
+@subheading Tuplets
 
-In input files, music is represent by so-called @emph{music
-expression}s.  We have already seen some in the previous examples;
-a single note is a music expression
+Tuplets are made with the @code{\times} keyword.  It takes two
+arguments: a fraction and a piece of music.  The duration of the piece
+of music is multiplied by the fraction.  Triplets make notes occupy
+2/3 of their notated duration, so a triplet has 2/3 as its fraction
 
-@lilypond[fragment,quote,verbatim,relative=3]
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+\times 2/3 { f8 g a }
+\times 2/3 { c r c }
+\times 2/3 { f,8 g16 a g a }
+\times 2/3 { d4 a8 }
+@end lilypond
+
+@cindex grace notes
+@cindex acciaccatura
+@cindex appoggiatura
+@subheading Grace notes
+
+Grace notes are created with the @code{\grace} command, although they
+can also be created by prefixing a music expression with the
+keyword @code{\appoggiatura} or @code{\acciaccatura}
+
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+c2 \grace { a32 b} c2
+c2 \appoggiatura b16 c2
+c2 \acciaccatura b16 c2
+@end lilypond
+
+@moreinfo
+@quotation
+@table @asis
+@item Grace notes
+see @ref{Grace notes},
+@item Tuplets
+see @ref{Tuplets},
+@item Pickups
+see @ref{Partial measures}.
+@end table
+@end quotation
+
+
+@node Multiple notes at once
+@section Multiple notes at once
+
+This section introduces having more than one note at the same time:
+multiple instruments, multiple staves for a single instrument (i.e. piano),
+and chords.
+
+Polyphony in music refers to having more than one voice occurring in
+a piece of music.  Polyphony in LilyPond refers to having more than
+one voice on the same staff.
+
+@menu
+* Music expressions explained::  
+* Multiple staves::             
+* Piano staves::                
+* Single staff polyphony::      
+* Combining notes into chords::  
+@end menu
+
+
+@node Music expressions explained
+@subsection Music expressions explained
+
+In LilyPond input files, music is represented by @emph{music
+expressions}.  A single note is a music expression, although it is not
+valid input all on its own.
+
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
 a4
 @end lilypond
 
-Enclosing a group of notes in braces creates a new music
-expression
+Enclosing a group of notes in braces creates a new music expression:
 
-@lilypond[fragment,quote,verbatim,relative=3]
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
 { a4 g4 }
 @end lilypond
 
-Putting a bunch of music expressions (e.g., notes) in braces, means that
-they should be played in sequence.  The result again is a music
-expression, which can be grouped with other expressions sequentially.
-Here, the expression from the previous example is combined with two
-notes
+Putting a group of music expressions (e.g. notes) in braces means that
+are in sequence (i.e. each one follows the previous one).  The result
+is another music expression:
 
-@lilypond[fragment,quote,verbatim,relative=3]
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
 { { a4 g } f g }
 @end lilypond
 
-This technique is useful for non-monophonic music.  To enter music
-with more voices or more staves, we also combine expressions in
-parallel.  Two voices that should play at the same time, are entered
-as a simultaneous combination of two sequences.  A @q{simultaneous}
-music expression is formed by enclosing expressions in @code{<<} and
-@code{>>}.  In the following example, three sequences (all containing
-two separate notes) are combined simultaneously
+@subheading Simultaneous music expressions: multiple staves
 
-@lilypond[fragment,quote,verbatim,relative=3]
-<<
-  { a4 g }
-  { f e }
-  { d b }
->>
+This technique is useful for polyphonic music.  To enter music
+with more voices or more staves, we combine expressions in
+parallel.  To indicate that two voices should play at the same time
+simple enter a simultaneous combination of music expressions.  A
+@q{simultaneous} music expression is formed by enclosing expressions inside
+@code{<<} and @code{>>}.  In the following example, three sequences (all
+containing two separate notes) are combined simultaneously:
+
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  <<
+    { a4 g }
+    { f e }
+    { d b }
+  >>
+}
 @end lilypond
 
+Note that we have indented each level of the input with a different
+amount of space.  LilyPond does not care how much (or little) space there
+is at the beginning of a line, but indenting LilyPond code like this makes
+it much easier for humans to read.
+
+@subheading Simultaneous music expressions: single staff
+
+To determine the number of staves in a piece, LilyPond looks at the first
+exression.  If it is a single note, there is one staff; if there is a
+simultaneous expression, there is more than one staff.
+
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  c2 <<c e>>
+  << { e f } { c <<b d>> } >>
+}
+@end lilypond
+
+@cindex expression
+@cindex music expression
+@subheading Analogy: mathematical expressions
+
 This mechanism is similar to mathematical
 formulas: a big formula is created by composing small formulas.  Such
-formulas are called expressions, and their definition is recursive, so
+formulas are called expressions, and their definition is recursive so
 you can make arbitrarily complex and large expressions.  For example,
 
 @example
@@ -630,8 +942,6 @@ you can make arbitrarily complex and large expressions.  For example,
 ((1 + 2) * 3) / (4 * 5)
 @end example
 
-@cindex expression
-@cindex music expression
 This is a sequence of expressions, where each expression is contained
 in the next (larger) one.  The simplest expressions are numbers, and larger
 ones are made by combining expressions with operators (like @samp{+},
@@ -639,66 +949,37 @@ ones are made by combining expressions with operators (like @samp{+},
 music expressions can be nested arbitrarily deep, which is necessary
 for complex music like polyphonic scores.
 
-Note that this example only has one staff, whereas
-the previous example had three separate staves.  That is because this
-example begins with a single note.  To determine the number of staves,
-LilyPond looks at the first element.  If it is a single note, there is one
-staff; if there is a simultaneous expression, there is more than one staff.
-
-@lilypond[fragment,quote,verbatim,relative=2]
-{
-  c <<c e>>
-  << { e f } { c <<b d>> } >>
-}
-@end lilypond
-
-Music files with deep nesting can be confusing to enter and
-maintain.  One convention that helps against this confusion is
-indenting.  When entering a file with deep nesting of braces and
-angles, it is customary to use an indent that indicates the nesting
-level.  Formatting music like this eases reading and helps you insert
-the right number of closing braces at the end of an expression.  For
-example,
-
-@example
-<<
-  @{
-    @dots{}
-  @}
-  @{
-    @dots{}
-  @}
->>
-@end example
 
-Some editors have special support for entering LilyPond, and can help
-indenting source files.  See @ref{Editor support} for more information.
+@node Multiple staves
+@subsection Multiple staves
 
-@node More staves
-@section More staves
+As we saw in @ref{Music expressions explained}, LilyPond input files
+are constructed out of music expressions.  If the score begins with
+simultaneous music expressions, LilyPond creates multiples staves.  However,
+it is easier to see what happens if we create each staff explicitly.
 
 To print more than one staff, each piece of music that makes up a
 staff is marked by adding @code{\new Staff} before it.  These
 @code{Staff} elements are then combined in parallel with @code{<<} and
-@code{>>}, as demonstrated here
+@code{>>}:
 
-@lilypond[quote,fragment,verbatim]
-<<
-  \new Staff { \clef treble c'' }
-  \new Staff { \clef bass c }
->>
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  <<
+    \new Staff { \clef treble c }
+    \new Staff { \clef bass c,, }
+  >>
+}
 @end lilypond
 
-
 The command @code{\new} introduces a @q{notation context.}  A notation
 context is an environment in which musical events (like notes or
 @code{\clef} commands) are interpreted.  For simple pieces, such
 notation contexts are created automatically.  For more complex pieces, it
-is best to mark contexts explicitly.  This ensures that each fragment
-gets its own stave.
+is best to mark contexts explicitly.
 
-There are several types of contexts.  @code{Staff}, @code{Voice} and
-@code{Score} handle melodic notation, while @code{Lyrics} sets lyric
+There are several types of contexts.  @code{Score}, @code{Staff},
+and @code{Voice} handle melodic notation, while @code{Lyrics} sets lyric
 texts and @code{ChordNames} prints chord names.
 
 In terms of syntax, prepending @code{\new} to a music expression
@@ -706,320 +987,188 @@ creates a bigger music expression.  In this way it resembles the minus
 sign in mathematics.  The formula @math{(4+5)} is an expression, so
 @math{-(4+5)} is a bigger expression.
 
-We can now typeset a melody with two staves
-
-@c TODO: (c) status of this Paul McCartney (?) song (let's all stand together)
-
-@lilypond[fragment,quote,verbatim,ragged-right]
-\relative <<
-  \new Staff {
-    \time 3/4
-    \clef treble
+Time signatures entered in one staff affects all other staves, but
+the key signature of one staff does @emph{not} affect other
+staves@footnote{This behavior may be changed if desired; see
+@ref{Changing defaults} for details.}.
 
-    e'2 d4 c2 b4 a8[ a]
-    b[ b] g[ g] a2.
-  }
-  \new Staff {
-     \clef bass
-     c,,2 e4 g2.
-     f4 e d c2.
-  }
->>
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  <<
+    \new Staff { \clef treble \time 3/4 c }
+    \new Staff { \clef bass \key d \major c,, }
+  >>
+}
 @end lilypond
 
-For more information on contexts see the description in
-@ref{Interpretation contexts}.
-
 
 
-@node Adding articulation marks to notes
-@section Adding articulation marks to notes
-
-@cindex articulation
-@cindex accents
-@cindex staccato
-
-Common accents can be added to a note using a dash (@samp{-}) and a
-single character
-
-@lilypond[fragment,quote,verbatim,relative=2]
-c-.  c-- c-> c-^ c-+ c-_
-@end lilypond
 
-@cindex fingering
-Similarly, fingering indications can be added to a note using a dash
-(@samp{-}) and the digit to be printed
-
-@lilypond[fragment,quote,verbatim,relative=2]
-c-3 e-5 b-2 a-1
-@end lilypond
+@node Piano staves
+@subsection Piano staves
 
-Articulations and fingerings are usually placed automatically, but you
-can specify a direction using @samp{^} (up) or @samp{_} (down).  You can
-also use multiple articulations on the same note.  In most cases, however,
-it is best to let LilyPond determine the articulation directions.
+@cindex staff switch, manual
+@cindex cross staff voice, manual
+Piano music is typeset in two staves connected by a brace.  Printing
+such a staff is similar to the polyphonic example in @ref{Multiple staves},
+but now this entire expression is inserted inside a @code{PianoStaff}:
 
-@lilypond[fragment,quote,verbatim,relative=2]
-c_-^1 d^. f^4_2-> e^-_+
-@end lilypond
+@example
+\new PianoStaff <<
+  \new Staff @dots{}
+  \new Staff @dots{}
+>>
+@end example
 
-Dynamic signs are made by adding the markings (with a backslash) to
-the note
+Here is a small example
 
-@lilypond[fragment,quote,verbatim,relative=2]
-c\ff c\mf
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  \new PianoStaff <<
+    \new Staff { \time 2/4 c4 e g g, }
+    \new Staff { \clef bass c,, c' e c }
+  >>
+}
 @end lilypond
 
-@cindex dynamics
-@cindex decrescendo
-@cindex crescendo
-
-Crescendi and decrescendi are started with the commands @code{\<} and
-@code{\>}.  An ending dynamic, for example @code{\f}, will finish the
-(de)crescendo, or the command @code{\!} can be used
-
-@lilypond[fragment,quote,verbatim,relative=2]
-c2\< c2\ff\> c2 c2\!
-@end lilypond
+@moreinfo
+@quotation
+See @ref{Piano music}.
+@end quotation
 
 
+@node Single staff polyphony
+@subsection Single staff polyphony
 
-@cindex slur
+@cindex polyphony
+@cindex multiple voices
+@cindex voices, more -- on a staff
+When different melodic lines are combined on a single staff they are
+printed as polyphonic voices; each voice has its own stems, slurs and
+beams, and the top voice has the stems up, while the bottom voice has
+them down.
 
-A @rglos{slur} is a curve drawn across many notes, and indicates
-legato articulation.  The starting note and ending note are marked
-with @samp{(} and @samp{)}, respectively
+Entering such parts is done by entering each voice as a sequence (with
+@code{@{...@}}) and combining these simultaneously, separating the
+voices with @code{\\}
 
-@lilypond[fragment,quote,fragment,relative=2,verbatim]
-d4( c16) cis( d e c cis d) e( d4)
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+<<
+  { a4 g2 f4~ f4 } \\
+  { r4 g4 f2 f4 }
+>>
 @end lilypond
 
-@cindex slurs versus ties
-A slur looks like a @rglos{tie}, but it has a different meaning.  A
-tie simply makes the first note sound longer, and can only be used on
-pairs of notes with the same pitch.  Slurs indicate the articulations
-of notes, and can be used on larger groups of notes.  Slurs and ties
-can be nested
+For polyphonic music typesetting, spacer rests can also be convenient;
+these are rests that do not print.  They are useful for filling up
+voices that temporarily do not play.  Here is the same example with a
+spacer rest (@samp{s}) instead of a normal rest (@samp{r}),
 
-@lilypond[quote,fragment,relative=2]
-c2~( c8 fis fis4 ~ fis2 g2)
+@lilypond[quote,ragged-right,verbatim,fragment,relative=2]
+<<
+  { a4 g2 f4~ f4 } \\
+  { s4 g4 f2 f4 }
+>>
 @end lilypond
 
-@cindex phrasing slurs
-Slurs to indicate phrasing can be entered with @code{\(} and
-@code{\)}, so you can have both legato slurs and phrasing slurs at the
-same time.  You cannot have simultaneous slurs or simultaneous
-phrasing slurs.
+@noindent
+Again, these expressions can be nested arbitrarily.
 
-@lilypond[quote,fragment,relative=2,verbatim]
-a8(\( ais b c) cis2 b'2 a4 cis, c\)
+@lilypond[quote,fragment,verbatim,relative=2,fragment]
+<<
+  \new Staff <<
+    { a4 g2 f4~ f4 } \\
+    { s4 g4 f2 f4 }
+  >>
+  \new Staff <<
+    \clef bass
+    { <c g>1 ~ <c g>4 } \\
+    { e,,4 d e2 ~ e4}
+  >>
+>>
 @end lilypond
 
-
-For more information on
-
+@moreinfo
 @quotation
-@table @asis
-@item Fingering
-see @ref{Fingering instructions}.
-@item Articulations
-see @ref{Articulations}.
-@item Slurs
-see @ref{Slurs}.
-@item Phrasing slurs
-see @ref{Phrasing slurs}.
-@item Dynamics
-see @ref{Dynamics}.
-@end table
+See @ref{Basic polyphony}.
 @end quotation
 
 
 @node Combining notes into chords
-@section Combining notes into chords
+@subsection Combining notes into chords
 
 @cindex chords
-Chords can be made by surrounding pitches with angle brackets.
-Angle brackets are the symbols @samp{<} and @samp{>}.
+Chords can be made by surrounding pitches with single angle brackets.  Angle
+brackets are the symbols @samp{<} and @samp{>}.
 
-@lilypond[quote,relative=1,fragment,verbatim]
-r4 <c e g>4 <c f a>8
+@lilypond[quote,fragment,verbatim,relative=2,fragment]
+r4 <c e g>4 <c f a>2
 @end lilypond
 
-
 You can combine markings like beams and ties with chords.  They must
 be placed outside the angled brackets
 
-@lilypond[quote,relative=1,fragment,verbatim]
-r4 <c e g>8[ <c f a>]~ <c f a>
-@end lilypond
-
-@example
-r4 <c e g>8\>( <c e g> <c e g> <c f a>\!)
-@end example
-
-@lilypond[quote,relative=1,fragment]
-\slurUp
-r4 <c e g>8\>( <c e g> <c e g> <c f a>\!)
-@end lilypond
-
-
-@node Advanced rhythmic commands
-@section Advanced rhythmic commands
-
-@cindex pickup
-@cindex anacruse
-@cindex partial measure
-A pickup is entered with the keyword @code{\partial}.  It
-is followed by a duration: @code{\partial 4} is a quarter note upstep
-and @code{\partial 8} an eighth note
-
-@lilypond[quote,relative=2,verbatim,fragment]
-\partial 8
-f8 c2 d e
-@end lilypond
-
-@cindex tuplets
-@cindex triplets
-Tuplets are made with the @code{\times} keyword.  It takes two
-arguments: a fraction and a piece of music.  The duration of the piece
-of music is multiplied by the fraction.  Triplets make notes occupy
-2/3 of their notated duration, so a triplet has 2/3 as its fraction
-
-@lilypond[quote,relative=1,verbatim,fragment]
-\times 2/3 { f8 g a }
-\times 2/3 { c r c }
+@lilypond[quote,fragment,verbatim,relative=2,fragment]
+r4 <c e g>8[ <c f a>]~ <c f a>2
 @end lilypond
 
-@cindex grace notes
-@cindex acciaccatura
-Grace notes are also made by prefixing a music expression with the
-keyword @code{\appoggiatura} or @code{\acciaccatura}
-@cindex appoggiatura
-@cindex acciaccatura
-
-@lilypond[quote,relative=2,verbatim,fragment]
-c4 \appoggiatura b16 c4
-c4 \acciaccatura b16 c4
+@lilypond[quote,fragment,verbatim,relative=2,fragment]
+r4 <c e g>8\>( <c e g> <c e g>4 <c f a>\!)
 @end lilypond
 
-@noindent
-
-For more information on
-
-@quotation
-@table @asis
-@item Grace notes
-see @ref{Grace notes},
-@item Tuplets
-see @ref{Tuplets},
-@item Pickups
-see @ref{Partial measures}.
-@end table
-@end quotation
-
-
-@node Commenting input files
-@section Commenting input files
-
-@cindex comments
-@cindex line comment
-@cindex block comment
-A comment is a remark for the human reader of the music input; it is
-ignored while parsing, so it has no effect on the printed output.
-There are two types of comments.  The percent symbol @samp{%}
-introduces a line comment; after @samp{%} the rest of the line is
-ignored.  A block comment marks a whole section of music
-input.  Anything that is enclosed in @code{%@{} and @code{%@}} is
-ignored.  The following fragment shows possible uses for comments
-
-@example
-% notes for twinkle twinkle follow
-  c4 c g' g a a g2
-
-%@{
-    This line, and the notes below
-    are ignored, since they are in a
-    block comment.
-
-    g g f f e e d d c2
-%@}
-@end example
 
-@c  TODO   post-2.6 reorg
-@c   This is good info, but I wouldn't call it a comment.  IMO it should
-@c   be moved somewhere else.
+@node Songs
+@section Songs
 
-@cindex versioning
-
-There is a special statement that is a kind of comment.  The @code{\version}
-statement marks for which version of LilyPond the file was written.
-To mark a file for version 2.10.1, use
-
-@example
-\version "2.10.1"
-@end example
+This section introduces vocal music and simple song sheets.
 
-@noindent
-These annotations make future upgrades of LilyPond go more
-smoothly.  Changes in the syntax are handled with a special program,
-@file{convert-ly} (see @ref{Updating files with convert-ly}), and it uses
-@code{\version} to determine what rules to apply.
+@menu
+* Printing lyrics::             
+* A lead sheet::                
+@end menu
 
 
 @node Printing lyrics
-@section Printing lyrics
-@cindex lyrics
-
-@c TODO: (c) status of the Queen fragment.
+@subsection Printing lyrics
 
 @cindex Lyrics
 @cindex Songs
-Lyrics are entered by separating each syllable with a space
+Consider a simple melody:
 
-@example
-I want to break free
-@end example
-
-Consider the melody
-
-@lilypond[quote,verbatim,fragment,ragged-right]
-\relative {
-  r4 c \times 2/3 { f g g }
-  \times 2/3 { g4( a2) }
+@lilypond[quote,ragged-right,verbatim]
+\relative c'' {
+  a4 e c r4
+       b2 c4( d)
 }
 @end lilypond
 
 The lyrics can be set to these notes, combining both with the
-@code{\addlyrics} keyword
+@code{\addlyrics} keyword.  Lyrics are entered by separating each
+syllable with a space.
 
-@lilypond[quote,verbatim,fragment,ragged-right]
+@lilypond[quote,ragged-right,verbatim]
 <<
-  \relative {
-    r4 c \times 2/3 { f g g }
-    \times 2/3 { g4( a2) }
+  \relative c'' {
+    a4 e c r4
+         b2 c4( d)
   }
-  \addlyrics { I want to break free }
+  \addlyrics { One day this shall be free }
 >>
 @end lilypond
 
 @cindex melisma
 @cindex extender line
-@c synonyms?
 This melody ends on a @rglos{melisma}, a single syllable (@q{free})
 sung to more than one note.  This is indicated with an @emph{extender
-line}.  It is entered as two underscores, i.e.,
-
-@example
-@{ I want to break free __ @}
-@end example
+line}.  It is entered as two underscores @code{__}:
 
-@lilypond[fragment,quote,ragged-right]
+@lilypond[quote,ragged-right,verbatim]
 <<
-  \relative {
-    r4 c \times 2/3 { f g g }
-    \times 2/3 { g4( a2) }
+  \relative c'' {
+    a4 e c r4
+         b2 c4( d)
   }
-  \addlyrics { I want to break free __ }
+  \addlyrics { One day this shall be free __ }
 >>
 @end lilypond
 
@@ -1030,34 +1179,38 @@ resulting in a centered hyphen between two syllables
 A -- le gri -- a
 @end example
 
-@c no ragged-right here, because otherwise the hypens get lost.
-@lilypond[fragment,quote]
+@c no ragged-right here because otherwise the hypens get lost.
+@lilypond[quote,verbatim]
 <<
-  \relative {
+  \relative c' {
     \time 2/4
-    f4 f c' c
+    f4 f c c
   }
   \addlyrics { A -- le gri -- a }
 >>
 @end lilypond
 
-More options, like putting multiple lines of lyrics below a melody are
+@moreinfo
+@quotation
+More options, such as putting multiple stanzas below a melody, are
 discussed in @ref{Vocal music}.
+@end quotation
 
 
 @node A lead sheet
-@section A lead sheet
+@subsection A lead sheet
 
 @cindex Lead sheets
 @cindex chords
 @cindex chord names
 
 @c TODO: revise this, \chords { } is shorter and more intuitive.
+@c  I need help for this.  -gp
 
-In popular music, it is common to denote accompaniment with chord names.
+In popular music it is common to denote accompaniment with chord names.
 Such chords can be entered like notes,
 
-@lilypond[quote,verbatim,ragged-right]
+@lilypond[quote,ragged-right,verbatim]
 \chordmode { c2 f4. g8 }
 @end lilypond
 
@@ -1086,16 +1239,8 @@ following result.
 When put together, chord names, lyrics and a melody form
 a lead sheet, for example,
 
-@example
-<<
-  \chords @{ @emph{chords} @}
-  @emph{the melody}
-  \addlyrics @{ @emph{the text} @}
->>
-@}
-@end example
-
-@lilypond[quote,ragged-right]
+@lilypond[quote,verbatim,ragged-right]
+%  this melody needs to be changed.  See my new example in 2.4.1. -gp
 <<
   \chords { r2 c:sus4 f }
   \relative {
@@ -1110,145 +1255,179 @@ A complete list of modifiers and other options for layout can be found
 in @ref{Chords}.
 
 
+@node Final touches
+@section Final touches
+
+This is the final section of the tutorial; it demonstrates how to add the
+final touches to simple pieces, and provides an introduction to the rest
+of the manual.
+
+@menu
+* Version number::              
+* Adding titles::               
+* Absolute note names::         
+* Organizing pieces with identifiers::  
+* After the tutorial::          
+* How to read the manual::      
+@end menu
+
+
+@node Version number
+@subsection Version number
+
+@cindex versioning
+The @code{\version} statement marks for which version of LilyPond the file
+was written.  To mark a file for version 2.10.1, place
+
+@example
+\version "2.10.1"
+@end example
+
+@noindent
+at the top of your LilyPond file.
+
+These annotations make future upgrades of LilyPond go more
+smoothly.  Changes in the syntax are handled with a special program,
+@file{convert-ly} (see @ref{Updating files with convert-ly}), and it uses
+@code{\version} to determine what rules to apply.
+
+
 @node Adding titles
-@section Adding titles
+@subsection Adding titles
 
-Bibliographic information is entered in a separate block, the
-@code{\header} block.  The name of the piece, its composer, etc., are
-entered as an assignment, within @code{\header
-@{@tie{}@dots{}@tie{}@}}.  The @code{\header} block is usually put at
-the top of the file.  For example,
+The title, composer, opus number, and similar information are entered
+in the @code{\header} block.  This exists outside of the main
+music expression; the @code{\header} block is usually placed underneath
+the @ref{Version number}.
 
 @example
+\version "2.10.1"
 \header @{
-  title = "Miniature"
-  composer = "Igor Stravinsky"
+  title = "Symphony"
+  composer = "Me"
+  opus = "Op. 9"
 @}
 
-@{ @dots{} @}
+@{
+  @dots{} music @dots{}
+@}
 @end example
 
-
 When the file is processed, the title and composer are printed above
 the music.  More information on titling can be found in @ref{Creating
 titles}.
 
 
-@node Single staff polyphony
-@section Single staff polyphony
+@node Absolute note names
+@subsection Absolute note names
 
-@cindex polyphony
-@cindex multiple voices
-@cindex voices, more -- on a staff
-When different melodic lines are combined on a single staff they are
-printed as polyphonic voices; each voice has its own stems, slurs and
-beams, and the top voice has the stems up, while the bottom voice has
-them down.
+So far we have always used @code{\relative} to define pitches.  This is
+the easiest way to enter most music, but another way of defining pitches
+exists: absolute mode.
 
-Entering such parts is done by entering each voice as a sequence (with
-@code{@{...@}}), and combining these simultaneously, separating the
-voices with @code{\\}
+If you omit the @code{\relative}, LilyPond treats all pitches as
+absolute values.  A @code{c'} will always mean middle C, a @code{b} will
+always mean the note one step below middle C, and a @code{g,} will
+always mean the note on the bottom staff of the bass clef.
 
-@lilypond[quote,verbatim,relative=2,fragment]
-<< { a4 g2 f4~ f4 } \\
-   { r4 g4 f2 f4 } >>
+@lilypond[quote,verbatim,ragged-right]
+{
+  \clef bass
+  c' b g, g,
+  g, f, f c'
+}
 @end lilypond
 
-For polyphonic music typesetting, spacer rests can also be convenient;
-these are rests that do not print.  They are useful for filling up
-voices that temporarily do not play.  Here is the same example with a
-spacer rest (@samp{s}) instead of a normal rest (@samp{r}),
+Here is a four-octave scale:
 
-@lilypond[quote,verbatim,relative=2,fragment]
-<< { a4 g2 f4~ f4 } \\
-   { s4 g4 f2 f4 } >>
+@lilypond[quote,verbatim,ragged-right]
+{
+  \clef bass
+  c, d, e, f,
+  g, a, b, c
+  d e f g
+  a b c' d'
+  \clef treble
+  e' f' g' a'
+  b' c'' d'' e''
+  f'' g'' a'' b''
+  c'''1
+}
 @end lilypond
 
-@noindent
-Again, these expressions can be nested arbitrarily
+As you can see, writing a melody in the treble clef involves a lot of
+quote ' marks.  Consider this fragment from Mozart:
 
-@lilypond[quote,fragment,verbatim,relative=2,fragment]
-<<
-  \new Staff <<
-    { a4 g2 f4~ f4 } \\
-    { s4 g4 f2 f4 }
-  >>
-  \new Staff <<
-    \clef bass
-    { <c g>1 ~ <c g>4 } \\
-    { e,,4 d e2 ~ e4}
-  >>
->>
+@lilypond[quote,verbatim,ragged-right]
+{
+  \key a \major
+  \time 6/8
+  cis''8. d''16 cis''8 e''4 e''8
+  b'8. cis''16 b'8 d''4 d''8
+}
 @end lilypond
 
-More features of polyphonic typesetting are described in this manual
-in section @ref{Basic polyphony}.
-
-
-@node Piano staves
-@section Piano staves
-
-@cindex staff switch, manual
-@cindex cross staff voice, manual
-Piano music is typeset in two staves connected by a brace.  Printing
-such a staff is similar to the polyphonic example in @ref{More staves},
-
-@example
-<< \new Staff @{ @dots{} @}
-   \new Staff @{ @dots{} @} >>
-@end example
-
-@noindent
-but now this entire expression must be interpreted as a
-@code{PianoStaff}
-
-@example
-\new PianoStaff << \new Staff @dots{} >>
-@end example
-
-Here is a small example
+All these quotes makes the input less readable and it is a source of
+errors.  With @code{\relative}, the previous example is much easier
+to read:
 
-@lilypond[quote,verbatim,relative=1,fragment]
-\new PianoStaff <<
-  \new Staff { \time 2/4 c4 c g' g }
-  \new Staff { \clef bass c,, c' e c }
->>
+@lilypond[quote,verbatim,ragged-right]
+\relative c'' {
+  \key a \major
+  \time 6/8
+  cis8. d16 cis8 e4 e8
+  b8. cis16 b8 d4 d8
+}
 @end lilypond
 
-More information on formatting piano music is given in @ref{Piano music}.
+If you make a mistake with an octave mark (@code{'} or @code{,}) while
+working in @code{\relative} mode, it is very obvious -- many notes will
+be in the wrong octave.  When working in absolute mode, a single mistake
+will not be as visible, and will not be as easy to find.
 
+However, absolute mode is useful for music which has large intervals, and
+is extremely useful for computer-generated LilyPond files.
 
-@node Organizing larger pieces
-@section Organizing larger pieces
+
+@node Organizing pieces with identifiers
+@subsection Organizing pieces with identifiers
 
 When all of the elements discussed earlier are combined to produce
-larger files, the @code{\score} blocks get a lot bigger because the
-music expressions are longer, and, in the case of polyphonic music,
-more deeply nested.  Such large expressions can become unwieldy.
+larger files, the music expressions get a lot bigger.  In polyphonic
+music with many staves, the input files can become very confusing.  We can
+reduce this confusion by using @emph{identifiers}.
 
-By using variables, also known as identifiers, it is possible to break
-up complex music expressions.  An identifier is assigned as follows
+Identifiers (also known as variables or macros), we can break up
+complex music expressions.  An identifier is assigned as follows
 
 @example
 namedMusic = @{ @dots{} @}
 @end example
 
-@noindent
-The contents of the music expression @code{namedMusic}, can be used
-later by preceding the name with a backslash, i.e., @code{\namedMusic}.
-In the next example, a two-note motive is repeated two times by using
-variable substitution
-
-@lilypond[quote,ragged-right,verbatim,nofragment]
-seufzer = {
-  e'4( dis'4)
+The contents of the music expression @code{namedMusic} can be used
+later by placing a backslash in front of the name
+(@code{\namedMusic}, just like a normal LilyPond command).  Identifiers
+must be defined @emph{before} the main music expression.
+
+@lilypond[quote,verbatim,ragged-right]
+violin = \new Staff { \relative c'' {
+  a4 b c b
+}}
+cello = \new Staff { \relative c {
+  \clef bass
+  e2 d
+}}
+{
+  <<
+    \violin
+    \cello
+  >>
 }
-{ \seufzer \seufzer }
 @end lilypond
 
+@noindent
 The name of an identifier should have alphabetic characters only: no
-numbers, underscores, or dashes.  The assignment should be outside of
-running music.
+numbers, underscores, or dashes.
 
 It is possible to use variables for many other types of objects in the
 input.  For example,
@@ -1260,7 +1439,7 @@ aFivePaper = \paper @{ paperheight = 21.0 \cm @}
 @end example
 
 Depending on its contents, the identifier can be used in different
-places.  The following example uses the above variables
+places.  The following example uses the above variables:
 
 @example
 \paper @{
@@ -1270,148 +1449,16 @@ places.  The following example uses the above variables
 @{ c4^\name @}
 @end example
 
-More information on the possible uses of identifiers is given in the
-technical manual, in @ref{Input variables and Scheme}.
-@c fixme: the ref is too technical.
-
-
-@node An orchestral part
-@section An orchestral part
-
-In orchestral music, all notes are printed twice.  Once in a part for
-the musicians, and once in a full score for the conductor.  Identifiers can
-be used to avoid double work.  The music is entered once, and stored in
-a variable.  The contents of that variable is then used to generate
-both the part and the full score.
-
-It is convenient to define the notes in a special file.  For example,
-suppose that the file @file{horn-music.ly} contains the following part
-of a horn/@/bassoon duo
-
-@example
-hornNotes = \relative c @{
-  \time 2/4
-  r4 f8 a cis4 f e d
-@}
-@end example
-
-@noindent
-Then, an individual part is made by putting the following in a file
-
-@example
-\include "horn-music.ly"
-\header @{
-  instrument = "Horn in F"
-@}
-
-@{
- \transpose f c' \hornNotes
-@}
-@end example
-
-The line
-
-@example
-\include "horn-music.ly"
-@end example
-
-@noindent
-substitutes the contents of @file{horn-music.ly} at this position in
-the file, so @code{hornNotes} is defined afterwards.  The command
-@code{\transpose f@tie{}c'} indicates that the argument, being
-@code{\hornNotes}, should be transposed by a fifth upwards.  Sounding
-@samp{f} is denoted by notated @code{c'}, which corresponds with the
-tuning of a normal French Horn in@tie{}F.  The transposition can be seen
-in the following output
-
-@lilypond[quote,ragged-right]
-\transpose f c' \relative c {
-  \time 2/4
-  r4 f8 a cis4 f e d
-}
-@end lilypond
-
-In ensemble pieces, one of the voices often does not play for many
-measures.  This is denoted by a special rest, the multi-measure
-rest.  It is entered with a capital @samp{R} followed by a duration
-(@code{1}@tie{}for a whole note, @code{2}@tie{}for a half note,
-etc.).  By multiplying the
-duration, longer rests can be constructed.  For example, this rest
-takes 3@tie{}measures in 2/4 time
-
-@example
-R2*3
-@end example
-
-When printing the part, multi-rests
-must be condensed.  This is done by setting a run-time variable
-
-@example
-\set Score.skipBars = ##t
-@end example
-
-@noindent
-This command sets the property @code{skipBars} in the
-@code{Score} context to true (@code{##t}).  Prepending the rest and
-this option to the music above, leads to the following result
-
-@lilypond[quote,ragged-right]
-\transpose f c' \relative c {
-  \time 2/4
-  \set Score.skipBars = ##t
-  R2*3
-  r4 f8 a cis4 f e d
-}
-@end lilypond
-
-
-The score is made by combining all of the music together.  Assuming
-that the other voice is in @code{bassoonNotes} in the file
-@file{bassoon-music.ly}, a score is made with
-
-@example
-\include "bassoon-music.ly"
-\include "horn-music.ly"
-
-<<
-  \new Staff \hornNotes
-  \new Staff \bassoonNotes
->>
-@end example
-
-@noindent
-leading to
-
-@lilypond[quote,ragged-right]
-\relative c <<
-  \new Staff {
-    \time 2/4 R2*3
-    r4 f8 a cis4 f e d
-  }
-  \new Staff {
-    \clef bass
-    r4 d,8 f | gis4 c | b bes |
-    a8 e f4 | g d | gis f
-  }
->>
-@end lilypond
-
-More in-depth information on preparing parts and scores can be found
-in the notation manual; see @ref{Orchestral music}.
-
-Setting run-time variables (@q{properties}) is discussed in
-@ref{Changing context properties on the fly}.
-
 
 @node After the tutorial
-@section After the tutorial
+@subsection After the tutorial
 
 After finishing the tutorial, you should probably try writing a
-piece or two.  Start with one of the @ref{Example templates} and
+piece or two.  Start with one of the @ref{Templates} and
 add notes.  If you need any notation that was not covered in the
 tutorial, look at the Notation Reference, starting with
 @ref{Basic notation}.  If you want to write for an instrument
-ensemble which is not covered in the @ref{Example templates},
+ensemble which is not covered in the templates,
 take a look at @ref{Extending the templates}.
 
 Once you have written a few short pieces, read the rest of
@@ -1422,3 +1469,24 @@ LilyPond input.  You may wish to skim these chapters right
 now, and come back to them after you have more experience.
 
 
+@node How to read the manual
+@subsection How to read the manual
+
+As we saw in @ref{How to read the tutorial}, many examples in the
+tutorial omitted a @code{\relative c'' @{ ... @}} around the printed
+example.
+
+In the rest of the manual, we are much more lax about the
+printed examples: sometimes they may have omitted a
+@code{\relative c'' @{ ... @}}, but in other times a different initial
+pitch may be used (such as @code{c'} or @code{c,,}), and in some cases
+the whole example is in absolute note mode!  However, ambiguities like
+this only exist where the pitches are not important.  In any example
+where the pitch matters, we have explicitly stated our @code{\relative}
+our our absolute-mode @code{@{ @}}.
+
+If you are still confused about the exact LilyPond input that was
+used in an example, read the HTML version (if you are not already doing
+so) and click on the picture of the music.  This will display the exact
+input that LilyPond used to generate this manual.
+
diff --git a/THANKS b/THANKS
index 19ea30a79f0ca7027c213f2bbe67dfe79dd751e3..2e7cd7cf4a59eabbb63051eaeb16d6eddd1ad972 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -45,12 +45,15 @@ Maarten Hijzelendoorn
 Matthijs Frankeno
 Martijn Vromans
 Marnen Laibow-Koser
+Maximilian Albert
 Mirosław Doroszewski
+Nicolas Mayencourt
 Nicolas Sceaux
 Orm Finnendahl
 Phillip Kirlin
 Ralph Palmer
 Rick Hansen
+Roland Goretzki
 Rune Zedeler
 Ruud van Silfhout
 Sean Reed
@@ -60,6 +63,7 @@ Thomas Scharkowski
 Trevor Bača
 Werner Lemberg
 Wilbert Berendsen
+William Oram
 Yota Moteuchi
 
 
diff --git a/VERSION b/VERSION
index 0b8b4feb65dd346078857f31b7f04bdb0d6cc046..1380565e9e23ad59c3090aec2eca325eec525959 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1,6 +1,6 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=2
 MINOR_VERSION=11
-PATCH_LEVEL=12
+PATCH_LEVEL=13
 MY_PATCH_LEVEL=
 
index 4c53c644e49437cbc956bc36c10aa53484c92369..072cf64520c2fab1640a4e10502f833651bd370e 100755 (executable)
@@ -32,11 +32,15 @@ cd $resultdir
 cat > long-score.ly << EOF
 \version "2.10.0"
 foo = \new Staff \new Voice \repeat unfold 50 \relative { c4 d8[ d16( e]~ e16[ e e) f] g8  }
-\new ChoirStaff << 
-  \foo \foo \foo \foo 
-  \foo \foo \foo \foo 
-
->>
+\score { 
+  \new ChoirStaff << 
+    \foo \foo \foo \foo 
+    \foo \foo \foo \foo 
+
+  >>
+  \midi {}
+  \layout {}
+}
 EOF
 
 rm gmon.sum
index 380e9e30755a17bfa3d67a45afd4483fbd1d2521..a3b68dd58d074230c5fb5598c1978ce5f15e4da4 100644 (file)
@@ -96,7 +96,7 @@ def read_gcov (f):
         
     return ls
 
-def get_chunks (ls, file):
+def get_c_chunks (ls, file):
     chunks = []
     chunk = []
 
@@ -115,6 +115,35 @@ def get_chunks (ls, file):
             
     return chunks
 
+def get_scm_chunks (ls, file):
+    chunks = []
+    chunk = []
+
+    def new_chunk ():
+        nums = [n-1 for (n, l) in chunk]
+        chunks.append (Chunk ((min (nums), max (nums)+1),
+                              last_c, ls, file))
+        chunk = []
+        
+    last_c = -1
+    for (c, n, l) in ls:
+
+        if l.startswith ('(define'):
+            new_chunk ()
+            last_c =
+            continue
+        
+        if not (c == last_c or c < 0):
+
+            
+            if chunk and last_c >= 0:
+
+        chunk.append ((n,l))
+        if c >= 0:
+            last_c = c
+            
+    return chunks
+
 def widen_chunk (ch, ls):
     a -= 1
     b += 1
@@ -129,7 +158,13 @@ def extract_chunks (file):
         print s
         return []
         
-    return get_chunks (ls, file)
+    cs = []
+    if 'scm' in file:
+        cs = get_scm_chunks (ls, file)
+    else:
+        cs = get_c_chunks (ls, file)
+    return cs
+
 
 def filter_uncovered (chunks):
     def interesting (c):
@@ -173,7 +208,13 @@ def main ():
     if options.uncovered or options.hotspots:
         chunks = []
         for a in args:
-            chunks += extract_chunks  ('%s.gcov' % a)
+            name = a
+            if name.endswith ('scm'):
+                name += '.cov'
+            else:
+                name += '.gcov'
+            
+            chunks += extract_chunks  (name)
 
         if options.uncovered:
             chunks = filter_uncovered (chunks)
index 07f8705e3fb7983e2b560f84fbd9a47ec61748fd..e56b1e477de1e044df67092e2269aa19428aabd5 100644 (file)
@@ -486,7 +486,7 @@ class ProfileFileLink (FileCompareLink):
                 str += '%-8s: %d\n' %  (k, int (self.results[oldnew][k]))
             else:
                 str += '%-8s: %8d (%5.3f)\n' % (k, int (self.results[oldnew][k]),
-                                         self.get_ratio (k))
+                                                self.get_ratio (k))
 
         return '<pre>%s</pre>' % str
             
@@ -509,11 +509,12 @@ class ProfileFileLink (FileCompareLink):
 
         dist = 0.0
         factor = {'time': 2.0 ,
-                  'cells': 10.0,
+                  'cells': 5.0,
                   }
         
         for k in ('time', 'cells'):
-            dist += math.tan (self.get_ratio (k) /(0.5* math.pi)) * factor[k]  - 1
+            real_val = math.tan (self.get_ratio (k) * 0.5* math.pi)
+            dist += math.exp (math.fabs (real_val) * factor[k])  - 1
 
         dist = min (dist, 100)
         return dist
index 022f9c3f12a1407957ff54ed6c2b42f9fda6d8d4..a8c4d4a26ba4b43290d499e44e8482eb44c47202 100644 (file)
@@ -1,6 +1,6 @@
 depth = ..
 
-SUBDIRS = test regression tutorial mutopia manual
+SUBDIRS = test regression tutorial mutopia manual lsr
 
 examples = typography-demo les-nereides wilhelmus proportional bach-schenker cary
 
diff --git a/input/lsr/GNUmakefile b/input/lsr/GNUmakefile
new file mode 100644 (file)
index 0000000..95cd95a
--- /dev/null
@@ -0,0 +1,7 @@
+depth = ../../
+
+SUBDIRS = advanced trick
+
+LOCALSTEPMAKE_TEMPLATES=ly mutopia
+
+include $(depth)/make/stepmake.make
diff --git a/input/lsr/advanced/+.ly b/input/lsr/advanced/+.ly
new file mode 100644 (file)
index 0000000..02d2c32
--- /dev/null
@@ -0,0 +1,21 @@
+\version "2.10.0"
+%% +.ly: Be the first .ly file for lys-to-tely.py.
+%% Better to make lys-to-tely.py include "introduction.texi" or
+%% other .texi documents too?
+
+\header{
+texidoc = #(string-append "
+@section Introduction
+
+This document shows all kinds of advanced snippets from the
+LilyPond Snippet Repository.
+
+In the web version of this document, you can click on the file name
+or figure for each example to see the corresponding input file.
+
+This document is for LilyPond version 
+" (lilypond-version) ".")
+}
+
+% make sure .png  is generated.
+\lyrics {  "(left blank intentionally)" }
diff --git a/input/lsr/advanced/Alternating-beam-directions.ly b/input/lsr/advanced/Alternating-beam-directions.ly
new file mode 100644 (file)
index 0000000..1298e8f
--- /dev/null
@@ -0,0 +1,31 @@
+\version "2.10.12"
+
+\header { texidoc = "
+<p>The eighth notes may be seemingly attached to different
+    beams, and the corresponding notes connected by ties. 
+    Such a situation may occur, for example, in the cello suites.
+" }
+
+wipeNote = {
+    \once \override NoteHead #'transparent = ##t
+    \once \override Stem #'transparent = ##t 
+}
+\layout { raggedright = ##t }
+
+
+\relative c''<< {
+    c8[~
+       \wipeNote
+       c8
+       c8~
+       \wipeNote
+       c
+       c]~
+    \wipeNote
+    c\noBeam
+}\\
+   { s8 c8 [ s c s c] }
+
+   
+>>
+
diff --git a/input/lsr/advanced/GNUmakefile b/input/lsr/advanced/GNUmakefile
new file mode 100644 (file)
index 0000000..6d37cd2
--- /dev/null
@@ -0,0 +1,16 @@
+
+depth = ../../../
+
+STEPMAKE_TEMPLATES=documentation texinfo tex
+LOCALSTEPMAKE_TEMPLATES=lilypond ly lysdoc
+
+## Hmm, would this work?  No -- if we really want examples, move
+## to other dir (input/) comes to mind.
+## examples = font20 ancient-font
+## LOCALSTEPMAKE_TEMPLATES += ly mutopia
+
+EXTRA_DIST_FILES= README
+
+include $(depth)/make/stepmake.make
+
+TITLE=Advanced snippets
diff --git a/input/lsr/advanced/SConscript b/input/lsr/advanced/SConscript
new file mode 100644 (file)
index 0000000..f72bfff
--- /dev/null
@@ -0,0 +1,4 @@
+# -*-python-*-
+
+Import ('env', 'collate')
+collate (title = 'Advanced snippets')
diff --git a/input/lsr/trick/+.ly b/input/lsr/trick/+.ly
new file mode 100644 (file)
index 0000000..4d5254f
--- /dev/null
@@ -0,0 +1,21 @@
+\version "2.10.0"
+%% +.ly: Be the first .ly file for lys-to-tely.py.
+%% Better to make lys-to-tely.py include "introduction.texi" or
+%% other .texi documents too?
+
+\header{
+texidoc = #(string-append "
+@section Introduction
+
+This document shows all kinds of `tricks and tips' snippets from the
+LilyPond Snippet Repository.
+
+In the web version of this document, you can click on the file name
+or figure for each example to see the corresponding input file.
+
+This document is for LilyPond version 
+" (lilypond-version) ".")
+}
+
+% make sure .png  is generated.
+\lyrics {  "(left blank intentionally)" }
diff --git a/input/lsr/trick/Adding-ambiti-per-voice.ly b/input/lsr/trick/Adding-ambiti-per-voice.ly
new file mode 100644 (file)
index 0000000..58d3f28
--- /dev/null
@@ -0,0 +1,22 @@
+\version "2.10.12"
+
+\header { texidoc = "
+<p>Ambits can be added per voice. In that case, the
+ambitus must be moved manually to prevent collisions.
+" }
+
+\new Staff <<
+    \new Voice \with {
+       \consists "Ambitus_engraver"
+    } \relative c'' {
+       \voiceOne
+       c4 a d e f2
+    }
+    \new Voice \with {
+       \consists "Ambitus_engraver"
+    } \relative c' {
+       \voiceTwo
+       es4 f g as b2
+    }
+>>
+
diff --git a/input/lsr/trick/Caesura-railtracks-with-fermata.ly b/input/lsr/trick/Caesura-railtracks-with-fermata.ly
new file mode 100644 (file)
index 0000000..d466fac
--- /dev/null
@@ -0,0 +1,25 @@
+\version "2.10.12"
+
+\header { texidoc = "
+A caesura is sometimes denoted with a double \"railtracks\" breath mark with a fermata sign positioned over the top of the railtracks. This snippet should present an optically pleasing combination of railtracks and a fermata.
+
+It works for lilypond 2.5 and above.
+" }
+
+{
+  \context Voice {
+    c''2.
+    % use some scheme code to construct the symbol
+    \override BreathingSign #'text = #(markup #:line 
+                                  (#:musicglyph "scripts.caesura"
+                                   #:translate (cons -1.75 1.6) 
+                                   #:musicglyph "scripts.ufermata"
+                                  ))
+    \breathe c''4
+    % set the breathe mark back to normal
+    \revert BreathingSign #'text
+    c''2. \breathe c''4
+    \bar "|."
+  }
+}
+
diff --git a/input/lsr/trick/GNUmakefile b/input/lsr/trick/GNUmakefile
new file mode 100644 (file)
index 0000000..8cd520e
--- /dev/null
@@ -0,0 +1,16 @@
+
+depth = ../../../
+
+STEPMAKE_TEMPLATES=documentation texinfo tex
+LOCALSTEPMAKE_TEMPLATES=lilypond ly lysdoc
+
+## Hmm, would this work?  No -- if we really want examples, move
+## to other dir (input/) comes to mind.
+## examples = font20 ancient-font
+## LOCALSTEPMAKE_TEMPLATES += ly mutopia
+
+EXTRA_DIST_FILES= README
+
+include $(depth)/make/stepmake.make
+
+TITLE=Trick snippets
diff --git a/input/lsr/trick/SConscript b/input/lsr/trick/SConscript
new file mode 100644 (file)
index 0000000..3845b7b
--- /dev/null
@@ -0,0 +1,4 @@
+# -*-python-*-
+
+Import ('env', 'collate')
+collate (title = 'Trick snippets')
diff --git a/input/lsr/trick/Tramlines-and-Feta-font-caesurae.ly b/input/lsr/trick/Tramlines-and-Feta-font-caesurae.ly
new file mode 100644 (file)
index 0000000..6d8fb0a
--- /dev/null
@@ -0,0 +1,66 @@
+\version "2.10.12"
+
+\header { texidoc = "
+This snippet shows a way to insert available Feta font symbols as caesurae and ways to create tramlines.  Normally a caesura is indicated by a pair of oblique lines lying through the top line of the staff, also called a fetura, tramlines, railroad tracks, or a cut-off.  LilyPond provides several alternatives.  A stylized version of tramlines is called caesura.  The normal tramline form, here called fetura, is not in the Feta font set, but can be constructed using the / character.
+" }
+
+\version "2.8.4"
+%{ This snippet shows a way to insert available Feta font symbols as caesurae
+ and ways to create tramlines.  Normally a caesura is indicated by a pair of
+ oblique lines lying through the top line of the staff, also called a fetura,
+ tramlines, railroad tracks, or a cut-off.  LilyPond provides several
+ alternatives.  A stylized version of tramlines is called caesura.  The normal
+ tramline form, here called fetura, is not in the Feta font set, but can be
+ constructed using the / character.%}
+                                               \relative c'' {
+\time 3/4
+e4 d e
+                                       % default
+e_\markup { "default - breathe" }
+       \breathe d e |
+                                       % rcomma
+       % by default, \breathe uses the rcomma, just as if saying:
+               \override BreathingSign   #'text =
+               #(make-musicglyph-markup "scripts.rcomma")
+e_\markup rcomma \breathe d e |
+                                       % lcomma
+               \override BreathingSign   #'text =
+               #(make-musicglyph-markup "scripts.lcomma")
+e_\markup lcomma \breathe d e |
+                                       % rvarcomma
+               \override BreathingSign   #'text =
+               #(make-musicglyph-markup "scripts.rvarcomma")
+e_\markup rvarcomma \breathe d e | \break
+                                       % lvarcomma
+               \override BreathingSign   #'text =
+               #(make-musicglyph-markup "scripts.lvarcomma")
+e_\markup lvarcomma \breathe d e |
+                                       % upbow or wedge
+               \override BreathingSign   #'text =
+                #(make-musicglyph-markup "scripts.upbow")
+e_\markup upbow \breathe d e |
+                                       % caesura
+               \override BreathingSign   #'text =
+                #(make-musicglyph-markup "scripts.caesura")
+e_\markup caesura \breathe d e |
+                                       % fetura, tramlines, or railroad tracks
+<<{
+\hideNotes a16 a a a a4 a \unHideNotes
+}\\{
+       \once\override TextScript   #'extra-offset = #'(4.0 . -2.7)
+e^\markup {\fontsize #2 {\bold "/" \hspace #-1.4 \bold "/"}}
+d_\markup { \hspace #-10 "fetura" } e |
+}>>
+       \once\override TextScript   #'font-name = #"cmb10"
+       \once\override TextScript   #'extra-offset = #'(4.0 . -2.2)
+e^\markup {\magnify #1.3 { "/" \hspace #-1.5 "/"}}
+       \once \override Score.SeparationItem #'padding = #4
+d_\markup { \hspace #-10 "fetura" } e |
+
+e d e \bar "||"
+                                               }%end relative
+                                       \layout{
+indent = 0.00\in
+                                       }%end layout
+
+
diff --git a/input/makelsr.py b/input/makelsr.py
new file mode 100755 (executable)
index 0000000..c902131
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+import sys
+import os
+import os.path
+import shutil
+
+dirs=['advanced','trick']
+
+try:
+       in_dir=sys.argv[1]
+except:
+       print "Please specify input_file."
+       exit
+
+for dir in dirs:
+       srcdir = os.path.join(in_dir, dir)
+       destdir = os.path.join(os.getcwd(), 'lsr', dir)
+
+       file_names=os.listdir(destdir)
+       for file in file_names:
+               if (file[-3:]=='.ly'):
+                       if not(file=='+.ly'):
+                               os.remove( os.path.join(destdir,file) )
+
+       file_names=os.listdir(in_dir + dir)
+       for file in file_names:
+               out_name=file
+               src = os.path.join(srcdir, file)
+               dest = os.path.join(destdir, out_name)
+               shutil.copyfile(src, dest)
+
diff --git a/input/regression/auto-beam-beaming-override.ly b/input/regression/auto-beam-beaming-override.ly
new file mode 100644 (file)
index 0000000..2eb529a
--- /dev/null
@@ -0,0 +1,21 @@
+
+\header {
+
+
+  texidoc = "Autobeamer remembers @code{subdivideBeams} and other
+beaming pattern related functions at the start of an autobeam."
+
+}
+
+
+\version "2.11.12"
+\paper { ragged-right = ##t }
+{
+  \time 2/4
+  b16 b b b
+  b16 b b b
+  \set subdivideBeams = ##t
+  \set Score.beatLength = #(ly:make-moment 1 8)
+  b16 b b b
+  b16 b b b
+}
index aaabb78a512e1d075a9ae6a0693b562cf3a0f362..002a2c172ce06e0d0a95bf35f0201017dbf672d8 100644 (file)
@@ -2,6 +2,7 @@
 
   texidoc = "Collision resolution may be forced manually with @code{force-hshift}. "
 }
+\version "2.11.10"
 
 \paper  {
   ragged-right = ##t
diff --git a/input/regression/hairpin-to-barline-mark.ly b/input/regression/hairpin-to-barline-mark.ly
new file mode 100644 (file)
index 0000000..488ae8b
--- /dev/null
@@ -0,0 +1,13 @@
+\version "2.11.12"
+\paper { ragged-right = ##t }
+\header {
+
+  texidoc = "hairpinToBarline is not confused by very long marks."
+
+}
+
+\new Staff \relative c' {
+  c1\< |
+  \mark "Very long mark"
+  c4\> c c c\! |
+}
diff --git a/input/regression/hara-kiri-stanza-number.ly b/input/regression/hara-kiri-stanza-number.ly
new file mode 100644 (file)
index 0000000..a0a9742
--- /dev/null
@@ -0,0 +1,24 @@
+
+\header {
+
+  texidoc = "stanza numbers remain, even on otherwise empty lyrics
+lines."
+         
+}
+
+\paper {
+  indent = #0.0
+  ragged-right = ##T
+}
+
+\version "2.10.11"
+
+<<
+  \new Voice = melody \relative c'{
+    r2 r4 r8 e8 |\break
+    e16 e8. 
+  }
+  \lyricsto "melody" \lyrics { 
+    \set stanza = "Verse 2."
+    _ bla bla  }
+>>
diff --git a/input/regression/lyric-combine-switch-voice-2.ly b/input/regression/lyric-combine-switch-voice-2.ly
new file mode 100644 (file)
index 0000000..27f6d4f
--- /dev/null
@@ -0,0 +1,29 @@
+\header
+{
+texidoc = "switching voices halfway a lyricsto is possible."
+  }
+\version "2.10.12"
+
+<<
+  \relative \new Voice = "lahlah" {
+    c4
+    <<
+      \new Voice = "alternative" {
+        \voiceOne
+       \override NoteColumn #'force-hshift = #-3
+       a'4 
+      } 
+      { \voiceTwo
+        c,4
+       \oneVoice
+      } >>
+    c4 c 
+    
+  }
+  \new Lyrics \lyricsto "lahlah" {
+    \set associatedVoice = alternative
+    two  
+    \set associatedVoice = lahlah
+    two this
+  } 
+>>
index c4199cb643fedce3ea7ef5e9417c56d8eced6119..1fdb502d1cf0e68098bf78b5375e03b4f6a386e6 100644 (file)
@@ -105,7 +105,6 @@ MyVoice = \context {
   \consists "Chord_tremolo_engraver"
   \consists "Percent_repeat_engraver"
   \consists "Slash_repeat_engraver"
-  \consists "Melisma_translator"
 
 %{
   Must come before text_engraver, but after note_column engraver.
index 323fa7d6f3d23764d361df92707fbe7f97772eee..cbc1478608fba2bc42ddf31c34ae5a5b59157da4 100644 (file)
@@ -397,8 +397,8 @@ Accidental_placement::calc_positioning_done (SCM smob)
   Real padding = robust_scm2double (me->get_property ("padding"), 0.2);
 
   Skyline left_skyline = head_ape->left_skyline_;
-  left_skyline.raise (-robust_scm2double (me->get_property ("right-padding"), 0))
-;
+  left_skyline.raise (-robust_scm2double (me->get_property ("right-padding"), 0));
+  
   /*
     Add accs entries right-to-left.
   */
@@ -442,9 +442,10 @@ Accidental_placement::calc_positioning_done (SCM smob)
   me->flush_extent_cache (X_AXIS);
   me->set_property ("X-extent", scm_width);
 
-  for (vsize i = apes.size (); i--;)
-    delete apes[i];
+  junk_pointers (apes);
 
+  delete head_ape;
+  
   return SCM_BOOL_T;
 }
 
index 46d7d53f8bbb750e035280e92d6d3c74b9d41a67..3bfd1b816d1e91f15f7257979381efde7df3c53d 100644 (file)
@@ -25,30 +25,12 @@ parenthesize (Grob *me, Stencil m)
   Stencil close
     = font->find_by_name ("accidentals.rightparen");
 
-  m.add_at_edge (X_AXIS, LEFT, Stencil (open), 0, 0);
-  m.add_at_edge (X_AXIS, RIGHT, Stencil (close), 0, 0);
+  m.add_at_edge (X_AXIS, LEFT, Stencil (open), 0);
+  m.add_at_edge (X_AXIS, RIGHT, Stencil (close), 0);
 
   return m;
 }
 
-/*
-  Hmm. Need separate callback, or perhaps #'live bool property.
- */
-MAKE_SCHEME_CALLBACK (Accidental_interface, after_line_breaking, 1);
-SCM
-Accidental_interface::after_line_breaking (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-  Grob *tie = unsmob_grob (me->get_object ("tie"));
-
-  if (tie && !tie->original ()
-      && !to_boolean (me->get_property ("forced")))
-    {
-      me->suicide ();
-    }
-  return SCM_UNSPECIFIED;
-}
 
 /* This callback exists for the sole purpose of allowing us to override
    its pure equivalent to accidental-interface::pure-height */
@@ -84,13 +66,16 @@ Accidental_interface::accurate_boxes (Grob *me, Grob **common)
   vector<Box> boxes;
 
   bool parens = to_boolean (me->get_property ("parenthesized"));
+  if (!me->is_live ())
+    return boxes;
 
   SCM scm_style = me->get_property ("style");
   if (!scm_is_symbol (scm_style)
       && !to_boolean (me->get_property ("restore-first"))
       && !parens)
     {
-      Rational alteration = ly_scm2rational (me->get_property ("alteration"));
+      Rational alteration
+       = robust_scm2rational (me->get_property ("alteration"), 0);
       if (alteration == FLAT_ALTERATION)
        {
          Box stem = b;
@@ -151,7 +136,15 @@ SCM
 Accidental_interface::print (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
+  Grob *tie = unsmob_grob (me->get_object ("tie"));
 
+  if (tie && !tie->original ()
+      && !to_boolean (me->get_property ("forced")))
+    {
+      me->suicide ();
+      return SCM_EOL;
+    }
+  
   Font_metric *fm = Font_interface::get_default_font (me);
 
   SCM alist = me->get_property ("glyph-name-alist");
@@ -161,7 +154,7 @@ Accidental_interface::print (SCM smob)
   if (!scm_is_string (glyph_name))
     {
       me->warning (_f ("Could not find glyph-name for alteration %s",
-                      ly_scm2rational (alt).to_string ().c_str ()));
+                      ly_scm_write_string (alt).c_str ()));
       return SCM_EOL;
     }
   
@@ -177,7 +170,7 @@ Accidental_interface::print (SCM smob)
       if (acc.is_empty ())
        me->warning (_ ("natural alteration glyph not found"));
       else
-       mol.add_at_edge (X_AXIS, LEFT, acc, 0.1, 0);
+       mol.add_at_edge (X_AXIS, LEFT, acc, 0.1);
     }
   
   if (to_boolean (me->get_property ("parenthesized")))
index 0d7fdd822bc0fdb320e3bb4ce81182d2df4c06f7..f8da4b2ecdf4ef205e0989baa64b83f85b0ba76c 100644 (file)
@@ -65,15 +65,10 @@ All_font_metrics::All_font_metrics (All_font_metrics const &)
 #if HAVE_PANGO_FT2
 
 Pango_font *
-All_font_metrics::find_pango_font (PangoFontDescription *description,
-                                  Real magnification,
+All_font_metrics::find_pango_font (PangoFontDescription const *description,
                                   Real output_scale
                                   )
 {
-  pango_font_description_set_size (description,
-                                  gint (magnification *
-                                        pango_font_description_get_size (description)));
-
   gchar *pango_fn = pango_font_description_to_filename (description);
   SCM key = ly_symbol2scm (pango_fn);
 
index 0e4e2d949b8006bfb899909b10837a1d9176e0f5..e2fdcc9595cb38dcf50aa7b46155b29efe3ab705 100644 (file)
@@ -149,7 +149,7 @@ Ambitus_engraver::finalize ()
                                start_key_sig_);
 
          Rational sig_alter = (handle != SCM_BOOL_F)
-           ? ly_scm2rational (scm_cdr (handle)) : Rational (0);
+           ? robust_scm2rational (scm_cdr (handle), Rational (0)) : Rational (0);
 
          if (sig_alter == p.get_alteration ())
            {
index 381f6fe48f63d4a63c42249ff10634fa97ae2142..234dbc44e3bd2575b9ffc5b87f9284ad49d7c4dc 100644 (file)
@@ -84,11 +84,11 @@ Arpeggio::print (SCM smob)
 
   for (Real y = heads[LEFT]; y < heads[RIGHT];
        y += squiggle.extent (Y_AXIS).length ())
-    mol.add_at_edge (Y_AXIS, UP, squiggle, 0.0, 0);
+    mol.add_at_edge (Y_AXIS, UP, squiggle, 0.0);
 
   mol.translate_axis (heads[LEFT], Y_AXIS);
   if (dir)
-    mol.add_at_edge (Y_AXIS, dir, arrow, 0, 0);
+    mol.add_at_edge (Y_AXIS, dir, arrow, 0);
 
   return mol.smobbed_copy ();
 }
index cb498f5dbf7f9acf4c7944108ba20479b0200d7f..8d3a3e39534384768a34ae87f2de82df9ea8b66e 100644 (file)
@@ -5,6 +5,7 @@
 
   (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
+#include <cassert> 
 
 #include "audio-element.hh"
 
index 7ddd646b53c7dd7e317594b7faa6d7854582fe20..353a26f270e272a2afc8c57389687b2686db941b 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "audio-staff.hh"
 
-#include "midi-item.hh"
+#include "midi-chunk.hh"
 #include "midi-stream.hh"
 #include "midi-walker.hh"
 
@@ -28,10 +28,13 @@ Audio_staff::output (Midi_stream &midi_stream, int channel)
 {
   Midi_track midi_track;
   midi_track.number_ = channel;
-  
-  for (Midi_walker i (this, &midi_track, channel); i.ok (); i++)
+
+  Midi_walker i (this, &midi_track, channel);
+  for (; i.ok (); i++)
     i.process ();
+
+  i.finalize ();
   
-  midi_stream << midi_track;
+  midi_stream.write (midi_track);
 }
 
index 4ff8d9d2b7c88e7632907e0651f02483ac90c55e..d2cef6ae1693ecb2bd9bf8a928958b9978a7fb4a 100644 (file)
@@ -68,15 +68,17 @@ private:
   Moment beam_start_moment_;
   Moment beam_start_location_;
 
-  bool subdivide_beams_;
-  Moment beat_length_;
-
   // We act as if beam were created, and start a grouping anyway.
   Beaming_pattern *grouping_;
   SCM beam_settings_;
 
   Beaming_pattern *finished_grouping_;
 
+
+  Beaming_options beaming_options_;
+  Beaming_options finished_beaming_options_;
+  
+  
   void check_bar_property ();
 };
 
@@ -207,6 +209,7 @@ Auto_beam_engraver::begin_beam ()
 
   stems_ = new vector<Item*>;
   grouping_ = new Beaming_pattern ();
+  beaming_options_.from_context (context ());
   beam_settings_ = updated_grob_properties (context (), ly_symbol2scm ("Beam"));
 
   beam_start_moment_ = now_mom ();
@@ -242,6 +245,7 @@ Auto_beam_engraver::end_beam ()
        {
          announce_end_grob (finished_beam_, SCM_EOL);
          finished_grouping_ = grouping_;
+         finished_beaming_options_ = beaming_options_;
        }
       delete stems_;
       stems_ = 0;
@@ -260,7 +264,7 @@ Auto_beam_engraver::typeset_beam ()
       if (!finished_beam_->get_bound (RIGHT))
        finished_beam_->set_bound (RIGHT, finished_beam_->get_bound (LEFT));
       
-      finished_grouping_->beamify (context ());
+      finished_grouping_->beamify (finished_beaming_options_);
       Beam::set_beaming (finished_beam_, finished_grouping_);
       finished_beam_ = 0;
 
index e6b1e10f2cac60a9f502a254436ae03fc9fe5f5a..23c30872474d31267c92d093122dd1be452d6a1b 100644 (file)
@@ -185,6 +185,17 @@ Axis_group_interface::pure_height (SCM smob, SCM start_scm, SCM end_scm)
   int end = robust_scm2int (end_scm, INT_MAX);
   Grob *me = unsmob_grob (smob);
 
+  /* Maybe we are in the second pass of a two-pass spacing run. In that
+     case, the Y-extent of a system is already given to us */
+  System *system = dynamic_cast<System*> (me);
+  if (system)
+    {
+      SCM line_break_details = system->column (start)->get_property ("line-break-system-details");
+      SCM system_y_extent = scm_assq (ly_symbol2scm ("system-Y-extent"), line_break_details);
+      if (scm_is_pair (system_y_extent))
+       return scm_cdr (system_y_extent);
+    }
+
   return pure_group_height (me, start, end);
 }
 
index f87ebd4767ad7a00aa4732e797af0a008e2843d3..75dbc6c1be36779ab174971dd9a7cafc6f46aca4 100644 (file)
@@ -78,37 +78,37 @@ Bar_line::compound_barline (Grob *me, string str, Real h,
     return thin;
   else if (str == "|." || (h == 0 && str == ":|"))
     {
-      m.add_at_edge (X_AXIS, LEFT, thick, 0, 0);
-      m.add_at_edge (X_AXIS, LEFT, thin, kern, 0);
+      m.add_at_edge (X_AXIS, LEFT, thick, 0);
+      m.add_at_edge (X_AXIS, LEFT, thin, kern);
     }
   else if (str == ".|" || (h == 0 && str == "|:"))
     {
-      m.add_at_edge (X_AXIS, RIGHT, thick, 0, 0);
-      m.add_at_edge (X_AXIS, RIGHT, thin, kern, 0);
+      m.add_at_edge (X_AXIS, RIGHT, thick, 0);
+      m.add_at_edge (X_AXIS, RIGHT, thin, kern);
     }
   else if (str == ":|")
     {
-      m.add_at_edge (X_AXIS, LEFT, thick, 0, 0);
-      m.add_at_edge (X_AXIS, LEFT, thin, kern, 0);
-      m.add_at_edge (X_AXIS, LEFT, colon, kern, 0);
+      m.add_at_edge (X_AXIS, LEFT, thick, 0);
+      m.add_at_edge (X_AXIS, LEFT, thin, kern);
+      m.add_at_edge (X_AXIS, LEFT, colon, kern);
     }
   else if (str == "|:")
     {
-      m.add_at_edge (X_AXIS, RIGHT, thick, 0, 0);
-      m.add_at_edge (X_AXIS, RIGHT, thin, kern, 0);
-      m.add_at_edge (X_AXIS, RIGHT, colon, kern, 0);
+      m.add_at_edge (X_AXIS, RIGHT, thick, 0);
+      m.add_at_edge (X_AXIS, RIGHT, thin, kern);
+      m.add_at_edge (X_AXIS, RIGHT, colon, kern);
     }
   else if (str == ":|:")
     {
-      m.add_at_edge (X_AXIS, LEFT, thick, thinkern, 0);
-      m.add_at_edge (X_AXIS, LEFT, colon, kern, 0);
-      m.add_at_edge (X_AXIS, RIGHT, thick, kern, 0);
-      m.add_at_edge (X_AXIS, RIGHT, colon, kern, 0);
+      m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
+      m.add_at_edge (X_AXIS, LEFT, colon, kern);
+      m.add_at_edge (X_AXIS, RIGHT, thick, kern);
+      m.add_at_edge (X_AXIS, RIGHT, colon, kern);
     }
   else if (str == ".|.")
     {
-      m.add_at_edge (X_AXIS, LEFT, thick, thinkern, 0);
-      m.add_at_edge (X_AXIS, RIGHT, thick, kern, 0);
+      m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
+      m.add_at_edge (X_AXIS, RIGHT, thick, kern);
     }
   else if (str == "||")
     {
@@ -116,8 +116,8 @@ Bar_line::compound_barline (Grob *me, string str, Real h,
        should align to other side? this never appears
        on the system-start?
       */
-      m.add_at_edge (X_AXIS, RIGHT, thin, 0, 0);
-      m.add_at_edge (X_AXIS, RIGHT, thin, thinkern, 0);
+      m.add_at_edge (X_AXIS, RIGHT, thin, 0);
+      m.add_at_edge (X_AXIS, RIGHT, thin, thinkern);
     }
   else if (str == ":")
     {
index 288a47494149b9077187d17902b224a791905be3..51569b0e270b6582366f4e3cf0b7bb3412a97d9f 100644 (file)
@@ -46,9 +46,9 @@ protected:
   /// moment (global time) where beam started.
   Moment beam_start_mom_;
 
-  bool subdivide_beams_;
-  Moment beat_length_;
-
+  Beaming_options beaming_options_;
+  Beaming_options finished_beaming_options_;
+  
   void typeset_beam ();
   void set_melisma (bool);
 
@@ -135,13 +135,17 @@ Beam_engraver::process_music ()
       beam_start_location_ = mp;
       beam_start_mom_ = now_mom ();
 
+      beaming_options_.from_context (context ());
       beam_info_ = new Beaming_pattern;
       /* urg, must copy to Auto_beam_engraver too */
     }
 
   typeset_beam ();
   if (stop_ev_ && beam_)
-    announce_end_grob (beam_, stop_ev_->self_scm ());
+    {
+      announce_end_grob (beam_, stop_ev_->self_scm ());
+      
+    }
 }
 
 void
@@ -151,8 +155,8 @@ Beam_engraver::typeset_beam ()
     {
       if (!finished_beam_->get_bound (RIGHT))
        finished_beam_->set_bound (RIGHT, finished_beam_->get_bound (LEFT));
-         
-      finished_beam_info_->beamify (context ());
+      
+      finished_beam_info_->beamify (finished_beaming_options_);
       Beam::set_beaming (finished_beam_, finished_beam_info_);
 
       delete finished_beam_info_;
@@ -179,7 +183,8 @@ Beam_engraver::stop_translation_timestep ()
     {
       finished_beam_ = beam_;
       finished_beam_info_ = beam_info_;
-
+      finished_beaming_options_ = beaming_options_;
+      
       stop_ev_ = 0;
       beam_ = 0;
       beam_info_ = 0;
index a782cdfac466447ee95429fc26b119488e021365..ecc9d0b5a6ea979dcec6546bb7078fe44cf8ebac 100644 (file)
@@ -554,7 +554,7 @@ Beam::print (SCM grob)
                                    (me->layout ()->self_scm (), properties, quant_score));
 
       if (!score.is_empty ())
-       the_beam.add_at_edge (Y_AXIS, stem_dir, score, 1.0, 0);
+       the_beam.add_at_edge (Y_AXIS, stem_dir, score, 1.0);
     }
 #endif
 
index 542ce8e455c61f6191a48c7a4d040948abd61285..ba5b8a4a72dee519ba9e1f254c61523e698cc6f7 100644 (file)
@@ -116,28 +116,24 @@ Beaming_pattern::de_grace ()
 }
 
 void
-Beaming_pattern::beamify (Context *context)
+Beaming_pattern::beamify (Beaming_options const &options)
 {
   if (infos_.size () <= 1)
     return;
 
   if (infos_[0].start_moment_.grace_part_)
     de_grace ();
-  
-  bool subdivide_beams = to_boolean (context->get_property ("subdivideBeams"));
-  Moment beat_length = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
-  Moment measure_length = robust_scm2moment (context->get_property ("measureLength"), Moment (1, 4));
 
   if (infos_[0].start_moment_ < Moment (0))
     for (vsize i = 0; i < infos_.size(); i++)
-      infos_[i].start_moment_ += measure_length;
+      infos_[i].start_moment_ += options.measure_length_;
   
-  SCM grouping = context->get_property ("beatGrouping");
   Moment measure_pos (0);
   
   vector<Moment> group_starts;
   vector<Moment> beat_starts;
-  
+
+  SCM grouping = options.grouping_;
   while (measure_pos <= infos_.back().start_moment_)
     {
       int count = 2;
@@ -150,9 +146,9 @@ Beaming_pattern::beamify (Context *context)
       group_starts.push_back (measure_pos);
       for (int i = 0; i < count; i++)
        {
-         beat_starts.push_back (measure_pos + beat_length * i);
+         beat_starts.push_back (measure_pos + options.beat_length_ * i);
        }
-      measure_pos += beat_length * count;
+      measure_pos += options.beat_length_ * count;
     }
    
   vsize j = 0;
@@ -163,16 +159,19 @@ Beaming_pattern::beamify (Context *context)
             && group_starts[j+1] <= infos_[i].start_moment_)
        j++;
 
-      infos_[i].group_start_ = group_starts[j];
-      infos_[i].beat_length_ = beat_length;  
+      if (j < group_starts.size ())
+       infos_[i].group_start_ = group_starts[j];
+      
+      infos_[i].beat_length_ = options.beat_length_;  
       while (k + 1 < beat_starts.size() 
             && beat_starts[k+1] <= infos_[i].start_moment_)
        k++;
 
-      infos_[i].beat_start_ = beat_starts[k];
+      if (k < beat_starts.size())
+       infos_[i].beat_start_ = beat_starts[k];
     }
   
-  beamify (subdivide_beams);
+  beamify (options.subdivide_beams_);
 }
 
 
@@ -234,3 +233,18 @@ Beaming_pattern::beamlet_count (int i, Direction d) const
 {
   return infos_.at (i).beam_count_drul_[d];
 }
+
+void
+Beaming_options::from_context (Context *context)
+{
+  grouping_ = context->get_property ("beatGrouping");
+  subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
+  beat_length_ = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
+  measure_length_ = robust_scm2moment (context->get_property ("measureLength"), Moment (1, 4));
+}
+
+Beaming_options::Beaming_options ()
+{
+  grouping_ = SCM_EOL;
+  subdivide_beams_ = false;
+}
index 0d0733b1e8a4509146beb27da4a7d4da999e1a4c..5fbc3f7fab55e743a7f5977092ec4c55f7986622 100644 (file)
@@ -322,8 +322,11 @@ Constrained_breaking::initialize ()
       
   Output_def *l = pscore_->layout ();
   System *sys = pscore_->root_system ();
-  Real padding = robust_scm2double (l->c_variable ("page-breaking-between-system-padding"), 0);
   Real space = robust_scm2double (l->c_variable ("ideal-system-space"), 0);
+  SCM padding_scm = l->c_variable ("page-breaking-between-system-padding");
+  if (!scm_is_number (padding_scm))
+    padding_scm = l->c_variable ("between-system-padding");
+  Real padding = robust_scm2double (padding_scm, 0.0);
 
   Interval first_line = line_dimensions_int (pscore_->layout (), 0);
   Interval other_lines = line_dimensions_int (pscore_->layout (), 1);
index 8a874c09b804587dfcc697461ddc4a285618b5b0..97ac61128e8e0ffe20901b1ec5ccec4313c6dd25 100644 (file)
@@ -52,7 +52,7 @@ Dots::print (SCM d)
       for (int i = scm_to_int (c); i--;)
        {
          d.translate_axis (2 * dw, X_AXIS);
-         mol.add_at_edge (X_AXIS, RIGHT, d, dw, 0);
+         mol.add_at_edge (X_AXIS, RIGHT, d, dw);
        }
     }
   return mol.smobbed_copy ();
index 8df7f8fccc0b39e840c38f7ccbcdf58c2c6daca2..49687a6b9bf7534233204b1b2822e827551fe2f6 100644 (file)
@@ -339,10 +339,18 @@ Dynamic_engraver::typeset_all ()
       if (!finished_cresc_->get_bound (RIGHT)
          || use_bar)
        {
-         Grob *column_bound = unsmob_grob (use_bar
-                                           ? get_property ("currentCommandColumn")
-                                           : get_property ("currentMusicalColumn"));
-           
+                 
+         Grob *column_bound = 0;
+         if (use_bar)
+           {
+             column_bound = unsmob_grob (get_property ("breakableSeparationItem"));
+           }
+         
+         if (!column_bound)
+           column_bound = unsmob_grob (use_bar
+                                       ? get_property ("currentCommandColumn")
+                                       : get_property ("currentMusicalColumn"));
+         
          finished_cresc_->set_bound (RIGHT, script_
                                      ? script_
                                      : column_bound);
index a74826c8ac7984821315bc6cb023edc2358e6ed8..cbc3b605ed13c9be41229f04db1119f952b772f4 100644 (file)
@@ -10,6 +10,7 @@
 #include "config.hh"
 
 #include <cstdio>
+#include <ctype.h>
 #include <cstring>  /* memset */
 using namespace std;
 
@@ -24,6 +25,7 @@ using namespace std;
 #include "file-path.hh"
 #include "relocate.hh"
 #include "file-name.hh"
+#include "string-convert.hh"
 
 LY_DEFINE (ly_find_file, "ly:find-file",
           1, 0, 0, (SCM name),
@@ -146,6 +148,20 @@ LY_DEFINE (ly_assoc_get, "ly:assoc-get",
   return default_value;
 }
 
+LY_DEFINE (ly_string_substitute, "ly:string-substitute",
+          3, 0, 0, (SCM a, SCM b, SCM s),
+          "Replace @var{a} by @var{b} in @var{s}.")
+{
+  SCM_ASSERT_TYPE (scm_is_string (a), s, SCM_ARG1, __FUNCTION__, "string");
+  SCM_ASSERT_TYPE (scm_is_string (b), s, SCM_ARG2, __FUNCTION__, "string");
+  SCM_ASSERT_TYPE (scm_is_string (s), s, SCM_ARG3, __FUNCTION__, "string");
+
+  string ss = ly_scm2string (s);
+  replace_all (ss, string (scm_i_string_chars (a)),
+                  string (scm_i_string_chars (b)));
+  return ly_string2scm (ss);
+}
+  
 LY_DEFINE (ly_number2string, "ly:number->string",
           1, 0, 0, (SCM s),
           "Convert @var{num} to a string without generating many decimals.")
@@ -165,7 +181,7 @@ LY_DEFINE (ly_number2string, "ly:number->string",
            r = 0.0;
          }
 
-      snprintf (str, sizeof (str), "%08.4f", r);
+      snprintf (str, sizeof (str), "%.4f", r);
     }
   else
     snprintf (str, sizeof (str), "%d", int (scm_to_int (s)));
@@ -379,3 +395,122 @@ LY_DEFINE (ly_truncate_list_x, "ly:truncate-list!",
   return lst;
 }
 
+string
+format_single_argument (SCM arg, int precision)
+{
+  if (scm_is_integer (arg) && scm_exact_p (arg) == SCM_BOOL_T)
+    return (String_convert::int_string (scm_to_int (arg)));
+  else if (scm_is_number (arg))
+    {
+      Real val = scm_to_double (arg);
+
+      if (isnan (val) || isinf (val))
+       {
+         warning (_ ("Found infinity or nan in output. Substituting 0.0"));
+         return ("0.0");
+         if (strict_infinity_checking)
+           abort();
+       }
+      else
+       return (String_convert::form_string ("%.*lf", precision, val));
+    }
+  else if (scm_is_string (arg))
+    return (ly_scm2string (arg));
+  else if (scm_is_symbol (arg))
+    return (ly_symbol2string (arg));
+  else
+    {
+      ly_progress (scm_from_locale_string ("Unsupported SCM value for format: ~a"),
+                  scm_list_1 (arg));
+    }
+  
+    
+  return "";    
+}
+
+LY_DEFINE (ly_format, "ly:format",
+          1, 0, 1, (SCM str, SCM rest),
+          "LilyPond specific format, supporting ~a ~[0-9]f.")
+{
+  SCM_ASSERT_TYPE (scm_is_string (str), str, SCM_ARG1, __FUNCTION__, "string");
+
+  string format = ly_scm2string (str);
+  vector<string> results;
+
+  vsize i = 0;
+  while (i < format.size())
+    {
+      vsize tilde = format.find ('~', i);
+
+      results.push_back (format.substr (i, (tilde-i)));
+
+      if (tilde == NPOS)
+       break ;
+      
+      tilde ++;
+
+      char spec = format.at (tilde ++);
+      if (spec == '~')
+       results.push_back ("~");
+      else
+       {
+         if (!scm_is_pair (rest))
+           {
+             programming_error (string (__FUNCTION__) 
+                                + ": not enough arguments for format.");
+             return ly_string2scm ("");
+           }
+         
+         SCM arg = scm_car (rest);
+         rest = scm_cdr (rest);
+
+         int precision = 8;
+         
+         if (spec == '$')
+           precision = '2';
+         else if (isdigit (spec))
+           {
+             precision = spec - '0';
+             spec = format.at (tilde ++);
+           }
+                  
+         if (spec == 'a' || spec == 'f')
+           results.push_back (format_single_argument (arg, precision));
+         else if (spec == 'l')
+           {
+             SCM s = arg;
+             for (; scm_is_pair (s); s = scm_cdr (s))
+               {
+                 results.push_back (format_single_argument (scm_car (s), precision));
+                 if (scm_cdr (s) != SCM_EOL)
+                   results.push_back (" ");
+               }
+
+             if (s != SCM_EOL)
+               results.push_back (format_single_argument (s, precision));
+               
+           }
+       }
+
+      i = tilde;
+    }
+
+  if (scm_is_pair (rest))
+    programming_error (string (__FUNCTION__)
+                      + ": too many  arguments");
+
+  vsize len = 0;
+  for (vsize i = 0; i < results.size(); i++)
+    len += results[i].size();
+  
+  char *result = (char*) scm_malloc (len + 1);
+  char *ptr = result;
+  for (vsize i = 0; i < results.size(); i++)
+    {
+      strncpy (ptr, results[i].c_str (), results[i].size());
+      ptr += results[i].size();
+    }
+  *ptr = '\0';
+    
+  return scm_take_locale_stringn (result, len);
+}
index 44c16e149fe9b478f55ad39615073718eae03da8..1011d47fdcf1f1a55441cfb31e6f703547880c56 100644 (file)
@@ -9,6 +9,7 @@
 #include "grob.hh"
 
 #include "paper-score.hh"
+#include "warn.hh"
 
 #include "ly-smobs.icc"
 
@@ -19,6 +20,8 @@ IMPLEMENT_TYPE_P (Grob, "ly:grob?");
 SCM
 Grob::mark_smob (SCM ses)
 {
+  ASSERT_LIVE_IS_ALLOWED();
+  
   Grob *s = (Grob *) SCM_CELL_WORD_1 (ses);
   scm_gc_mark (s->immutable_property_alist_);
 
index f11e78def56b17a95cfa46188ac42ce8a3dc17a0..20808956ae9607264d9ee84699bf778835e19cd2 100644 (file)
@@ -246,7 +246,7 @@ Hairpin::print (SCM smob)
        don't add another circle the hairpin is broken
       */
       if (!broken[tip_dir])
-       mol.add_at_edge (X_AXIS, tip_dir, Stencil (circle), 0, 0);
+       mol.add_at_edge (X_AXIS, tip_dir, Stencil (circle), 0);
     }
 
   mol.translate_axis (x_points[LEFT]
index ee971d7cad75f523ffd901f3fc24c4a38b5b91dc..617b1ace32ad706392b45bf797048eafd57ef7a8 100644 (file)
@@ -17,7 +17,7 @@ using namespace std;
 #include "international.hh"
 #include "main.hh"
 #include "source-file.hh"
-#include "source.hh"
+#include "sources.hh"
 #include "warn.hh"
 
 #ifndef YY_BUF_SIZE
index 534ac706b558972b22ff6bf644a4250f6e9f38fe..a90680537f9a9eefeca52e8fdee1cc60a93a1c6e 100644 (file)
@@ -20,7 +20,6 @@ class Accidental_interface
 public:
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_stencils, (SCM));
-  DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM));
   DECLARE_SCHEME_CALLBACK (height, (SCM));
   DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM));
   
index edf50f301fef357a4762e8211e41d656a8c27415..073b839d9a1ff874cd9b0f880a665468f82f9d32 100644 (file)
@@ -43,11 +43,8 @@ public:
   All_font_metrics (string search_path);
   ~All_font_metrics ();
 
-#if HAVE_PANGO_FT2
-  Pango_font *find_pango_font (PangoFontDescription *description,
-                              Real magnification,
+  Pango_font *find_pango_font (PangoFontDescription const *description,
                               Real scale);
-#endif
 
   Font_metric *find_font (string name);
   Open_type_font *find_otf (string name);
index 134c4488d5e4a986c0cb3ef317fe2e57d330b19d..4a9eae6198c7eb8ab61b0a8cbea846e6953641e0 100644 (file)
 #include "moment.hh"
 #include "lily-proto.hh"
 
+struct Beaming_options
+{
+  SCM grouping_;
+  bool subdivide_beams_;
+  Moment beat_length_;
+  Moment measure_length_;
+
+  Beaming_options ();
+  void from_context (Context*);  
+};
+
 struct Beam_rhythmic_element
 {
   Moment start_moment_;
@@ -38,7 +49,7 @@ class Beaming_pattern
 public:
   Beaming_pattern ();
   
-  void beamify (Context*);
+  void beamify (Beaming_options const&);
   void de_grace ();
   void add_stem (Moment d, int beams);
   int beamlet_count (int idx, Direction d) const;
index 6eef555bf599cef61ca47dc41299d06e31cf4551..6f21a29b03c172e53c7c720a9628027a556a7e06 100644 (file)
@@ -32,7 +32,7 @@
     A ly_B2A (B b);  */
 
 SCM ly_last (SCM list);
-SCM ly_write2scm (SCM s);
+string ly_scm_write_string (SCM s);
 SCM ly_deep_copy (SCM);
 SCM ly_truncate_list (int k, SCM lst);
 
@@ -65,6 +65,7 @@ Drul_array<bool> robust_scm2booldrul (SCM, Drul_array<bool>);
 Interval robust_scm2interval (SCM, Drul_array<Real>);
 Offset robust_scm2offset (SCM, Offset);
 string robust_scm2string (SCM, string);
+Rational robust_scm2rational (SCM, Rational);
 
   
 SCM ly_quote_scm (SCM s);
@@ -81,6 +82,8 @@ SCM ly_hash2alist (SCM tab);
 SCM ly_hash_table_keys (SCM tab);
 
 SCM ly_assoc_prepend_x (SCM alist, SCM key, SCM val);
+inline bool ly_is_fraction (SCM x) { return SCM_FRACTIONP(x) || scm_is_integer (x); }
+    
 inline bool ly_is_list (SCM x) { return SCM_NFALSEP (scm_list_p (x)); }
 inline bool ly_is_procedure (SCM x) { return SCM_NFALSEP (scm_procedure_p (x)); }
 inline bool ly_is_port (SCM x) { return SCM_NFALSEP (scm_port_p (x)); }
index 56c80f56654ec7fb67b4dbf25d278b8308084d39..fca8aa372f9a553e1c8541ad83d0fce18caadf65 100644 (file)
@@ -90,6 +90,7 @@ class Mensural_ligature_engraver;
 class Midi_chunk;
 class Midi_duration;
 class Midi_dynamic;
+class Midi_event;
 class Midi_header;
 class Midi_instrument;
 class Midi_item;
diff --git a/lily/include/midi-chunk.hh b/lily/include/midi-chunk.hh
new file mode 100644 (file)
index 0000000..fc41a54
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+  midi-chunk.hh -- declare  Midi_chunk
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2007 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
+*/
+
+#ifndef MIDI_CHUNK_HH
+#define MIDI_CHUNK_HH
+
+#include "lily-proto.hh"
+#include "virtual-methods.hh"
+#include "std-vector.hh"
+
+
+/**
+   timed MIDI event
+*/
+class Midi_event
+{
+public:
+  Midi_event (int delta, Midi_item *midi);
+
+  int delta_ticks_;
+  Midi_item *midi_;
+  string to_string () const;
+};
+
+
+
+
+/**
+   variable sized MIDI data
+*/
+class Midi_chunk
+{
+public:
+  void set (string header_string, string data_string, string footer_string);
+  virtual string to_string () const;
+  virtual string data_string () const;
+  DECLARE_CLASSNAME(Midi_chunk);
+  virtual ~Midi_chunk ();
+private:
+  string data_string_;
+  string footer_string_;
+  string header_string_;
+};
+
+class Midi_header : public Midi_chunk
+{
+public:
+  DECLARE_CLASSNAME(Midi_header);
+
+  Midi_header (int format_i, int tracks_i, int clocks_per_4_i);
+};
+
+class Midi_track : public Midi_chunk
+{
+public:
+  int number_;
+  DECLARE_CLASSNAME(Midi_track);
+
+  vector<Midi_event*> events_;
+
+  Midi_track ();
+  ~Midi_track ();
+
+  void add (int, Midi_item *midi);
+  virtual string data_string () const;
+};
+
+#endif /* MIDI_CHUNK_HH */
+
index 6d77f21afc29872c1162f040b50f1ed61bb3cba9..a3cea87e619c7f2c591e7e73ed8d25428cfbe930 100644 (file)
@@ -10,6 +10,8 @@
 #include "audio-item.hh"
 #include "std-vector.hh"
 
+string int2midi_varint_string (int i);
+  
 /**
    Any piece of midi information.
 
@@ -23,10 +25,8 @@ public:
   virtual ~Midi_item ();
   virtual char const *name () const;
 
-  /// factory
   static Midi_item *get_midi (Audio_item *a);
 
-  static string i2varint_string (int i);
 
   virtual string to_string () const = 0;
 };
@@ -37,38 +37,6 @@ public:
   int channel_;
   DECLARE_CLASSNAME(Midi_channel_item);
   Midi_channel_item ();
-  virtual const char *name () const { return "Midi_channel_item"; }
-  virtual ~Midi_channel_item ();
-};
-
-/**
-   timed MIDI event
-*/
-class Midi_event
-{
-public:
-  Midi_event (int delta, Midi_item *midi);
-
-  int delta_ticks_;
-  Midi_item *midi_;
-  string to_string () const;
-};
-
-/**
-   variable sized MIDI data
-*/
-class Midi_chunk : public Midi_item
-{
-public:
-  void set (string header_string, string data_string, string footer_string);
-  virtual string to_string () const;
-  virtual string data_string () const;
-  DECLARE_CLASSNAME(Midi_chunk);
-
-private:
-  string data_string_;
-  string footer_string_;
-  string header_string_;
 };
 
 class Midi_duration : public Midi_item
@@ -80,13 +48,6 @@ public:
   Real seconds_;
 };
 
-class Midi_header : public Midi_chunk
-{
-public:
-    DECLARE_CLASSNAME(Midi_header);
-
-  Midi_header (int format_i, int tracks_i, int clocks_per_4_i);
-};
 
 /**
    Change instrument event
@@ -125,9 +86,6 @@ public:
   int clocks_per_1_;
 };
 
-/**
-   Turn a note on.
-*/
 class Midi_note : public Midi_channel_item
 {
 public:
@@ -145,9 +103,6 @@ public:
   Byte dynamic_byte_;
 };
 
-/**
-   Turn a note off
-*/
 class Midi_note_off : public Midi_note
 {
 public:
@@ -210,22 +165,6 @@ public:
   Audio_tempo *audio_;
 };
 
-class Midi_track : public Midi_chunk
-{
-public:
-  int number_;
-  DECLARE_CLASSNAME(Midi_track);
 
-  /*
-    Compensate for starting grace notes.
-  */
-  vector<Midi_event*> events_;
-
-  Midi_track ();
-  ~Midi_track ();
-
-  void add (int, Midi_item *midi);
-  virtual string data_string () const;
-};
 
 #endif // MIDI_ITEM_HH
index 18e38ca2c00c6cebb41367b32d9128d02ff170f4..fe31d6590fb03a461ce5160616726169996cb745 100644 (file)
 using namespace std;
 
 #include "std-string.hh"
+#include "lily-proto.hh"
 
-class Midi_item;
-
-/// Midi outputfile
 struct Midi_stream
 {
   Midi_stream (string file_name_string);
   ~Midi_stream ();
 
-  Midi_stream &operator << (string str);
-  Midi_stream &operator << (Midi_item const &midi_c_r);
-  Midi_stream &operator << (int i);
-
+  void write (string);
+  void write (Midi_chunk const &);
   void open ();
 
   FILE *out_file_;
index ee523e5faa850a0dbc71d5daf3d32cbd101b80d4..8ea8b27b6442b73829c9b68f9e4d2b8a862e11f5 100644 (file)
@@ -14,7 +14,7 @@
 
 struct Midi_note_event : PQueue_ent<int, Midi_note *>
 {
-  bool ignore_b_;
+  bool ignore_;
   Midi_note_event ();
 };
 
@@ -33,12 +33,12 @@ public:
   void process ();
   void operator ++ (int);
   bool ok () const;
-
+  void finalize ();
 private:
   void do_start_note (Midi_note *note);
   void do_stop_notes (int);
   void output_event (int, Midi_item *l);
-
+  Midi_item *get_midi (Audio_item*); 
   int channel_;
   Midi_track *track_;
   Audio_staff *staff_;
@@ -46,6 +46,8 @@ private:
   vector<Audio_item*> items_;
   PQueue<Midi_note_event> stop_note_queue;
   int last_tick_;
+
+  vector<Midi_item*> midi_events_;
 };
 
 #endif // MIDI_WALKER_HH
index 013f3504638a2c7d867f132a69cab44d265b7f5e..c0d6ff336863d7ff022005257a1276b2eb612a39 100644 (file)
@@ -31,7 +31,7 @@ class Pango_font : public Font_metric
 public:
   SCM physical_font_tab () const;
   Pango_font (PangoFT2FontMap *,
-             PangoFontDescription *,
+             PangoFontDescription const *,
              Real);
   ~Pango_font ();
 
index a8f3ac5164c70151d7c67c4d2b10e7296b6f6840..5bd403bce45364763f307fb2014960034e146b58 100644 (file)
@@ -142,12 +142,16 @@ void unprotect_smob (SCM smob, SCM *prot_cons);
 
 extern bool parsed_objects_should_be_dead;
 
+#ifndef NDEDUG
 #define ASSERT_LIVE_IS_ALLOWED()     \
   static bool passed_here_once;\
   if (parsed_objects_should_be_dead && !passed_here_once) { \
-    programming_error (string ("Parsed object should be dead: ")  + __PRETTY_FUNCTION__ ); \
+    ::programming_error (string ("Parsed object should be dead: ")  + __PRETTY_FUNCTION__ ); \
     passed_here_once = true;\
   }    
+#else
+#define ASSERT_LIVE_IS_ALLOWED()
+#endif
 
 #endif /* SMOBS_HH */
 
index 9cc52192c6b79a5e1dcb14e22b77c4e1786adffa..09c7cfafd0cb2ee13152e399db7d99198272b2fd 100644 (file)
@@ -1,31 +1 @@
-/*
-  source.hh -- part of LilyPond
-
-  (c) 1997--2007 Jan Nieuwenhuizen <janneke@gnu.org>
-*/
-
-#ifndef SOURCE_HH
-#define SOURCE_HH
-
-#include "flower-proto.hh"
-#include "std-vector.hh"
-
-/*   A set of sourcefiles.  */
-class Sources
-{
-  Sources (Sources const &);
-  vector<Source_file*> sourcefiles_;
-
-public:
-  Sources ();
-  ~Sources ();
-
-  Source_file *get_file (string *file_name);
-  Source_file *get_sourcefile (char const *);
-  void add (Source_file *sourcefile);
-  void set_path (File_path *);
-
-  const File_path *path_;
-};
-
-#endif /* SOURCE_HH */
+#error
diff --git a/lily/include/sources.hh b/lily/include/sources.hh
new file mode 100644 (file)
index 0000000..13776f3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+  sources.hh -- part of LilyPond
+
+  (c) 1997--2007 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#ifndef SOURCES_HH
+#define SOURCES_HH
+
+#include "flower-proto.hh"
+#include "std-vector.hh"
+
+class Sources
+{
+  Sources (Sources const &);
+  vector<Source_file*> sourcefiles_;
+
+public:
+  Sources ();
+  ~Sources ();
+
+  Source_file *get_file (string *file_name);
+  Source_file *get_sourcefile (char const *);
+  void add (Source_file *sourcefile);
+  void set_path (File_path *);
+
+  const File_path *path_;
+};
+
+#endif /* SOURCE_HH */
index 055728de0584c6dde0eb293868f156724ccc5441..445e461380b61550241da5920d200926b324561e 100644 (file)
@@ -46,12 +46,6 @@ using namespace std;
 */
 class Stencil
 {
-  /*
-    This provides the reference point of the symbol, for example with
-    characters, it is on the base line of the character. Usually,
-    ORIGIN is inside DIM_
-  */
-  Offset origin_;
   Box dim_;
   SCM expr_;
 
@@ -60,17 +54,12 @@ public:
   Stencil (Box, SCM s);
   Stencil ();
 
-  Offset origin () const;
   SCM expr () const;
 
   /**
      Set dimensions to empty, or to (Interval (0, 0), Interval (0, 0) */
   void set_empty (bool);
-  Stencil moved_to_edge (Axis a, Direction d, const Stencil &m, Real padding,
-                        Real minimum) const;
-
-  void add_at_edge (Axis a, Direction d, const Stencil &m, Real padding,
-                   Real minimum);
+  void add_at_edge (Axis a, Direction d, const Stencil &m, Real padding);
   void add_stencil (Stencil const &m);
   void translate (Offset);
   Stencil translated (Offset) const;
index ebee98877fd69b4c9f03686ff008fbb250028149..50f1746b86ba374abb138d9e1a2372051fb16fff 100644 (file)
@@ -31,6 +31,7 @@ struct Tie_configuration_variation
 typedef map < Tuple<int, 2>, Skyline> Chord_outline_map;
 typedef map < Tuple<int, 2>, Box> Column_extent_map;
 typedef map <int, Slice> Position_extent_map;
+
 class Tie_formatting_problem
 {
   Chord_outline_map chord_outlines_;
index 3d998b384e6d806761ce122ede378e69cf200c8e..09028d0858ea4a00fbaf39c24055c370c1e74dad 100644 (file)
@@ -13,7 +13,7 @@ using namespace std;
 
 #include "international.hh"
 #include "source-file.hh"
-#include "source.hh"
+#include "sources.hh"
 #include "warn.hh"
 
 Input::Input (Input const &i)
index c086f3d250198c6ce37431a81e70952825e8e5a3..36199d704146b7b9b1609a5c971ee1929526a296 100644 (file)
@@ -77,7 +77,7 @@ Key_engraver::create_key (bool is_default)
          for (SCM s = last; scm_is_pair (s); s = scm_cdr (s))
            {
              SCM new_alter_pair = scm_assoc (scm_caar (s), key);
-             Rational old_alter = ly_scm2rational (scm_cdar (s));
+             Rational old_alter = robust_scm2rational (scm_cdar (s), 0);
              if (new_alter_pair == SCM_BOOL_F
                  || extranatural
                  && (ly_scm2rational (scm_cdr (new_alter_pair)) - old_alter)*old_alter < Rational (0))
index 0db5cf7b69be290076c63ac55dc1668542ffde6c..7c88268b624b9a70d1542932e354b3bab760f73e 100644 (file)
@@ -97,7 +97,7 @@ Key_signature_interface::print (SCM smob)
              && last_pos > pos - 6)
            padding = 0.3;
 
-         mol.add_at_edge (X_AXIS, LEFT, acc, padding, 0);
+         mol.add_at_edge (X_AXIS, LEFT, acc, padding);
          last_pos = pos;
        }
     }
index e7e286d5a64c1d4d0a0445bf4b8b392d0f09930e..976b19e47c0819a32111fea6f28d5261d24ee2ae 100644 (file)
@@ -34,9 +34,8 @@ using namespace std;
 /*
   symbols/strings.
  */
-
-SCM
-ly_write2scm (SCM s)
+string
+ly_scm_write_string (SCM s)
 {
   SCM port = scm_mkstrport (SCM_INUM0,
                            scm_make_string (SCM_INUM0, SCM_UNDEFINED),
@@ -47,7 +46,7 @@ ly_write2scm (SCM s)
 
   // scm_apply (write, port, SCM_EOL);
   scm_call_2 (write, s, port);
-  return scm_strport_to_string (port);
+  return ly_scm2string (scm_strport_to_string (port));
 }
 
 SCM
@@ -392,14 +391,10 @@ ly_deep_copy (SCM src)
   return src;
 }
 
-
-
-
-
 string
 print_scm_val (SCM val)
 {
-  string realval = ly_scm2string (ly_write2scm (val));
+  string realval = ly_scm_write_string (val);
   if (realval.length () > 200)
     realval = realval.substr (0, 100)
       + "\n :\n :\n"
@@ -587,6 +582,14 @@ ly_scm2rational (SCM r)
                   scm_to_int (scm_denominator (r)));
 }
 
+Rational
+robust_scm2rational (SCM n, Rational rat)
+{
+  if (ly_is_fraction (n))
+    return ly_scm2rational (n);
+  else
+    return rat;
+}
 
 SCM
 alist_to_hashq (SCM alist)
@@ -658,13 +661,7 @@ parse_symbol_list (char const *symbols)
   return ly_string_array_to_scm (string_split (s, ' '));
 }
 
-
-bool
-ly_is_fraction (SCM x)
-{
-  return SCM_FRACTIONP(x);
-}
-
+/* GDB debugging. */
 struct ly_t_double_cell
 {
   SCM a;
index c3ac4afa3c9a98e53a1ca1441e7fb6b2777567c5..ca1d224bd6ac7703f7d8f54b64434fe4102965ee 100644 (file)
@@ -18,7 +18,7 @@
 #include "ly-module.hh"
 #include "main.hh"
 #include "program-option.hh"
-#include "source.hh"
+#include "sources.hh"
 #include "warn.hh"
 
 /* Do not append `!' suffix, since 1st argument is not modified. */
index 356615adc3cbf3d2ea93a42ed9d40964eabf3987..456acd1a9e023109c88139e1a66b270a4f3f3323 100644 (file)
@@ -20,7 +20,7 @@
 #include "paper-book.hh"
 #include "parser.hh"
 #include "score.hh"
-#include "source.hh"
+#include "sources.hh"
 #include "text-metrics.hh"
 #include "warn.hh"
 
index 8baa5363e872e343025fe12191c9a919874af7e2..f6809cda266d7f69ffb33487cbe018f2d90129b3 100644 (file)
@@ -136,7 +136,7 @@ Line_spanner::line_stencil (Grob *me,
       Stencil mol;
 
       do
-       mol.add_at_edge (X_AXIS, RIGHT, m, 0, 0);
+       mol.add_at_edge (X_AXIS, RIGHT, m, 0);
       while (m.extent (X_AXIS).length ()
             && mol.extent (X_AXIS).length ()
             + m.extent (X_AXIS).length () < dz[X_AXIS])
index 4235289486e89262bcd0eb621be698c44cf000c8..e6fcf4ea0a4a42d9cbb640b36e145cb9f360842d 100644 (file)
@@ -57,7 +57,8 @@ private:
   Context *music_context_;
   SCM lyricsto_voice_name_;
 
-  bool busy_;
+  Moment busy_moment_;
+  
   Music_iterator *lyric_iter_;
 };
 
@@ -68,17 +69,26 @@ Lyric_combine_music_iterator::Lyric_combine_music_iterator ()
   lyric_iter_ = 0;
   music_context_ = 0;
   lyrics_context_ = 0;
-  busy_ = false;
+  busy_moment_.set_infinite (-1);
 }
 
+
+/*
+  It's dubious whether we can ever make this fully work.  Due to
+  associatedVoice switching, this routine may be triggered for 
+  the wrong music_context_ 
+ */
 IMPLEMENT_LISTENER (Lyric_combine_music_iterator, set_busy)
 void
 Lyric_combine_music_iterator::set_busy (SCM se)
 {
   Stream_event *e = unsmob_stream_event (se);
 
-  if (e->in_event_class ("note-event") || e->in_event_class ("cluster-note-event"))
-    busy_ = true;
+  if ((e->in_event_class ("note-event") || e->in_event_class ("cluster-note-event"))
+      && music_context_)
+    busy_moment_ = max (music_context_->now_mom (),
+                       busy_moment_);
+  
 }
 
 void
@@ -87,22 +97,19 @@ Lyric_combine_music_iterator::set_music_context (Context *to)
   if (music_context_)
     {
       music_context_->event_source()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event"));
-      lyrics_context_->unset_property (ly_symbol2scm ("associatedVoiceContext"));
     }
 
   music_context_ = to;
   if (to)
     {
       to->event_source()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event"));
-      if (lyrics_context_)
-       lyrics_context_->set_property ("associatedVoiceContext", to->self_scm ());
     }
 }
 
 bool
 Lyric_combine_music_iterator::start_new_syllable () const
 {
-  if (!busy_)
+  if (busy_moment_ < music_context_->now_mom ())
     return false;
 
   if (!lyrics_context_)
@@ -283,12 +290,16 @@ Lyric_combine_music_iterator::process (Moment)
        pending_grace_lyric_ = false;
       
       Moment m = lyric_iter_->pending_moment ();
+      lyrics_context_->set_property (ly_symbol2scm ("associatedVoiceContext"),
+                                    music_context_->self_scm ());
       lyric_iter_->process (m);
 
       music_found_ = true;
     }
 
-  busy_ = false;
+  new_voice = find_voice ();
+  if (new_voice)
+    set_music_context (new_voice);
 }
 
 void
index 02e0b09397ed1ef3fe59f76fc6131607d602c783..ae0464f97dd29fea92496270596ac2914c2473ee 100644 (file)
@@ -115,12 +115,20 @@ get_voice_to_lyrics (Context *lyrics)
 Grob *
 get_current_note_head (Context *voice)
 {
+  Moment now = voice->now_mom ();
   for (SCM s = voice->get_property ("busyGrobs");
        scm_is_pair (s); s = scm_cdr (s))
     {
-      Item *g = dynamic_cast<Item *> (unsmob_grob (scm_cdar (s)));
-
-      if (g && !g->get_column ()
+      Grob *g = unsmob_grob (scm_cdar (s));;
+      Moment *end_mom = unsmob_moment (scm_caar (s));
+      if (!end_mom || !g)
+       {
+         programming_error ("busyGrobs invalid");
+         continue;
+       }
+      
+      if (end_mom->main_part_ > now.main_part_
+         && dynamic_cast<Item *> (g)
          && Note_head::has_interface (g))
        return g;
     }
diff --git a/lily/midi-chunk.cc b/lily/midi-chunk.cc
new file mode 100644 (file)
index 0000000..5aaf5bd
--- /dev/null
@@ -0,0 +1,157 @@
+/* 
+  midi-chunk.cc -- implement Midi_chunk
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2007 Han-Wen Nienhuys <hanwen@lilypond.org>
+  
+*/
+
+#include "midi-chunk.hh"
+
+#include "midi-item.hh"
+#include "std-string.hh"
+#include "string-convert.hh"
+
+Midi_track::Midi_track ()
+{
+  //                4D 54 72 6B     MTrk
+  //                00 00 00 3B     chunk length (59)
+  //        00      FF 58 04 04 02 18 08    time signature
+  //        00      FF 51 03 07 A1 20       tempo
+
+  // FF 59 02 sf mi  Key Signature
+  //         sf = -7:  7 flats
+  //         sf = -1:  1 flat
+  //         sf = 0:  key of C
+  //         sf = 1:  1 sharp
+  //         sf = 7: 7 sharps
+  //         mi = 0:  major key
+  //         mi = 1:  minor key
+
+  number_ = 0;
+
+  char const *data_str0 = ""
+    //        "00" "ff58" "0404" "0218" "08"
+    // "00" "ff51" "0307" "a120"
+    // why a key at all, in midi?
+    // key: C
+    // "00" "ff59" "02" "00" "00"
+    // key: F (scsii-menuetto)
+    //                           "00" "ff59" "02" "ff" "00"
+    ;
+
+  string data_string;
+  // only for format 0 (currently using format 1)?
+  data_string += String_convert::hex2bin (data_str0);
+
+  char const *footer_str0 = "00" "ff2f" "00";
+  string footer_string = String_convert::hex2bin (footer_str0);
+
+  set ("MTrk", data_string, footer_string);
+}
+
+void
+Midi_track::add (int delta_ticks, Midi_item *midi)
+{
+  assert (delta_ticks >= 0);
+
+  Midi_event *e = new Midi_event (delta_ticks, midi);
+  events_.push_back (e);
+}
+
+string
+Midi_track::data_string () const
+{
+  string str = Midi_chunk::data_string ();
+
+  for (vector<Midi_event*>::const_iterator i (events_.begin());
+       i != events_.end(); i ++)
+    {
+      str += (*i)->to_string ();
+    }
+  return str;
+}
+
+
+Midi_track::~Midi_track ()
+{
+  junk_pointers (events_); 
+}
+
+/****************************************************************
+  event
+*/
+Midi_event::Midi_event (int delta_ticks, Midi_item *midi)
+{
+  delta_ticks_ = delta_ticks;
+  midi_ = midi;
+}
+
+string
+Midi_event::to_string () const
+{
+  string delta_string = int2midi_varint_string (delta_ticks_);
+  string midi_string = midi_->to_string ();
+  assert (midi_string.length ());
+  return delta_string + midi_string;
+}
+/****************************************************************
+ header
+*/ 
+
+Midi_header::Midi_header (int format, int tracks, int clocks_per_4)
+{
+  string str;
+
+  string format_string = String_convert::int2hex (format, 4, '0');
+  str += String_convert::hex2bin (format_string);
+
+  string tracks_string = String_convert::int2hex (tracks, 4, '0');
+  str += String_convert::hex2bin (tracks_string);
+
+  string tempo_string = String_convert::int2hex (clocks_per_4, 4, '0');
+  str += String_convert::hex2bin (tempo_string);
+
+  set ("MThd", str, "");
+}
+
+
+/****************************************************************
+   chunk
+ */
+Midi_chunk::~Midi_chunk ()
+{
+  
+}
+
+void
+Midi_chunk::set (string header_string, string data_string, string footer_string)
+{
+  data_string_ = data_string;
+  footer_string_ = footer_string;
+  header_string_ = header_string;
+}
+
+string
+Midi_chunk::data_string () const
+{
+  return data_string_;
+}
+
+string
+Midi_chunk::to_string () const
+{
+  string str = header_string_;
+  string dat = data_string ();
+  string length_string = String_convert::int2hex (dat.length ()
+                                                 + footer_string_.length (), 8, '0');
+  length_string = String_convert::hex2bin (length_string);
+
+  str += length_string;
+  str += dat;
+  str += footer_string_;
+
+  return str;
+}
+
index ee05d4ed58dcabbf614703854bb542ba4c2c41f6..3d2d67a38e6b56319516a4322d78ee35842ffb4f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  midi-item.cc -- implement Midi items.
+  midi-item.cc -- implement MIDI items.
 
   source file of the GNU LilyPond music typesetter
 
@@ -40,44 +40,14 @@ Midi_item::get_midi (Audio_item *a)
   else if (Audio_time_signature *i = dynamic_cast<Audio_time_signature *> (a))
     return new Midi_time_signature (i);
   else if (Audio_text *i = dynamic_cast<Audio_text *> (a))
-    //return i->text_string_.length () ? new Midi_text (i) : 0;
     return new Midi_text (i);
   else
     assert (0);
 
-  // isn't C++ grand?
   return 0;
 }
 
-void
-Midi_chunk::set (string header_string, string data_string, string footer_string)
-{
-  data_string_ = data_string;
-  footer_string_ = footer_string;
-  header_string_ = header_string;
-}
 
-string
-Midi_chunk::data_string () const
-{
-  return data_string_;
-}
-
-string
-Midi_chunk::to_string () const
-{
-  string str = header_string_;
-  string dat = data_string ();
-  string length_string = String_convert::int2hex (dat.length ()
-                                                 + footer_string_.length (), 8, '0');
-  length_string = String_convert::hex2bin (length_string);
-
-  str += length_string;
-  str += dat;
-  str += footer_string_;
-
-  return str;
-}
 
 Midi_duration::Midi_duration (Real seconds_f)
 {
@@ -90,37 +60,6 @@ Midi_duration::to_string () const
   return string ("<duration: ") + ::to_string (seconds_) + ">";
 }
 
-Midi_event::Midi_event (int delta_ticks, Midi_item *midi)
-{
-  delta_ticks_ = delta_ticks;
-  midi_ = midi;
-}
-
-string
-Midi_event::to_string () const
-{
-  string delta_string = Midi_item::i2varint_string (delta_ticks_);
-  string midi_string = midi_->to_string ();
-  assert (midi_string.length ());
-  return delta_string + midi_string;
-}
-
-Midi_header::Midi_header (int format, int tracks, int clocks_per_4)
-{
-  string str;
-
-  string format_string = String_convert::int2hex (format, 4, '0');
-  str += String_convert::hex2bin (format_string);
-
-  string tracks_string = String_convert::int2hex (tracks, 4, '0');
-  str += String_convert::hex2bin (tracks_string);
-
-  string tempo_string = String_convert::int2hex (clocks_per_4, 4, '0');
-  str += String_convert::hex2bin (tempo_string);
-
-  set ("MThd", str, "");
-}
-
 Midi_instrument::Midi_instrument (Audio_instrument *a)
 {
   audio_ = a;
@@ -150,11 +89,6 @@ Midi_item::Midi_item ()
 {
 }
 
-Midi_channel_item::~Midi_channel_item ()
-{
-  channel_ = 0;
-}
-
 Midi_channel_item::Midi_channel_item ()
 {
   channel_ = 0;
@@ -165,7 +99,7 @@ Midi_item::~Midi_item ()
 }
 
 string
-Midi_item::i2varint_string (int i)
+int2midi_varint_string (int i)
 {
   int buffer = i & 0x7f;
   while ((i >>= 7) > 0)
@@ -398,84 +332,13 @@ Midi_text::to_string () const
 {
   string str = "ff" + String_convert::int2hex (audio_->type_, 2, '0');
   str = String_convert::hex2bin (str);
-  str += i2varint_string (audio_->text_string_.length ());
+  str += int2midi_varint_string (audio_->text_string_.length ());
   str += audio_->text_string_;
   return str;
 }
 
-Midi_track::Midi_track ()
-  : Midi_chunk ()
-{
-  //                4D 54 72 6B     MTrk
-  //                00 00 00 3B     chunk length (59)
-  //        00      FF 58 04 04 02 18 08    time signature
-  //        00      FF 51 03 07 A1 20       tempo
-
-  // FF 59 02 sf mi  Key Signature
-  //         sf = -7:  7 flats
-  //         sf = -1:  1 flat
-  //         sf = 0:  key of C
-  //         sf = 1:  1 sharp
-  //         sf = 7: 7 sharps
-  //         mi = 0:  major key
-  //         mi = 1:  minor key
-
-  number_ = 0;
-
-  char const *data_str0 = ""
-    //        "00" "ff58" "0404" "0218" "08"
-    // "00" "ff51" "0307" "a120"
-    // why a key at all, in midi?
-    // key: C
-    // "00" "ff59" "02" "00" "00"
-    // key: F (scsii-menuetto)
-    //                           "00" "ff59" "02" "ff" "00"
-    ;
-
-  string data_string;
-  // only for format 0 (currently using format 1)?
-  data_string += String_convert::hex2bin (data_str0);
-
-  char const *footer_str0 = "00" "ff2f" "00";
-  string footer_string = String_convert::hex2bin (footer_str0);
-
-  set ("MTrk", data_string, footer_string);
-}
-
-void
-Midi_track::add (int delta_ticks, Midi_item *midi)
-{
-  assert (delta_ticks >= 0);
-
-  Midi_event *e = new Midi_event (delta_ticks, midi);
-  events_.push_back (e);
-}
-
-string
-Midi_track::data_string () const
-{
-  string str = Midi_chunk::data_string ();
-  if (do_midi_debugging_global)
-    str += "\n";
-
-  for (vector<Midi_event*>::const_iterator i (events_.begin());
-       i != events_.end(); i ++)
-    {
-      str += (*i)->to_string ();
-      if (do_midi_debugging_global)
-       str += "\n";
-    }
-  return str;
-}
-
-
 char const *
 Midi_item::name () const
 {
    return this->class_name ();
 }
-
-Midi_track::~Midi_track ()
-{
-  junk_pointers (events_);
-}
index 893ca3d8df1b5883ad9134c2249c8ccb4cf46f67..bcaefe7c181fc461fde48f8a6b9b744c865321cf 100644 (file)
@@ -13,7 +13,7 @@ using namespace std;
 
 #include "international.hh"
 #include "main.hh"
-#include "midi-item.hh"
+#include "midi-chunk.hh"
 #include "misc.hh"
 #include "program-option.hh"
 #include "stream.hh"
@@ -33,8 +33,8 @@ Midi_stream::~Midi_stream ()
   fclose (out_file_);
 }
 
-Midi_stream &
-Midi_stream::operator << (string str)
+void
+Midi_stream::write (string str)
 {
   size_t sz = sizeof (Byte);
   size_t n = str.length ();
@@ -42,34 +42,13 @@ Midi_stream::operator << (string str)
 
   if (written != sz * n)
     warning (_ ("cannot write to file: `%s'"));
-
-  return *this;
 }
 
-Midi_stream &
-Midi_stream::operator << (Midi_item const &midi_c_r)
+void
+Midi_stream::write (Midi_chunk const &midi)
 {
-  string str = midi_c_r.to_string ();
-
-  // ugh, should have separate debugging output with Midi*::print routines
-  if (do_midi_debugging_global)
-    {
-      str = String_convert::bin2hex (str) + "\n";
-      for (ssize i = str.find ("0a"); i != NPOS; i = str.find ("0a"))
-       {
-         str[i] = '\n';
-         str[i + 1] = '\t';
-       }
-    }
+  string str = midi.to_string ();
 
-  return operator << (str);
-}
-
-Midi_stream &
-Midi_stream::operator << (int i)
-{
-  // output binary string ourselves
-  *this << Midi_item::i2varint_string (i);
-  return *this;
+  return write (str);
 }
 
index aa491bc930ddf8e202010b2a8ddf30df3b967a98..cef858c92768ebacf1374fb6d8f9bddb418a6536 100644 (file)
 #include "audio-column.hh"
 #include "audio-staff.hh"
 #include "midi-item.hh"
+#include "midi-chunk.hh"
 #include "midi-stream.hh"
 #include "warn.hh"
 
 Midi_note_event::Midi_note_event ()
 {
-  ignore_b_ = false;
+  ignore_ = false;
 }
 
 int
@@ -53,7 +54,13 @@ Midi_walker::Midi_walker (Audio_staff *audio_staff, Midi_track *track,
 
 Midi_walker::~Midi_walker ()
 {
-  do_stop_notes (last_tick_ + 384);
+  junk_pointers (midi_events_);
+}
+
+void
+Midi_walker::finalize ()
+{
+  do_stop_notes (INT_MAX);
 }
 
 /**
@@ -77,7 +84,8 @@ Midi_walker::do_start_note (Midi_note *note)
            {
              /* let stopnote in queue be ignored,
                 new stop note wins */
-             stop_note_queue[i].ignore_b_ = true;
+             stop_note_queue[i].ignore_ = true;
+
              /* don't replay start note, */
              play_start = false;
              break;
@@ -86,7 +94,6 @@ Midi_walker::do_start_note (Midi_note *note)
            {
              /* skip this stopnote,
                 don't play the start note */
-             delete note;
              note = 0;
              break;
            }
@@ -97,6 +104,8 @@ Midi_walker::do_start_note (Midi_note *note)
     {
       Midi_note_event e;
       e.val = new Midi_note_off (note);
+
+      midi_events_.push_back (e.val);
       e.key = int (stop_ticks);
       stop_note_queue.insert (e);
 
@@ -114,9 +123,8 @@ Midi_walker::do_stop_notes (int max_ticks)
   while (stop_note_queue.size () && stop_note_queue.front ().key <= max_ticks)
     {
       Midi_note_event e = stop_note_queue.get ();
-      if (e.ignore_b_)
+      if (e.ignore_)
        {
-         delete e.val;
          continue;
        }
 
@@ -127,9 +135,6 @@ Midi_walker::do_stop_notes (int max_ticks)
     }
 }
 
-/**
-   Advance the track to #now#, output the item, and adjust current "moment".
-*/
 void
 Midi_walker::output_event (int now_ticks, Midi_item *l)
 {
@@ -155,12 +160,11 @@ Midi_walker::process ()
   Audio_item *audio = items_[index_];
   do_stop_notes (audio->audio_column_->ticks ());
 
-  if (Midi_item *midi = Midi_item::get_midi (audio))
+  if (Midi_item *midi = get_midi (audio))
     {
       if (Midi_channel_item *mci = dynamic_cast<Midi_channel_item*> (midi))
        mci->channel_ = channel_;
       
-      //midi->channel_ = track_->number_;
       if (Midi_note *note = dynamic_cast<Midi_note *> (midi))
        {
          if (note->audio_->length_mom_.to_bool ())
@@ -171,6 +175,14 @@ Midi_walker::process ()
     }
 }
 
+Midi_item*
+Midi_walker::get_midi (Audio_item *i)
+{
+  Midi_item *mi = Midi_item::get_midi (i);
+  midi_events_.push_back (mi);
+  return mi;
+}
+
 bool
 Midi_walker::ok () const
 {
index 5be417004b33b9a1711248bf6d7c3756d1395e44..1b66670a7c780bc05e22a2e0544edd17cc2d1852 100644 (file)
@@ -183,8 +183,8 @@ Multi_measure_rest::big_rest (Grob *me, Real width)
   Stencil m = Lookup::round_filled_box (b, blot);
   Stencil yb = Lookup::round_filled_box (Box (Interval (-0.5, 0.5) * ythick, Interval (-ss, ss)), blot);
 
-  m.add_at_edge (X_AXIS, RIGHT, yb, 0, 0);
-  m.add_at_edge (X_AXIS, LEFT, yb, 0, 0);
+  m.add_at_edge (X_AXIS, RIGHT, yb, 0);
+  m.add_at_edge (X_AXIS, LEFT, yb, 0);
 
   m.align_to (X_AXIS, LEFT);
 
@@ -268,7 +268,7 @@ Multi_measure_rest::church_rest (Grob *me, Font_metric *musfont, int measures,
   Stencil mol;
   for (SCM s = mols; scm_is_pair (s); s = scm_cdr (s))
     mol.add_at_edge (X_AXIS, LEFT, *unsmob_stencil (scm_car (s)),
-                    inner_padding, 0);
+                    inner_padding);
   mol.align_to (X_AXIS, LEFT);
   mol.translate_axis (outer_padding_factor * inner_padding, X_AXIS);
 
index db70fc4737e4f62edcd1c486efca71302bf1044c..c4a79e403f7b18bb0313ce9a823ab481cf2cd8d3 100644 (file)
@@ -64,7 +64,8 @@ Note_spacing::get_spacing (Grob *me, Item *right_col,
              continue;
            }
 
-         if (d == LEFT)
+         if (d == LEFT
+             && Note_column::has_interface (it))
            {
              SCM r = it->get_object ("rest");
              Grob *g = unsmob_grob (r);
index 4dc46d96739f7aca6cd2e05531a2112e679feecc..c1afcfed3c7dee3588a244a62e469530e05da739 100644 (file)
@@ -61,7 +61,7 @@ Ottava_spanner_engraver::process_music ()
          span_->set_property ("text", ott);
 
          SCM c0 (get_property ("middleCPosition"));
-         SCM oc0 (get_property ("originalCentralCPosition"));
+         SCM oc0 (get_property ("originalMiddleCPosition"));
          if (scm_less_p (oc0, c0) == SCM_BOOL_T)
            span_->set_property ("direction", scm_from_int (DOWN));
        }
@@ -132,5 +132,10 @@ ADD_ACKNOWLEDGER (Ottava_spanner_engraver, note_column);
 ADD_TRANSLATOR (Ottava_spanner_engraver,
                /* doc */ "Create a text spanner when the ottavation property changes..",
                /* create */ "OttavaBracket",
-               /* read */ "ottavation",
+               /* read */ "ottavation "
+               "originalMiddleCPosition "
+               "currentMusicalColumn "
+               
+               ,
+               
                /* write */ "");
index 75103e3b7bbed5651f1e6454e98e69c717e92428..f91eafb9844743dd1a6ae89904e5c48ebb0f81b8 100644 (file)
 #include "stencil.hh"
 
 Pango_font::Pango_font (PangoFT2FontMap *fontmap,
-                       PangoFontDescription *description,
+                       PangoFontDescription const *description,
                        Real output_scale)
 {
   (void) fontmap;
+  
   physical_font_tab_ = scm_c_make_hash_table (11);
   PangoDirection pango_dir = PANGO_DIRECTION_LTR;
   context_
     = pango_ft2_get_context (PANGO_RESOLUTION, PANGO_RESOLUTION);
-  //  context_ = pango_ft2_font_map_create_context (fontmap);
 
   pango_description_ = pango_font_description_copy (description);
   attribute_list_ = pango_attr_list_new ();
@@ -104,7 +104,7 @@ Pango_font::pango_item_string_stencil (PangoItem const *item, string str,
   char glyph_name[GLYPH_NAME_LEN];
   PangoAnalysis const *pa = &(item->analysis);
   PangoGlyphString *pgs = pango_glyph_string_new ();
-
+  
   pango_shape (str.c_str () + item->offset,
               item->length, (PangoAnalysis*) pa, pgs);
 
@@ -215,6 +215,8 @@ Pango_font::pango_item_string_stencil (PangoItem const *item, string str,
       tail = SCM_CDRLOC (*tail);
     }
 
+  pango_glyph_string_free (pgs);  
+  pgs = 0;
   PangoFontDescription *descr = pango_font_describe (pa->font);
   Real size = pango_font_description_get_size (descr)
     / (Real (PANGO_SCALE));
@@ -363,6 +365,7 @@ Pango_font::text_stencil (string str, bool tight) const
       return Stencil (b, exp);
     }
 
+  g_list_free (items);
 
   return dest;
 }
index ed4b7579d4da6fc21f2c4a413ab7d55867d0d65e..bc97f787514a1b98b2d361f0ba597abe388dc158 100644 (file)
@@ -58,7 +58,8 @@ select_pango_font (Output_def *layout, SCM chain)
   char *str = pango_font_description_to_string (pfd);
   SCM scm_str = scm_from_locale_string (str);
   g_free (str);
-
+  pango_font_description_free (pfd);
+  
   return find_pango_font (layout, scm_str, 1.0);
 }
 
index c313475f49cdf0760d317bce8ad73a6b3461641c..4dba6bbbd58f08784b55e5cbef2e38e96edc8355 100644 (file)
@@ -160,7 +160,7 @@ Paper_column::print (SCM p)
                                                   properties,
                                                   ly_string2scm (when));
   Stencil t = *unsmob_stencil (scm_mol);
-  t.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (when_mol), 0.1, 0.1);
+  t.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (when_mol), 0.1);
   t.align_to (X_AXIS, CENTER);
   t.align_to (Y_AXIS, DOWN);
 
index 3a1cafbb199178f61ed7677f1521745b65992117..e9a56ae0e190f269ce0c0ed690c933e0c46defd8 100644 (file)
@@ -80,10 +80,17 @@ find_pango_font (Output_def *layout, SCM descr, Real factor)
 
   PangoFontDescription *description
     = pango_font_description_from_string (scm_i_string_chars (descr));
+
+  pango_font_description_set_size (description,
+                                  gint (factor *
+                                        pango_font_description_get_size (description)));
+
+  
   Font_metric *fm = all_fonts_global->find_pango_font (description,
-                                                      factor,
                                                       output_scale (layout));
 
+  pango_font_description_free (description);
   sizes = scm_acons (size_key, fm->self_scm (), sizes);
   scm_hash_set_x (table, descr, sizes);
 
index fabc5c2e891d943161c56f765c25fae3558c1967..c4d535d85dbe94b3be7833b40997bc16d06c7479 100644 (file)
@@ -31,6 +31,9 @@ internal_ly_parse_scm (Parse_start *ps)
   scm_seek (port, scm_long2num (off), scm_long2num (SEEK_SET));
   SCM from = scm_ftell (port);
 
+  scm_set_port_line_x (port,  scm_from_int (ps->start_location_.line_number () -1));
+  scm_set_port_column_x (port,  scm_from_int (ps->start_location_.column_number () -1));
+  
   SCM answer = SCM_UNSPECIFIED;
   SCM form = scm_read (port);
 
index 6d37c0c6198ae2bed2f71775d7641e8e286b3df5..451647fb5cc03739fc9a98ee58dc1f12e7621eb1 100644 (file)
@@ -38,14 +38,14 @@ Percent_repeat_item_interface::x_percent (Grob *me, int count,
   Stencil s = brew_slash (me);
 
   for (int i = count; i--;)
-    m.add_at_edge (X_AXIS, RIGHT, s, -slash_neg_kern, 0);
+    m.add_at_edge (X_AXIS, RIGHT, s, -slash_neg_kern);
   Stencil d1 = Font_interface::get_default_font (me)->find_by_name ("dots.dot");
   Stencil 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, 0);
-  m.add_at_edge (X_AXIS, RIGHT, d2, -dot_neg_kern, 0);
+  m.add_at_edge (X_AXIS, LEFT, d1, -dot_neg_kern);
+  m.add_at_edge (X_AXIS, RIGHT, d2, -dot_neg_kern);
 
   return m;
 }
index 2c02fc32f94f3ff64aacab4a6dfc1bce18845982..e536622f06f550336876ea29f4e3b421df787bce 100644 (file)
@@ -17,7 +17,7 @@ using namespace std;
 #include "international.hh"
 #include "lily-version.hh"
 #include "main.hh"
-#include "midi-item.hh"
+#include "midi-chunk.hh"
 #include "midi-stream.hh"
 #include "score.hh"
 #include "string-convert.hh"
@@ -38,7 +38,7 @@ Performance::output (Midi_stream &midi_stream) const
 {
   int tracks_ = audio_staffs_.size ();
 
-  midi_stream << Midi_header (1, tracks_, 384);
+  midi_stream.write (Midi_header (1, tracks_, 384));
   if (be_verbose_global)
     progress_indication (_ ("Track...") + " ");
   
index 8f593aaa393c3d9e8a8a28bbd3fecd25a258914b..5d9bebd7382728656addb4e9e5b01ac75fe1776c 100644 (file)
@@ -19,8 +19,6 @@ using namespace std;
 #include "string-convert.hh"
 #include "warn.hh"
 
-/* Write midi as formatted ascii stream? */
-bool do_midi_debugging_global;
 bool debug_skylines;
 
 /*
@@ -48,11 +46,6 @@ void internal_set_option (SCM var, SCM val)
       profile_property_accesses = to_boolean (val);
       val = scm_from_bool (to_boolean (val));
     }
-  else if (var == ly_symbol2scm ("debug-midi"))
-    {
-      do_midi_debugging_global = to_boolean (val);
-      val = scm_from_bool (to_boolean (val));
-    }
   else if (var == ly_symbol2scm ("point-and-click"))
     {
       point_and_click_global = to_boolean (val);
index 3dfb2a07d7bb9a214a7761de59ca5692e154c2a9..47502f7dbda9f054f9524c0587763cf5b26bc91b 100644 (file)
@@ -44,7 +44,12 @@ sane_putenv (char const *key, string value, bool overwrite)
        progress_indication (_f ("Setting %s to %s" , key, value.c_str ())
                             + "\n");
                             
-      return putenv (s);
+      int retval =  putenv (s);
+      /*
+       unfortunately, we can't portably free S here,
+       due to various bugs in glibc prior to 2.1.1
+       */ 
+      return retval;
     }
   
   return -1;
@@ -228,11 +233,7 @@ setup_paths (char const *argv0_ptr)
   /*
     When running from build dir, a full LILYPOND_PREFIX is set-up at
 
-        $(OUTBASE)/share/lilypond/TOPLEVEL_VERSION
-
-     This historical hack will allow the shorthand
-
-        LILYPONDPREFIX=out lily/out/lilypond ...
+        $(OUTBASE)/{share,lib}/lilypond/current
 
   */
   
index 744cceb4c3219a65fd3e7a5e8d800bc151db1d72..b729e5312b15a56471f9f7b58ca542e0db947281 100644 (file)
@@ -651,6 +651,7 @@ IMPLEMENT_DEFAULT_EQUAL_P (Skyline_pair);
 SCM
 Skyline::mark_smob (SCM)
 {
+  ASSERT_LIVE_IS_ALLOWED();
   return SCM_EOL;
 }
 
index 269c6b551b5bf56c3fd42133a8b3c593b14c974b..1f9e605fb96f10d5e26bccb8507a87f7d9a0adbc 100644 (file)
@@ -153,7 +153,7 @@ Slur::print (SCM smob)
       Stencil tm = *unsmob_stencil (Text_interface::interpret_markup
                                    (me->layout ()->self_scm (), properties,
                                     quant_score));
-      a.add_at_edge (Y_AXIS, get_grob_direction (me), tm, 1.0, 0);
+      a.add_at_edge (Y_AXIS, get_grob_direction (me), tm, 1.0);
     }
 #endif
 
index 068baed379405c532d1b144eac81dd228322d365..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,66 +0,0 @@
-/*
-  source.cc -- implement Sources
-
-  source file of the LilyPond music typesetter
-
-  (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
-*/
-
-#include "source.hh"
-
-#include "source-file.hh"
-#include "file-path.hh"
-
-Sources::Sources ()
-{
-  path_ = 0;
-}
-
-
-Sources::Sources (Sources const &)
-{
-  assert (false);
-}
-
-
-void
-Sources::set_path (File_path *f)
-{
-  path_ = f;
-}
-
-/**
-   open a file
-
-   File_string the file to be opened, name might be changed if it is
-   found in a search path.
-*/
-Source_file *
-Sources::get_file (string *file_string) //UGH
-{
-  if (*file_string != "-" && path_)
-    {
-      string file_string_o = path_->find (*file_string);
-      if ((file_string_o == "") && (*file_string != ""))
-       return 0;
-      *file_string = file_string_o;
-    }
-  Source_file *f = new Source_file (*file_string);
-  add (f);
-  return f;
-}
-
-void
-Sources::add (Source_file *sourcefile)
-{
-  sourcefiles_.push_back (sourcefile);
-}
-
-Sources::~Sources ()
-{
-  for (vsize i = 0; i < sourcefiles_.size (); i++)
-    {
-      sourcefiles_[i]->unprotect ();
-    }
-}
-
diff --git a/lily/sources.cc b/lily/sources.cc
new file mode 100644 (file)
index 0000000..bfd3e0d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+  source.cc -- implement Sources
+
+  source file of the LilyPond music typesetter
+
+  (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+*/
+
+#include "sources.hh"
+
+#include "source-file.hh"
+#include "file-path.hh"
+
+Sources::Sources ()
+{
+  path_ = 0;
+}
+
+
+Sources::Sources (Sources const &)
+{
+  assert (false);
+}
+
+
+void
+Sources::set_path (File_path *f)
+{
+  path_ = f;
+}
+
+/**
+   open a file
+
+   File_string the file to be opened, name might be changed if it is
+   found in a search path.
+*/
+Source_file *
+Sources::get_file (string *file_string) //UGH
+{
+  if (*file_string != "-" && path_)
+    {
+      string file_string_o = path_->find (*file_string);
+      if ((file_string_o == "") && (*file_string != ""))
+       return 0;
+      *file_string = file_string_o;
+    }
+  Source_file *f = new Source_file (*file_string);
+  add (f);
+  return f;
+}
+
+void
+Sources::add (Source_file *sourcefile)
+{
+  sourcefiles_.push_back (sourcefile);
+}
+
+Sources::~Sources ()
+{
+  for (vsize i = 0; i < sourcefiles_.size (); i++)
+    {
+      sourcefiles_[i]->unprotect ();
+    }
+}
+
index 7cb014c942b54563816b8a9b609a833a2d6c8228..2e862dc269854da93dcdefc37cb12617b3efc820 100644 (file)
@@ -60,9 +60,10 @@ Stanza_number_align_engraver::stop_translation_timestep ()
 
 ADD_ACKNOWLEDGER (Stanza_number_align_engraver, lyric_syllable);
 ADD_ACKNOWLEDGER (Stanza_number_align_engraver, stanza_number);
+
 ADD_TRANSLATOR (Stanza_number_align_engraver,
                "This engraver ensures that stanza numbers are neatly aligned. ",
                "",
-               " ",
+               "",
                "");
 
index 22d7eb9cb0c664710555b48efd7e5e8d44366631..7c369e4bb060c281d4aeaeb797eaf097c08e02bc 100644 (file)
@@ -801,8 +801,16 @@ SCM
 Stem::offset_callback (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
-  Real r = 0.0;
 
+  extract_grob_set (me, "rests", rests);
+  if (rests.size ())
+    {
+      Grob *rest = rests.back ();
+      Real r = rest->extent (rest, X_AXIS).center ();
+      return scm_from_double (r);
+    }
+
+  
   if (Grob *f = first_head (me))
     {
       Interval head_wid = f->extent (f, X_AXIS);
@@ -815,7 +823,7 @@ Stem::offset_callback (SCM smob)
 
       Direction d = get_grob_direction (me);
       Real real_attach = head_wid.linear_combination (d * attach);
-      r = real_attach;
+      Real r = real_attach;
 
       /* If not centered: correct for stem thickness.  */
       if (attach)
@@ -823,17 +831,11 @@ Stem::offset_callback (SCM smob)
          Real rule_thick = thickness (me);
          r += -d * rule_thick * 0.5;
        }
+      return scm_from_double (r);
     }
-  else
-    {
-      extract_grob_set (me, "rests", rests);
-      if (rests.size ())
-       {
-         Grob *rest = rests.back ();
-         r = rest->extent (rest, X_AXIS).center ();
-       }
-    }
-  return scm_from_double (r);
+
+  programming_error ("Weird stem.");
+  return scm_from_double (0.0);
 }
 
 Spanner *
index 13c291da3526d04014b0f1c42c66ad8ae09758f4..6ef0e191fd4394bad150cf94dfc7aa45151f3e23 100644 (file)
@@ -85,60 +85,6 @@ LY_DEFINE (ly_stencil_empty_p, "ly:stencil-empty?",
   return scm_from_bool (s->is_empty ());
 }
 
-LY_DEFINE (ly_stencil_origin, "ly:stencil-origin",
-          2, 0, 0, (SCM stil, SCM axis),
-          "Return a pair of numbers signifying the origin @var{stil} in "
-          "@var{axis} direction (0 or 1 for x and y axis respectively).")
-{
-  Stencil *s = unsmob_stencil (stil);
-  SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil");
-  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG2, __FUNCTION__, "axis");
-
-  return scm_from_double (s->origin ()[Axis (scm_to_int (axis))]);
-}
-
-LY_DEFINE (ly_stencil_moved_to_edge, "ly:stencil-moved-to-edge",
-          4, 2, 0, (SCM first, SCM axis, SCM direction, SCM second,
-                    SCM padding, SCM minimum),
-          "Similar to @code{ly:stencil-combine-edge}, but returns "
-          "@var{second} positioned to be next to @var{first}. ")
-{
-  /*
-    C&P from combine-at-edge.
-
-    fixme: just used once.
-  */
-  Stencil *s1 = unsmob_stencil (first);
-  Stencil *s2 = unsmob_stencil (second);
-  Stencil first_stencil;
-
-  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG3, __FUNCTION__, "axis");
-  SCM_ASSERT_TYPE (is_direction (direction), direction, SCM_ARG4, __FUNCTION__, "dir");
-
-  Real p = 0.0;
-  if (padding != SCM_UNDEFINED)
-    {
-      SCM_ASSERT_TYPE (scm_is_number (padding), padding, SCM_ARG5, __FUNCTION__, "number");
-      p = scm_to_double (padding);
-    }
-  Real m = 0.0;
-  if (minimum != SCM_UNDEFINED)
-    {
-      SCM_ASSERT_TYPE (scm_is_number (minimum), minimum, SCM_ARG6, __FUNCTION__, "number");
-      m = scm_to_double (minimum);
-    }
-
-  if (s1)
-    first_stencil = *s1;
-
-  if (s2)
-    return first_stencil.moved_to_edge (Axis (scm_to_int (axis)),
-                                       Direction (scm_to_int (direction)),
-                                       *s2, p, m).smobbed_copy ();
-  else
-    return Stencil ().smobbed_copy ();
-}
-
 LY_DEFINE (ly_stencil_combine_at_edge, "ly:stencil-combine-at-edge",
           4, 2, 0, (SCM first, SCM axis, SCM direction,
                     SCM second,
@@ -181,7 +127,7 @@ LY_DEFINE (ly_stencil_combine_at_edge, "ly:stencil-combine-at-edge",
 
   if (s2)
     result.add_at_edge (Axis (scm_to_int (axis)),
-                       Direction (scm_to_int (direction)), *s2, p, m);
+                       Direction (scm_to_int (direction)), *s2, p);
 
   return result.smobbed_copy ();
 }
index 0da8031c4ba05e6e50dc27d67044a76aee16aa06..b88b0c8bdebb50581e275babe0a9fdb819e17f23 100644 (file)
@@ -72,11 +72,6 @@ Stencil::extent_box () const
 {
   return dim_;
 }
-Offset
-Stencil::origin () const
-{
-  return origin_;
-}
 
 /*
  * Rotate this stencil around the point [x, y]
@@ -143,7 +138,6 @@ Stencil::translate (Offset o)
                      expr_, SCM_UNDEFINED);
   if (!is_empty ())
     dim_.translate (o);
-  origin_ += o;
 }
 
 void
@@ -186,13 +180,9 @@ Stencil::align_to (Axis a, Real x)
   translate_axis (-i.linear_combination (x), a);
 }
 
-/* FIXME: unintuitive naming, you would expect *this to be moved.
-   Kept (keeping?) API for compat with add_at_edge ().
-
-   What is PADDING, what is MINIMUM, exactly?  */
-Stencil
-Stencil::moved_to_edge (Axis a, Direction d, Stencil const &s,
-                       Real padding, Real minimum) const
+/*  See scheme Function.  */
+void
+Stencil::add_at_edge (Axis a, Direction d, Stencil const &s, Real padding)
 {
   Interval my_extent = dim_[a];
   Interval i (s.extent (a));
@@ -210,20 +200,7 @@ Stencil::moved_to_edge (Axis a, Direction d, Stencil const &s,
 
   Stencil toadd (s);
   toadd.translate_axis (offset, a);
-
-  if (minimum > 0 && d * (-origin ()[a] + toadd.origin ()[a]) < minimum)
-    toadd.translate_axis (-toadd.origin ()[a]
-                         + origin ()[a] + d * minimum, a);
-
-  return toadd;
-}
-
-/*  See scheme Function.  */
-void
-Stencil::add_at_edge (Axis a, Direction d, Stencil const &s, Real padding,
-                     Real minimum)
-{
-  add_stencil (moved_to_edge (a, d, s, padding, minimum));
+  add_stencil (toadd);
 }
 
 Stencil
index d36bb8d432db95e3b5f57de847d2751d771fa3a2..8056ea89a2448a99bafb24493ad00eb9921ecb4c 100644 (file)
@@ -58,7 +58,7 @@ Sustain_pedal::print (SCM smob)
        idx += string (&text.c_str ()[i], 1);
       Stencil m = Font_interface::get_default_font (e)->find_by_name (idx);
       if (!m.is_empty ())
-       mol.add_at_edge (X_AXIS, RIGHT, m, 0, 0);
+       mol.add_at_edge (X_AXIS, RIGHT, m, 0);
     }
 
   return mol.smobbed_copy ();
index a558965f1094a9f6ee5bf42f9207047d1f9ada9e..479618addcdb1b50aef2c4768a373964ce157aff 100644 (file)
@@ -96,8 +96,7 @@ Bracket_nesting_group::add_support (Grob *g)
 
 Bracket_nesting_group::~Bracket_nesting_group ()
 {
-  for (vsize i = 0 ; i < children_.size (); i++)
-    delete children_[i];
+  junk_pointers (children_);
 }
 
 void
@@ -212,6 +211,8 @@ System_start_delimiter_engraver::finalize ()
       nesting_->set_bound (RIGHT,
                           unsmob_grob (get_property ("currentCommandColumn")));
       nesting_->set_nesting_support (0);
+
+      delete nesting_;
     }
 }
 
index a42d73c16d9d5e35886f130deab3a8dd82f78e15..206ccd84db7cf68dfede69e5c67c0095b75b64a7 100644 (file)
@@ -42,7 +42,7 @@ System_start_delimiter::staff_bracket (Grob *me, Real height)
   Stencil bracket = Lookup::filled_box (box);
   Direction d = DOWN;
   do
-    bracket.add_at_edge (Y_AXIS, d, tips[d], -overlap, 0.0);
+    bracket.add_at_edge (Y_AXIS, d, tips[d], -overlap);
   while (flip (&d) != DOWN);
   bracket = Stencil (box, bracket.expr ());
 
index 273fe1c56c9ef013886d13ac0f94595ab39324e2..c4afd8caa0d2d092e24d339019c4f593006e7acd 100644 (file)
@@ -106,8 +106,8 @@ Time_signature::numbered_time_signature (Grob *me, int num, int den)
   Stencil m;
   if (den)
     {
-      m.add_at_edge (Y_AXIS, UP, n, 0.0, 0);
-      m.add_at_edge (Y_AXIS, DOWN, d, 0.0, 0);
+      m.add_at_edge (Y_AXIS, UP, n, 0.0);
+      m.add_at_edge (Y_AXIS, DOWN, d, 0.0);
     }
   else
     {
index 53636c709e94ed192210c0463520e5788e0ef79d..49018d8adb1692f4a3913bde223974ad6813a73f 100644 (file)
@@ -99,7 +99,7 @@ Volta_bracket_interface::print (SCM smob)
       num.align_to (Y_AXIS, UP);
       num.translate_axis (-0.5, Y_AXIS);
       total.add_at_edge (X_AXIS, LEFT, num, - num.extent (X_AXIS).length ()
-                        - 1.0, 0);
+                        - 1.0);
     }
   
   total.translate_axis (left, X_AXIS);
index 0364ac96af946130061ee1b9fc77675c42f0ed1e..ea7d9c5db0ff0e239576e2767d2e394ec1cf600f 100644 (file)
@@ -377,6 +377,7 @@ printing of a single line of lyrics.  "
   \consists "Skip_event_swallow_translator"
   \consists "Font_size_engraver"
   \consists "Hara_kiri_engraver"
+
   \override VerticalAxisGroup #'remove-first = ##t
   \override VerticalAxisGroup #'remove-empty = ##t
   \override SeparationItem #'padding = #0.2
@@ -610,6 +611,9 @@ AncientRemoveEmptyStaffContext = \context {
   keepAliveInterfaces = #'(
     rhythmic-grob-interface
     lyric-interface
+
+    ;; need this, as stanza numbers are items, and appear only once. 
+    stanza-number-interface
     percent-repeat-interface)
   quotedEventTypes = #'(
     note-event
index 431012eaeeb913cbb5792bfea54a13122c3874f6..2a8af551e98aaacd049907d738126b74c238958e 100644 (file)
@@ -528,7 +528,8 @@ the `parameters' assoc list.")
    #{
       \overrideProperty #"Score.NonMusicalPaperColumn"
         #'line-break-system-details
-        #$(list (cons 'alignment-extra-space (cdr (assoc 'system-stretch parameters))))
+        #$(list (cons 'alignment-extra-space (cdr (assoc 'system-stretch parameters)))
+               (cons 'system-Y-extent (cdr (assoc 'system-Y-extent parameters))))
    #})
 
 %% Parser used to read page-layout file, and then retreive score tweaks.
index a4d47978915c0915f0b14f07694f7f5040990f9c..06f572e2048c4514c5be02271245e7f87f09b474 100644 (file)
@@ -604,24 +604,25 @@ def conv (str):
     return str
 
 conversions.append (((1,3,113), conv, 'LyricVoice -> LyricsVoice'))
+def regularize_id (str):
+    s = ''
+    lastx = ''
+    for x in str:
+        if x == '_':
+            lastx = x
+            continue
+        elif x in string.digits:
+            x = chr(ord (x) - ord ('0')  +ord ('A'))
+        elif x not in string.letters:
+            x = 'x'
+        elif x in string.lowercase and lastx == '_':
+            x = string.upper (x)
+        s = s + x
+        lastx = x
+    return s
 
 def conv (str):
-    def regularize_id (str):
-       s = ''
-       lastx = ''
-       for x in str:
-           if x == '_':
-               lastx = x
-               continue
-           elif x in string.digits:
-               x = chr(ord (x) - ord ('0')  +ord ('A'))
-           elif x not in string.letters:
-               x = 'x'
-           elif x in string.lowercase and lastx == '_':
-               x = string.upper (x)
-           s = s + x
-           lastx = x
-       return s
+
 
     def regularize_dollar_reference (match):
        return regularize_id (match.group (1))
index facf06446a3e1ae2f2399c593b7714cc20c05701..69ac12848cea0a9f2b9eb060e722fe79dd762ee1 100644 (file)
@@ -304,10 +304,10 @@ midi_parse_track (unsigned char **track, unsigned char *track_end)
 
   {  
     PyObject *pytime = PyInt_FromLong (0L);
+    unsigned char running_status = 0;
+       
     while (*track < track_end)
       {
-       unsigned char running_status = 0;
-       
        long dt = get_variable_length_number(track, track_end);
        PyObject *pyev = 0;
 
diff --git a/scm/coverage.scm b/scm/coverage.scm
new file mode 100644 (file)
index 0000000..aefef13
--- /dev/null
@@ -0,0 +1,98 @@
+(define-module (scm coverage))
+
+(use-modules (lily)
+            (ice-9 rdelim)
+            (ice-9 regex)
+            (ice-9 format))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-public (coverage:show-all filter?)
+  
+  (newline)
+  (hash-fold
+   (lambda (key val acc)
+     (if (filter? key)
+        (begin
+          (format #t
+                "
+Coverage for file: ~a
+"
+                key)
+        (display-coverage key val
+                          (format #f "~a.cov" (basename key))
+                          )))
+     #t)
+   #t
+   coverage-table))
+
+(define-public (coverage:enable)
+  (trap-set! memoize-symbol-handler record-coverage)
+  (trap-enable 'memoize-symbol)
+  (trap-enable 'traps))
+
+     
+(define-public (coverage:disable)
+  (trap-set! memoize-symbol-handler #f)
+  (trap-disable 'memoize-symbol))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define coverage-table (make-hash-table 57))
+
+(define (read-lines port)
+  (string-split (read-delimited "" port) #\newline))
+
+(define (display-coverage file vec out-file)
+  (let*
+      ((lines (read-lines (open-file file "r")))
+       (format-str "~8@a: ~5@a:~a\n")
+       (out (if out-file (open-output-file out-file)
+               (current-output-port))))
+
+    (format out format-str "-" 0 (format #f "Source:~a" file))
+    (do
+       ((i 0 (1+ i))
+        (l lines (cdr l)))
+       ((or (null? l) ))
+
+      (format out format-str
+                      (cond
+                       ((and (< i (vector-length vec)) (vector-ref vec i)) "1")
+                       ((and (string-contains file ".ly") (string-match "^[ \t]*%.*$" (car l)))
+                        "-")
+                       ((string-match  "^[ \t]*[()'`,]*$" (car l))
+                        "-")
+                       ((string-match  "^[ \t]*;.*$" (car l))
+
+                        "-")
+                       (else "0"))
+                      (1+ i)
+                      (car l)))))
+
+(define (record-coverage key cont exp env)
+  (let*
+      ((name (source-property exp 'filename))
+       (line (source-property exp 'line))
+       (vec (and name (hashv-ref coverage-table name #f)))
+       (veclen (and vec (vector-length vec)))
+       (veccopy (lambda (src dst)
+                 (vector-move-left! src 0 (vector-length src)
+                                    dst 0)
+                 dst)))
+    (if (and line name)
+       (begin
+         (if (or (not vec) (>= line (vector-length vec)))
+             (set! vec
+                   (hashv-set! coverage-table name
+                               (if vec
+                                   (veccopy vec (make-vector (1+ line) #f))
+                                   (make-vector (1+ line) #f)))))
+
+         (vector-set! vec line #t))
+    )))
+
+
+
+
+
index 5debc1d10d531e510b84f5944c4178aad72deab3..7dda76b16bf885aa8986e1a502dc41573c1efdb3 100644 (file)
@@ -280,9 +280,10 @@ alterations should be printed.  The format is (@var{step}
 ")
 
      (keySignature ,list? "The current key signature. This is an alist
-containing (@var{name} . @var{alter}) or ((@var{octave} . @var{name}) . @var{alter}).
- where @var{name} is from 0.. 6 and
-@var{alter} from -4 (double flat) to 4 (double sharp).
+containing (@var{step} . @var{alter}) or ((@var{octave} . @var{step})
+. @var{alter}).  where @var{step} is from 0.. 6 and @var{alter} a fraction, denoting
+alteration.  For alterations, use symbols, eg.
+@code{keySignature = #`((6 . ,FLAT))}
 ")
      (majorSevenSymbol ,markup? "How should
 the major 7th be formatted in a chord name?")
@@ -485,7 +486,7 @@ Valid values are described in @internalsref{bar-line-interface}.
      )
 
    `((slurMelismaBusy ,boolean? "Signal if a slur is present.")
-     (originalCentralCPosition
+     (originalMiddleCPosition
       ,integer?
       "Used for temporary overriding middle C in octavation brackets. ")
      (melismaBusy ,boolean? "Signifies
@@ -507,9 +508,6 @@ measure.  The format is the same as for keySignature, but can also
 contain ((@var{octave} . @var{name}) . (@var{alter} . @var{barnumber}))
 pairs. It is reset at every bar line.")
 
-     
-     (localKeySignatureChanges ,list? "Experimental. [DOCME]")
-
      (finalizations ,list? "List of expressions to evaluate before proceeding to next time step. Internal variable.")
      (busyGrobs ,list? "a queue of (@var{end-moment} . @var{GROB})
 conses. This is for internal (C++) use only.  This property contains
index c7949ece77c9c6aa8f996d725accef52939b536c..79c53c0dc031cd4bbbd5d4d0864da1d79d9a6a8f 100644 (file)
@@ -265,7 +265,8 @@ dimension, measured in staff space.")
      (minimum-Y-extent ,number-pair? "See @code{minimum-X-extent}.")
      (minimum-length ,ly:dimension? "Try to make a spanner at least
 this long. This requires an appropriate callback for the
-@code{springs-and-rods} property.")
+@code{springs-and-rods} property.  If added to a Tie, this sets the
+minimum distance between noteheads.")
      (minimum-space ,ly:dimension? "Minimum distance that the victim
 should move (after padding).")
      (neutral-direction ,ly:dir? "Which direction to take in the
index 2130dab4be14fe07b8a65170eec4be5f7316ac56..0dc2235031de89d58a5383b643363889cfabde56 100644 (file)
@@ -24,8 +24,6 @@
        (alteration . ,accidental-interface::calc-alteration) 
        (stencil . ,ly:accidental-interface::print)
        (Y-extent . ,ly:accidental-interface::height)
-       (after-line-breaking
-        . ,ly:accidental-interface::after-line-breaking)
        (meta . ((class . Item)
                 (interfaces . (accidental-interface
                                font-interface))))))
@@ -37,8 +35,6 @@
        (alteration . ,accidental-interface::calc-alteration) 
        (stencil . ,ly:accidental-interface::print)
        (Y-extent . ,ly:accidental-interface::height)
-       (after-line-breaking
-        . ,ly:accidental-interface::after-line-breaking)
        (meta . ((class . Item)
                 (interfaces . (accidental-interface
                                font-interface))))))
        (stencil . ,ly:accidental-interface::print)
        (Y-extent . ,ly:accidental-interface::height)
        (glyph-name-alist . ,standard-alteration-glyph-name-alist)      
-       (after-line-breaking . ,ly:accidental-interface::after-line-breaking)
        (side-axis . ,X)
        (meta . ((class . Item)
                 (interfaces . (
index aef9e3aa284eeab47ca7a76ffa09c0416f59c1fe..12dd691634b4bf127761ac77f29056e1dcf1145e 100644 (file)
@@ -716,7 +716,7 @@ alignment accordingly."
   (let* ((m1 (interpret-markup layout props arg1))
         (m2 (interpret-markup layout props arg2)))
 
-    (ly:stencil-combine-at-edge m1 axis dir m2 0.0 0.0)
+    (ly:stencil-combine-at-edge m1 axis dir m2 0.0)
   ))
 
 (define-builtin-markup-command (transparent layout props arg) (markup?)
@@ -1465,80 +1465,6 @@ that.
   (let ((th 0.1) ;; todo: take from GROB.
         (m (interpret-markup layout props arg)))
     (bracketify-stencil m Y th (* 2.5 th) th)))
-
-(define-builtin-markup-command (bracketed-y-column layout props indices args)
-  (list? markup-list?)
-  "Make a column of the markups in @var{args}, putting brackets around
-the elements marked in @var{indices}, which is a list of numbers.
-
-"
-;;
-;; DROPME? This command is a relic from the old figured bass implementation.
-;;
-  
-  (define (sublist lst start stop)
-    (take (drop lst start) (- (1+ stop) start)))
-
-  (define (stencil-list-extent ss axis)
-    (cons
-     (apply min (map (lambda (x) (car (ly:stencil-extent x axis))) ss))
-     (apply max (map (lambda (x) (cdr (ly:stencil-extent x axis))) ss))))
-  
-
-  (define (stack-stencils-vertically stencils bskip last-stencil)
-    (cond
-     ((null? stencils) '())
-     ((not (ly:stencil? last-stencil))
-      (cons (car stencils)
-           (stack-stencils-vertically (cdr stencils) bskip (car stencils))))
-     (else
-      (let* ((orig (car stencils))
-            (dir (chain-assoc-get 'direction  props DOWN))
-            (new (ly:stencil-moved-to-edge last-stencil Y dir
-                                           orig
-                                           0.1 bskip)))
-
-       (cons new (stack-stencils-vertically (cdr stencils) bskip new))))))
-
-  (define (make-brackets stencils indices acc)
-    (if (and stencils
-            (pair? indices)
-            (pair? (cdr indices)))
-       (let* ((encl (sublist stencils (car indices) (cadr indices)))
-              (x-ext (stencil-list-extent encl X))
-              (y-ext (stencil-list-extent encl Y))
-              (thick 0.10)
-              (pad 0.35)
-              (protusion (* 2.5 thick))
-              (lb
-               (ly:stencil-translate-axis 
-                (ly:bracket Y y-ext thick protusion)
-                (- (car x-ext) pad) X))
-              (rb (ly:stencil-translate-axis
-                   (ly:bracket Y y-ext thick (- protusion))
-                   (+ (cdr x-ext) pad) X)))
-
-         (make-brackets
-          stencils (cddr indices)
-          (append
-           (list lb rb)
-           acc)))
-       acc))
-
-  (let* ((stencils
-         (map (lambda (x)
-                (interpret-markup
-                 layout
-                 props
-                 x)) args))
-        (leading
-         (chain-assoc-get 'baseline-skip props))
-        (stacked (stack-stencils-vertically
-                  (remove ly:stencil-empty? stencils) 1.25 #f))
-        (brackets (make-brackets stacked indices '())))
-
-    (apply ly:stencil-add
-          (append stacked brackets))))
 \f
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
index 4a4ae30b7a9145bed67632b08efa7197b11511c2..670e28e538d35cb053aee265af64a41c8124ce41 100644 (file)
@@ -8,9 +8,7 @@
 
 ;;; this is still too big a mess.
 
-(use-modules (ice-9 regex)
-            (ice-9 string-fun)
-            (ice-9 format)
+(use-modules (ice-9 string-fun)
             (guile)
             (scm page)
             (scm paper-system)
             (scm clip-region)
             (lily))
 
+(define (format dest . rest)
+  (if (string? dest)
+      (apply simple-format (cons #f (cons dest rest)))
+      (apply simple-format (cons dest rest))))
 
 (define framework-ps-module (current-module))
 
 
     (string-append
      "magfont"
-     (string-regexp-substitute "[ /%]" "_" name)
+     (ly:string-substitute
+      " " "_"
+      (ly:string-substitute
+       "/" "_"
+       (ly:string-substitute
+       "%" "_" name)))
      "m" (string-encode-integer (inexact->exact (round (* 1000 magnify)))))))
 
 (define (tex-font? fontname)
               (ly:output-def-lookup paper 'output-scale))
            (ly:bp 1)))
        (landscape? (eq? (ly:output-def-lookup paper 'landscape) #t)))
-  (format "%%DocumentMedia: ~a ~$ ~$ ~a ~a ~a\n"
+  (format "%%DocumentMedia: ~a ~a ~a ~a ~a ~a\n"
    (ly:output-def-lookup paper 'papersizename)
-   (if landscape? h w)
-   (if landscape? w h)
+   (round2 (if landscape? h w))
+   (round2 (if landscape? w h))
    80  ;; weight
    "()" ;; color
    "()"  ;; type
        (if (mac-font? bare-file-name)
           (handle-mac-font name bare-file-name)
           (cond
-           ((string-match "^([eE]mmentaler|[Aa]ybabtu)" file-name)
+           ((or (string-startswith file-name "Emmentaler")
+                (string-startswith file-name "emmentaler")
+                (string-startswith file-name "aybabtu")
+                (string-startswith file-name "Aybabtu"))
             (ps-load-file (ly:find-file
                            (format "~a.otf"  file-name))))
            ((string? bare-file-name)
          ((downcase-file-name (string-downcase file-name)))
        
       (cond
-       ((and file-name (string-match "\\.pfa" downcase-file-name))
+       ((and file-name (string-endswith downcase-file-name ".pfa"))
        (embed-document file-name))
-       ((and file-name (string-match "\\.pfb" downcase-file-name))
+       ((and file-name (string-endswith downcase-file-name ".pfb"))
        (ly:pfb->pfa file-name))
-       ((and file-name (string-match "\\.ttf" downcase-file-name))
+       ((and file-name (string-endswith downcase-file-name ".ttf"))
        (ly:ttf->pfa file-name))
-       ((and file-name (string-match "\\.otf" downcase-file-name))
+       ((and file-name (string-endswith downcase-file-name ".otf"))
        (ps-embed-cff (ly:otf->cff file-name) name 0))
        (else
        (ly:warning (_ "do not know how to embed ~S=~S") name file-name)
        (eq? PLATFORM 'darwin)
        bare-file-name
        (or
-       (string-match "\\.dfont" bare-file-name)
+       (string-endswith  bare-file-name ".dfont")
        (= (stat:size (stat bare-file-name)) 0))))
 
   (define (load-font font-name-filename)
index a682a824be38baaa5d87f3c0f978e4028dd138b3..69194956f326c1810c1745c942e05103f1e461af 100644 (file)
@@ -80,44 +80,44 @@ Line thickness is given by @var{th}, fret & string spacing by
         (ly:stencil-combine-at-edge
          (draw-strings (- string-count 1) fret-range th size) X RIGHT
          string-stencil
-         gap 0))))
+         gap))))
 
 (define (draw-fret-lines fret-count string-count th size)
- "Draw @var{fret-count} frets (horizontal lines) for a fret diagram
 "Draw @var{fret-count} frets (horizontal lines) for a fret diagram
 with @var{string-count} strings.  Line thickness is given by @var{th},
 fret & string spacing by @var{size}. "
-   (let* ((fret-length (* (- string-count 1) size))
-          (sth (* size th))
-          (half-thickness (* sth 0.5))
-          (gap (- size sth))
-          (fret-line (ly:make-stencil (list 'draw-line sth half-thickness size (- fret-length half-thickness) size)
-                          (cons 0 fret-length)
-                          (cons (- size half-thickness) (+  size half-thickness)))))
-       (if (= fret-count 1)
-         fret-line
-         (ly:stencil-combine-at-edge fret-line Y UP
-          (draw-fret-lines (- fret-count 1) string-count th size)
-          gap 0))))
-          
+  (let* ((fret-length (* (- string-count 1) size))
+        (sth (* size th))
+        (half-thickness (* sth 0.5))
+        (gap (- size sth))
+        (fret-line (ly:make-stencil (list 'draw-line sth half-thickness size (- fret-length half-thickness) size)
+                                    (cons 0 fret-length)
+                                    (cons (- size half-thickness) (+  size half-thickness)))))
+    (if (= fret-count 1)
+       fret-line
+       (ly:stencil-combine-at-edge fret-line Y UP
+                                   (draw-fret-lines (- fret-count 1) string-count th size)
+                                   gap))))
+
 (define (draw-thick-top-fret props string-count th size)
- "Draw a thick top fret for a fret diagram whose base fret is not 1."
-   (let* ((sth (* th size))
-;          (top-fret-thick (* sth (chain-assoc-get 'top-fret-thickness props 3.0)))
-          (top-fret-thick (* sth 3.0))
-;          (top-half-thick (* top-fret-thick 0.5))
-          (half-thick (* sth 0.5))
-          (x1 half-thick)
-          (x2 (+ half-thick (* size (- string-count 1))))
-          (y1 (- half-thick))
-          (y2 (+ top-fret-thick half-thick))
-          (x-extent (cons (- x1) x2))
-          (y-extent (cons 0 y2)))
-          (ly:make-stencil (list 'round-filled-box x1 x2 y1 y2 sth)
-                            x-extent y-extent)))           
 "Draw a thick top fret for a fret diagram whose base fret is not 1."
+  (let* ((sth (* th size))
+                                       ;          (top-fret-thick (* sth (chain-assoc-get 'top-fret-thickness props 3.0)))
+        (top-fret-thick (* sth 3.0))
+                                       ;          (top-half-thick (* top-fret-thick 0.5))
+        (half-thick (* sth 0.5))
+        (x1 half-thick)
+        (x2 (+ half-thick (* size (- string-count 1))))
+        (y1 (- half-thick))
+        (y2 (+ top-fret-thick half-thick))
+        (x-extent (cons (- x1) x2))
+        (y-extent (cons 0 y2)))
+    (ly:make-stencil (list 'round-filled-box x1 x2 y1 y2 sth)
+                    x-extent y-extent)))           
+
+
 (define (draw-frets layout props fret-range string-count th size)
- "Draw the frets (horizontal lines) for a fret diagram with
 "Draw the frets (horizontal lines) for a fret diagram with
 @var{string-count} strings and frets as indicated in @var{fret-range}.
 Line thickness is given by @var{th}, fret & string spacing by
 @var{size}. "
@@ -125,13 +125,13 @@ Line thickness is given by @var{th}, fret & string spacing by
          (fret-length (* (- string-count 1) size))
          (half-thickness (* th 0.5))
          (base-fret (car fret-range)))
-       (ly:stencil-combine-at-edge
-          (draw-fret-lines fret-count string-count th size) Y UP
-             (if (= base-fret 1)
-                 (draw-thick-top-fret props string-count th size)
-                 (draw-fret-lines 1 string-count th size)) 
-                 (- size th) 0))) 
-                 
+    (ly:stencil-combine-at-edge
+     (draw-fret-lines fret-count string-count th size) Y UP
+     (if (= base-fret 1)
+        (draw-thick-top-fret props string-count th size)
+        (draw-fret-lines 1 string-count th size)) 
+     (- size th)))) 
+
 
 (define (draw-dots layout props string-count fret-range size finger-code 
                     dot-position dot-radius dot-thickness dot-list)
@@ -383,11 +383,11 @@ indications per string.
          (if (not (null? xo-list))
              (set! fret-diagram-stencil (ly:stencil-combine-at-edge
                                     fret-diagram-stencil Y UP
-                                    (draw-xo layout props string-count fret-range size xo-list) xo-padding 0)))
+                                    (draw-xo layout props string-count fret-range size xo-list) xo-padding)))
          (if (> (car fret-range) 1) 
              (set! fret-diagram-stencil
                    (ly:stencil-combine-at-edge fret-diagram-stencil X label-dir
-                                              (label-fret layout props string-count fret-range size) label-space 0)))
+                                              (label-fret layout props string-count fret-range size) label-space)))
          (ly:stencil-aligned-to fret-diagram-stencil X alignment)
         ))
          
index 9e8971ac7e1df569cdc158305169c777334e71ed..264d38054871e015b83f2f0f6e5f09e99d24c1de 100644 (file)
                           (space-to-fill (page-maximum-space-to-fill
                                            page lines paper))
                           (spacing (space-systems space-to-fill lines ragged paper #f)))
-                     (if (or (not (car spacing)) (inf? (car spacing)))
-                         (cdr (space-systems space-to-fill lines ragged paper #t))
+                     (if (and (> (length lines) 1)
+                              (or (not (car spacing)) (inf? (car spacing))))
+                         (begin
+                           (ly:warning (_ "Can't fit systems on page -- ignoring between-system-padding"))
+                           (cdr (space-systems space-to-fill lines ragged paper #t)))
                          (cdr spacing))))))
     (page-set-property! page 'configuration posns)
     page))
index dc69ad5df74de3e5ebbd620ff679fb1e058caf4f..0746876ca3d6625d9c678c857618fe38f8ebf00a 100644 (file)
@@ -380,6 +380,9 @@ found."
 
 (define-public interval-end cdr)
 
+(define-public (interval-bound interval dir)
+  ((if (= dir RIGHT) cdr car) interval))
+
 (define-public (interval-index interval dir)
   "Interpolate INTERVAL between between left (DIR=-1) and right (DIR=+1)"
   
@@ -423,9 +426,16 @@ found."
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-
-
+;; string
+
+(define-public (string-endswith s suffix)
+  (equal? suffix (substring s
+                           (max 0 (- (string-length s) (string-length suffix)))
+                           (string-length s))))
+            
+(define-public (string-startswith s prefix)
+  (equal? prefix (substring s 0 (min (string-length s) (string-length prefix)))))
+            
 (define-public (string-encode-integer i)
   (cond
    ((= i  0) "o")
@@ -516,6 +526,12 @@ possibly turned off."
       0
       (if (< x 0) -1 1)))
 
+(define-public (round2 num)
+  (/ (round (* 100 num)) 100))
+
+(define-public (round4 num)
+  (/ (round (* 10000 num)) 10000))
+
 (define-public (car< a b) (< (car a) (car b)))
 
 (define-public (symbol<? lst r)
index e10b4b7d3374b4d687ed282ea1988fcec87b012d..183b71e4902b1f46d9ec2ddd68a81fc2e2343f20 100644 (file)
@@ -36,7 +36,6 @@
              (debug-gc-assert-parsed-dead #f "for memory debugging:
 ensure that all refs to parsed objects are dead.  This is an internal option, and is switched on automatically for -ddebug-gc.") 
              (debug-lexer #f "debug the flex lexer")
-             (debug-midi #f "generate human readable MIDI")
              (debug-parser #f "debug the bison parser")
              (debug-skylines #f "debug skylines")
              (delete-intermediate-files #f
@@ -71,6 +70,8 @@ on errors, and print a stack trace.")
              (safe #f "Run safely")
              (strict-infinity-checking #f "If yes, crash on encountering Inf/NaN.")
              (separate-log-files #f "Output to FILE.log per file.")
+             (trace-memory-frequency #f "Record Scheme cell usage this many times per second, and dump to file.")
+             (trace-scheme-coverage #f "Record coverage of Scheme files") 
              (ttf-verbosity 0
                             "how much verbosity for TTF font embedding?")
              (show-available-fonts #f
@@ -100,12 +101,15 @@ on errors, and print a stack trace.")
 
 (use-modules (ice-9 regex)
             (ice-9 safe)
+            (ice-9 rdelim)
              (ice-9 optargs)
             (oop goops)
             (srfi srfi-1)
             (srfi srfi-13)
             (srfi srfi-14)
             (scm clip-region)
+            (scm memory-trace)
+            (scm coverage)
             )
 
 ;; my display
@@ -120,13 +124,20 @@ on errors, and print a stack trace.")
 ;;; debugging evaluator is slower.  This should
 ;;; have a more sensible default.
 
-(if (ly:get-option 'verbose)
+(if (or (ly:get-option 'verbose)
+       (ly:get-option 'trace-memory-frequencency)
+       (ly:get-option 'trace-scheme-coverage)
+       )
     (begin
       (ly:set-option 'protected-scheme-parsing #f)
       (debug-enable 'debug)
       (debug-enable 'backtrace)
       (read-enable 'positions)))
 
+
+(if (ly:get-option 'trace-scheme-coverage)
+    (coverage:enable))
+
 (define-public tex-backend?
   (member (ly:output-backend) '("texstr" "tex")))
 
@@ -402,6 +413,15 @@ The syntax is the same as `define*-public'."
 
 (define gc-dumping #f)
 (define gc-protect-stat-count 0)
+
+(define-public (dump-live-object-stats outfile)
+  (for-each
+   (lambda (x)
+     (format outfile "~a: ~a\n" (car x) (cdr x)))
+   (sort (gc-live-object-stats)
+        (lambda (x y)
+          (string<? (car x) (car y))))))
+
 (define-public (dump-gc-protects)
   (set! gc-protect-stat-count (1+ gc-protect-stat-count))
   (let* ((protects (sort
@@ -450,14 +470,7 @@ The syntax is the same as `define*-public'."
 
          (set! stats (gc-live-object-stats))
          (display "Dumping live object statistics.\n")
-         
-         (for-each
-          (lambda (x)
-            (format outfile "~a: ~a\n" (car x) (cdr x)))
-          (sort (gc-live-object-stats)
-                (lambda (x y)
-                  (string<? (car x) (car y)))))))
-
+         (dump-live-object-stats outfile)))
 
     (newline outfile)
     (let*
@@ -479,6 +492,36 @@ The syntax is the same as `define*-public'."
                           )))
 
     (set! gc-dumping #f)
+    (close-port outfile)
+    
+    ))
+
+
+(define (check-memory)
+  "read /proc/self to check up on memory use." 
+  (define (gulp-file name)
+    (let* ((file (open-input-file name))
+          (text (read-delimited "" file)))
+      (close file)
+      text))
+  (let*
+      ((stat (gulp-file "/proc/self/status"))
+       (lines (string-split stat #\newline))
+       (interesting (filter identity
+                           (map
+                            (lambda (l)
+                              (string-match "^VmData:[ \t]*([0-9]*) kB" l))
+                            lines)))
+       (mem (string->number (match:substring (car interesting) 1)))
+       )
+
+    
+    (display (format  "VMDATA: ~a\n" mem))
+    (display (gc-stats))
+    (if (> mem 100000)
+       (begin
+         (dump-gc-protects)
+         (raise 1)))
     
     ))
 
@@ -583,6 +626,13 @@ The syntax is the same as `define*-public'."
 
   
   (let ((failed (lilypond-all files)))
+    (if (ly:get-option 'trace-scheme-coverage)
+       (begin
+         (coverage:disable)
+         (coverage:show-all (lambda (f) (string-contains f "lilypond"))
+                            )))
+         
+    
     (if (pair? failed)
        (begin
          (ly:error (_ "failed files: ~S") (string-join failed))
@@ -619,21 +669,28 @@ The syntax is the same as `define*-public'."
 
         (if separate-logs
             (ly:stderr-redirect (format "~a.log" base) "w"))
-       
+        (if (ly:get-option 'trace-memory-frequency) 
+            (mtrace:start-trace  (ly:get-option 'trace-memory-frequency)))
+        
         (lilypond-file handler x)
         (if start-measurements
             (dump-profile x start-measurements (profile-measurements)))
-       
+
+        (if (ly:get-option 'trace-memory-frequency)
+            (begin
+              (mtrace:stop-trace)
+              (mtrace:dump-results base)))
+                
         (for-each
          (lambda (s)
            (ly:set-option (car s) (cdr s)))
          all-settings)
-        
+
         (ly:clear-anonymous-modules)
         (ly:set-option 'debug-gc-assert-parsed-dead #t)
         (gc)
         (ly:set-option 'debug-gc-assert-parsed-dead #f)
-        
+
         
         (if (ly:get-option 'debug-gc)
             (dump-gc-protects)
diff --git a/scm/memory-trace.scm b/scm/memory-trace.scm
new file mode 100644 (file)
index 0000000..0b63637
--- /dev/null
@@ -0,0 +1,157 @@
+(define-module (scm memory-trace))
+(use-modules (lily)
+            (ice-9 format))
+
+(define-public (mtrace:start-trace freq)
+  (set! usecond-interval (inexact->exact (/ 1000000 freq)))
+  (call-with-new-thread start-install-tracepoint))
+
+(define-public (mtrace:stop-trace)
+  (set! continue-tracing #f))
+
+(define-public mtrace:trace-depth 12)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define trace-points '())
+(define continue-tracing #t)
+(define busy-tracing #f)
+(define trace-thread #f)
+(define start-time 0)
+(define start-memory 0)
+
+(define trace-count 0)
+(define usecond-interval 100000)
+(define (arg-procedure args)
+  (if (and (pair? args)
+          (pair? (cdr args))
+          (pair? (cadr args)))
+      (caadr args) #f))
+(define last-count 0)
+(define (record-stack key continuation . args)
+  (if (eq? (current-thread) trace-thread)
+      #t ;; do nothing.
+      (let*
+         ((cells (cdr (assoc 'total-cells-allocated (gc-stats))))
+          (proc (arg-procedure args))
+          (time (tms:utime (times)))
+          (stack (extract-trace continuation)))
+       
+       (set! busy-tracing #t)
+       (trap-disable 'traps)
+       (trap-disable 'enter-frame)
+
+       (set! trace-count (1+ trace-count))
+       (ly:progress "<~a: ~a/~a>\n"
+                    trace-count
+                    (- time start-time)
+                    (- cells last-count))
+
+       (set! last-count cells)
+       (set! trace-points
+             (cons (list
+                    (cons 'cells cells)
+                    (cons 'proc proc)
+                    (cons 'stack stack)
+                    (cons 'time time)
+                    )
+                   
+                   trace-points))
+
+       (set! busy-tracing #f))))
+
+(define (start-install-tracepoint)
+  (set! trace-thread (current-thread))
+  (set! trace-points '())
+  (set! continue-tracing #t)
+  (set! trace-count 0)
+  (set! start-memory (cdr (assoc 'total-cells-allocated (gc-stats))))
+  (set! start-time (tms:utime (times)))
+  
+  (install-tracepoint))
+
+(define (install-tracepoint)
+  (if busy-tracing
+      (display "last trace not finished yet\n" (current-error-port))
+      (begin
+       (trap-set! enter-frame-handler record-stack)
+       (trap-enable 'enter-frame)
+       (trap-enable 'traps)))
+  
+  (usleep usecond-interval)
+  (if continue-tracing
+      (install-tracepoint)))
+
+(define-public (mtrace:dump-results base)
+  (let*
+      ((stacks-name (format #f "~a.stacks" base))
+       (graph-name (format #f "~a.graph" base))
+       (graph-out (open-output-file graph-name))
+       (stacks-out (open-output-file stacks-name))
+       (i 0)
+       (last-mem 0)
+       )
+
+    (ly:progress "Memory statistics to ~a and ~a..."
+                stacks-name graph-name)
+    (format graph-out "# memory trace with ~a points\n" (length trace-points))
+    (for-each
+     (lambda (r)
+       (let*
+          ((mem (- (cdr (assoc 'cells r)) start-memory))
+           (proc (cdr (assoc 'proc r)))
+           (stack (cdr (assoc 'stack r)))
+           (time (- (cdr (assoc 'time r)) start-time)))
+        
+        (format graph-out "~a ~a\n" time mem)
+        (if stack
+            (begin
+              (format stacks-out "~5a t = ~5a - delta-mem: ~15a - ~a \n" i
+                      time
+                      (- mem last-mem) proc)
+              (do
+                  ((j 0 (1+ j))
+                   (stack (cdr (assoc 'stack r)) stack))
+                  ((>= j (vector-length stack)))
+                
+                (format stacks-out "\t~a\n"
+                        (vector-ref stack j)))))
+        
+        (set! i (1+ i))
+        (set! last-mem mem)
+        ))
+     (reverse trace-points))))
+
+
+(define (test-graph . rest)
+  (mtrace:start-trace 100)
+  (iota 100000)
+  (mtrace:stop-trace)
+  (mtrace:dump-results "test"))
+
+
+
+(define (extract-trace continuation)
+  (let*
+      ((stack (make-stack continuation))
+       (depth (min (stack-length stack) mtrace:trace-depth))
+       (trace (make-vector depth #f)))
+
+    (do
+       ((i 0 (1+ i)))
+       ((>= i depth))
+
+      (vector-set!
+       trace i
+       (let*
+          ((source (frame-source (stack-ref stack i))))
+
+          (and source
+               (cons (source-property source 'filename)
+                     (source-property source 'line))))))
+
+    trace))
+
+
+       
+       
index ed93b33fbdf396f759d60375ce3b80aa81a355a7..234faf41b5c40ac3237133971a76d855fe3542a4 100644 (file)
@@ -430,23 +430,26 @@ i.e.  this is not an override"
 old middleCPosition, add OCTAVATION to middleCPosition, and set
 OTTAVATION to `8va', or whatever appropriate."     
       (if (number? (ly:context-property         context 'middleCPosition))
-         (if (= octavation 0)
-             (let ((where (ly:context-property-where-defined context 'middleCPosition))
-                   (oc0 (ly:context-property context 'originalCentralCPosition)))
-               (ly:context-set-property! context 'middleCPosition oc0)
-               (ly:context-unset-property where 'originalCentralCPosition)
-               (ly:context-unset-property where 'ottavation))
-             (let* ((where (ly:context-property-where-defined context 'middleCPosition))
-                    (c0 (ly:context-property context 'middleCPosition))
-                    (new-c0 (+ c0 (* -7 octavation)))
-                    (string (cdr (assoc octavation '((2 . "15ma")
-                                                     (1 . "8va")
-                                                     (0 . #f)
-                                                     (-1 . "8vb")
-                                                     (-2 . "15mb"))))))
-               (ly:context-set-property! context 'middleCPosition new-c0)
-               (ly:context-set-property! context 'originalCentralCPosition c0)
-               (ly:context-set-property! context 'ottavation string)))))
+         (begin
+           (if (number? (ly:context-property context 'originalMiddleCPosition))
+               (let ((where (ly:context-property-where-defined context 'middleCPosition)))
+                 
+                 (ly:context-set-property! context 'middleCPosition
+                                           (ly:context-property context 'originalMiddleCPosition))
+                 (ly:context-unset-property where 'originalMiddleCPosition)
+                 (ly:context-unset-property where 'ottavation)))
+ot         
+           (let* ((where (ly:context-property-where-defined context 'middleCPosition))
+                  (c0 (ly:context-property context 'middleCPosition))
+                  (new-c0 (+ c0 (* -7 octavation)))
+                  (string (cdr (assoc octavation '((2 . "15ma")
+                                                   (1 . "8va")
+                                                   (0 . #f)
+                                                   (-1 . "8vb")
+                                                   (-2 . "15mb"))))))
+             (ly:context-set-property! context 'middleCPosition new-c0)
+             (ly:context-set-property! context 'originalMiddleCPosition c0)
+             (ly:context-set-property! context 'ottavation string)))))
     (set! (ly:music-property m 'procedure) ottava-modify)
     (context-spec-music m 'Staff)))
 
index 42aecc1dbcb0364720adcb10a5bf687846a7bc3a..7a2972525b8a6620081862c89010924c2b4d1830 100644 (file)
 ;;;
 
 
-(define (escape-parentheses s)
-  (regexp-substitute/global #f "(^|[^\\])([\\(\\)])" s 'pre 1 "\\" 2 'post))
-
-(define (ps-encoding text)
-  (escape-parentheses text))
-
-(define (round2 num)
-  (/ (round (* 100 num)) 100))
-
-(define (round4 num)
-  (/ (round (* 10000 num)) 10000))
+;; ice-9 format uses a lot of memory
+;; using simple-format almost halves lilypond cell usage
 
 (define (str4 num)
   (if (or (nan? num) (inf? num))
        (if (ly:get-option 'strict-infinity-checking)
            (exit 1))
        "0.0")
-      (format #f "~f" (round4 num))))
+      (ly:number->string num)))
 
 (define (number-pair->string4 numpair)
-  (string-append (str4 (car numpair))
-                " "
-                (str4 (cdr numpair))))
+  (ly:format "~4l" numpair)) 
 
 (define (numbers->string4 numlist)
   (string-join (map str4 numlist) " "))
 
 ;; FIXME: lily-def
 (define-public (ps-string-def prefix key val)
-  (format #f "/ ~a~a (~a) def\n"
+  (ly:format "/ ~a~a (~a) def\n"
          prefix
          (symbol->string key)
          (escape-parentheses val)))
@@ -92,9 +81,9 @@
   (let ((s (if (integer? val)
               (ly:number->string val)
               (ly:number->string (exact->inexact val)))))
-    (format #f "/~a~a ~a def\n"
-           prefix
-           (symbol->string key) s)))
+    (ly:format "/~a~a ~a def\n"
+              prefix
+              (symbol->string key) s)))
 
 
 ;;;
 
 ;; two beziers
 (define (bezier-sandwich lst thick)
-  (format #f "~a ~a draw_bezier_sandwich" 
-         (string-join (map number-pair->string4 lst) " ")
-         (str4 thick)))
+  (ly:format "~l ~4f draw_bezier_sandwich" 
+            (map number-pair->string4 lst)
+         thick))
 
 (define (char font i)
-  (format #f "~a (\\~a) show"
+  (ly:format "~a (\\~a) show"
    (ps-font-command font)
    (ly:inexact->string i 8)))
 
 (define (circle radius thick fill)
-  (format #f
-   "~a ~f ~f draw_circle"
+  (ly:format
+   "~a ~4f ~4f draw_circle"
    (if fill
      "true"
      "false")
-   (round4 radius) (round4 thick)))
+   radius thick))
 
 (define (dashed-line thick on off dx dy phase)
-  (format #f "~a ~a ~a [ ~a ~a ] ~a draw_dashed_line"
-   (str4 dx)
-   (str4 dy)
-   (str4 thick)
-   (str4 on)
-   (str4 off)
-   (str4 phase)
-   
-   ))
+  (ly:format "~4f ~4f ~4f [ ~4f ~4f ] ~4f draw_dashed_line"
+   dx
+   dy
+   thick
+   on
+   off
+   phase))
 
 ;; what the heck is this interface ?
 (define (dashed-slur thick on off l)
-  (format #f "~a ~a [ ~a ~a ] 0 draw_dashed_slur"
+  (ly:format "~l ~4f [ ~4f ~4f ] 0 draw_dashed_slur"
          (let ((control-points (append (cddr l) (list (car l) (cadr l)))))
-           (string-join (map number-pair->string4 control-points) " "))
-         (str4 thick)
-         (str4 on)
-         (str4 off)))
+           (map number-pair->string4 control-points) " ")
+         thick
+         on
+         off))
 
 (define (dot x y radius)
-  (format #f " ~a draw_dot"
-   (numbers->string4 (list radius x y))))
+  (ly:format " ~4l draw_dot" (list radius x y)))
 
 (define (draw-line thick x1 y1 x2 y2)
-  (format #f "~a ~a ~a ~a ~a draw_line"
-         (str4 (- x2 x1))
-         (str4 (- y2 y1))
-         (str4 x1)
-         (str4 y1)
-         (str4 thick)))
+  (ly:format "~4f ~4f ~4f ~4f ~4f draw_line"
+         (- x2 x1) (- y2 y1)
+         x1 y1 thick))
 
 (define (embedded-ps string)
   string)
 
   (define (glyph-spec w x y g)
     (let ((prefix (if (string? g) "/" "")))
-      (format #f "~f ~f ~a~a"
-             (round2 (+ w x))
-             (round2 y)
-             prefix g)))
+      (ly:format "~4f ~4f ~a~a"
+                (+ w x)  y
+                prefix g)))
   
-  (format #f
-         (if cid?
+  (ly:format 
+   (if cid?
 "/~a /CIDFont findresource ~a output-scale div scalefont setfont
 ~a
 ~a print_glyphs"
 
          (if (and (< 0 (interval-length x-ext))
                   (< 0 (interval-length y-ext)))
-             (format #f "~$ ~$ ~$ ~$ (textedit://~a:~a:~a:~a) mark_URI\n"
-                     (+ (car offset) (car x-ext))
-                     (+ (cdr offset) (car y-ext))
-                     (+ (car offset) (cdr x-ext))
-                     (+ (cdr offset) (cdr y-ext))
-
-                     ;; TODO
-                     ;;full escaping.
-
-                     ;; backslash is interpreted by GS.
-                     (string-regexp-substitute "\\\\" "/" 
-                                     (string-regexp-substitute " " "%20" file))
-                     (cadr location)
-                     (caddr location)
-                     (cadddr location))
+             (ly:format "~4f ~4f ~4f ~4f (textedit://~a:~a:~a:~a) mark_URI\n"
+                        (+ (car offset) (car x-ext))
+                        (+ (cdr offset) (car y-ext))
+                        (+ (car offset) (cdr x-ext))
+                        (+ (cdr offset) (cdr y-ext))
+
+                        ;; TODO
+                        ;;full escaping.
+
+                        ;; backslash is interpreted by GS.
+                        (ly:string-substitute "\\" "/" 
+                                              (ly:string-substitute " " "%20" file))
+                        (cadr location)
+                        (caddr location)
+                        (cadddr location))
              "")))))
 
 (define (lily-def key val)
       (format "/~a (~a) def\n" key val))))
 
 (define (named-glyph font glyph)
-  (format #f "~a /~a glyphshow " ;;Why is there a space at the end?
-         (ps-font-command font)
-         glyph))
+  (ly:format "~a /~a glyphshow " ;;Why is there a space at the end?
+            (ps-font-command font)
+            glyph))
 
 (define (no-origin)
   "")
 
 (define (placebox x y s) 
-  (format #f
-"~a ~a moveto
-~a\n"
-  (str4 x)
-  (str4 y)
-  s))
+  (ly:format
+"~4f ~4f moveto
+~a\n" x y s))
 
 (define (polygon points blot-diameter filled?)
-  (format #f "~a ~a ~a ~a draw_polygon"
-         (if filled? "true" "false")
-         (numbers->string4 points)
-         (number->string (- (/ (length points) 2) 1))
-         (str4 blot-diameter)))
+  (ly:format "~a ~4l ~a ~4f draw_polygon"
+            (if filled? "true" "false")
+            points
+            (- (/ (length points) 2) 1)
+            blot-diameter))
 
 (define (repeat-slash width slope beam-thickness)
   (define (euclidean-length x y)
 
   (let ((x-width (euclidean-length beam-thickness (/ beam-thickness slope)))
        (height (* width slope)))
-    (format #f "~a draw_repeat_slash"
-           (numbers->string4 (list x-width width height)))))
+    (ly:format "~4l draw_repeat_slash"
+            (list x-width width height))))
 
 
 (define (round-filled-box left right bottom top blotdiam)
         (width (- right (+ halfblot x)))
         (y (- halfblot bottom))
         (height (- top (+ halfblot y))))
-    (format #f "~a draw_round_box"
-           (numbers->string4
-             (list width height x y blotdiam)))))
+    (ly:format  "~4l draw_round_box"
+               (list width height x y blotdiam))))
 
 ;; save current color on stack and set new color
 (define (setcolor r g b)
-  (format #f "gsave ~a setrgbcolor\n"
-         (numbers->string4 (list r g b))))
+  (ly:format "gsave ~4l setrgbcolor\n"
+             (list r g b)))
 
 ;; restore color from stack
 (define (resetcolor) "grestore \n")
 
 ;; rotation around given point
 (define (setrotation ang x y)
-  (format "gsave ~a translate ~a rotate ~a translate\n"
-    (numbers->string4 (list x y))
-    (number->string ang)
-    (numbers->string4 (list (* -1 x) (* -1 y)))))
+  (ly:format "gsave ~4l translate ~a rotate ~4l translate\n"
+            (list x y)
+            ang
+            (list (* -1 x) (* -1 y))))
 
 (define (resetrotation ang x y)
   "grestore  ")
   "\n unknown\n")
 
 (define (url-link url x y)
-  (format #f "~$ ~$ ~$ ~$ (~a) mark_URI"
-         (car x)
-         (car y)
-         (cdr x)
-         (cdr y)
-         url))
+  (ly:format "~a ~a ~a ~a (~a) mark_URI"
+            (car x)
+            (car y)
+            (cdr x)
+            (cdr y)
+            url))
 
 (define (utf-8-string pango-font-description string)
   (ly:warning (_ "utf-8-string encountered in PS backend")))
 
 
-(define (zigzag-line centre? zzw zzh thick dx dy)
-  (format #f "~a ~a ~a ~a 0 0 ~a ~a draw_zigzag_line"
-   (if centre? "true" "false")
-   (str4 zzw)
-   (str4 zzh)
-   (str4 thick)
-   (str4 dx)
-   (str4 dy)))
+(define (zigzag-line is-center zzw zzh thick dx dy)
+  (ly:format "~a ~4f ~4f ~4f 0 0 ~4f ~4f draw_zigzag_line"
+   (if is-center "true" "false")
+   zzw
+   zzh
+   thick
+   dx
+   dy))
 
 
 (define (path thickness exps)
             )
 
          ;; WARNING: this is a vulnerability: a user can output arbitrary PS code here.
-         (cons (format "~a ~a "
-                       (string-join (map (lambda (x) (format "~a " x)) args) " ")
+         (cons (ly:format
+                       "~l ~a "
+                       args 
                        head)
                (convert-path-exps (drop rest arity))))
        '()))
     
     
-  (format
-   "1 setlinecap ~a setlinewidth\n~a stroke"
+  (ly:format
+   "1 setlinecap ~a setlinewidth\n~l stroke"
    thickness
-   (string-join (convert-path-exps exps) " ")))
+   (convert-path-exps exps) ))
   
index 40fd537557f0ad6b5c8f91d03e97c52f5620308e..3e25bdaaee3b46059ce22a90eb1578cb8b7b6426 100644 (file)
          (set! head-stencil
                (ly:stencil-combine-at-edge
                 stencil Y dir head-stencil
-                sep 0.0))
+                sep))
 
          
          ;; add arrow markers 
index 65c5bfa6dddc5d9f5c3b7946bb3967192e7b5e7f..c47f05583b26f21e3b2f888ef44f15a78090f1ce 100644 (file)
    ly:stencil-combine-at-edge
    ly:stencil-expr
    ly:stencil-extent
-   ly:stencil-moved-to-edge
    ly:stencil-translate
    ly:stencil-translate-axis
    ly:stencil?
index e12cdd07dd65a9c49ee47ec1b5676cb395c88854..a31e201abab03290ecf773760b8ab89aeea4540c 100644 (file)
@@ -45,6 +45,7 @@
     ("accentus" .
      ((script-stencil . (feta . ("uaccentus" . "uaccentus")))
       (side-relative-direction .  -1)
+      (avoid-slur . #f)
       (padding . 0.20)    
       (quantize-position . #t)
       (script-priority . -100)
@@ -53,6 +54,7 @@
      ((script-stencil . (feta . ("ictus" . "ictus")))
       (side-relative-direction .  -1)
       (quantize-position . #t)
+      (avoid-slur . #f)
       (padding . 0.20)    
       (script-priority . -100)
       (direction  . -1)))
      ((script-stencil . (feta . ("dsemicirculus" . "dsemicirculus")))
       (side-relative-direction .  -1)
       (quantize-position . #t)
+      (avoid-slur . #f)
       (padding . 0.20)    
       (script-priority . -100)
       (direction  . 1)))
     ("circulus" .
      ((script-stencil . (feta . ("circulus" . "circulus")))
       (side-relative-direction .  -1)
+      (avoid-slur . #f)
       (padding . 0.20)    
       (quantize-position . #t)
       (script-priority . -100)
@@ -74,6 +78,7 @@
     ("signumcongruentiae" .
      ((script-stencil . (feta . ("dsignumcongruentiae" . "usignumcongruentiae")))
       (padding . 0.20)    
+      (avoid-slur . outside)
       (direction .  1)))
     ("fermata" .
      ((script-stencil . (feta . ("dfermata" . "ufermata")))
     ("shortfermata" .
      ((script-stencil . (feta . ("dshortfermata" . "ushortfermata")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction .  1)))
     ("longfermata" .
      ((script-stencil . (feta . ("dlongfermata" . "ulongfermata")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction .  1)))
     ("verylongfermata" .
      ((script-stencil . (feta . ("dverylongfermata" . "uverylongfermata")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction .  1)))
     ("stopped" .
      ((script-stencil . (feta . ("stopped" . "stopped")))
      ((script-stencil . (feta . ("lcomma" . "rcomma")))
       (quantize-position . #t)
       (padding . 0.20)    
+      (avoid-slur . #f)
       (direction . 1)))
     ("varcomma" .
      ((script-stencil . (feta . ("lvarcomma" . "rvarcomma")))
       (quantize-position . #t)
       (padding . 0.20)    
+      (avoid-slur . #f)
       (direction . 1)))
     ("upbow" .
      ((script-stencil . (feta . ("upbow" . "upbow")))
     ("lheel" .
      ((script-stencil . (feta . ("upedalheel" . "upedalheel")))
       (padding . 0.20)    
+      (avoid-slur . around) ;guessing?
       (direction .  -1))
      )
     ("rheel" .
      ((script-stencil . (feta . ("dpedalheel" . "dpedalheel")))
       (padding . 0.20)    
+      (avoid-slur . around) ;guessing?
       (direction  . 1)))
     ("ltoe" .
      ((script-stencil . (feta . ("upedaltoe" . "upedaltoe")))
       (padding . 0.20)    
+      (avoid-slur . around) ;guessing?
       (direction  . -1)))
     ("rtoe" .
      ((script-stencil . (feta . ("dpedaltoe" . "dpedaltoe")))
       (padding . 0.20)    
+      (avoid-slur . around) ;guessing?
       (direction  . 1)))
     ("turn" .
      ((script-stencil . (feta . ("turn" . "turn")))
     ("flageolet" .
      ((script-stencil . (feta . ("flageolet" . "flageolet")))
       (padding . 0.20)    
+      (avoid-slur . around) ;guessing?
       (direction  . 1)))
     ("reverseturn" .
      ((script-stencil . (feta . ("reverseturn" . "reverseturn")))
       (padding . 0.20)    
+      (avoid-slur . inside)
       (direction  . 1)))
     ("trill" .
      ((script-stencil . (feta . ("trill" . "trill")))
     ("prall" .
      ((script-stencil . (feta . ("prall" . "prall")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("mordent" .
      ((script-stencil . (feta . ("mordent" . "mordent")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("prallprall" .
      ((script-stencil . (feta . ("prallprall" . "prallprall")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("prallmordent" .
      ((script-stencil . (feta . ("prallmordent" . "prallmordent")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("upprall" .
      ((script-stencil . (feta . ("upprall" . "upprall")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("downprall" .
      ((script-stencil . (feta . ("downprall" . "downprall")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("upmordent" .
      ((script-stencil . (feta . ("upmordent" . "upmordent")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("downmordent" .
      ((script-stencil . (feta . ("downmordent" . "downmordent")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("lineprall" .
      ((script-stencil . (feta . ("lineprall" . "lineprall")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("pralldown" .
      ((script-stencil . (feta . ("pralldown" . "pralldown")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("prallup" .
      ((script-stencil . (feta . ("prallup" . "prallup")))
       (padding . 0.20)    
+      (avoid-slur . around)
       (direction  . 1)))
     ("segno" .
      ((script-stencil . (feta . ("segno" . "segno")))
       (padding . 0.20)    
+      (avoid-slur . outside)
       (direction  . 1)))
     ("coda" .
      ((script-stencil . (feta . ("coda" . "coda")))
       (padding . 0.20)    
+      (avoid-slur . outside)
       (direction  . 1)))
     ("varcoda" .
      ((script-stencil . (feta . ("varcoda" . "varcoda")))
       (padding . 0.20)    
+      (avoid-slur . outside)
       (direction  . 1)))))
index 681a49d04297727f11ff25c2ac8a757e7d755811..5a644d2b3d1b8c9e1312f90b5b39ea306e469ab2 100644 (file)
@@ -5,6 +5,9 @@
 ;;;; (c) 1998--2006 Jan Nieuwenhuizen <janneke@gnu.org>
 ;;;;                 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
+
+(use-modules (ice-9 rdelim))
+
 (define standalone (not (defined? 'ly:gulp-file)))
 ;;(write standalone (current-error-port))
 
@@ -16,8 +19,8 @@
 
 (define (scm-gulp-file name)
   (set! %load-path 
-       (cons (string-append (getenv 'LILYPONDPREFIX) "/ly")
-             (cons (string-append (getenv 'LILYPONDPREFIX) "/ps")
+       (cons (string-append (getenv "LILYPONDPREFIX") "/ly")
+             (cons (string-append (getenv "LILYPONDPREFIX") "/ps")
                    %load-path)))
   (let ((path (%search-load-path name)))
        (if path
index 62b43cebc260a13f4f2ec3402c99ba9475dbe4df..463a082fd337e63e25230fc4fe89f70c3091206f 100644 (file)
 
 (define-public (stack-lines dir padding baseline stils)
   "Stack vertically with a baseline-skip."
-  (if (null? stils)
-      empty-stencil
-      (if (null? (cdr stils))
-         (car stils)
-         (ly:stencil-combine-at-edge
-          (car stils) Y dir 
-          (stack-lines dir padding baseline (cdr stils))
-          padding baseline))))
+  (define result empty-stencil)
+  (define last-y #f)
+  (do
+      ((last-stencil #f (car p))
+       (p stils (cdr p)))
+      
+      ((null? p))
+
+    (if (number? last-y)
+       (begin
+         (let* ((dy (max (+ (* dir (interval-bound (ly:stencil-extent last-stencil Y) dir))
+                            padding
+                            (* (- dir) (interval-bound (ly:stencil-extent (car p) Y) (- dir))))
+                         baseline))
+                (y (+ last-y  (* dir dy))))
+           
+                         
+           
+           (set! result
+                 (ly:stencil-add result (ly:stencil-translate-axis (car p) y Y)))
+           (set! last-y y)))
+       (begin
+         (set! last-y 0)
+         (set! result (car p)))))
+
+  result)
+    
 
 (define-public (bracketify-stencil stil axis thick protusion padding)
   "Add brackets around STIL, producing a new stencil."
@@ -240,11 +259,11 @@ encloses the contents.
          (set! annotation
                 (center-stencil-on-extent text-stencil))
          (set! annotation
-               (ly:stencil-combine-at-edge arrows X RIGHT annotation 0.5 0))
+               (ly:stencil-combine-at-edge arrows X RIGHT annotation 0.5))
          (set! annotation
                (ly:stencil-combine-at-edge annotation X LEFT
                                             (center-stencil-on-extent dim-stencil)
-                                            0.5 0))
+                                            0.5))
          (set! annotation
                (ly:make-stencil (list 'color color (ly:stencil-expr annotation))
                                 (ly:stencil-extent annotation X)