NAME = documentation
LANGS = $(shell $(PYTHON) $(top-src-dir)/python/langdefs.py)
-MANUALS_SUBDIRS = usage automated-engraving contributor essay \
+MANUALS_SUBDIRS = usage contributor essay \
web learning notation extending
SUBDIRS = $(MANUALS_SUBDIRS) snippets logo pictures misc po css topdocs \
included $(LANGS)
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-@ignore
-hmm, the one big page is too big, but it was really inviting to
- read. this is not. maybe just scrap this menu and introduction
- to index?
-@end ignore
-
-@c @setfilename automated-engraving.info
-@c @settitle Obsessed with putting ink on paper
-@c @documentencoding UTF-8
-@c @documentlanguage en
-
-@c @set web
-@c @include macros.itexi
-
-@c @afourpaper
-
-@c @ifnottex
-@c @node Top
-@c @top
-@c @chapheading
-@c @end ifnottex
-
-@node automated-engraving
-@unnumbered Obsessed with putting ink on paper
-@c @finalout
-
-@heading What is behind LilyPond?
-
-@sourceimage{hader-collage,,,.png}
-
-LilyPond is not unique in making music notation: there are a lot of
-programs that print music, and nowadays most of the newly printed
-music is made with computers. Unfortunately, that also shows: just
-ask any musician that plays classical music: new scores do not look as
-nice as old ones.
-
-What is the difference between hand-work and machine work, and what
-has caused it? How can we improve the situation? This essay explains
-problems in music notation (software), and our approach to solving
-them.
-
-@menu
-* introduction:: Introduction -- what is wrong with computer music notation.
-* software:: What is wrong with software -- or how Finale is not the end-all of music software.
-* problem-statement:: How not to design software -- or modeling music notation.
-* divide-and-conquer:: Divide and conqueror -- a blue print for automated notation.
-* implementing-notation:: Impressive, but does it also work in theory -- a practical approach to capturing notation.
-* engraving:: Music engraving -- the art of printing music.
-* implementing-typography:: Implementing typography -- hackers attack the engraving problem.
-* formatting-architecture:: A flexible program architecture -- lets us write engraving software
-* scoring-esthetics:: Beautiful numbers -- how LilyPond participates in the Miss World contests.
-* benchmarking:: Notation benchmarking -- is a flexible architecture enough?
-* schubert:: Notation benchmarking -- project too?
-* typography-features:: Typographical features -- unique to LilyPond.
-* input-format:: Input format -- how to enter music.
-* conclusion:: Conclusion.
-@end menu
-
-@contents
-
-@c This essay is also available in @ref{big-page.html,one big page}.
-
-@include automated-engraving/introduction.itexi
-@include automated-engraving/software.itexi
-@include automated-engraving/problem-statement.itexi
-@include automated-engraving/divide-and-conquer.itexi
-@include automated-engraving/implementing-notation.itexi
-@include automated-engraving/engraving.itexi
-@include automated-engraving/implementing-typography.itexi
-@include automated-engraving/formatting-architecture.itexi
-@include automated-engraving/scoring-esthetics.itexi
-@include automated-engraving/benchmarking.itexi
-@include automated-engraving/schubert.itexi
-@include automated-engraving/typography-features.itexi
-@include automated-engraving/input-format.itexi
-@include automated-engraving/conclusion.itexi
+++ /dev/null
-depth = ../..
-
-LOCALSTEPMAKE_TEMPLATES = ly
-
-include $(depth)/make/stepmake.make
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node benchmarking
-
-@unnumberedsec Notation benchmarking
-
-A flexible architecture is necessary for good
-formatting. Unfortunately, it is not sufficient. Only a careful
-emulation of printed matter will give a good result. We suggested in
-the introduction to compare program output with existing hand-engraved
-scores. It is exactly this technique that we use to perfect LilyPond
-output. In a way, this is a benchmarking technique: the performance of
-the program, in terms of quality, is measured in relation to a known
-quantity.
-
-Here you see parts of a benchmark piece. At the top the reference
-edition (B@"arenreiter BA 320) at the bottom the output from
-LilyPond 1.4:
-
-@divClass{float-center}
-@c @ref{baer-sarabande-hires.png,
-@sourceimage{baer-sarabande,,,.png}
-@c }
-@divEnd
-
-@divClass{float-center}
-B@"arenreiter (click to enlarge)
-@divEnd
-
-@divClass{float-center}
-@sourceimage{lily14-sarabande,,,.png}
-@divEnd
-
-@divClass{float-center}
-LilyPond 1.4
-@divEnd
-
-The LilyPond output is certainly readable, and for many people it
-would be acceptable. However, close comparison with a hand-engraved
-score showed a lot of errors in the formatting details:
-
-@divClass{float-center}
-@sourceimage{lily14-sarabande-correct,,,.png}
-@divEnd
-
-@divClass{float-center}
-@itemize
-@item
- Lots of symbols were unbalanced. In particular the trill sign was
-too large.
-
-
-@item
- Stems and beams were all wrong: the stems were too long, and
-beam should be slanted to cover staff lines exactly. The beam was also
-too light.
-
-
-@item
- The spacing was irregular: some measures were too tight, other
-too wide.
-
-
-@end itemize
-@divEnd
-
-(And there were missing notes in the original version for LilyPond)
-
-By addressing the relevant algorithms, settings, and font designs, we
-were able to improve the output. The output for LilyPond 1.8 is shown
-below. Although it is not a clone of the reference edition, this
-output is very close to publication quality.
-
-@divClass{float-center}
-@sourceimage{lily17-sarabande,,,.png}
-@divEnd
-
-@divClass{float-center}
-LilyPond 1.8
-@divEnd
-
-@divClass{float-center}
-@sourceimage{baer-sarabande,,,.png}
-@divEnd
-
-@divClass{float-center}
-B@"arenreiter
-@divEnd
-
-Another example of benchmarking is our project for the 2.1 series, a
-@ref{schubert,Schubert song}.
-
-@divClass{float-right}
-Next: @ref{typography-features,Cool features},
-typographical hoops that we made LilyPond jump through.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node conclusion
-
-@unnumberedsec Conclusion
-
-We have shown you what engraved music should look like, and how we built
-our software to emulate that look. We have put a lot of effort into
-building it. Thanks to all that hard work, you can
-
-TODO: this whole dir should be deleted; see
-http://code.google.com/p/lilypond/issues/detail?id=1017
-
-@c @ref{@DEPTH@switch/tour.html,use the program to print nice music too}.
-
-To complete the reading of this essay, you may want to have a look at
-
-@c @ref{@DEPTH@about/pubs.html,publications and articles},
-especially @uref{http://www.musicbyandrew.ca/finale-lilypond-1.html,Andrew
-Hawryluk's writings}, which include Finale and LilyPond notation
-benchmarking.
-
-@c @divClass{float-right}
-@c @divEnd
-@c Go @ref{Top,back} to the top.
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-@node divide-and-conquer
-@unnumberedsec Plan de campagne
-
-Since content and form of a score are separate, we have to match that
-in the design of software. Hence, the basic blueprint of our program
-should follow this scheme
-
-@multitable @columnfractions .3 .3 .3
-@item
-
-@sourceimage{simple-notation,,,.png}
-
-
-@tab
-
-@result{}
-
-
-@tab
-
-@code{@{ c'4 d'8 @}}
-
-
-
-
-@item
-
-1. form
-
-
-@tab
-
-2. translation
-
-
-@tab
-
-3. content
-
-
-
-
-@end multitable
-
-In effect, we are conquering the problem by dividing it into
-subproblems
-
-@enumerate 1
-@item
-Typography: @strong{where} to put symbols
-
-@item
-Notation: @strong{what} symbols to produce
-@item
-Representation: how to @strong{encode} music
-@end enumerate
-
-Finally, whenever you subdivide a problem, a new problem is created,
-@enumerate 4
-
-
-@item
- Architecture: glue everything @strong{together}
-
-@end enumerate
-
-@divClass{float-right}
-Next: @ref{implementing-notation,Impressive, but does it also
-work in theory}? A practical approach to capturing notation.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-@node engraving
-@unnumberedsec Music engraving
-
-@sourceimage{hader-slaan,,,.png}
-
-
-When we know what symbols to print, we have to decide where to put
-them so the the result looks pleasing. This art is called @emph{music
-engraving}. The term derives from the traditional process of
-music printing. Only a few decades ago, sheet music was made by
-cutting and stamping the music into zinc or pewter plates in mirror
-image. The plate would be inked, and the depressions caused by the
-cutting and stamping would hold ink. An image was formed by pressing
-paper to the plate. The stamping and cutting was completely done by
-hand. Making corrections was cumbersome, so engraving had to be done
-correctly in one go. Of course, this was a highly specialized skill
-
-
-@itemize
-@item
- Music engraving is a traditional craft, and was learned in
-practice. An accomplished master had to complete around 10 years of
-practice.
-
-
-@item
- Most of the knowledge was passed from master to apprentice during
-practical training. Consequently, little has been explicitly laid down
-about the rules of elegant engraving.
-
-
-@item
- Finally, engraving is about selecting proper distance and
-blackness for scores. @sourceimage{stone-distance,,,.png} The
-quality of the end result must be judged visually. This is virtually
-impossible to capture in formal rules.
-
-
-@end itemize
-
-@divClass{float-right}
-Next: @ref{implementing-typography,Stamping computer
-screens?}. Computer hackers take over the engraving business.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node formatting-architecture
-
-@unnumberedsec A flexible formatting architecture
-
-Remember the music notation problem? Its solution left us with a
-bunch of objects. The formatting architecture is built on these
-objects. Each object carries variables:
-
-@itemize
-@item
- Variables control layout decisions. For example, many objects
-have a @code{direction} variable that encodes the choice between up
-and down (or left and right). Here you see two chords, with accents
-and arpeggio. In the first chord, the objects have all directions down
-(or left). The second chord has all directions up (right).
-
-@divClass{float-center}
-@sourceimage{directions-updown,,,.png}
-@divEnd
-
-The process of formatting a score consists of reading and writing
-object variables.
-
-
-
-@item
-Some variables have a preset value. For example, the thickness of
- many lines – a characteristic of typographical style – are preset
- variables. Changing them gives a different typographical impression:
-
-@divClass{float-center}
-@sourceimage{thickness-tweaks,,,.png}
-@divEnd
-
-@item
-Formatting rules are also preset variables: each object has
-variables containing procedures. These procedure perform the actual
-formatting, and by substituting different ones, we can change
-behavior. In the following example, the rule that note head objects
-use to draw their symbol is changed during the music fragment:
-
-@divClass{float-center}
-@sourceimage{mc-squared,,,.png}
-@divEnd
-
-@end itemize
-
-@divClass{float-right}
-Next:
- @ref{scoring-esthetics,Beautiful numbers}: how
-LilyPond participates in the Miss World contests.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node implementing-notation
-
-@unnumberedsec Music notation
-
-Common music notation encompasses some 500 years of music. Its
-applications range from monophonic melodies to monstruous counterpoint
-for large orchestras. How can we get a grip on such a many-headed
-beast? Our solution is to make a strict distinction between notation,
-@emph{what} symbols to use, and engraving, @emph{where} to put
-them. For tackling notation, we have broken up the problem into
-digestible (and programmable) chunks: every type of symbol is handled
-by a separate plugin. All plugins cooperate through the LilyPond
-architecture. They are completely modular and independent, so each
-can be developed and improved separately.
-
-@itemize
-@item
-The most basic plug-in creates Note-heads:
-
-@divClass{float-center}
-@sourceimage{engraver-noteheads,,,.png}
-@divEnd
-
-This plug-in creates graphical objects from musical events. People
-that put graphics to musical ideas are called copyists or engravers,
-so by analogy, this plug-in is called @code{Note_head_engraver}.
-
-
-@item
- The @code{Staff_symbol_engraver} generates the object
-representing the staff lines.
-
-@divClass{float-center}
-@sourceimage{engraver-staff,,,.png}
-@divEnd
-
-@item
-
- The @code{Clef_engraver} tells @code{Note_head_engraver} how high
-each head should be placed.
-
-@divClass{float-center}
-@sourceimage{engraver-clef,,,.png}
-@divEnd
-
-
-
-@item
-
-For the flags and stems we add a @code{Stem_engraver}:
-
-@divClass{float-center}
-@sourceimage{engraver-stem,,,.png}
-@divEnd
-
-This engraver is notified of any note head coming along. Every time
-one (or more, for a chord) note head is seen, a stem object is
-created, and attached to the note head.
-
-@item
-
-Beams, slurs, accents are handled by separate engravers. Like the
-@code{Stem_engraver}, they create objects and connect them to stems,
-note heads, etc.:
-
-@divClass{float-center}
-@sourceimage{engraver-slur,,,.png}
-@divEnd
-
-
-
-@item
-
-Accidentals, bar lines, time signature, and key signature each have a
-separate
-engraver.
-
-@divClass{float-center}
-@sourceimage{engraver-acc,,,.png}
-@divEnd
-
-The @code{Accidental_engraver} is the most complex plug-in: it has
-to look at the key signature, note pitches, ties, and bar lines to
-decide when to print accidentals.
-
-
-@end itemize
-
-
-@c @unnumberedsec Polyphonic notation
-@heading Polyphonic notation
-
-The system shown in the last section works well for monophonic music,
-but what about polyphony? In polyphonic notation, many voices can
-share a staff:
-
-@divClass{float-center}
-@sourceimage{engraver-final,,,.png}
-@divEnd
-
-In this situation, the accidentals and staff are shared, but the
-stems, slurs, beams, etc. are private to each voice. Hence, engravers
-should be grouped. The engravers for note head, stems, slurs, etc. go
-into a group called "Voice context," while the engravers for key,
-accidental, bar, etc. go into a group called "Staff context." In the
-case of polyphony, a single Staff context contains more than one Voice
-context. Similarly, more Staff contexts can be put into a single
-Score context:
-
-@divClass{float-center}
-@sourceimage{engraver-score,,,.png}
-@divEnd
-
-@divClass{float-right}
-Next: @ref{engraving,The art of stamping}:
-how @emph{did} they make hand-made music?
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-
-@node implementing-typography
-
-
-@unnumberedsec Implementing typography
-
-How do we go about implementing typography? Answering the "music
-notation" problem left us with a bunch of graphic objects
-representing note heads, the staff, stems, etc.
-
-If craftsmen need over ten years to become true masters, how could we
-simple hackers ever write a program to take over their jobs?
-
-The answer is: we cannot! Since typography relies on human judgement
-of appearance, people cannot be replaced. However, much of their dull
-work can be automated: if LilyPond solves most of the common
-situations correctly, then this will be a huge improvement over
-existing software. The remaining cases can be tuned by hand.
-Over the course of years, the software can be refined to do
-more and more automatically, so manual overrides are necessary less
-and less.
-
-How do we go about building such a system? When we started, we wrote
-the program in C++. Essentially, this means that the program
-functionality is set in stone by us developers. That proved to be
-unsatisfactory:
-
-@itemize
-@item
- If things must be tuned by hand, then the user must access to the
- formatting engine. Hence, rules and settings cannot be fixed at
- compile time, but they must be accessible at run-time.
-
-
-@item
- Engraving is a matter of visual judgement, and hence it is a
- matter of taste. As knowledgeable as we are, users can disagree with
- our personal decision. Therefore, the definitions of typographical
- style must also be accessible to the user.
-
-
-@item
- Finally, we continually refine the formatting algorithms, so we
- need a flexible approach to rules. The C++ language forces a certain
- method of grouping rules that does not match how music notation works.
-
-
-@end itemize
-
-Clearly, there is a need for a flexible architecture. The architecture
-should encompass formatting rules, typographical style and individual
-formatting decisions.
-
-@divClass{float-right}
-Next: @ref{formatting-architecture,Program architecture,
-your flexible friend}: tuning, tweaking and developing typography
-rules.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node input-format
-
-@unnumberedsec Input format
-
-As discussed earlier, the ideal input format for a music engraving
-system is the content: the music itself. This poses a formidable
-problem: how can we define what music really @emph{is}? Our way out
-of this problem, is to reverse it. Instead of defining what music is,
-our program serves as a definition: we write a program capable of
-producing sheet music, and adjust the format to be as lean as
-possible. When the format can no longer be trimmed down, by
-definition we are left with content itself.
-
-The syntax is also the user-interface for LilyPond, hence it is easily
-typable, e.g.,
-
-@verbatim
-
- c'4 d'8
-
-@end verbatim
-Are a quarter note C1 and eighth note D1, as in this example:
-
-@divClass{float-center}
-@sourceimage{simple-notation,,,.png}
-@divEnd
-
-On a microscopic scale, such syntax is easy to use. On a larger scale,
-syntax also needs structure. How else can you enter complex pieces
-like symphonies and operas? The structure is formed by the concept of
-music expressions: by combining small fragments of music into larger
-ones, more complex music can be expressed. For example,
-
-@multitable @columnfractions .5 .5
-@item
-
-c4
-
-@tab
-
-@sourceimage{simultaneous-0,,,.png}
-
-
-@end multitable
-
-Combine this simultaneously with two other notes by enclosing in <<
-and >>.
-
-@multitable @columnfractions .5 .5
-
-@item
-
-@verbatim
-
- <<c4 d4 e4>>
-
-@end verbatim
-
-
-@tab
-
-@sourceimage{simultaneous-1,,,.png}
-
-
-
-@end multitable
-
-This expression is put in sequence by enclosing it in braces, i.e.,
-@multitable @columnfractions .5 .5
-@item
-
-@verbatim
-
- { <<c4 d4 e4>> f4 }
-@end verbatim
-
-
-@tab
-
-@sourceimage{simultaneous-2,,,.png}
-
-
-
-@end multitable
-
-The above is another expression, and therefore, it may be combined
-again with a simultaneous expression (in this case, a half note).
-
-@multitable @columnfractions .5 .5
-@item
-
-@verbatim
-
-<< { <<c4 d4 e4>> f4 } g2 >>
-
-@end verbatim
-
-
-@tab
-
-@sourceimage{simultaneous-3,,,.png}
-
-
-
-
-@end multitable
-
-Such recursive structures can be specified neatly and formally in a
-@emph{context-free grammar}. The parsing code is also generated
-from this grammar. In other words, the syntax of LilyPond is clearly
-and unambiguously defined.
-
-User-interfaces and syntax are what people see and deal with
-most. They are partly a matter of taste, and also subject of much
-discussion. Although discussions on taste do have their merit, they
-are not very productive. In the larger picture of LilyPond, the
-importance of input syntax is small: inventing neat syntax is easy,
-writing decent formatting code is much harder. This is also
-illustrated by the line-counts for the respective components: parsing
-and representation take up less than 10% of the code.
-
-@multitable @columnfractions .5 .5
-@item
-Parsing + representation
-@tab
-@item
-total
-@tab
-@item
-6000 lines C++
-@tab
-61500 lines C++
-@end multitable
-
-@ignore
- TODO :
-
- blurbs about lilypond today
-
- future?
-@end ignore
-
-@divClass{float-right}
-Next: @ref{conclusion,wrapping it up}, the conclusion.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node introduction
-
-@unnumberedsec What is wrong with computer music notation?
-
-We like to call LilyPond an "automated engraving system." It will
-format music notation beautifully without requiring typographical
-expertise of its users.
-
-LilyPond is not unique in making music notation: there are a lot of
-programs that print music, and nowadays most of the newly printed
-music is made with computers. Unfortunately, that also shows: just
-ask any musician that plays classical music: new scores do not look as
-nice as old (from before, say, 1970) scores: the new ones have a
-bland, mechanical look. They are not at all pleasurable to play from.
-
-To illustrate this, take a look at the following examples. Both are
-editions of the 1st Cello Suite by J.S.Bach. The one on the left is a
-very beautifully hand-engraved edition from 1950, the one on the right
-is a typical contemporary computer product. Take a few seconds to let
-the looks of both pages sink in. Which one do you like better, and
-why?
-
-@ifnottex
-@multitable @columnfractions .5 .5
-@item
-
-@sourceimage{baer-suite1-fullpage,,,.png}
-
-@tab
-
-@sourceimage{henle-suite1-fullpage,,,.png}
-
-
-
-@item
-B@"arenreiter (BA 320, (c) 1950)
-
-@tab
-Henle (nr. 666 (c) 2000)
-
-@end multitable
-@end ifnottex
-
-The left picture looks nice: it has flowing lines and movement. It's
-music, and it's alive. Now, the picture on the right shows the same
-music, and it was written by Bach. His music surely has liveliness
-and flowing lines.... Except, the score doesn't show it: it looks
-rigid and mechanical. To understand better why that is, let's blow up
-a fragment of both pieces:
-
-@divClass{float-center}
-@sourceimage{baer-suite1-line,,,.png}
-@divEnd
-
-@divClass{float-center}
-Hand-made
-@divEnd
-
-@*
-
-@divClass{float-center}
-@sourceimage{henle-suite1-line,,,.png}
-@divEnd
-
-@divClass{float-center}
-Computer-made
-@divEnd
-
-The location of the bar lines is a giveaway. In the new edition,
-both barlines are on exactly the same horizontal location. Also, the
-note heads are on the exact same horizontal location. When you look
-back at the whole page, you can easily verify that almost all barlines
-are in the same location, as are most of the note heads. The entire
-thing is spaced as if it were put to a big grid, which is what causes
-the mechanical impression.
-
-This is not the only error on this example, and more importantly, this
-piece is not the only one with typographical errors. Sadly, almost
-all music printed nowadays is full of basic typographical mistakes.
-
-Musicians are usually more absorbed with performing the music than
-with studying its looks, so this nitpicking about typographical
-details may seem academical. That is not justified. This piece here
-has a monotonous rhythm. If all lines look the same, they become like
-a labyrinth. If the musician looks away once or has a lapse in his
-concentration, he will be lost on the page.
-
-In general, this is a common characteristic of typography. Layout
-should be pretty, not only for its own sake, but especially because it
-helps the reader in his task. For performance material like sheet
-music, this is doubly important: musicians have a limited amount of
-attention. The less attention they need for reading, the more they can
-focus on playing itself. In other words, better typography translates
-to better performances.
-
-@divClass{float-right}
-Next: @ref{software,What is wrong with software}, or how
-Finale is not the end-all of music software.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-
-@node problem-statement
-@unnumberedsec Designing notation software: how not to do it
-
-It would be nice if notation software didn't need any babysitting to
-produce acceptable output.
-
-Our goal with @emph{LilyPond} was to write such a system: a program
-that will produce beautiful music ("engraving") automatically.
-
-At first sight, music notation follows a straightforward hierarchical
-pattern. Consider the example below, with two staves containing two
-measures.
-
-@sourceimage{naive-notation,,,.png}
-
-Isn't writing software all about finding hierarchies and modeling the
-real world in terms of trees? In the view of a naive programmer, the
-above fragment of notation is easily abstracted to a nested set of
-boxes
-
-@sourceimage{naive-notation-uml,,,.png}
-
-It's easy to follow this model when writing software. It's obvious
-how to store this data in memory, and writing on disk can be easily
-mirrored. In an XML-file you could write something like
-
-@verbatim
-
- <score>
- <staff>
- <measure id="1">
- <chord length="1/2">
- <pitch name="c">
- </chord>
- <chord>
-
- ....
- </measure>
- </staff>
- </score>
-
-@end verbatim
-
-In short, this model is obvious, simple and neat. It's the format
-used by a lot software. Unfortunately, it's also wrong. The
-hierarchical representation works for a lot of simpler music, but it
-falls apart for advanced use. Consider the following example:
-
-@sourceimage{nonnaive-notation,,,.png}
-
-In this example, several assumptions of the previous model are
-violated: staves start and stop at will, voices jump around between
-staves, and sometimes span two staves.
-
-Music notation is really different from music itself. Notation is an
-intricate symbolic diagramming language for visualizing an often much
-simpler musical concept. Hence, software should reflect that separation.
-
-@divClass{float-right}
-Next: @ref{divide-and-conquer,Divide and conqueror},
-a blue print for automated notation
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-@node schubert
-@unnumberedsec S@"angers Morgenlied, by Franz Schubert
-
-The benchmarking project for the LilyPond 2.1.x series, was the
-Ed. Peters version of a Schubert song.
-
-The result of 2.1.5 was nice, but certainly not perfect,
-
-@sourceimage{bench-morgenlied,,,.png}
-
-Here is the original,
-
-@sourceimage{morgenlied-crop-2,,,png}
-
-and the result of LilyPond 2.1.35.
-
-@sourceimage{morgenlied-ly-crop2,,,.png}
-
-This is a page from a song-book, which is printed in a smaller format.
-Normal print uses 20 pt staff height, this uses 17 pt. In smaller
-print, staff lines should be relatively thicker. To match the thicker
-lines, the music symbols should also be relatively heavier. Both have
-been implemented in LilyPond 2.1. The difference is hard to see here,
-due to the limited resolution of computer screens. For a more detailed
-view, see the LilyPond PDF, available
-
-@uref{http://lilypond.org/documentation/v2.2/input/mutopia/F.Schubert/out-www/morgenlied.pdf,here}.
-
-@divClass{float-right}
-@ref{benchmarking,Back to the essay}
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-@node scoring-esthetics
-@unnumberedsec Beautiful numbers
-
-How do we actually make formatting decisions? In other words, which
-of the three configurations should we choose for the following slur?
-
-@sourceimage{slur-esthetics,,,.png}
-
-There are a few books on the art of music engraving
-available. Unfortunately, they contain rules of simple thumbs and some
-examples. Such rules can be instructive, but they are a far cry from
-an algorithm that we could readily implement in a computer. Following
-the instructions from literature leads to algorithms with lots of
-handcoded exceptions. Doing all this case analysis is a lot of work,
-and often not all cases are covered completely.
-
-@divClass{float-center}
-@sourceimage{ross-beam-scan,,,.png}
-@divEnd
-
-@divClass{float-center}
-@emph{Formatting rules defined by example. Image from Ted Ross' The Art of
-Music Engraving}
-@divEnd
-
-We have developed a much easier and robust method of determining the
-best formatting solution: score based formatting. The principle is the
-same as a beauty contest: for each possible configuration, we compute an
-ugliness score. Then we choose the least ugly configuration.
-
-@sourceimage{slur-esthetics-annotate-1,,,.png}
-
-For example, in the above configuration, the slur nicely connects the
-starting and ending note of the figure, a desirable trait. However, it
-also grazes one note head closely, while staying away from the others.
-Therefore, for this configuration, we deduct a `variance' score of
-15.39.
-
-@sourceimage{slur-esthetics-annotate-2,,,.png}
-
-In this configuration, the slur keeps a uniform distance from the
-heads, but we have to deduct some points because the slur doesn't
-start and end on the note heads. For the left edge, we deduct 1.71,
-and for the right edge (which is further from the head) we deduct 9.37
-points.
-
-Furthermore, the slur goes up, while the melody goes down. This incurs
-a penalty of 2.00 points
-
-@sourceimage{slur-esthetics-annotate-3,,,.png}
-
-Finally, in this configuration, only the ending the slur is far away
-from the ending note head, at a score of 10.04 ugliness points.
-
-Adding up all scores, we notice that the third option is the least
-ugly, or most beautiful version. Hence we select that one.
-
-This technique is a general technique, and it is used in a lot of
-situations, for example
-
-@itemize
-@item
- determining beam slopes
-
-@sourceimage{beam-scoring-example,,,.png}
-
-@item
- formatting tied chords
-
-@sourceimage{ties-scoring-example,,,.png}
-@item
- formatting dotted chords
-
-
-@item
- line breaking
-
-@item
- page breaking
-
-@end itemize
-
-This technique evaluates a lot of possibilities, which takes some time
-to compute. However, that is a worthwhile expense, because the end
-result is much better, and because it makes our lives easy.
-
-@divClass{float-right}
-Next: @ref{benchmarking,Man is the measure of things}: is a
-flexible architecture enough?
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node software
-@unnumberedsec What is wrong with music notation software
-
-Computers have made music printing accessible to the masses, but they
-tend to deliver mediocre typography. Apparently, programmers have
-been doing a shoddy job on notation programs. To illustrate that, we
-had an amateur user set a piece of music in one of the most popular
-@quotedblleft{}professional@quotedblright{} notation programs sold today, Finale
-2003. It was made with all of the default settings. The music is from
-the Sarabande of the 2nd Cello Suite by J. S. Bach.
-
-@emph{
-(Finale is a registered trademark of MakeMusic! Inc.)
-}
-
-@divClass{float-center}
-@sourceimage{finale-sarabande-full,,,.png}
-@divEnd
-
-This example far surpasses the previous one when it comes to
-formatting errors: there are serious errors in literally
-@emph{every} measure. The errors come in all sizes: a big one is the
-oddly s p a c e d @ o u t last line. A smaller one is the flat in
-measure 13, which is covered by the note preceding it. Here is a
-magnification of that measure:
-
-@divClass{float-center}
-@sourceimage{finale-flat-detail,,,.png}
-@divEnd
-
-The errors go down to the teensy details: below is a blowup of the
-beam in that measure. Of course, in proper typography the beam should
-not stick out to the right of the stem, and the ribbles provide a
-telling glimpse into Coda Music Technology programmers' aptness (or
-lack thereof) with the underlying PostScript technology.
-
-@divClass{float-center}
-@sourceimage{finale-beam-detail,,,.png}
-@divEnd
-
-Now, one could refute that Finale has a graphical interface, and it
-lets you easily move about elements to correct errors, or use plug-ins
-to do so. This is certainly true: in fact, good professional
-engravers that use Finale typically spend the majority of their time
-correcting all the errors that Finale routinely makes. But do you
-want to spend your time on correcting all glaring errors? For the
-spaced out line, it is doable, but imagine that you have to correct
-each and every beam that sticks out of the stems.... by hand?
-
-There is a less obvious reason why correcting things by hand is a bad
-idea. Consider again measure 13 reproduced above. The misplaced flat
-is pretty obvious, but did you notice that repeat bar? Its lines are
-too far apart. Did you notice that the eighth rest is too far down?
-Did it occur to you that the stem of the last eighth note is too long?
-
-@divClass{float-center}
-@sourceimage{finale-flat-correct,,,.png}
-@divEnd
-
-Unless you are an expert, typographical errors will irk you without
-being obvious. Many of them will go uncorrected and will still be in the
-final print.
-
-This example may seem contrived, but in fact, it's not. All
-major producers of notation software claim to follow engraving
-standards, but we have not seen any that gets the basics right; all of
-them make systematic mistakes. If you want to assess the output of your
-favorite program, then buy a decent hand-made score from a respectable
-publisher, and try to reproduce one page of it. Then compare them:
-
-@itemize
-@item
-
-How does the page layout compare? Typically, computer scores are more
-widely spaced so they take up more pages, meaning more annoying page
-turns.
-
-
-@item
-
-How does the spacing compare? Is it as lively and flowing as the
-hand-made score? If in doubt, try measuring both with a ruler.
-
-
-@item
-
-Put both on a music stand, 1 meter away; that is not uncommon when
-performing. Can you read both pages? Almost all computer scores have
-an anemic look: they use lines which are too thin, and symbols which
-are too light. That makes them hard to read from a distance. If in
-doubt, measure the difference with a magnifying glass.
-
-
-@end itemize
-
-@divClass{float-right}
-Next: @ref{problem-statement,How not to design software},
-or: modeling music notation.
-@divEnd
+++ /dev/null
-@c -*- coding: utf-8; mode: texinfo; -*-
-@ignore
- Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
-
- When revising a translation, copy the HEAD committish of the
- version that you are working on. For details, see the Contributors'
- Guide, node Updating translation committishes..
-@end ignore
-
-
-
-@node typography-features
-
-@unnumberedsec Font design
-
-A large factor that makes LilyPond output look traditional lies in the
-blackness of the page. By using heavy stafflines, and a font design to
-match that, the overall impression is much stronger. This is also very
-clear from the following blowups:
-
-@multitable @columnfractions .3 .3 .3
-@item
-
-@sourceimage{henle-flat-gray,,,.png}
-
-@tab
-
-@sourceimage{baer-flat-gray,,,.png}
-
-@tab
-
-@sourceimage{lily-flat-bw,,,.png}
-
-
-@item
-Henle (2000)
-
-@tab
-B@"arenreiter (1950)
-
-@tab
-LilyPond (2003)
-
-
-
-@end multitable
-
-Another typical aspect of hand-engraved scores is the general look of
-the symbols. They almost never have sharp corners. This is because
-sharp corners of the punching dies are fragile and quickly wear out
-when stamping in metal. The general rounded shape of music symbols is
-also present in all glyphs of our "Feta" font.
-
-
-
-
-@c @unnumberedsec Spacing
-@heading Spacing
-
-One of the problems that the Bach piece above inspired us to attack
-is the spacing engine. One of its features is optical spacing.
-It is demonstrated in the fragment below.
-
-@divClass{float-center}
-@sourceimage{spacing-with-corr,,,.png}
-@divEnd
-
-@divClass{float-center}
-@sourceimage{spacing-no-corr,,,.png}
-@divEnd
-
-This fragment only uses quarter notes: notes that are played in a
-constant rhythm. The spacing should reflect that. Unfortunately, the
-eye deceives us a little: not only does it notice the distance between
-note heads, it also takes into account the distance between
-consecutive stems. As a result, the notes of an up-stem/down-stem
-combination should be put farther apart, and the notes of a down-up
-combination should be put closer together, all depending on the
-combined vertical positions of the notes. The top fragment is printed
-with this correction, the bottom one without. In the last case, the
-down-stem/up-stems combinations form clumps of notes.
-
-
-@c @unnumberedsec Ledger lines
-@heading Ledger lines
-
-Ledger lines are typographically difficult. They can easily blot
-together with other signs, such as ledger lines or
-accidentals. Other software prevents these collisions by spacing the
-lines wider (thus taking up more space), or shortening ledger lines
-(which hampers readability.)
-
-@multitable @columnfractions .3 .3 .3
-@item
-
-@sourceimage{henle-ledger,,,.png}
-
-@tab
-
-@sourceimage{baer-ledger,,,.png}
-
-
-
-@tab
-
-@sourceimage{lily-ledger,,,.png}
-
-
-@item
-Henle (2000)
-
-@tab
-B@"arenreiter (1950)
-
-@tab
-LilyPond (2004)
-
-
-
-@end multitable
-
-Traditional engravers would adjust the size of a ledger line,
-depending on what symbols were in the neighborhood. LilyPond does the
-same. Ledgers are shortened so they never collide with neighboring
-lines, and they are shortened when there is an accidental.
-
-@divClass{float-right}
-Next: @ref{input-format,Use the Source Luke}, or: what
-goes into LilyPond.
-@divEnd
@end ignore
@item
-Se ofrece una variante de la llamada de tipo segno:
+A variant of the segno sign is provided:
@lilypond[quote,relative=2]
c4 d e f \bar "S"
g4 f e d
@chapter Regression tests
@menu
-* Introduction to regression tests::
-* Current regtest output::
-* Comparison regtest output::
-* MusicXML tests::
+* Introduction to regression tests::
+* Current regtest output::
+* Comparison regtest output::
+* MusicXML tests::
@end menu
@node Introduction to regression tests
@section Introduction to regression tests
+LilyPond has a complete suite of regression tests that are used
+to ensure that changes to the code do not break existing behavior.
+These regression tests comprise small LilyPond snippets that test
+the functionality of each part of LilyPond.
+
+Regression tests are added when new functionality is added to
+LilyPond. They are also added when bugs are identified. The
+snippet that causes the bug becomes a regression test to verify
+that the bug has been fixed.
+
+The regression tests are automatically compiled using special @code{make}
+targets. The output of the regression tests is also automatically
+checked to identify changes in LilyPond output.
+
+The output of the regression tests is available on the website
+for every stable version of LilyPond. This allows the comparison
+of different versions to see when bugs appeared.
+
@node Current regtest output
@section Current regtest output
verwenden, um den Text einzugrenzen, für den Melismen ignoriert
werden sollen.
+@subsubheading Silben zu Verzierungsnoten hinzufügen
+
+Normalerweise werden Verzierungsnoten (z.B. durch @code{\grace}) bei
+@code{\lyricsto} keine Silben zugeordnet. Dieses Verhalten kann
+geändert werden, wie das folgende Beispiel zeigt.
+
+@lilypond[verbatim,ragged-right,quote]
+\relative c' {
+ f4 \appoggiatura a32 b4
+ \grace { f16[ a16] } b2
+ \afterGrace b2 { f16[ a16] }
+ \appoggiatura a32 b4
+ \acciaccatura a8 b4
+}
+\addlyrics {
+ normal
+ \set includeGraceNotes = ##t
+ case,
+ gra -- ce case,
+ after -- grace case,
+ \set ignoreMelismata = ##t
+ app. case,
+ acc. case.
+}
+@end lilypond
+
+@knownissues
+Wie bei @code{associatedVoice} muss @code{includeGraceNotes}
+spätestens eine Silbe vor derjenigen gesetzt werden, die unter einer
+Verzierungsnote stehen soll. Im Fall, dass eine Verzierungsnote
+die erste des Musikstückes ist, kann ein @code{\with}- oder
+@code{\context}-Block verwendet werden:
+
+@lilypond[verbatim,ragged-right,quote]
+<<
+ \new Voice = melody \relative c' {
+ \grace { c16[( d e f] }
+ g1) f
+ }
+ \new Lyrics \with { includeGraceNotes = ##t }
+ \lyricsto melody {
+ Ah __ fa
+ }
+>>
+@end lilypond
@subsubheading Zu einer alternativen Melodie umschalten
@end ignore
@item
-A variant of the segno sign is provided:
+Se ofrece una variante de la llamada de tipo segno:
@lilypond[quote,relative=2]
c4 d e f \bar "S"
g4 f e d
\once \override Beam #'positions = #$beg-end
#@})
-\relative @{
+\relative c' @{
\manualBeam #'(3 . 6) c8 d e f
@}
@end example
\once \override Beam #'positions = #(cons $beg $end)
#})
-\relative {
+\relative c' {
\manualBeam #3 #6 c8 d e f
}
@end lilypond
(eq? (ly:grob-property grob 'staff-position) 0))
(set! (ly:grob-property grob 'transparent) #t)))
-\relative {
+\relative c' {
e4 g8 \applyOutput #'Voice #blanker b d2
}
@end lilypond
--- /dev/null
+@c -*- coding: utf-8; mode: texinfo; documentlanguage : fr -*-
+@ignore
+ Translation of GIT committish: 83c81ef45b6e94bac53f6261f9631cd84e8ece37
+
+ When revising a translation, copy the HEAD committish of the
+ version that you are working on. For details, see the Contributors'
+ Guide, node Updating translation committishes..
+@end ignore
+
+@c Translators: Jean-Charles Malahieude, John Mandereau
+@c Translation checkers: Jean-Charles Malahieude
+
+
+@include included/authors.itexi
+@include included/helpus.itexi
+
+@node Communauté
+@unnumbered Communauté
+@translationof Community
+
+@divClass{column-center-top}
+@subheading Échanger avec la communauté
+@translationof Interacting with the community
+
+@itemize
+
+@item
+@ref{Contact} : obtenir de l'aide, discuter et rester en contact.
+
+@item
+@ref{Exemples minimaux} : une nécessité lorsque l'on discute de LilyPond.
+
+@item
+@ref{Signalement de bogue} : disfonctionnement du programme.
+
+@end itemize
+@divEnd
+
+@divClass{column-left-bottom}
+@subheading Rendre LilyPond encore meilleur
+@translationof Making LilyPond better
+
+@itemize
+
+@item
+@ref{Participation} : pour les bonnes volontés qui se sentent concernées.
+
+@item
+@ref{Développement} : pour ceux qui veulent contribuer et tester.
+
+@item
+@ref{Auteurs} : ceux qui ont permis à LilyPond d'être ce qu'il est
+aujourd'hui.
+
+@end itemize
+@divEnd
+
+@divClass{column-right-bottom}
+@subheading Divers
+@translationof Miscellaneous
+
+@itemize
+
+@item
+@ref{Publications} : ce que nous avons écrit, et ce que l'on dit de nous.
+
+@item
+@ref{Archives des annonces} : nouvelles archivées.
+
+@end itemize
+@divEnd
+
+
+@divClass{hide}
+@menu
+* Contact::
+* Exemples minimaux::
+* Signalement de bogue::
+* Participation::
+* Développement::
+* Auteurs::
+* Publications::
+* Archives::
+@end menu
+@divEnd
+
+
+@node Contact
+@unnumberedsec Contact
+@translationof Contact
+
+@divClass{column-left-bottom}
+@subheading Discuter entre utilisateurs et demander de l'aide
+@translationof Discussions and Help
+
+@subsubheading Liste de diffusion des utilisateurs : @code{lilypond-user@@gnu.org}
+
+Cette liste de diffusion @strong{anglophone} est le lieu privilégié des
+utilisateurs pour discuter et s'entraider.
+
+@quotation
+@uref{http://lists.gnu.org/mailman/listinfo/lilypond-user,
+page de souscription à lilypond-user}
+
+@uref{http://lists.gnu.org/archive/html/lilypond-user/,
+archive1 de la liste},
+@uref{http://www.mail-archive.com/lilypond-user@@gnu.org/,
+archive2},
+@uref{http://dir.gmane.org/gmane.comp.gnu.lilypond.general,
+archive3}.
+
+@uref{http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.general,
+poster sur lilypond-user à l'aide de gmane}
+@end quotation
+
+@warning{Lorsque vous posez une question, merci de fournir des
+@ref{Exemples minimaux}@tie{}!}
+
+
+@subsubheading IRC
+
+Vous pouvez obtenir quelque support au travers de notre canal IRC@tie{}:
+
+@example
+@uref{irc://irc.freenode.net/lilypond, #lilypond@@irc.freenode.net}
+@end example
+
+Ce canal ne disposant pas d'archive publique, nous vous invitons à
+plutôt utiliser les listes de diffusion pour toute question qui pourrait
+intéresser d'autres utilisateurs.
+
+@html
+<form action="http://webchat.freenode.net"
+ method="get"
+ name="f_lily_irc"
+ <label>alias irc :
+ <input name="nick" type="text" size="15" value="">
+ </label>
+ <input name="channels" type="hidden" value="lilypond">
+ <input type="submit" value="Rejoindre #lilypond IRC Chat">
+</form>
+
+<script language="JavaScript" type="text/javascript">
+ var username = "web";
+ var lang = window.navigator.userLanguage ? window.navigator.userLanguage
+ : window.navigator.language;
+ username += '-' + lang.substr(0, 2);
+ username += '-' + navigator.appName.substr(0, 2);
+ username += navigator.appCodeName.replace (" ", "").substr(0, 2);
+ username += navigator.platform.replace (" ", "").replace("nux", "").replace("n32", "");
+ document.forms["f_lily_irc"].nick.value = username;
+</script>
+@end html
+
+@subsubheading Autres langues
+
+@quotation
+@uref{http://lists.gnu.org/mailman/listinfo/lilypond-es,
+Liste de diffusion hispanophone}
+
+@uref{http://www.lilypondforum.de/,
+Forum germanophone}
+
+@uref{http://groups.google.com/group/lilypond-brasil,
+Groupe des utilisateurs brésiliens}
+
+@uref{http://lists.gnu.org/mailman/listinfo/lilypond-user-fr,
+Liste de diffusion francophone}
+
+@uref{http://www.lilypondforum.nl/,
+Forum hollandais}
+@end quotation
+
+@divEnd
+
+
+@divClass{column-right-top}
+@subheading Se tenir informé
+
+@subsubheading LilyPond Report
+
+Le @uref{http://news.lilynet.net/, LilyPond Report} est le bulletin de
+la communauté. À lire pour savoir ce qui se passe.
+
+@subsubheading Liste de diffusion des versions : @code{info-lilypond@@gnu.org}
+
+Cette liste de diffusion est en lecture seule. Son but est de notifier
+la mise à disposition des versions.
+
+@quotation
+@uref{http://lists.gnu.org/mailman/listinfo/info-lilypond,
+page de souscription à info-lilypond}
+
+@uref{http://lists.gnu.org/archive/html/info-lilypond/,
+archive1 de la liste},
+@uref{http://www.mail-archive.com/info-lilypond@@gnu.org/,
+archive2},
+@uref{http://dir.gmane.org/gmane.comp.gnu.lilypond.announce,
+archive3}
+
+@c don't include gmane posting here. -gp
+@end quotation
+
+
+@divEnd
+
+
+@divClass{column-right-bottom}
+@subheading Contacter les développeurs
+
+@subsubheading Liste de diffusion des développeurs : @code{lilypond-devel@@gnu.org}
+
+C'est sur cette liste que se tiennent la plupart des discussions ayant
+trait au développement. C'est aussi à cette liste que doivent être
+adressés les patches.
+
+@quotation
+@uref{http://lists.gnu.org/mailman/listinfo/lilypond-devel,
+Page de souscription à lilypond-devel}
+
+@uref{http://lists.gnu.org/archive/html/lilypond-devel/,
+archive1 de la liste},
+@uref{http://www.mail-archive.com/lilypond-devel@@gnu.org/,
+archive2},
+@uref{http://dir.gmane.org/gmane.comp.gnu.lilypond.devel,
+archive3}.
+
+@uref{http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.devel,
+poster sur lilypond-devel à l'aide de gmane}
+@end quotation
+
+
+@subsubheading Liste de diffusion des bogues : @code{bug-lilypond@@gnu.org}
+
+Cette liste @strong{anglophone} est tout spécialement consacrée aux
+discussions à propos des bogues ou limitations.
+
+@quotation
+@uref{http://lists.gnu.org/mailman/listinfo/bug-lilypond,
+page de souscription à bug-lilypond}
+
+@uref{http://lists.gnu.org/archive/html/bug-lilypond/,
+archive1 de la liste},
+@uref{http://www.mail-archive.com/bug-lilypond@@gnu.org/,
+archive2},
+@uref{http://dir.gmane.org/gmane.comp.gnu.lilypond.bugs,
+archive3}.
+
+@c don't include gmane posting here. -gp
+@end quotation
+
+@warning{Les directives à suivre pour poster un message sur cette
+liste sont répertoriées dans @ref{Signalement de bogue}.}
+
+@divEnd
+
+
+
+@node Exemples minimaux
+@unnumberedsec Exemples minimaux
+@translationof Tiny examples
+
+@divClass{column-center-top}
+@subheading Exemple minimal@dots{} mais qu'est-ce donc que cela ?
+
+Un exemple minimal est un bout de code duquel plus rien ne peut être retiré.
+@divEnd
+
+@divClass{column-left-bottom}
+@subheading Pourquoi être minimaliste ?
+
+@divClass{keep-bullets}
+@itemize
+
+@item
+Au plus l'exemple est simpliste, au plus vite ceux qui pourraient vous
+aider comprendront votre propos et vous apporteront une réponse.
+
+@item
+Réduire l'exemple à sa plus simple expression indique que vous avez déjà
+tenté par vous-même de trouver une solution. Des tonnes de lignes
+laissent à penser que celui qui les envoie se soucie peu de ce qui arrive.
+
+@item
+La génération d'un exemple minimaliste permet de comprendre ce qui se
+passe et évite la plupart du temps de signaler un problème qui, en
+réalité, n'existe pas@tie{}: lorsqu'un @qq{bogue} ne peut être
+reproduit dans le cadre d'un exemple minimal, il y a de fortes
+présomptions qu'il s'agisse d'une inadéquation entre l'utilisateur et
+LilyPond plutôt que réellement d'un @qq{bogue}.
+
+@end itemize
+@divEnd
+
+@divEnd
+
+
+@divClass{column-right-bottom}
+@subheading Comment être minimaliste@tie{}?
+
+@divClass{keep-bullets}
+@itemize
+
+@item
+Inclure une mention \version pour indiquer le numéro de version utilisée.
+
+@item
+Être aussi bref et concis que possible. Si des problèmes concernant les
+espacements ou la mise en page peuvent nécessiter un certain nombre de
+mesures, la plupart des litiges peuvent se cantonner à une seule mesure.
+
+@item
+Lorsque vous créez un exemple minimal à partir de votre code, commencez
+par commenter des portions de votre fichier -- à l'aide de @w{@code{%}
+ou @code{%@{ @dots{} %@}}}. Tout ce que vous mettez en commentaire et
+qui ne nuit pas à la démonstration est superflu@tie{};
+suprimez-le@tie{}!
+
+@item
+Évitez autant que faire se peut toute notation, tonalité ou métrique
+complexe, à moins que leur traitement ne soit précisément l'objet du
+litige.
+
+@item
+N'utilisez pas les commandes @code{\override} ou @code{\set} à moins que
+le problème ne soit directement lié à leur utilisation.
+
+@end itemize
+@divEnd
+
+@divEnd
+
+
+
+
+@node Signalement de bogue
+@unnumberedsec Signalement de bogue
+@translationof Bug reports
+
+@divClass{column-center-top}
+@subheading Étape 1 : Le bogue est-il déjà recensé ?
+
+Si votre saisie entraine un crash ou une sortie erronée, c'est un bogue.
+Un recensement des bogues non encore résolus est disponible sur notre
+@emph{google bug tracker}@tie{}; suivez le lien
+
+@example
+@uref{http://code.google.com/p/lilypond/issues/list}
+@end example
+
+@warning{Nous vous remercions de ne pas ajouter directement de
+signalement sur le traceur de bogues. Vous pourrez toujours, une fois
+qu'il aura été duement répertorié, y apporter vos commentaires et
+compléments d'information.}
+
+@divEnd
+
+
+@divClass{column-left-bottom}
+@subheading Étape 2 : Génération d'un signalement de bogue
+
+Lorsque le disfonctionnement que vous avez repéré n'est pas répertorié,
+faites-le nous savoir en créant un signalement de bogue.
+
+@warning{Nous n'acceptons les signalements de bogue que s'ils sont
+rédigés sous la forme d'@ref{Exemples minimaux}. Nous ne disposons
+pas de suffisamment de ressources pour traiter les rapports de bogue,
+aussi tout exemple non minimaliste sera rejeté. Dans la plupart des
+cas, seules quelques notes suffisent à démontrer le disfonctionnement.}
+
+Voici ce à quoi devrait ressembler tout signalement de bogue@tie{}:
+
+@example
+%% la commande d'octaviation
+%% ne fonctionne pas !
+
+\version "2.10.0"
+\paper@{ ragged-right=##t @}
+\relative c''' @{
+ c1
+ #(set-octavation 1)
+ c1
+@}
+@end example
+
+@divEnd
+
+@divClass{column-right-bottom}
+@subheading Étape 3 : Transmission d'un signalement de bogue
+
+Après avoir vérifié que votre problème n'est pas déjà répertorié et
+rédigé votre rapport de bogue, n'hésitez pas à nous le transmettre.
+
+Nous tenons à préciser que la liste dédiées aux bogues est soumise à une
+politique stricte de @qq{no top-posting} bien souvent mise en défaut par
+les fichiers LilyPond. Aussi nous vous prions de bien vouloir ajouter
+une ligne
+
+@example
+> I'm not top posting.
+@end example
+
+@noindent
+(sans oublier le @code{>} ) au tout début de votre message.
+
+@uref{http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs,
+Postez à lilypond.bugs par l'interface gmane}, ou envoyez un courriel à
+@uref{mailto:bug-lilypond@@gnu.prg, bug-lilypond@@gnu.org}.
+
+Une fois le message reçu, notre @qq{responsable des bogues} analysera
+votre rapport et vous demandera peut-être des informations
+supplémentaires avant de l'ajouter au traceur. Il vous transmettra
+ensuite le numéro de référence de votre signalement une fois qu'il
+l'aura ajouté.
+
+Vous serez automatiquement notifié du traitement apporté à ce bogue, dès
+lors que vous avez une compte chez google.
+
+Si vous ne voulez ou ne pouvez pas envoyer un rapport de bogue selon les
+instructions et en anglais, envoyez votre rapport ou posez votre
+question sur la @uref{http://lists.gnu.org/mailman/listinfo/lilypond-user-fr,
+liste francophone}@tie{}; nous transmettrons un rapport à
+la liste anglophone et assurerons le suivi.
+@divEnd
+
+
+@node Participation
+@unnumberedsec Participation
+@translationof Help us
+
+@divClass{column-center-top}
+@helpusNeed
+
+@divEnd
+
+@divClass{column-left-top}
+@divClass{keep-bullets}
+@helpusTasks
+
+@divEnd
+@divEnd
+
+@divClass{column-right-top}
+@helpusProjects
+
+@divEnd
+
+
+@node Développement
+@unnumberedsec Développement
+@translationof Development
+
+@divClass{heading-center}
+@ifclear web_version
+ @heading Développement pour LilyPond @version
+@end ifclear
+@ifset web_version
+ @heading Développement pour LilyPond @versionDevel
+@end ifset
+
+
+@warning{Il s'agit des versions @emph{instables et de développement}.
+Si vous avez le moindre doute quant à l'utilisation ou l'installation de
+LilyPond, nous vous enjoignons à utiliser le @ref{Téléchargement} et la
+lecture des @ref{Manuels} pour la version stable.}
+
+@divEnd
+
+@divClass{column-center-top}
+@subheading Numérotation des versions
+
+Il existe deux jeux de version pour LilyPond@tie{} des versions stables
+et des versions instables de développement. Les versions stables
+comportent, en versionnage @qq{mineur}, un numéro pair (p.ex. 2.8, 2.10,
+ou 2.12). Les versions de développement, quant à elles, comportent un
+versionnage @qq{mineur} impair (p.ex. 2.7, 2.9 ou 2.11).
+
+@divEnd
+
+
+@divClass{column-left-top}
+@subheading Téléchargement
+
+Des instructions concernant @code{git} et la compilation sont exposées
+dans le Guide du contributeur.
+
+@quotation
+@uref{http://git.sv.gnu.org/gitweb/?p=lilypond.git, dépôt git de LilyPond}
+@end quotation
+
+Les rédacteurs de la documentation ainsi que les testeurs préfèreront
+travailler à partir des binaires les plus à jour@tie{}:
+
+@quotation
+
+@downloadDevelLinuxNormal
+
+@downloadDevelLinuxBig
+
+@downloadDevelLinuxPPC
+
+@downloadDevelFreeBSDNormal
+
+@downloadDevelFreeBSDBig
+
+@downloadDevelDarwinNormal
+
+@downloadDevelDarwinPPC
+
+@downloadDevelWindows
+
+@downloadDevelSource
+
+@end quotation
+
+@divEnd
+
+
+@divClass{column-right-top}
+@subheading Le guide du contributeur
+
+Le développement de LilyPond est relativement complexe. Dans l'espoir
+d'aider les nouveaux contributeurs, et dans le but de préserver au mieux
+la stabilité de ce système, nous avons rédigé un manuel dédié aux
+activités de développement.
+
+@docLinksBare{Guide du contributeur, contributor,
+ @rcontribnamed{Top,Guide du Contributeur},
+ @manualDevelContributorSplit,
+ @manualDevelContributorBig, 500 kB,
+ @manualDevelContributorPdf, 2.8 MB}
+
+@divEnd
+
+
+@divClass{column-center-top}
+@subheading Tests de régression
+
+@divClass{keep-bullets}
+@itemize
+
+@ifclear web_version
+
+@item
+@uref{../../input/regression/collated-files.html, Tests de régression} :
+relatifs à ce niveau de mise à jour
+(@uref{../../input/regression/collated-files.pdf, version pdf}).
+
+@item
+@uref{../../input/regression/musicxml/collated-files.html, Tests de MusicXML} :
+relatifs à ce niveau de mise à jour
+(@uref{../../input/regression/musicxml/collated-files.pdf, version pdf}).
+@end ifclear
+
+@ifset web_version
+@item @regtestDevel (@regtestDevelPdf{})
+
+@item @regtestDevelXml (@regtestDevelXmlPdf{})
+
+@item @regtestStable (@regtestStablePdf{})
+
+@item @regtestStableXml (@regtestStableXmlPdf{})
+@end ifset
+
+
+@item @uref{http://lilypond.org/test, Archives des tests de régression} :
+Comparaisons entre différentes versions.
+
+@end itemize
+@divEnd
+@divEnd
+
+
+
+@divClass{column-center-bottom}
+@subheading Manuels
+
+@ifclear web_version
+@warning{Il s'agit des manuels pour LilyPond @version{}@tie{}; la
+dernière mouture est consultable sur @url{http://lilypond.org}}
+@end ifclear
+
+@divClass{normal-table}
+@multitable @columnfractions .3 .3 .3
+@headitem Introduction
+@item
+@docLinkSplit{Apprentissage,learning,@manualDevelLearningSplit}
+@tab
+@docLinkBig{Apprentissage,learning,@manualDevelLearningBig}
+@tab
+@docLinkPdf{Apprentissage,learning,@manualDevelLearningPdf}
+
+@item
+@docLinkSplit{Glossaire,music-glossary,@manualDevelGlossarySplit}
+@tab
+@docLinkBig{Glossaire,music-glossary,@manualDevelGlossaryBig}
+@tab
+@docLinkPdf{Glossaire,music-glossary,@manualDevelGlossaryPdf}
+
+@item
+@docLinkSplit{Essai,essay,@manualDevelEssaySplit}
+@tab
+@docLinkBig{Essai,essay,@manualDevelEssayBig}
+@tab
+@docLinkPdf{Essai,essay,@manualDevelEssayPdf}
+
+@headitem Utilisation courante
+
+@item
+@docLinkSplit{Notation,notation,@manualDevelNotationSplit}
+@tab
+@docLinkBig{Notation,notation,@manualDevelNotationBig}
+@tab
+@docLinkPdf{Notation,notation,@manualDevelNotationPdf}
+
+@item
+@docLinkSplit{Utilisation,usage,@manualDevelUsageSplit}
+@tab
+@docLinkBig{Utilisation,usage,@manualDevelUsageBig}
+@tab
+@docLinkPdf{Utilisation,usage,@manualDevelUsagePdf}
+
+@item
+@docLinkSplit{Morceaux choisis,snippets,@manualDevelSnippetsSplit}
+@tab
+@docLinkBig{Morceaux choisis,snippets,@manualDevelSnippetsBig}
+@tab
+@docLinkPdf{Morceaux choisis,snippets,@manualDevelSnippetsPdf}
+
+@headitem Utilisation ponctuelle
+
+@item
+@docLinkSplit{Web,web,@manualDevelWebSplit}
+@tab
+@docLinkBig{Web,web,@manualDevelWebBig}
+@tab
+@docLinkPdf{Web,web,@manualDevelWebPdf}
+
+@item
+@docLinkSplit{Nouveautés,changes,@manualDevelChangesSplit}
+@tab
+@docLinkBig{Nouveautés,changes,@manualDevelChangesBig}
+@tab
+@docLinkPdf{Nouveautés,changes,@manualDevelChangesPdf}
+
+@item
+@docLinkSplit{Extension,extending,@manualDevelExtendingSplit}
+@tab
+@docLinkBig{Extension,extending,@manualDevelExtendingBig}
+@tab
+@docLinkPdf{Extension,extending,@manualDevelExtendingPdf}
+
+@item
+@docLinkSplit{Références internes,internals,@manualDevelInternalsSplit}
+@tab
+@docLinkBig{Références internes,internals,@manualDevelInternalsBig}
+@tab
+@docLinkPdf{Références internes,internals,@manualDevelInternalsPdf}
+
+@ifset web_version
+@headitem En téléchargement
+
+@item
+@doctarballDevel
+@end ifset
+
+@end multitable
+
+@divEnd
+@divEnd
+
+
+
+
+@node Auteurs
+@unnumberedsec Auteurs
+@translationof Authors
+
+@help{En cours d'élaboration ; cette liste demande à être affinée !}
+
+
+@divClass{column-left-top}
+@subheading Équipe actuelle de développement
+
+@divClass{keep-bullets}
+@developersCurrent
+@divEnd
+@divEnd
+
+@divClass{column-right-top}
+@subheading Ceux qui ont participé
+
+@divClass{keep-bullets}
+@developersPrevious
+@divEnd
+@divEnd
+
+
+@divClass{column-center-top}
+@subheading Contributeurs actifs
+
+@divClass{keep-bullets}
+@subsubheading Programmation
+
+@coreCurrent
+
+@subsubheading Fontes et polices
+
+@fontCurrent
+
+@subsubheading Documentation
+
+@docCurrent
+
+@subsubheading Résolution de bogue
+
+@bugsquadCurrent
+
+@subsubheading Support
+
+@supportCurrent
+
+@subsubheading Traduction
+
+@translationsCurrent
+
+@divEnd
+@divEnd
+
+
+@divClass{column-center-bottom}
+@subheading Ceux qui ont contribué
+
+@divClass{keep-bullets}
+@subsubheading Programmmation
+
+@corePrevious
+
+@subsubheading Fontest et polices
+
+@fontPrevious
+
+@subsubheading Documentation
+
+@docPrevious
+
+@c uncomment when we have any previous members -gp
+@c @subsubheading Résolution de bogue
+
+@c @bugsquadCurrent
+
+@subsubheading Support
+
+@supportPrevious
+
+@subsubheading Traduction
+
+@translationsPrevious
+
+@divEnd
+@divEnd
+
+
+
+@node Publications
+@unnumberedsec Publications
+@translationof Publications
+
+@divClass{column-center-top}
+@subheading Ce que nous avons écrit
+
+@divClass{keep-bullets}
+@itemize
+
+@item
+Han-Wen Nienhuys, @emph{LilyPond, Automated music formatting and
+the Art of Shipping}. Forum Internacional Software Livre 2006
+(FISL7.0) (@uref{http://lilypond.org/web/images/FISL7-slides.pdf,
+PDF 1095k})
+
+@item
+Erik Sandberg, @emph{Separating input language and formatter in
+GNU LilyPond}. Master's Thesis, Uppsala University, Department of
+Information Technology March 2006.
+(@uref{http://lilypond.org/web/images/thesis-erik-sandberg.pdf,
+PDF 750k})
+
+@item
+Han-Wen Nienhuys and Jan Nieuwenhuizen, @emph{LilyPond, a system
+for automated music engraving}. Proceedings of the XIV Colloquium
+on Musical Informatics (XIV CIM 2003), Firenze, Italy, May 2003.
+(@uref{ http://lilypond.org/web/images/xivcim.pdf, PDF 95k})
+
+@end itemize
+
+@divEnd
+@divEnd
+
+
+@divClass{column-center-bottom}
+
+@subheading Ce que d'autres ont écrit
+
+@divClass{keep-bullets}
+@itemize
+
+@item
+Septembre 2009
+
+The German LinuxUser magazine wrote an
+@uref{http://www.linux-community.de/Internal/Artikel/Print-Artikel/LinuxUser/2009/10/Digitaler-Notenschluessel,
+article about LilyPond}.
+
+
+@item
+Février 2008
+
+In @uref{http://www.musicbyandrew.ca/finale-lilypond-1.html,
+articles on his personal site}, Andrew Hawryluk compares Finale
+and LilyPond in general terms, and evaluates engraving
+capabilities of both pieces of software in detail. The second
+article is an instructive analysis of engraving issues in
+Rachmaninoff's Piano Prelude No. 6, including comparisons with a
+hand-engraved reference edition.
+
+@item
+Juin 2006
+
+@uref{http://distrowatch.com,DistroWatch} awards LilyPond and
+@uref{http://distrowatch.com/weekly.php?issue=20060605,writes}
+@qq{Ladies and Gentleman, we are pleased to announce that, based
+on readers' requests, the DistroWatch May 2006 donation has been
+awarded to LilyPond (@euro{}190.00) and Lua (US$250.00).}
+
+@item
+Décembre 2005
+
+@uref{http://linuxjournal.com,Linux Journal} publishes an article
+titled @uref{http://www.linuxjournal.com/article/8364, Make
+Stunning Schenker Graphs with GNU LilyPond}. It is an in-depth
+but hands-on feature article with crisp LilyPond graphics. Author
+Kris Shaffer remarks @qq{GNU LilyPond generates beautiful graphics
+that make commercial alternatives seem second-rate.}
+
+@item
+20 août 2005
+
+The Belgian newspaper De Standaard investigates what drives Free
+Software authors in an article titled
+@uref{http://www.standaard.be/Artikel/Detail.aspx?artikelId=G42H5GD6,
+Delen van KENNIS zonder WINSTBEJAG} (Non-profit sharing of
+knowlegde) in its @q{DS2 bijlage}. LilyPond is used as an example
+and the article is interspersed with quotes from an email
+interview with Jan Nieuwenhuizen. This marks LilyPond's first
+appearance in mainstream printed press.
+
+@item
+Juin 2005
+
+A French article on the LilyPond 2.6 release appeared on
+@uref{http://linuxfr.org/2005/06/27/19210.html, linuxfr.org}.
+
+@item
+Octobre 2004
+
+The editors of Computer!Totaal, a Dutch computer magazine,
+@uref{http://lilypond.org/web/images/computer-totaal.jpeg,
+describe LilyPond} in the October 2004 issue as: @qq{Wonderful
+free (open source) software [..] The sheet music produced by
+LilyPond is exceptionally pretty [..] a very powerful system that
+can do almost anything.}
+
+@item
+Juillet--août 2004
+
+Dave Phillips wrote an introductory article for
+@uref{http://linuxjournal.com,Linux Journal}: At
+the sounding edge: LilyPond, parts
+@uref{http://www.linuxjournal.com/article/7657, one} and
+@uref{http://www.linuxjournal.com/article/7719, two}.
+
+@item
+Mars 2004
+
+Chris Cannam
+@uref{http://www.all-day-breakfast.com/cannam/linux-musician/lilypond.html,interviewed}
+Han-Wen Nienhuys and Jan Nieuwenhuizen on linuxmusician.com
+(original site defunct). This interview was also reviewed in a
+@uref{http://slashdot.org/article.pl?sid=04/03/13/2054227&tid=,
+slashdot story}.
+
+@item
+Février 2004
+
+Jazz singer Gail Selkirk writes about
+@uref{http://www.songbirdofswing.com/editorial_page/lilypond/,
+Diving into LilyPond}. @qq{dots{} you can make lead sheets or full
+orchestral parts, and the results can be stunning.}
+@uref{http://www.computermusic.co.uk/, Computer Music Special},
+issue CMS06.
+
+@end itemize
+
+@divEnd
+@divEnd
+
+
+@node Archives des annonces
+@unnumberedsec Archives des annonces
+@translationof Old news
+
+@include web/news-front.itexi
+
+@include web/news.itexi
+
+
@c -*- coding: utf-8; mode: texinfo; documentlanguage: fr -*-
@c This file is part of web.texi
@ignore
- Translation of GIT committish: c650e54334b64e0e9fd534ee13742f6c07257637
+ Translation of GIT committish: 67d6d3fd903a5dbe9b3a1112c646db29abb622e2
When revising a translation, copy the HEAD committish of the
version that you are working on. For details, see the Contributors'
@divEnd
@divClass{column-left-top}
-@subheading Pourquoi utiliser LilyPond?
+@subheading Pourquoi utiliser LilyPond ?
@itemize
@ref{Productions} : cas d'utilisation de LilyPond.
@item
-@ref{Témoignages}: que disent les gens sur LilyPond ?
+@ref{Témoignages} : que disent les gens sur LilyPond ?
@end itemize
@divEnd
@itemize
@item
-@ref{Entrée sous forme de texte}: vous écrivez de la musique comme du @emph{texte} ?!
+@ref{Entrée sous forme de texte} : vous écrivez de la musique comme du
+@emph{texte} ?
@item
-@ref{Facilités d'édition}: autres façons de travailler avec LilyPond.
+@ref{Facilités d'édition} : autres façons de travailler avec LilyPond.
@end itemize
@divEnd
déterminant l'espacement, les sauts de système et de page, afin de
produire une mise en page compacte et homogène. Le logiciel résout les
collisions entre paroles, notes et accords, et calcule la
-courbure des liaisons, tout cela automatiquement !
+courbure des liaisons, tout cela automatiquement@tie{}!
@subsubheading Entrée sous forme de texte
LilyPond prend en entrée du texte brut, que vous pouvez écrire dans
votre éditeur de texte préféré, rapidement et confortablement. Vous
pouvez oublier les prises de tête avec la souris. Le fichier texte
-d'entrée contient toute la description de la musique à graver ; ainsi,
-il n'est pas nécessaire de se rappeler de complexes séquences de
+d'entrée contient toute la description de la musique à graver@tie{};
+ainsi, il n'est pas nécessaire de se rappeler de complexes séquences de
commandes, il suffit de relire du texte d'entrée existant pour retrouver
ce que l'on a déjà réussi à faire.
Ce logiciel est également et avant tout libre : son code source est
également disponible, et il est possible sous certaines conditions de le
copier, de le modifier et de le redistribuer. Êtes-vous irrité par un
-bogue, ou désirez-vous une fonctionnalité ? Ajoutez-la vous-même, ou
+bogue, ou désirez-vous une fonctionnalité@tie{}? Ajoutez-la vous-même, ou
payez quelqu'un d'autre pour le faire.
LilyPond excelle également dans les grands projets tels qu'un opéra ou
une œuvre pour grand orchestre symphonique. De plus, l'entrée sous
-forme de texte offre une meilleure accessibilité — cet exemple est
+forme de texte offre une meilleure accessibilité -- cet exemple est
extrait de l'œuvre de Hu Haipeng, compositeur aveugle.
@exampleImage{orchestra}
Documentation GNU FDL}, accordant à tous la liberté de le corriger, le
modifier et étendre ses fonctionnalités. La gravure musicale de qualité
ne devrait pas vous coûter des centaines d'euros dépensés pour acheter
-une licence de logiciel !
+une licence de logiciel@tie{}!
@divEnd
@item
Aucun coût d'essai : téléchargez-le et essayez-le sans aucune
-restriction ! Qu'avez-vous à perdre ?
+restriction@tie{}! Qu'avez-vous à perdre@tie{}?
@item
Partage : si vous appréciez ce logiciel, donnez-en une copie à vos amis,
-professeurs, étudiants et collègues !
+professeurs, étudiants et collègues@tie{}!
@item
Code source disponible : si vous êtes curieux du fonctionnement interne de
@item
Indépendance par rapport aux éditeurs de logiciel : si une entreprise
fait faillite, qu'advient-il des logiciels et fichiers dans le format de
-ces logiciels que cette entreprise développait et éditait ? Ce n'est
+ces logiciels que cette entreprise développait et éditait@tie{}? Ce n'est
pas un problème avec LilyPond ; même si toute l'équipe de développement
laissait ce logiciel à l'abandon, il serait encore légalement et
effectivement disponible afin d'être copié, modifié et distribué.
@c @divClass{column-right-top}
@divClass{color3}
@divClass{keep-bullets}
-@subheading Pourquoi les développeurs de LilyPond @qq{donnent} leur travail gratuitement ?
+@subheading Pourquoi les développeurs de LilyPond @qq{donnent-ils} leur travail gratuitement ?
La plupart d'entre nous conçoivent le développement de LilyPond comme un
passe-temps ou un travail bénévole, c'est pourquoi cette question serait mieux
-formulée ainsi : pourquoi des gens contribuent bénévolement à LilyPond ?
+formulée ainsi@tie{}: pourquoi des gens contribuent bénévolement à
+LilyPond@tie{}?
@itemize
@item
Pour le plaisir : travailler pour un but particulier peut être motivant,
-d'autant plus que le travail d'équipe apporte de l'entraide !
+d'autant plus que le travail d'équipe apporte de l'entraide@tie{}!
@item
Des objectifs communs : nous voulons tous produire des partitions de
musique de qualité, mais peu de gens ont l'expertise -- et personne n'a le
-temps ! -- de créer un logiciel qui gère toutes les situations. En
+temps@tie{}! -- de créer un logiciel qui gère toutes les situations. En
travaillant tous ensemble -- l'un améliore le code des ligatures
automatiques, un autre corrige le galbe des liaisons, et un troisième
écrit de la documentation expliquant l'utilisation de ces
Si vous voulez une introduction rapide à LilyPond et préférez l'essayer
au plus vite, la lecture de l'essai serait trop longue. Si toutefois
vous préférez le lire maintenant, allez à la section @ref{Essai}.
-
+@divEnd
@divClass{column-center-bottom}
@subheading Et ensuite ?
@item
Le @uref{http://www.mutopiaproject.org/index.html, projet Mutopia}
propose en téléchargement libre des partitions de plus de 1@tie{}500 pièces de
-musique classique ; c'est la plus grande vitrine de partitions LilyPond.
+musique classique@tie{}; c'est la plus grande vitrine de partitions LilyPond.
@item
@uref{http://www.adoromusicpub.com/, Adoro Music Publishing} propose des
@qq{@dots{} J'avais écrit avec Encore quelques pièces pour violoncelle
solo. Je les ai imprimées avec LilyPond avant de les soumettre à
Schirmer en vue de les publier. J'en mettrais ma main à couper que
- leur édition ne sera jamais aussi pointue que la mienne !}
+ leur édition ne sera jamais aussi pointue que la mienne@tie{}!}
@divEnd
je suis néanmoins @emph{très} impressionné. J'ai utilisé ce programme
pour un motet de Josquin Desprez en notation mensurale et je dois dire
que lilypond dépasse de loin tous les autres programmes de notation
- tant au niveau de la rapidité que de l'ergonomie et du résultat !}
+ tant au niveau de la rapidité que de l'ergonomie et du résultat@tie{}!}
@divEnd
Warner Bros., que même les plus récentes productions des @qq{bonnes
vieilles maisons}. [@dots{}]}
-@qq{Faites donc mieux que Finale/Sibelius/Igor et consorts !!!}
+@qq{Faites donc mieux que Finale/Sibelius/Igor et consorts@tie{}!!!}
@divEnd
@subsubheading David Bobroff, trombone basse, Orchestre symphonique d'Islande
@qq{LilyPond est tout simplement génial [@dots{}] Plus j'en
- apprends sur LilyPond, plus je l'apprécie !}
+ apprends sur LilyPond, plus je l'apprécie@tie{}!}
@divEnd
@qq{J'avais une sorte de passion conflictuelle avec lui. Passion parce
que la première partition que j'en ai vu m'a vraiment émerveillé ! Le
descriptif de LilyPond ne dit pas tout de ses capacités, il est trop
- modeste ! [@dots{}] au fur et à mesure que LilyPond s'améliore, et
+ modeste@tie{}! [@dots{}] au fur et à mesure que LilyPond s'améliore, et
que je regarde de plus près comment cela se passe avec Scheme, je suis
de moins en moins frustré. En fait, ce que je veux dire, c'est un
grand merci de nous fournir LilyPond, c'est vraiment un bon
@divClass{testimonial-item}
@subsubheading @uref{http://www.troff.org/whoswho.html#werner, Werner Lemberg}, Chef au Théâtre de Coblence (Allemagne) et éminent hacker GNU
-@qq{À vrai dire, LilyPond fait un boulot des plus
- étonnants !}
+@qq{À vrai dire, LilyPond fait un boulot des plus étonnants@tie{}!}
@divEnd
Cette façon de faire peut demander aux habitués des interfaces
graphiques l'apprentissage d'une nouvelle façon de travailler, mais les
-résultats en valent vraiment la peine !
+résultats en valent vraiment la peine@tie{}!
@warning{nous ne présentons ici qu'un rapide aperçu du langage de
-LilyPond -- ce n'est pas si compliqué que ça en a l'air ! Ce n'est pas
+LilyPond -- ce n'est pas si compliqué que ça en a l'air@tie{}! Ce n'est pas
la peine de comprendre ces exemples en détail, notre manuel d'initiation
aborde d'une façon progressive tout ceci et bien d'autres choses encore.}
@subsubheading Pièces orchestrales
Le fichier source contient les notes de la pièce. Le conducteur et les
-parties séparées peuvent être réalisés à partir de la même source ;
+parties séparées peuvent être réalisés à partir de la même source@tie{};
ainsi, la modification d'une note se répercute toujours à la fois sur
les parties et le conducteur. Pour pouvoir utiliser la même musique à
plusieurs endroits, celle-ci est stockée dans une variable, c'est-à-dire
@uref{http://musescore.org,MuseScore} produit du code LilyPond.
@item
@uref{http://canorus.org,Canorus} peut également exporter vers LilyPond,
-mais est encore au stade de développement bêta. Les testeurs sont les
+mais est encore au stade de développement beta. Les testeurs sont les
bienvenus.
@uref{http://lilycomp.sourceforge.net,LilyComp} permet de saisir
graphiquement des notes. Il fonctionne comme un pavé numérique
chefs ont appris à écrire de la musique dans notre format texte. Des
utilisateurs expérimentés nous font savoir qu'ils parviennent à entrer
une partition LilyPond complète plus rapidement qu'avec un clavier MIDI
-ou la souris dans une interface graphique ! Peut-être souhaitez-vous
+ou la souris dans une interface graphique@tie{}! Peut-être souhaitez-vous
relire les @ref{Fonctionnalités}, les @ref{Exemples}, la @ref{Liberté}
donnée par LilyPond, ou revoir les @ref{Témoignages} ou
@ref{Productions} des utilisateurs. De plus, nous expliquons notre
Frédéric Bron,
Hajo Dezelski,
+Richard Gay,
Andrew Hawryluk,
Ian Hulin,
Michael Käppler,
+David Kastrup,
Marek Klein,
Kieren MacMillan,
Thomas Morgan,
@cindex relative note entry and polyphony
Polyphony does not change the relationship of notes within a
-@code{\relative @{ @}} block. Each note is still calculated
-relative to the note immediately preceding it, or to the first
-note of the preceding chord. So in
+@code{\relative} block. Each note is still calculated relative to
+the note immediately preceding it, or to the first note of the
+preceding chord. So in
@example
\relative c' @{ noteA << < noteB noteC > \\ noteD >> noteE @}
examples in the manual, see @ref{How to read the manuals}.}
In addition, LilyPond input is @strong{case sensitive}.
-@w{@code{@{ c d e @}}} is valid input; @w{@code{@{ C D E @}}} will
+@w{@samp{@{ c d e @}}} is valid input; @w{@samp{@{ C D E @}}} will
produce an error message.
middle C.
By adding (or removing) quotes @code{'} or commas @code{,} from
-the @code{@w{\relative c' @{}} command, we can change the starting
-octave:
+the @q{@w{@code{@bs{}relative c'}}} command, we can change the
+starting octave:
@lilypond[verbatim,quote]
% one octave above middle C
@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{@w{\relative c'}} may also be modified like
-this.
+quotes @code{''} and not one double quote @code{"}@tie{}!
@c " - keeps quotes in order for context-sensitive editor -td
@subheading Durations (rhythms)
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.
+quarter note.
@lilypond[verbatim,quote]
\relative c'' {
@funindex %@{ ... %@}
LilyPond input files are similar to source files in many common
-programming languages. They contain a version statement,
-are case sensitive, and white-space
-is generally ignored. Expressions are formed with curly braces
-@{ @}, and comments are denoted with @code{%} or
-@w{@code{%@{ ... %@}}}.
+programming languages. They contain a version statement, are case
+sensitive, and white-space is generally ignored. Expressions are
+formed with curly braces @w{@code{@{ @}}}, and comments are
+denoted with @code{%} or @w{@code{%@{ @dots{} %@}}}@tie{}.
If the previous sentences sound like nonsense, don't worry! We'll
explain what all these terms mean:
@item
@strong{Case sensitive}:
it matters whether you enter a letter in lower case (e.g.
-@w{@code{a, b, s, t}}) or upper case (e.g. @w{@code{A, B, S, T}}).
-Notes are lower case: @w{@code{@{ c d e @}}} is valid input;
-@w{@code{@{ C D E @}}} will produce an error message.
+@w{@code{a, b, s, t}}) or upper case (e.g. @w{@code{A, B, S, T}}).
+Notes are lower case: @w{@samp{@{ c d e @}}} is valid input;
+@w{@samp{@{ C D E @}}} will produce an error message.
@item
@strong{Whitespace insensitive}:
it does not matter how many spaces (or tabs or new lines) you add.
-@w{@code{@{ c d e @}}} means the same thing as
-@w{@code{@{ c @tie{}} @tie{} @tie{} d e @}} and:
+@w{@samp{@{ c d e @}}} means the same thing as
+@w{@samp{@{ c @tie{} @tie{} @tie{} d e @}}} and:
@example
@{ c d
@}
@end example
-However, whitespace @emph{is} required to separate many syntactical
-elements from others. In other words, whitespace can always be
-@emph{added}, but it cannot be @emph{eliminated}. As missing
-whitespace can give rise to strange errors it is advisable to
-always insert whitespace before and after every syntactic element,
-for example, before and after every curly brace.
+However, whitespace @emph{is} required to separate many
+syntactical elements from others. In other words, whitespace can
+always be @emph{added}, but not always @emph{eliminated}. Since
+missing whitespace can give rise to strange errors, it is
+advisable to always insert whitespace before and after every
+syntactic element, for example, before and after every curly
+brace.
@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 parentheses
-@code{()} in mathematics. The braces should be surrounded by a
-space unless they are at the beginning or end of a line to avoid
-ambiguities.
+every piece of LilyPond input needs to have
+@strong{@{@tie{}curly@tie{}braces@tie{}@}} placed around the
+input. These braces tell LilyPond that the input is a single
+music expression, just like parentheses @code{()} 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 LilyPond command followed by a simple expression in braces (such
-as @w{@code{\relative @{ @}}}) also counts as a single music
-expression.
+as @q{@w{@code{@bs{}relative c' @{ @dots{} @}}}}) also counts as a
+single music expression.
@cindex comments
@cindex line comment
@cindex constructing files, tips
@cindex files, tips for constructing
-LilyPond input must be surrounded by @{ @} marks or a
-@code{@w{\relative c'' @{ ... @}}}, as we saw in @ref{Working on
-input files}. For the rest of this manual, most examples will
-omit this. To replicate the examples, you may copy and paste the
-displayed input, but you @strong{must} add the
-@code{@w{\relative c'' @{ @}}} like this:
+LilyPond input must be surrounded by @code{@{ @}} marks or a
+@q{@w{@code{@bs{}relative c'' @{ @dots{} @}}}}, as we saw in
+@ref{Working on input files}. For the rest of this manual, most
+examples will omit this. To replicate the examples, you may copy
+and paste the displayed input, but you @strong{must} add the
+@q{@w{@code{@bs{}relative c'' @{ @dots{} @}}}} like this:
@example
\relative c'' @{
- ... example goes here...
+ @dots{}example goes here@dots{}
@}
@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{@w{\relative c'' @{ @}}} --
-you should not place a @code{\relative} inside another
-@code{\relative}! If we included @code{@w{\relative c'' @{ @}}}
-around every example, you would not be able to copy a small
-documentation example and paste it inside a longer piece of your
-own. Most people want to add material to an existing piece, so we
-format the manual this way.
-
-Also, remember that every LilyPond file should have a @code{@bs{}version}
-statement. Because the examples in the manuals are snippets, not files,
-the @code{@bs{}version} statement is omitted. But you should make a
-practice of including them in your files.
+it does not make sense to add
+@q{@w{@code{@bs{}relative c'' @{ @dots{} @}}}} -- you should not
+place a @code{\relative} inside another @code{\relative}! If we
+included @q{@w{@code{@bs{}relative c'' @{ @dots{} @}}}} around
+every example, you would not be able to copy a small documentation
+example and paste it inside a longer piece of your own. Most
+people want to add material to an existing piece, so we format the
+manual this way.
+
+Also, remember that every LilyPond file should have a
+@code{\version} statement. Because the examples in the manuals
+are snippets, not files, the @code{\version} statement is omitted.
+But you should make a practice of including them in your files.
@node Clickable examples
@subsection Clickable examples
Learning manual's @ref{Tweaking output}.
@item
-@strong{Before undertaking a large project}: read Usage document's
-@rprogram{Suggestions for writing files}.
+@strong{Before undertaking a large project}: read the Usage
+document's @rprogram{Suggestions for writing files}.
@end itemize
à vo -- cê uma can -- ção legal
}
-\relative {
+\relative c' {
c2 d e f g f e
}
\addlyrics { \bulgarian }
@subsubheading Installation Instructions for MacOS
-Download and extract the zip file. Using @code{Terminal.app}, move
-the @code{lilyfonts} directory to
-@file{@var{INSTALLDIR}/LilyPond.app/Contents/Resources/share/lilypond/current}.
+Download and extract the zip file. Copy the @code{lilyfonts}
+directory to @file{@var{SHARE_DIR}/lilypond/current}; for more
+information, see @rlearning{Other sources of information}.
Move the existing @code{fonts} directory to @code{fonts_orig} and
move the @code{lilyfonts} directory to @code{fonts}. Simply move
@code{fonts_orig} back to @code{fonts} to revert back to Feta.
-@subsubheading Installation Instructions for Windows
-
-Download and extract the zip file. Using Explorer, copy the @code{lilyfonts}
-directory to
-@file{@var{INSTALLDIR}/LilyPond/usr/share/lilypond/current}. Rename
-the existing @code{fonts} directory to @code{fonts_orig} and
-rename the @code{lilyfonts} directory to @code{fonts}. Simply rename
-@code{fonts_orig} back to @code{fonts} to revert back to Feta.
+@seealso
+Learning Manual: @rlearning{Other sources of information}.
@knownissues
#(set-default-paper-size "a6" 'landscape)
\book {
\score {
- \relative { c1 \break c1 }
+ \relative c' { c1 \break c1 }
}
\paper {
system-separator-markup = \slashSeparator
@code{\set} and @code{\unset} to bracket the lyrics where melismata
are to be ignored.
+@subsubheading Adding syllables to grace notes
+
+By default, grace notes (e.g. via @code{\grace}) do not get assigned
+syllables when using @code{\lyricsto}, but this behavior can be
+changed:
+
+@lilypond[verbatim,ragged-right,quote]
+\relative c' {
+ f4 \appoggiatura a32 b4
+ \grace { f16[ a16] } b2
+ \afterGrace b2 { f16[ a16] }
+ \appoggiatura a32 b4
+ \acciaccatura a8 b4
+}
+\addlyrics {
+ normal
+ \set includeGraceNotes = ##t
+ case,
+ gra -- ce case,
+ after -- grace case,
+ \set ignoreMelismata = ##t
+ app. case,
+ acc. case.
+}
+@end lilypond
+
+@knownissues
+Like for @code{associatedVoice}, @code{includeGraceNotes} needs to be
+set at latest one syllable before the one which is to be put under a
+grace note. For the case of a grace note at the very beginning of a
+piece of music, consider using a @code{\with} or @code{\context}
+block:
+
+@lilypond[verbatim,ragged-right,quote]
+<<
+ \new Voice = melody \relative c' {
+ \grace { c16[( d e f] }
+ g1) f
+ }
+ \new Lyrics \with { includeGraceNotes = ##t }
+ \lyricsto melody {
+ Ah __ fa
+ }
+>>
+@end lilypond
+
@subsubheading Switching to an alternative melody
More complex variations in text underlay are possible. It is possible
\begin{document}
\begin{lilypond}
-\relative { c' d e f g a b c }
+\relative c' { c d e f g a b c }
\end{lilypond}
Texinfo text
@@lilypond
-\relative @{
+\relative c' @{
a4 b c d
@}
@@end lilypond
@copying
Copyright @copyright{} 2009--2010 by the authors.
+@c next line is necessary for broken pre-4.13 texinfo's
+@c install-info, so leave it there until we officially
+@c bump the required version. -gp
+This file documents the LilyPond website.
+
@quotation
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
* List all commands in direntry.
-@c * lilypond: (lilypond-application)Running LilyPond. Invoking the
-@c LilyPond program.
@end ignore
@c Info files are no longer installed in a subdirectory, images are
* LilyPond: (lilypond-notation). LilyPond Notation Reference.
* LilyPond Snippets: (lilypond-snippets). Short tricks, tips, and examples.
* LilyPond Internals Reference: (lilypond-internals). Definitions for tweaking.
-* LilyPond Application Usage: (lilypond-application). Installing and running applications.
-* LilyPond Website: (lilypond-general). Preview of new website.
-* abc2ly: (lilypond-application)Invoking abc2ly. Importing ABC.
-* convert-ly: (lilypond-application)Updating files with convert-ly. Older LilyPond versions.
-* etf2ly: (lilypond-application)Invoking etf2ly. Importing Finale.
-* lilypond-book: (lilypond-application)LilyPond-book. Integrating text and music.
-* midi2ly: (lilypond-application)Invoking midi2ly. Importing MIDI.
-* musicxml2ly: (lilypond-application)Invoking musicxml2ly. Importing MusicXML.
+* LilyPond Application Usage: (lilypond-usage). Installing and running applications.
+* LilyPond Website: (lilypond-web). Preview of new website.
+* lilypond: (lilypond-usage)Running LilyPond. Invoking the LilyPond program.
+* abc2ly: (lilypond-usage)Invoking abc2ly. Importing ABC.
+* convert-ly: (lilypond-usage)Updating files with convert-ly. Older LilyPond versions.
+* etf2ly: (lilypond-usage)Invoking etf2ly. Importing Finale.
+* lilypond-book: (lilypond-usage)LilyPond-book. Integrating text and music.
+* midi2ly: (lilypond-usage)Invoking midi2ly. Importing MIDI.
+* musicxml2ly: (lilypond-usage)Invoking musicxml2ly. Importing MusicXML.
@end direntry
Created as a plugin for the
@uref{http://www.jedit.org,jEdit} text editor,
-LilyPondTool is one of the most feature-rich text-based tool for
+LilyPondTool is one of the most feature-rich text-based tools 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.
@uref{http://www.frescobaldi.org}
-Frescobaldi is a dedicated LilyPond music and text editor with
+Frescobaldi is a dedicated LilyPond music and text editor with a
built-in PDF previewer, a powerful score wizard and many editing
features. It is built on top of the KDE4 libraries and runs
currently on all flavours of Linux and other UNIX-like operating
@subheading Other
-@subsubheading Mixed environment: LilyKDE
-
-@imageClickable{lilykde-screenshot-small,png,
- (click to enlarge),lilykde-screenshot,png,right}
-
-@sourceimage{logo-linux,,,}
-@sourceimage{logo-freebsd,,,}
-
-@uref{http://lilykde.googlecode.com/}
-
-LilyKDE has been replaced by @uref{http://www.frescobaldi.org/,Frescobaldi},
-and exists as LilyKDE3 for KDE 3.5 and lilypond-KDE4 for KDE 4.1 only.
-
-LilyKDE is a plugin for KDE's text editor
-@uref{http://kate-editor.org/,Kate}. It has a powerful Score
-Wizard to quickly setup a LilyPond document and an embedded
-PDF viewer.
-
-LilyKDE can use @uref{http://www.volny.cz/smilauer/rumor/,Rumor},
-so music can entered by playing on a MIDI keyboard.
-
-Other features are lyric hyphenation and running LilyPond on
-multiple files at once from within the KDE file manager.
-
-
@subsubheading Text environment: TexShop
@sourceimage{logo-macosx,,,}
The TexShop editor for MacOS@tie{}X can be extended to run LilyPond,
@command{lilypond-book} and @command{convert-ly} from within the editor,
-using the extensions available at
-@uref{http://www.dimi.uniud.it/vitacolo/freesoftware.html#desktoppub}.
+using the extensions available at:
-@ignore
-TODO: ask somebody to sponsor/check these. -gp
+@example
+@uref{http://users.dimi.uniud.it/~nicola.vitacolonna/home/content/lilypond-scripts}
+@end example
@subsubheading TextMate
cd /Library/Application\ Support/TextMate/Bundles
svn co http://svn.textmate.org/trunk/Bundles/LilyPond.tmbundle/
@end example
-@end ignore
@divEnd
@itemize
@item
-@uref{http://noteedit.berlios.de,NoteEdit}
-which imports @uref{http://www.musicxml.com/xml.html,MusicXML}
-@item
-@uref{http://www.rosegardenmusic.com,Rosegarden},
-which imports MIDI.
+@uref{http://www.rosegardenmusic.com,Rosegarden}, an audio and
+MIDI sequencer, which also has a score editor for single-staff
+editing.
+
@item
@uref{http://vsr.informatik.tu-chemnitz.de/staff/jan/nted/nted.xhtml,NtEd},
+is based on the @uref{http://cairographics.org, Cairo} library and
has experimental export for LilyPond.
+
@item
-@uref{http://www.tuxguitar.com.ar/,TuxGuitar}, can export to LilyPond.
+@uref{http://www.tuxguitar.com.ar/,TuxGuitar}, a multitrack
+tablature editor and player, provides a score view as well as tab,
+and can export to LilyPond.
+
@item
-@uref{http://musescore.org,MuseScore} can export to LilyPond.
+@uref{http://musescore.org,MuseScore} has incomplete LilyPond
+export but is being actively developed.
+
@item
-@uref{http://canorus.org,Canorus} can also export to LilyPond, but is still
-beta-software. Testers welcome though.
+@uref{http://canorus.org,Canorus} can also export to LilyPond, but
+is still beta-software. Testers are welcome, though.
+
@item
-@uref{http://lilycomp.sourceforge.net, LilyComp} is a graphical note entry
-program, acting much like a number-pad which produces lilypond notes.
+@uref{http://www.volny.cz/smilauer/rumor/rumor.html,Rumor}, a
+realtime monophonic MIDI to LilyPond converter.
+
+@item
+@uref{http://strasheela.sourceforge.net, Strasheela} is @qq{a
+highly expressive constraint-based music composition system}.
+
@end itemize
@subsubheading Command Line Tools:
@item
@uref{http://www.volny.cz/smilauer/rumor/rumor.html,Rumor}, a realtime
monophonic MIDI to LilyPond converter.
+
@item
@uref{http://nicolas.sceaux.free.fr/lilypond/lyqi.html,lyqi}, an
Emacs major mode.
+
+@end itemize
+
+@subheading Other programs not being actively developed
+
+@itemize
+
+@item
+@uref{http://lilykde.googlecode.com/,LilyKDE} has been replaced by
+@uref{http://www.frescobaldi.org/,Frescobaldi}, and exists as
+LilyKDE3 for KDE 3.5 and lilypond-KDE4 for KDE 4.1 only.
+
+@item
+@uref{http://noteedit.berlios.de,NoteEdit}, which imported
+@uref{http://www.musicxml.com/xml.html,MusicXML}, has been forked
+into
+@uref{http://vsr.informatik.tu-chemnitz.de/staff/jan/nted/nted.xhtml,NtEd}
+and @uref{http://canorus.org,Canorus}.
+
+@item
+@uref{http://common-lisp.net/project/fomus/,FOMUS}, a LISP library
+to generate music notation a LISP library to generate music
+notation.
+
@item
-@uref{http://common-lisp.net/project/fomus/,FOMUS},
-a LISP library to generate music notation
+@uref{http://lilycomp.sourceforge.net, LilyComp} is a graphical
+note entry program, acting much like a number-pad which produces
+lilypond notes.
+
@end itemize
+
@divEnd
@c DO NOT WRITE BETWEEN THESE LINES
@c DO NOT WRITE BETWEEN THESE LINES
+@newsItem
+@subsubheading LilyPond 2.13.18 released! @emph{April 16, 2010}
+
+We are happy to announce the release of LilyPond 2.13.18. This
+release contains the usual number of bugfixes, along with improved
+website translations. However, 14 critical issues still remain,
+so this release is intended for developers only.
+@newsEnd
+
@newsItem
@subsubheading LilyPond 2.13.17 released! @emph{April 2, 2010}
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=13
-PATCH_LEVEL=18
+PATCH_LEVEL=19
MY_PATCH_LEVEL=
VERSION_STABLE=2.12.3
-VERSION_DEVEL=2.13.17
+VERSION_DEVEL=2.13.18
/* define if you have sstream */
#define HAVE_SSTREAM 0
-/* define if you have boost/lambda/lambda.hpp */
-#define HAVE_BOOST_LAMBDA_LAMBDA_HPP 0
-
/* define if you have fontconfig */
#define HAVE_FONTCONFIG 0
/* define if you have pango FT2 binding */
#define HAVE_PANGO_FT2 0
+
+/* define if Guile has types scm_t_hash_fold_fn and scm_t_hash_handle_fn */
+#define HAVE_GUILE_HASH_FUNC 0
STEPMAKE_TEXMF_DIRS
STEPMAKE_GUILE_DEVEL(REQUIRED, 1.8.2)
+# check for 2 typedefs added in Guile 1.9
+save_CFLAGS="$CFLAGS"
+CFLAGS="$GUILE_CFLAGS $CFLAGS"
+AC_CHECK_TYPES([scm_t_hash_fold_fn, scm_t_hash_handle_fn],
+ [AC_DEFINE(HAVE_GUILE_HASH_FUNC)], [],
+ [#include <libguile.h>])
+CFLAGS="$save_CFLAGS"
## check rational bugfix.
save_CPPFLAGS="$CPPFLAGS"
AC_CHECK_HEADERS([assert.h grp.h libio.h pwd.h sys/stat.h wchar.h fpu_control.h])
AC_LANG_PUSH(C++)
-AC_CHECK_HEADERS([sstream boost/lambda/lambda.hpp])
+AC_CHECK_HEADERS([sstream])
AC_LANG_POP(C++)
AC_HEADER_STAT
AC_FUNC_MEMCMP
using namespace std;
-#if HAVE_BOOST_LAMBDA_LAMBDA_HPP
-#include <boost/lambda/lambda.hpp>
-#endif
-
template<typename T>
int default_compare (T const &a, T const &b)
{
return find (v.begin (), v.end (), key);
}
-#if HAVE_BOOST_LAMBDA_LAMBDA_HPP
-#include <boost/lambda/lambda.hpp>
-using namespace boost::lambda;
-template<typename T>
-void
-junk_pointers (vector<T> &v)
-{
- for_each (v.begin (), v.end (), (delete _1, _1 = 0));
- v.clear ();
-}
-#else
-
template<typename T> struct del : public unary_function<T, void>
{
void operator() (T x)
for_each (v.begin (), v.end (), del<T> ());
v.clear ();
}
-#endif /* HAVE_BOOST_LAMBDA */
vector<string> string_split (string str, char c);
string string_join (vector<string> const &strs, string infix);
ragged-right = ##t
}
-\relative {
- gis'4 ~ gis!~ gis?
- }
+\relative c'' {
+ gis4 ~ gis!~ gis?
+}
\header {
-
+
texidoc = "The autobeamer may be switched off for a single note
with @code{\\noBeam}."
ragged-right = ##t
}
-\relative { c8 c-\noBeam c c }
+\relative c' { c8 c-\noBeam c c }
\paper { ragged-right = ##t }
-\relative {
+\relative c'' {
\new StaffGroup \new PianoStaff <<
\new Staff
{
\ottava #1
- \times 2/3 { c'8[\< f]( f''\!) }
+ \times 2/3 { c8[\< f]( f''\!) }
\ottava #0
<f,, \5>4
\override TextScript #'color = #red
g4^"red"
}
-
+
\new Staff \relative c'' {
\makeClusters { <g a>8 <e a> <g a>4 }
-
+
\override Glissando #'style = #'zigzag
\slurDashed
f2( \glissando f')
\easyHeadsOn
- f e
+ f e
}
>>
}
\header {
texidoc = "beamlets don't run to end of line if there are no other
beamlets on the same height."
-
+
}
\version "2.12.0"
raggedright = ##t
}
-\relative {
+\relative c' {
\time 1/4
\override Beam #'breakable = ##t
r16 r16. c32[ c16 \break c8. ] r16
texidoc = "This file tests a few standard beam quants, taken from
Ted Ross' book. If LilyPond finds another quant, the correct quant
is printed over the beam."
-
+
}
\version "2.12.0"
#(define debug-beam-quanting #t)
}
-filler = \new Voice \relative {
+filler = \new Voice \relative c' {
\hideNotes
e4 e
}
- %
+ %
%%
%% Ross p108--112
-primes = \relative {
- \time 3/4
+primes = \relative c' {
+ \time 3/4
\assertBeamQuant #'(0 . 0) #'(0 . 0)
c8[ c]
\filler
\assertBeamQuant #'(1 . -1) #'(1 . -1)
d8[ d]
-
+
\filler
-
+
\assertBeamQuant #'(1 . 0) #'(1 . 0)
e8[ e]
\filler
-
-
+
+
\assertBeamQuant #'(2 . -1) #'(2 . -1)
f8[ f]
\filler
-
-
+
+
\assertBeamQuant #'(2 . 0) #'(2 . 0)
g8[ g]
\filler
-
-
+
+
\assertBeamQuant #'(2 . 1) #'(2 . 1)
a8[ a]
\filler
-
+
%{
\once \override Beam #'inspect-quants = #'(2.2 . 2.2)
- \assertBeamQuant
+ \assertBeamQuant
a8[ a]
\filler
-
+
%}
-
+
}
-seconds = \relative {
-
+seconds = \relative c' {
+
\assertBeamQuant #'(0 . 0) #'(0 . 1)
a8[ b]
\filler
-
+
\assertBeamQuant #'(0 . 0) #'(0 . 1)
b8[ c]
\filler
-
+
\assertBeamQuant #'(0 . 0) #'(0 . 1)
c8[ d]
\filler
-
+
\assertBeamQuant #'(1 . -1) #'(1 . 0)
d8[ e]
\filler
-
-
+
+
\assertBeamQuant #'(1 . 0) #'(1 . 1)
e8[ f]
\filler
-
-
+
+
\assertBeamQuant #'(2 . -1) #'(2 . 0)
f8[ g]
\filler
-
-
+
+
\assertBeamQuant #'(2 . 0) #'(2 . 1)
g8[ a]
\filler
\filler
}
-filler = \new Voice \relative {
+filler = \new Voice \relative c' {
\hideNotes
e4 e4.
}
- % Ross, p122
-primeSixteenths = \relative {
+ % Ross, p122
+primeSixteenths = \relative c' {
\stemUp
\assertBeamQuant #'(0 . -1) #'(0 . -1)
g16[ g]
ragged-right = ##t
}
-\relative {
+\relative c {
\stemDown
- \repeat tremolo 16 {d,32 a'32 }
-}
+ \repeat tremolo 16 { d32 a'32 }
+}
"
}
-scales = \relative {
+scales = \relative c' {
a ais b c cis d dis e f fis g gis
a
}
#(define output-suffix "1")
origScore = \score{
- \relative {
+ \relative c' {
\set Staff.instrumentName = #"bla"
c1
d
ragged-right = ##t
}
-\relative {
+\relative c' {
<< { f
\override NoteColumn #'force-hshift = #0.1
f } \\
\paper { ragged-right = ##t }
-\relative {
+\relative c' {
\override Accidental #'color = #darkgreen
\override Beam #'color = #cyan
\override NoteHead #'color = #darkyellow
-\version "2.12.0"
+\version "2.13.19"
#(use-modules (srfi srfi-13)
(ice-9 format))
\test "" ##[ \lyricmode { a -- b } #] % HyphenEvent
\test "" ##[ \lyricmode { a __ b } #] % ExtenderEvent
\test "" ##[ \lyricmode { "a " } #] % LyricEvent
-\test "" ##[ \lyricsto "foo" { bla bla } #] % LyricCombineMusic
+\test "" ##[ \lyricsto "foo" { bla bla } #] % LyricCombineMusic
\test "" ##[ { { c d }
- \addlyrics { bla bla } } #]
+ \addlyrics { bla bla } } #]
%% Drums
\test "" ##[ \drums { hihat } #]
You also get ledger lines, of course."
}
-\relative {
+\relative c' {
\easyHeadsOn
f1 e
f2 e
\paper { ragged-right = ##t }
-\relative {
+\relative c' {
%% input order is not 1 2 3 , output is.
<c-1 g'-3 e-2 b'-4 d-5 f-6 a-7 c-8 > 4
\version "2.12.0"
-\paper {
- % change for other default global staff size.
+\paper {
+ % change for other default global staff size.
myStaffSize = #20
lilypond -dshow-available-fonts blabla
- to show all fonts available in the process log.
-
+ to show all fonts available in the process log.
+
%}
-
+
#(define fonts
(make-pango-font-tree "Times New Roman"
"Nimbus Sans"
(/ myStaffSize 20)))
}
-\relative {
+\relative c'' {
- c'^\markup { roman: foo \bold bla \italic bar \italic \bold baz }
+ c^\markup { roman: foo \bold bla \italic bar \italic \bold baz }
c'_\markup {
\override #'(font-family . sans)
{
mono: foo \bold bla \italic bar \italic \bold baz
}
}
-}
+}
indent = 0\cm
}
-\relative {
+\relative c' {
\set Staff.shortInstrumentName = "foo"
f1 | f1 | f1 |
f1\< | f1 | f1\! |
ragged-right = ##t
}
-\relative {
+\relative c' {
<c e g>\laissezVibrer r4
<c f g>\laissezVibrer r
<c d f g>\laissezVibrer r
\header { texidoc = " Scores may be printed in landscape mode."}
-pattern = \relative { a b c d \break }
+pattern = \relative c' { a b c d \break }
\book {
\score {
ragged-right = ##t
}
-\relative {
+\relative c' {
\time 2/4
c4
\version "2.12.0"
-\relative {
+\relative c' {
\override Staff.OttavaBracket #'dash-period = #0.1
\override Score.OttavaBracket #'dash-fraction = #1
--- /dev/null
+\version "2.13.19"
+
+\header {
+ texidoc="
+If @code{includeGraceNotes} is enabled, lyric extenders work as
+expected also for syllables starting under grace notes.
+"
+}
+
+\relative c' {
+ c2 \grace { c16([ d e f] } g2)
+ f1
+}
+\addlyrics {
+ \set includeGraceNotes = ##t
+ _ Ah __ fa
+}
ragged-right = ##t
}
-\relative {
+\relative c' {
\set melismaBusyProperties = #'()
c d( e) f f( e) e e }
\addlyrics
--- /dev/null
+\version "2.13.19"
+
+\header {
+ texidoc="
+Setting @code{includeGraceNotes} enables lyrics syllables to be
+assigned to grace notes.
+"
+}
+
+\relative c' {
+ f4 \appoggiatura a32 b4
+ \grace { f16[ a16] } b2
+ \afterGrace b2 { f16[ a16] }
+ \appoggiatura a32 b4
+ \acciaccatura a8 b4
+}
+\addlyrics {
+ normal
+ \set includeGraceNotes = ##t
+ case,
+ gra -- ce case,
+ after -- grace case,
+ \set ignoreMelismata = ##t
+ app. case,
+ acc. case.
+}
ragged-right = ##t
}
-\relative { \clef "G_8" c c c c }
+\relative c' { \clef "G_8" c c c c }
\addlyrics { bla bla bla bla }
subsubtitle = \markup { "Originalstimmung:" \tuning }
}
-\relative {
+\relative c'' {
\time 4/8
- \times 2/3 { c'8 d e } \times 2/3 {c d e}
\times 2/3 { c8 d e } \times 2/3 {c d e}
- g8 a8 g8 a
- g8 a8 g8 a
+ \times 2/3 { c8 d e } \times 2/3 {c d e}
+ g8 a8 g8 a
+ g8 a8 g8 a
}
\version "2.12.0"
\score {
- \relative {
+ \relative c' {
\set midiMinimumVolume = #0.0
\set midiMaximumVolume = #1.0
\score
{
-
- \relative {
+
+ \relative c' {
a geseh \acciaccatura a geseh
}
\version "2.12.0"
\score {
- \relative {
+ \relative c' {
{
{ c16 e g c }
\header {
-
+
texidoc = "newlyrics, multiple stanzas, multiple lyric voices."
-
+
}
\layout { ragged-right = ##t }
<<
- \new Staff \relative {
- d'2 d c4 bes a2 \break
+ \new Staff \relative c'' {
+ d2 d c4 bes a2 \break
}
\addlyrics {
My first Li -- ly song,
\addlyrics {
Not much can go wrong!
}
- \new Staff \relative {
+ \new Staff \relative c' {
\clef bass
d2 d c4 bes a2 \break
}
grob is tweaked."
}
-\relative {
+\relative c' {
\override Stem #'details #'beamed-lengths = #'(6 10 8)
c8[ c] c16[ c] c32[ c]
\revert Stem #'details
}
}
<<
- \new Staff \relative {
- d'2 d c4 bes a2 \break
+ \new Staff \relative c'' {
+ d2 d c4 bes a2 \break
}
\addlyrics {
My first Li -- ly song,
\new Lyrics \lyricmode {
Not2 much can4 go wrong!
}
- \context Voice = "voice" \relative {
- d'2 d c4 bes a2
+ \context Voice = "voice" \relative c'' {
+ d2 d c4 bes a2
}
>>
My2 first Li4 -- ly song,2
My2 first Li4 -- ly song,2
}
- \context Voice = "voice" \relative {
- d'2 d c4 bes a2 \break
+ \context Voice = "voice" \relative c'' {
+ d2 d c4 bes a2 \break
d'2 d c4 bes a2
}
\new Lyrics \lyricmode {
\book {
\score {
- \relative {
+ \relative c' {
c1\break\pageBreak
c1\break\pageBreak
c1
}
\score {
- \relative {
+ \relative c' {
\set Score.skipBars = ##t
% this should be kept on one page
\repeat volta 2 {
\version "2.12.0"
-\relative {
+\relative c' {
c4 -\parenthesize -.
\override ParenthesesItem #'padding = #0.1
vone = \relative a' { R1*2 g2 r2 g2 r2 a4 r4 g }
vtwo = \relative a' { R1*2 g2 r2 g2 r2 f4 r4 g }
-comment = \relative { s1*2 s2_"a2" s2 s2_"no a2" s2 s4 s4 s4_"a2" }
+comment = \relative c' { s1*2 s2_"a2" s2 s2_"no a2" s2 s4 s4 s4_"a2" }
\layout { ragged-right = ##T }
-\new Staff << \set Score.skipBars = ##t
+\new Staff << \set Score.skipBars = ##t
\partcombine \vone \vtwo
\comment
>>
-
+
\version "2.12.0"
-\relative {
+\relative c' {
f2 \glissando c
\override Glissando #'bound-details #'right #'Y = #4
f2 \glissando c |
}
-foo = \relative {
+foo = \relative c' {
\times 2/3 { c4 c c } \times 2/3 { c4 c c }
}
\version "2.12.0"
-\relative {
+\relative c' {
\override Score.RehearsalMark #'break-align-symbols = #'(clef key-signature staff-bar)
c1
\clef "bass"
}
}
-\relative {
+\relative c' {
c1 \mark "foo"
c1
\key cis \major
\version "2.12.0"
-\relative {
+\relative c' {
c1 \mark "foo"
c1
\key cis \major
}
\version "2.12.0"
-\relative {
+\relative c' {
\repeat "unfold" 3
{ f2 bes2 }
\alternative { a1 e b }
line-width = #110
}
-%% using Book and Score to get text in lilypond-book
+%% using Book and Score to get text in lilypond-book
\book {
\markup {
\fill-line { "High up above" }
}
\score {
<<
- \relative {
+ \relative c {
\clef bass
- d,2 d c4 bes a2 \break
+ d2 d c4 bes a2 \break
c2 c d4 f g2
}
\addlyrics {
}
}
}
-}
\ No newline at end of file
+}
}
-\relative {
+\relative c' {
c4
\set Score.skipTypesetting = ##t
c4 c4
<bis f' b>) s2..\break
\stemNeutral
- \new Voice \relative {
+ \new Voice \relative c' {
c'8[( c c c] g2 ~ | \break
g1) | \break
\slurDown c8[( c] g4 ~ g2 ~ | \break
texidoc = "Slurs that depend on a cross-staff beam are not calculated until after line-breaking."
}
-\paper{ ragged-right=##t }
+\paper { ragged-right=##t }
\score {
\new PianoStaff <<
- \context Staff = rh \relative { c'8([ d) \change Staff = lh c,] }
+ \context Staff = rh \relative c'' { c8([ d) \change Staff = lh c,] }
\context Staff = lh { s4. }
>>
-}
\ No newline at end of file
+}
\version "2.12.0"
\layout { ragged-right = ##t }
-\relative {
+\relative c' {
\set doubleSlurs = ##t
<c e>4 ( <d f> <c e> <d f> )
}
\version "2.12.0"
\paper { ragged-right = ##T }
-\relative {
+\relative c' {
\override Slur #'positions = #'(-4 . -5)
e( f g)
}
one big file, since changing one score parameter for one situation
may affect several other situations.
- Tunable parameters are in @file{scm/slur.scm}.
+ Tunable parameters are in @file{scm/slur.scm}.
"
}
% #(define debug-slur-scoring #t)
}
-\relative {
-
- \grace e'=''16( d8.[) c16]
+\relative c'' {
+
+ \grace e=''16( d8.[) c16]
d=''8.[ \grace f16( e16)]
s2
<< {c=''8.([ es16] bes4~bes )}
{r8 <as es> r <f des> r }
>>
\new Voice { \voiceOne b='8[ c16( d]) }
- g,='8[( a b b! ] c4 bes)
+ g,='8[( a b b! ] c4 bes)
bes='8( f' des bes) as4( bes)
r8 d( f e d c b a)
cis=''4( d) f=''16( e) d( c)
s4
-
+
c=''2(~c8 d16 c b8 a)
-
+
<c,=' g>4 ( f <g b>) f
<c g>^( f <g b>) f
<c g>_( f <g b>)
<g b>_( g <b d>)
<g b>_( \stemDown g \stemNeutral <b d>)
- c,='^( c'' c)
+ c,='^( c'' c)
c,,^( c'')
c,,^( c')
| b='2( a4) s4
| << { b='8[( c]) } \\
{ b='8[( c]) }>>
-
+
s2.|
e4( dis4)
- e4( dis4)
+ e4( dis4)
g,='16( b d fis)
\clef bass a,,=8[ e16(f] g[ a b d,)] s4 | \break
e=8[( f] g[ a b d,)] s4 |
-
+
\clef treble
\new Voice {
\slurDown
% #(define debug-slur-scoring #t)
}
-\relative {
+\relative c' {
\slurUp
\override TupletBracket #'bracket-visibility = ##f
\override Slur #'(details region-size) = #6
\festivalsyl #"song-basic-nonenglish.xml" { \tempo 4 = 100 }
{
-\relative { c e g r }
+\relative c' { c e g r }
\addlyrics { ov -- čá -- ci }
}
#(ly:progress "song-basic-nonenglish")
\festival #"song-basic.xml" { \tempo 4 = 100 }
{
\time 3/4
-\relative { c2 r2 e4 g2. }
+\relative c' { c2 r2 e4 g2. }
\addlyrics { play the game }
}
#(ly:progress "song-basic")
\festival #"song-breathe.xml" { \tempo 4 = 100 }
{
\time 3/4
-\relative { c2 e \breathe g }
+\relative c' { c2 e \breathe g }
\addlyrics { play the game }
}
#(ly:progress "song-breathe")
#(set! *skip-word* #f)
\festival #"song-skip-noword.xml" { \tempo 4 = 100 }
-\relative { c c g' }
+\relative c' { c c g' }
\addlyrics {
twin -- \skip 4
kle
\include "festival.ly"
\festival #"song-skip.xml" { \tempo 4 = 100 }
-\relative { c c g' }
+\relative c' { c c g' }
\addlyrics {
twin -- \skip 4
kle
\festival #"song-stanzas.xml" { \tempo 4 = 100 }
{
\time 3/4
-\relative { c2 e4 g2. }
+\relative c' { c2 e4 g2. }
\addlyrics { play the game }
\addlyrics { speel het spel }
\addlyrics { joue le jeu }
\festival #"song-tempo.xml" { \tempo 4=90 }
{
\time 3/4
-\relative { c4 e g \tempo 4=60 c, e g }
+\relative c' { c4 e g \tempo 4=60 c, e g }
\addlyrics { do re mi do re mi }
}
#(ly:progress "song-tempo")
ragged-right=##t
}
-\new Staff \relative {
+\new Staff \relative c' {
\override Score.NonMusicalPaperColumn #'stencil = #ly:paper-column::print
\override Score.NonMusicalPaperColumn #'layer = #1
ragged-right = ##t
}
-\relative {
- \stemUp c''4...*1/2
+\relative c''' {
+ \stemUp c4...*1/2
ceses,,!
eses!
ceses!
geses'!
ceses,!
-
+
}
-
+
\version "2.12.0"
-\relative {
+\relative c' {
\override Score.SpacingSpanner #'packed-spacing = ##t
c2 d4 f8[ g] a
}
ragged-right = ##t
}
\version "2.12.0"
-\relative {
+\relative c' {
\time 2/4
c4 c8 c
c8 c c4 c16[ c c8] c4
\layout { ragged-right = ##t }
-\relative {
+\relative c' {
\override Score.PaperColumn #'keep-inside-line = ##t
c1 c1^"This is a really long text" c
}
\header {
-
+
texidoc = "Staves may be present in several sizes within a score.
-This is achieved with an internal scaling factor. If the scaling factor is
-forgotten in some places, objects generally become too thick or too
+This is achieved with an internal scaling factor. If the scaling factor is
+forgotten in some places, objects generally become too thick or too
large on smaller staves."
}
ragged-right = ##t
}
-melody = \relative {
+melody = \relative c''' {
\override DynamicText #'extra-offset = #'(0 . 3)
- s1-\f c''8[(\< r a g]) e[ r d( <f a>])\! \times 2/3 { d4 d d }
+ s1-\f c8[(\< r a g]) e[ r d( <f a>])\! \times 2/3 { d4 d d }
}
<<
\melody
}
\new Staff {
- \relative c' {
- \melody
- }
+ \melody
}
>>
\version "2.12.0"
\layout { ragged-right = ##t }
-\relative {
+\relative c' {
\override Stem #'stemlet-length = #0.75
c8[ r8 c16 r16 c8]
c4
ragged-right = ##t
}
-\relative {
+\relative c' {
<c\1 e\2 g\3>
c4
\set fingeringOrientations = #'(down left up)
ragged-right = ##f
}
-\relative { c4 d f8_\f[ g-.] }
+\relative c' { c4 d f8_\f[ g-.] }
\version "2.12.0"
\paper { ragged-right = ##t }
-\relative {
+\relative c' {
c~ e~ g~ <c, e g>
\set tieWaitForNote = ##t
c~ e~ g~ <c, e g>
line-width = 40.0\mm
}
-\relative {
+\relative c' {
\override Tie #'minimum-length = #5
f2. f16 f f f ~ | \break
f1
ragged-right = ##t
}
-\relative {
+\relative c' {
<c~ e g> <c e g~> <c e g>
}
ragged-right = ##t
}
-\relative {
+\relative c' {
\pitchedTrill c4.\startTrillSpan es f\stopTrillSpan
}
Red Hat Fedora
taipeifonts fonts-xorg-truetype ttfonts-ja fonts-arabic \
- ttfonts-zh_CN fonts-ja fonts-hebrew
+ ttfonts-zh_CN fonts-ja fonts-hebrew
Debian GNU/Linux
apt-get install emacs-intl-fonts xfonts-intl-.* \
ttf-kochi-gothic ttf-kochi-mincho \
- xfonts-bolkhov-75dpi xfonts-cronyx-100dpi xfonts-cronyx-75dpi
-%}
+ xfonts-bolkhov-75dpi xfonts-cronyx-100dpi xfonts-cronyx-75dpi
+%}
\header {
will render Bulgarian (Cyrillic), Hebrew, Japanese and Portuguese.
"
-
+
}
% Cyrillic font
Жълтата дюля беше щастлива, че пухът, който цъфна, замръзна като гьон.
}
-hebrew = \lyricmode {
+hebrew = \lyricmode {
זה כיף סתם לשמוע איך תנצח קרפד עץ טוב בגן.
}
-japanese = \lyricmode {
+japanese = \lyricmode {
いろはにほへど ちりぬるを
わがよたれぞ つねならむ
うゐのおくや まけふこえて
- あさきゆめみじ ゑひもせず
+ あさきゆめみじ ゑひもせず
}
% "a legal song to you"
-portuguese = \lyricmode {
+portuguese = \lyricmode {
à vo -- cê uma can -- ção legal
}
ragged-right = ##T
}
-\relative {
+\relative c' {
c2 d e f g f e
}
\addlyrics { \bulgarian }
int start_rank = Paper_column::get_rank (all_[breaks_[start]]);
int end_rank = Paper_column::get_rank (all_[breaks_[end]]);
System *sys = pscore_->root_system ();
- Interval extent = sys->pure_height (sys, start_rank, end_rank);
+ Interval begin_of_line_extent = sys->begin_of_line_pure_height (start_rank, end_rank);
+ Interval rest_of_line_extent = sys->rest_of_line_pure_height (start_rank, end_rank);
Grob *c = all_[breaks_[end]];
out->last_column_ = c;
out->turn_permission_ = min_permission (out->page_permission_,
out->turn_permission_);
- // TODO: see the hack regarding begin_of_line and
- // rest_of_line extents in align-interface. Perhaps we
- // should do the same thing here so that the effect extends
- // between systems as well as within systems. It isn't as
- // crucial here, however, because the effect is largest when
- // dealing with large systems.
- out->extent_ = (extent.is_empty ()
- || isnan (extent[LEFT])
- || isnan (extent[RIGHT]))
- ? Interval (0, 0) : extent;
+ begin_of_line_extent = (begin_of_line_extent.is_empty ()
+ || isnan (begin_of_line_extent[LEFT])
+ || isnan (begin_of_line_extent[RIGHT]))
+ ? Interval (0, 0) : begin_of_line_extent;
+ rest_of_line_extent = (rest_of_line_extent.is_empty ()
+ || isnan (rest_of_line_extent[LEFT])
+ || isnan (rest_of_line_extent[RIGHT]))
+ ? Interval (0, 0) : rest_of_line_extent;
+ out->shape_ = Line_shape (begin_of_line_extent, rest_of_line_extent);
out->padding_ = between_system_padding_;
out->title_padding_ = before_title_padding_;
out->space_ = between_system_space_;
- out->inverse_hooke_ = extent.length () + between_system_space_;
+ out->inverse_hooke_ = out->full_height () + between_system_space_;
}
Real
last_column_ = 0;
force_ = 0;
- extent_ = unsmob_stencil (pb->get_property ("stencil")) ->extent (Y_AXIS);
+ Interval stencil_extent = unsmob_stencil (pb->get_property ("stencil"))->extent (Y_AXIS);
+ shape_ = Line_shape (stencil_extent, stencil_extent); // pretend it goes all the way across
+ tallness_ = 0;
bottom_padding_ = 0;
space_ = 0.0;
inverse_hooke_ = 1.0;
SCM first_scm = pb->get_property ("first-markup-line");
first_markup_line_ = to_boolean (first_scm);
}
+
+Real
+Line_details::full_height () const
+{
+ Interval ret;
+ ret.unite(shape_.begin_);
+ ret.unite(shape_.rest_);
+ return ret.length();
+}
+
+Real
+Line_details::tallness () const
+{
+ return tallness_;
+}
+
+Line_shape::Line_shape (Interval begin, Interval rest)
+{
+ begin_ = begin;
+ rest_ = rest;
+}
+
+Line_shape
+Line_shape::piggyback (Line_shape mount, Real padding) const
+{
+ Real elevation = max (begin_[UP]-mount.begin_[DOWN], rest_[UP]-mount.rest_[DOWN]);
+ Interval begin = Interval (begin_[DOWN], elevation + mount.begin_[UP] + padding);
+ Interval rest = Interval (rest_[DOWN], elevation + mount.rest_[UP] + padding);
+ return Line_shape (begin, rest);
+}
You should have received a copy of the GNU General Public License
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include "context.hh"
#include "engraver.hh"
#include "international.hh"
#include "stream-event.hh"
#include "warn.hh"
#include "spanner.hh"
-#include "paper-column.hh"
-
#include "translator.icc"
void completize_extender (Spanner *sp);
Stream_event *ev_;
Spanner *extender_;
Spanner *pending_extender_;
- bool current_lyric_is_skip_;
public:
TRANSLATOR_DECLARATIONS (Extender_engraver);
protected:
DECLARE_TRANSLATOR_LISTENER (extender);
+ DECLARE_TRANSLATOR_LISTENER (completize_extender);
DECLARE_ACKNOWLEDGER (lyric_syllable);
virtual void finalize ();
Extender_engraver::Extender_engraver ()
{
- current_lyric_is_skip_ = false;
extender_ = 0;
pending_extender_ = 0;
ev_ = 0;
ASSIGN_EVENT_ONCE (ev_, ev);
}
+
+/*
+ A CompletizeExtenderEvent is sent at the end of each lyrics block
+ to ensure any pending extender can be correctly terminated if the lyrics
+ end before the associated voice (this prevents the right bound being extended
+ to the next note-column if no lyric follows the extender)
+*/
+IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, completize_extender);
+void
+Extender_engraver::listen_completize_extender (Stream_event * /* ev */)
+{
+ if (pending_extender_)
+ {
+ completize_extender (pending_extender_);
+ pending_extender_ = 0;
+ }
+}
+
void
Extender_engraver::process_music ()
{
if (extender_)
extender_->set_bound (LEFT, item);
- SCM text = item->get_property ("text");
- current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" "));
-
- if (pending_extender_ && !current_lyric_is_skip_)
+ if (pending_extender_)
{
pending_extender_->set_object ("next", item->self_scm ());
completize_extender (pending_extender_);
if (extender_ || pending_extender_)
{
Context *voice = get_voice_to_lyrics (context ());
- Grob *h = voice ? get_current_note_head (voice) : 0;
+ Grob *h = voice ? get_current_note_head (voice, to_boolean (get_property ("includeGraceNotes"))) : 0;
if (h)
{
ly_symbol2scm ("heads"), h);
}
- if (pending_extender_)
- {
- Pointer_group_interface::add_grob (pending_extender_,
- ly_symbol2scm ("heads"), h);
- /*
- The following check addresses the case where the lyrics end before
- the associated voice. The current_lyric_is_skip_ check is
- necessary to handle manual melismata, which should not result in
- extenders being completized. We also need to make sure that we're not
- in the middle of a note (happens when this function is called because
- of an event in a voice other than our associated one).
- */
- if (!melisma_busy (voice) && !current_lyric_is_skip_)
- {
- Moment now = voice->now_mom ();
- Paper_column *column = (dynamic_cast<Item *> (h))->get_column ();
- Moment *start_mom = column ? unsmob_moment (column->get_property ("when")) : 0;
- if (!column || (start_mom->main_part_ == now.main_part_))
- {
- completize_extender (pending_extender_);
- pending_extender_ = 0;
- }
- }
- }
- }
+ if (pending_extender_)
+ {
+ Pointer_group_interface::add_grob (pending_extender_,
+ ly_symbol2scm ("heads"), h);
+ }
+ }
else
{
if (pending_extender_
completize_extender (pending_extender_);
pending_extender_ = 0;
}
-
}
if (extender_)
{
"LyricExtender ",
/* read */
- "extendersOverRests ",
+ "extendersOverRests "
+ "includeGraceNotes ",
/* write */
""
1,0,0, (SCM tab),
"Return a list of keys in @var{tab}.")
{
- return scm_internal_hash_fold ((Hash_closure_function) & accumulate_symbol,
+ return scm_internal_hash_fold ((scm_t_hash_fold_fn) &accumulate_symbol,
NULL, SCM_EOL, tab);
}
Spanner *hyphen_;
Spanner *finished_hyphen_;
- bool current_lyric_is_skip_;
public:
TRANSLATOR_DECLARATIONS (Hyphen_engraver);
Hyphen_engraver::Hyphen_engraver ()
{
- current_lyric_is_skip_ = false;
hyphen_ = 0;
finished_hyphen_ = 0;
finished_ev_ = 0;
Hyphen_engraver::acknowledge_lyric_syllable (Grob_info i)
{
Item *item = i.item ();
- SCM text = item->get_property ("text");
- current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" "));
-
- if (!hyphen_ && !current_lyric_is_skip_)
+
+ if (!hyphen_)
hyphen_ = make_spanner ("LyricSpace", item->self_scm ());
if (hyphen_)
hyphen_->set_bound (LEFT, item);
-
- if (finished_hyphen_ && !current_lyric_is_skip_)
+
+ if (finished_hyphen_)
finished_hyphen_->set_bound (RIGHT, item);
}
finished_hyphen_ = 0;
finished_ev_ = 0;
}
-
- if (finished_hyphen_ && hyphen_ && !current_lyric_is_skip_)
+
+ if (finished_hyphen_ && hyphen_)
{
programming_error ("hyphen not finished yet");
finished_hyphen_ = 0;
finished_hyphen_ = hyphen_;
finished_ev_ = ev_;
}
-
+
hyphen_ = 0;
ev_ = 0;
}
+++ /dev/null
-/*
- This file is part of LilyPond, the GNU music typesetter.
-
- Copyright (C) 1996--2010 Han-Wen Nienhuys
-
- LilyPond is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- LilyPond is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef BAR_HH
-#define BAR_HH
-
-#include "lily-proto.hh"
-#include "grob-interface.hh"
-
-/**
- A vertical bar.
-*/
-class Bar
-{
-public:
- DECLARE_GROB_INTERFACE();
-
- static Stencil compound_barline (Grob *, string, Real height);
- static Stencil simple_barline (Grob *, Real wid, Real height);
- DECLARE_SCHEME_CALLBACK (get_staff_bar_size, (SCM));
- DECLARE_SCHEME_CALLBACK (print, (SCM));
- DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM));
-};
-#endif // BAR_HH
-
DECLARE_SMOBS (Book);
public:
- string user_key_;
SCM header_;
Output_def *paper_;
SCM scores_;
SCM input_location_;
Book (Book const &);
- Input *origin() const;
- VIRTUAL_COPY_CONSTRUCTOR(Book, Book);
+ Input *origin () const;
+ VIRTUAL_COPY_CONSTRUCTOR (Book, Book);
Book ();
void add_score (SCM);
void add_bookpart (SCM);
#include "matrix.hh"
#include "prob.hh"
+/*
+ * Begin/rest-of-line hack. This geometrical shape is a crude approximation
+ * of Skyline, but it is better than a rectangle.
+ */
+struct Line_shape
+{
+ Interval begin_;
+ Interval rest_;
+
+ Line_shape ()
+ {
+ }
+ Line_shape (Interval begin, Interval rest);
+ Line_shape piggyback (Line_shape mount, Real padding) const;
+};
+
struct Line_details {
Grob *last_column_;
Real force_;
- Interval extent_; /* Y-extent of the system */
+ Line_shape shape_;
+ Real tallness_; /* Y-extent, adjusted according to begin/rest-of-line*/
Real padding_; /* compulsory space after this system (if we're not
last on a page) */
compressed_nontitle_lines_count_ = 1;
last_markup_line_ = false;
first_markup_line_ = false;
+ tallness_ = 0;
}
Line_details (Prob *pb, Output_def *paper);
+ Real full_height () const;
+ Real tallness () const;
};
/*
bool melisma_busy (Context *);
Context *get_voice_to_lyrics (Context *lyrics);
-Grob *get_current_note_head (Context *voice);
+Grob *get_current_note_head (Context *voice, bool include_grace_notes);
Grob *get_current_rest (Context *voice);
DECLARE_UNSMOB (Context, context);
class Music_wrapper_iterator;
class Note_performer;
class Output_def;
-class Object_key;
-class Object_key_dumper;
-class Object_key_undumper;
class Open_type_font;
class Output_property;
class Page_breaking;
class Transposed_music;
class yyFlexLexer;
-typedef void (*Engraver_void_function_engraver_grob_info) (Engraver *, Grob_info);
+typedef void (*Engraver_void_function_engraver_grob_info) (Engraver *,
+ Grob_info);
typedef void (*Translator_void_method_ptr) (Translator *);
#endif /* LILY_PROTO_HH */
#ifndef LY_MODULE_HH
#define LY_MODULE_HH
+#include "config.hh"
#include "lily-guile.hh"
SCM ly_make_anonymous_module (bool safe);
void clear_anonymous_modules ();
SCM ly_use_module (SCM mod, SCM used);
-/* Ugh signature of scm_internal_hash_fold () is inaccurate. */
-typedef SCM (*Hash_closure_function) (GUILE_ELLIPSIS);
+/* For backward compatability with Guile 1.8 */
+#if !HAVE_GUILE_HASH_FUNC
+typedef SCM (*scm_t_hash_fold_fn) (GUILE_ELLIPSIS);
+typedef SCM (*scm_t_hash_handle_fn) (GUILE_ELLIPSIS);
+#endif
#define MODULE_GC_KLUDGE
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MUSIC_OUTPUT_DEF_HH
-#define MUSIC_OUTPUT_DEF_HH
+#ifndef OUTPUT_DEF_HH
+#define OUTPUT_DEF_HH
#include "lily-proto.hh"
#include "virtual-methods.hh"
Output_def *parent_;
Input input_origin_;
- string user_key_;
Output_def (Output_def const&);
Output_def ();
Font_metric* find_pango_font (Output_def *layout, SCM descr, Real factor);
-Font_metric *find_scaled_font (Output_def *od, Font_metric *f, Real magnification);
+Font_metric *find_scaled_font (Output_def *od, Font_metric *f,
+ Real magnification);
Output_def *scale_output_def (Output_def *def, Real scale);
Real output_scale (Output_def*);
-#endif /* MUSIC_OUTPUT_DEF_HH */
+#endif /* OUTPUT_DEF_HH */
vsize current_end_breakpoint_;
void cache_line_details (vsize configuration_index);
+ void compute_line_heights ();
void clear_line_details_cache ();
vsize cached_configuration_index_;
vector<Line_details> cached_line_details_;
SCM input_location_;
SCM header_;
public:
- Input *origin() const;
-
- vector<Output_def*> defs_;
- string user_key_;
+ Input *origin () const;
+
+ vector<Output_def *> defs_;
bool error_found_;
Score ();
Score (Score const &);
VIRTUAL_COPY_CONSTRUCTOR (Score, Score);
-
+
SCM get_music () const;
void add_output_def (Output_def *def);
void set_music (SCM music);
DECLARE_UNSMOB (Score, score);
-SCM ly_render_output (SCM, SCM);
SCM ly_run_translator (SCM, SCM);
#endif /* SCORE_HH */
void set_inverse_compress_strength (Real);
void set_blocking_force (Real);
void set_default_strength ();
+ void set_default_compress_strength ();
+ void set_default_stretch_strength ();
void operator*= (Real);
bool operator> (Spring const&) const;
void typeset_grob (Grob *);
void pre_processing ();
+ Interval begin_of_line_pure_height (vsize start, vsize end);
+ Interval rest_of_line_pure_height (vsize start, vsize end);
+
protected:
virtual void derived_mark () const;
virtual Grob *clone () const;
+
+private:
+ Interval part_of_line_pure_height (vsize start, vsize end, bool begin);
};
void set_loose_columns (System *which, Column_x_positions const *posns);
#include <sstream>
using namespace std;
-#include "context.hh" // for nested_property_alist
+#include "context.hh" // for nested_property_alist
#include "international.hh"
#include "interval.hh"
#include "keyword.hh"
{"name", NAME},
{"new", NEWCONTEXT},
{"notemode", NOTEMODE},
- {"objectid", OBJECTID},
{"once", ONCE},
{"override", OVERRIDE},
{"paper", PAPER},
Lily_lexer::Lily_lexer (Lily_lexer const &src, Lily_parser *parser)
: Includable_lexer ()
{
- parser_ = parser;
+ parser_ = parser;
keytable_ = (src.keytable_) ? new Keyword_table (*src.keytable_) : 0;
chordmodifier_tab_ = src.chordmodifier_tab_;
pitchname_tab_stack_ = src.pitchname_tab_stack_;
{
if (!keytable_)
return SCM_EOL;
-
+
SCM l = SCM_EOL;
SCM *tail = &l;
for (vsize i = 0; i < keytable_->table_.size (); i++)
yy_flex_debug = get_program_option ("debug-lexer");
parser_->set_yydebug (get_program_option ("debug-parser"));
-
new_input (main_input_name_, sources_);
scm_module_define (scm_car (scopes_),
Lily_lexer::mark_smob (SCM s)
{
ASSERT_LIVE_IS_ALLOWED ();
-
+
Lily_lexer *lexer = (Lily_lexer *) SCM_CELL_WORD_1 (s);
scm_gc_mark (lexer->chordmodifier_tab_);
SCM_VALIDATE_MODULE (1, mod);
SCM obarr = SCM_MODULE_OBARRAY (mod);
- return scm_internal_hash_fold ((Hash_closure_function) & entry_to_alist, NULL, SCM_EOL, obarr);
+ return scm_internal_hash_fold ((scm_t_hash_fold_fn) &entry_to_alist,
+ NULL, SCM_EOL, obarr);
}
void
{
ly_export (mod, ly_module_symbols (mod));
}
-
-#ifdef MODULE_GC_KLUDGE
-static SCM
-redefine_keyval (void * /* closure */,
- SCM key,
- SCM val,
- SCM result)
-{
- SCM new_tab = result;
- scm_hashq_set_x (new_tab, key, val);
- return new_tab;
-}
-
-/*
- UGH UGH.
- Kludge for older GUILE 1.6 versions.
-*/
-void
-make_stand_in_procs_weak ()
-{
- /*
- Ugh, ABI breakage for 1.6.5: scm_stand_in_procs is a hashtab from
- 1.6.5 on.
- */
- if (scm_is_pair (scm_stand_in_procs))
- {
- return;
- }
-
- if (scm_weak_key_hash_table_p (scm_stand_in_procs) == SCM_BOOL_T)
- {
-#if (SCM_MINOR_VERSION == 7)
- perform_gc_kludge = false;
-#endif
- return;
- }
-
-
- perform_gc_kludge = true;
-
-
- SCM old_tab = scm_stand_in_procs;
- SCM new_tab = scm_make_weak_key_hash_table (scm_from_int (257));
-
- new_tab = scm_internal_hash_fold ((Hash_closure_function) & redefine_keyval,
- NULL,
- new_tab,
- old_tab);
-
- scm_stand_in_procs = new_tab;
-}
-
-ADD_SCM_INIT_FUNC (make_stand_in_procs_weak, make_stand_in_procs_weak);
-#endif
set_music_context (0);
}
-
if (music_context_
&& (start_new_syllable () ||
(busy_moment_ >= pending_grace_moment_))
&& lyric_iter_->ok ())
{
Moment now = music_context_->now_mom ();
- if (now.grace_part_)
+ if (now.grace_part_ && !to_boolean (lyrics_context_->get_property ("includeGraceNotes")))
{
pending_grace_moment_ = now;
pending_grace_moment_.grace_part_ = Rational (0);
{
pending_grace_moment_.set_infinite (1);
}
-
+
Moment m = lyric_iter_->pending_moment ();
lyrics_context_->set_property (ly_symbol2scm ("associatedVoiceContext"),
music_context_->self_scm ());
if (last_text_)
last_text_->set_property ("self-alignment-X", scm_from_int (LEFT));
}
- /*
- "Empty" LyricText objects are needed to allow the Extender_engraver to
- distinguish between the end of a lyrics block and manual melismata.
- */
- text_ = make_item ("LyricText", event_->self_scm ());
+ else
+ text_ = make_item ("LyricText", event_->self_scm ());
}
}
}
Grob *
-get_current_note_head (Context *voice)
+get_current_note_head (Context *voice, bool include_grace_notes)
{
Moment now = voice->now_mom ();
for (SCM s = voice->get_property ("busyGrobs");
continue;
}
- if (end_mom->main_part_ > now.main_part_
- && dynamic_cast<Item *> (g)
- && Note_head::has_interface (g))
- return g;
+ if (((end_mom->main_part_ > now.main_part_) ||
+ (include_grace_notes && end_mom->grace_part_ > now.grace_part_))
+ && dynamic_cast<Item *> (g)
+ && Note_head::has_interface (g))
+ {
+ return g;
+ }
}
return 0;
if (voice)
{
- Grob *head = get_current_note_head (voice);
+ bool include_grace_notes = to_boolean (get_property ("includeGraceNotes"));
+ Grob *head = get_current_note_head (voice, include_grace_notes);
if (head)
{
if (melisma_busy (voice)
&& !to_boolean (get_property ("ignoreMelismata")))
text_->set_property ("self-alignment-X",
- get_property("lyricMelismaAlignment"));
+ get_property ("lyricMelismaAlignment"));
}
else
{
/* read */
"ignoreMelismata "
+ "includeGraceNotes "
"lyricMelismaAlignment ",
/* write */
{
#define FUNC_NAME __FUNCTION__
SCM_VALIDATE_MODULE (1, src);
- scm_internal_hash_fold ((Hash_closure_function) & module_define_closure_func,
+ scm_internal_hash_fold ((scm_t_hash_fold_fn) &module_define_closure_func,
(void *) dest,
SCM_EOL, SCM_MODULE_OBARRAY (src));
return SCM_UNSPECIFIED;
Line_details compressed = orig[i];
Real padding = orig[i].title_ ? old.title_padding_ : old.padding_;
- compressed.extent_[DOWN] = old.extent_[DOWN];
- compressed.extent_[UP] = old.extent_[UP] + orig[i].extent_.length () + padding;
+ compressed.shape_ = old.shape_.piggyback (orig[i].shape_, padding);
compressed.space_ += old.space_;
compressed.inverse_hooke_ += old.inverse_hooke_;
}
}
+void
+Page_breaking::compute_line_heights ()
+{
+ Real prev_hanging = 0;
+ Real prev_hanging_begin = 0;
+ Real prev_hanging_rest = 0;
+ for (vsize i = 0; i < cached_line_details_.size (); i++)
+ {
+ Line_shape shape = cached_line_details_[i].shape_;
+ Real a = shape.begin_[UP];
+ Real b = shape.rest_[UP];
+ Real midline_hanging = max (prev_hanging_begin + a, prev_hanging_rest + b);
+ Real hanging_begin = midline_hanging - shape.begin_[DOWN];
+ Real hanging_rest = midline_hanging - shape.rest_[DOWN];
+ Real hanging = max (hanging_begin, hanging_rest);
+ cached_line_details_[i].tallness_ = hanging - prev_hanging;
+ prev_hanging = hanging;
+ prev_hanging_begin = hanging_begin;
+ prev_hanging_rest = hanging_rest;
+ }
+}
+
vsize
Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
{
int line_count = 0;
cache_line_details (configuration);
+ compute_line_heights ();
if (cached_line_details_.size ())
cur_page_height -= min_whitespace_at_top_of_page (cached_line_details_[0]);
for (vsize i = 0; i < cached_line_details_.size (); i++)
{
- Real ext_len = cached_line_details_[i].extent_.length ();
Real padding = 0;
+ Real ext_len;
if (cur_rod_height > 0)
- padding = cached_line_details_[i].title_ ?
- cached_line_details_[i-1].title_padding_ : cached_line_details_[i-1].padding_;
-
+ {
+ padding = cached_line_details_[i].title_ ?
+ cached_line_details_[i-1].title_padding_ :
+ cached_line_details_[i-1].padding_;
+ ext_len = cached_line_details_[i].tallness_;
+ }
+ else
+ {
+ ext_len = cached_line_details_[i].full_height();
+ }
Real next_rod_height = cur_rod_height + ext_len + padding;
Real next_spring_height = cur_spring_height + cached_line_details_[i].space_;
Real next_height = next_rod_height + (ragged () ? next_spring_height : 0)
&& cached_line_details_[i-1].page_permission_ == ly_symbol2scm ("force")))
{
line_count = cached_line_details_[i].compressed_nontitle_lines_count_;
- cur_rod_height = ext_len;
+ cur_rod_height = cached_line_details_[i].full_height();
cur_spring_height = cached_line_details_[i].space_;
page_starter = i;
if (!too_few_lines (line_count - cached_line_details_.back ().compressed_nontitle_lines_count_)
&& cur_height > cur_page_height
/* don't increase the page count if the last page had only one system */
- && cur_rod_height > cached_line_details_.back ().extent_.length ())
+ && cur_rod_height > cached_line_details_.back ().full_height ())
ret++;
assert (ret <= cached_line_details_.size ());
ly_symbol2scm ("padding"));
// FIXME: take into account the height of the header
- return max (0.0, max (padding, min_distance - line.extent_[UP]));
+ Real translate = max (line.shape_.begin_[UP], line.shape_.rest_[UP]);
+ return max (0.0, max (padding, min_distance - translate));
}
Real
ly_symbol2scm ("padding"));
// FIXME: take into account the height of the footer
- return max (0.0, max (padding, min_distance + line.extent_[DOWN]));
+ Real translate = min (line.shape_.begin_[DOWN], line.shape_.rest_[DOWN]);
+ return max (0.0, max (padding, min_distance + translate));
}
int
void
Page_spacing::append_system (const Line_details &line)
{
- if (!rod_height_)
- first_line_ = line;
-
+ if (rod_height_)
+ {
+ rod_height_ += line.tallness_;
+ }
+ else
+ {
+ rod_height_ += line.full_height ();
+ first_line_ = line;
+ }
rod_height_ += line.title_ ? last_line_.title_padding_ : last_line_.padding_;
-
- rod_height_ += line.extent_.length ();
spring_len_ += line.space_;
inverse_spring_k_ += line.inverse_hooke_;
else
last_line_ = line;
- rod_height_ += line.extent_.length ();
+ rod_height_ -= first_line_.full_height ();
+ rod_height_ += first_line_.tallness_;
+ rod_height_ += line.full_height();
spring_len_ += line.space_;
inverse_spring_k_ += line.inverse_hooke_;
%token MIDI "\\midi"
%token NAME "\\name"
%token NOTEMODE "\\notemode"
-%token OBJECTID "\\objectid"
%token OCTAVE "\\octave"
%token ONCE "\\once"
%token OVERRIDE "\\override"
%type <scm> number_expression
%type <scm> number_factor
%type <scm> number_term
-%type <scm> object_id_setting
%type <scm> octave_check
%type <scm> optional_context_mod
%type <scm> optional_id
;
-object_id_setting:
- OBJECTID STRING { $$ = $2; }
- ;
-
toplevel_expression:
lilypond_header {
PARSER->lexer_->set_identifier (ly_symbol2scm ("$defaultheader"), $1);
$$->scores_ = SCM_EOL;
$$->bookparts_ = SCM_EOL;
}
- | book_body object_id_setting {
- $$->user_key_ = ly_scm2string ($2);
- }
;
bookpart_block:
$$->paper_ = 0;
$$->scores_ = SCM_EOL;
}
- | bookpart_body object_id_setting {
- $$->user_key_ = ly_scm2string ($2);
- }
;
score_block:
$$->protect ();
$$->origin ()->set_spot (@$);
}
- | score_body object_id_setting {
- $$->user_key_ = ly_scm2string ($2);
- }
| score_body lilypond_header {
$$->set_header ($2);
}
static void
copy_scm_hashes (SCM dest, SCM src)
{
- scm_internal_hash_for_each_handle ( (SCM (*)(GUILE_ELLIPSIS)) ©_handle, dest, src);
+ scm_internal_hash_for_each_handle ((scm_t_hash_handle_fn) ©_handle,
+ dest, src);
}
Scheme_hash_table::Scheme_hash_table ()
SCM
Scheme_hash_table::to_alist () const
{
- return scm_internal_hash_fold ((SCM (*)(GUILE_ELLIPSIS)) &collect_handles, NULL, SCM_EOL, hash_tab_);
+ return scm_internal_hash_fold ((scm_t_hash_fold_fn) &collect_handles,
+ NULL, SCM_EOL, hash_tab_);
}
IMPLEMENT_SMOBS (Scheme_hash_table);
return sc->get_header ();
}
-
LY_DEFINE (ly_score_set_header_x, "ly:score-set-header!",
2, 0, 0, (SCM score, SCM module),
"Set the score header.")
LY_ASSERT_SMOB (Score, score, 1);
SCM_ASSERT_TYPE (ly_is_module (module), module, SCM_ARG2, __FUNCTION__,
"module");
-
+
Score *sc = unsmob_score (score);
sc->set_header (module);
return SCM_UNSPECIFIED;
}
-
LY_DEFINE (ly_score_music, "ly:score-music",
1, 0, 0, (SCM score),
"Return score music.")
2, 0, 0, (SCM score, SCM layout),
"Run @var{score} through @var{layout} (an output definition)"
" scaled to correct output-scale already, returning a list of"
- " layout-lines. This function takes an optional"
- " @code{Object_key} argument.")
+ " layout-lines.")
{
LY_ASSERT_SMOB (Score, score, 1);
LY_ASSERT_SMOB (Output_def, layout, 2);
ret.unite (d);
}
- ret.widen (height * 0.5);
+ // The +0.5 comes from the fact that we try to place a slur
+ // 0.5 staff spaces from the note-head.
+ // (see Slur_score_state.get_base_attachments ())
+ ret.widen (height * 0.5 + 0.5);
return ly_interval2scm (ret);
}
Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r, Spacing_options const *options)
{
Real min_dist = max (0.0, Paper_column::minimum_distance (l, r));
- Real ideal;
if (Paper_column::is_breakable (l) && Paper_column::is_breakable (r))
{
mlen = *dt;
Real incr = robust_scm2double (me->get_property ("spacing-increment"), 1);
+ Real space = incr * double (mlen.main_part_ / options->global_shortest_) * 0.8;
+ Spring spring = Spring (min_dist + space, min_dist);
- ideal = min_dist + incr * double (mlen.main_part_ / options->global_shortest_) * 0.8;
+ /*
+ By default, the spring will have an inverse_stretch_strength of space+min_dist.
+ However, we don't want stretchability to scale with min_dist or else an
+ empty first measure on a line (which has a large min_dist because of the clef)
+ will stretch much more than an empty measure later in the line.
+ */
+ spring.set_inverse_stretch_strength (space);
+ return spring;
}
- else
- {
- Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
- if (dt == Moment (0, 0))
- {
- /*
- In this case, Staff_spacing should handle the job,
- using dt when it is 0 is silly.
- */
- ideal = min_dist + 0.5;
- }
- else
- ideal = min_dist + options->get_duration_space (dt.main_part_);
+ Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
+ Real ideal;
+
+ if (dt == Moment (0, 0))
+ {
+ /*
+ In this case, Staff_spacing should handle the job,
+ using dt when it is 0 is silly.
+ */
+ ideal = min_dist + 0.5;
}
+ else
+ ideal = min_dist + options->get_duration_space (dt.main_part_);
+
return Spring (ideal, min_dist);
}
{
Real full_measure_extra_space = robust_scm2double (l->get_property ("full-measure-extra-space"), 1.0);
spring.set_distance (spring.distance () + full_measure_extra_space);
- spring.set_default_strength ();
+ spring.set_default_compress_strength ();
}
if (options->stretch_uniformly_ && l->break_status_dir () != RIGHT)
void
Spring::set_default_strength ()
+{
+ set_default_stretch_strength ();
+ set_default_compress_strength ();
+}
+
+void
+Spring::set_default_compress_strength ()
{
inverse_compress_strength_ = (distance_ >= min_distance_) ? distance_ - min_distance_ : 0;
- inverse_stretch_strength_ = distance_;
update_blocking_force ();
}
+void
+Spring::set_default_stretch_strength ()
+{
+ inverse_stretch_strength_ = distance_;
+}
+
Real
Spring::length (Real f) const
{
return 0;
}
+Interval
+System::part_of_line_pure_height (vsize start, vsize end, bool begin)
+{
+ Grob *alignment = get_vertical_alignment ();
+ if (!alignment)
+ {
+ programming_error("system does not have a vertical alignment");
+ return Interval();
+ }
+ extract_grob_set (alignment, "elements", staves);
+ vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+
+ Interval ret;
+ for (vsize i = 0; i < staves.size(); ++i)
+ {
+ Interval iv = begin?
+ Axis_group_interface::begin_of_line_pure_height (staves[i], start) :
+ Axis_group_interface::rest_of_line_pure_height (staves[i], start, end);
+ if (i<offsets.size())
+ iv.translate (offsets[i]);
+ ret.unite (iv);
+ }
+ return ret;
+}
+
+Interval
+System::begin_of_line_pure_height (vsize start, vsize end)
+{
+ return part_of_line_pure_height (start, end, true);
+}
+
+Interval
+System::rest_of_line_pure_height (vsize start, vsize end)
+{
+ return part_of_line_pure_height (start, end, false);
+}
+
ADD_INTERFACE (System,
"This is the top-level object: Each object in a score"
" ultimately has a @code{System} object as its X and"
printed as numbers, but only as extender lines.")
(implicitTimeSignatureVisibility ,vector? "break visibility for
the default time signature.")
+ (includeGraceNotes ,boolean? "Do not ignore grace notes for
+@rinternals{Lyrics}.")
(instrumentCueName ,markup? "The name to print if another
instrument is to be taken.")
(instrumentEqualizer ,procedure? "A function taking a string
harmonic-event hyphen-event laissez-vibrer-event mark-event
multi-measure-text-event note-grouping-event
pes-or-flexa-event repeat-tie-event spacing-section-event
- layout-instruction-event))
+ layout-instruction-event completize-extender-event))
(layout-instruction-event . (apply-output-event ))
(script-event . (articulation-event text-script-event))
(music->lily-string ?lyric-sequence parser)))
#f)))
-
+;; Silence internal event sent at end of each lyrics block
+(define-display-method CompletizeExtenderEvent (expr parser)
+ "")
rhythmic-event event))
))
+ (CompletizeExtenderEvent
+ . ((description . "Used internally to signal the end of a lyrics block to
+ensure extenders are completed correctly when a @code{Lyrics} context ends
+before its associated @code{Voice} context.")
+ (types . (general-music completize-extender-event event))
+ ))
+
(ContextChange
. ((description . "Change staves in Piano staff.
(cons (cons (car coords) (cadr coords))
(ly:list->offsets accum (cddr coords)))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; numbers
-
-(if (not (defined? 'nan?)) ;; guile 1.6 compat
- (define-public (nan? x) (not (or (< 0.0 x)
- (> 0.0 x)
- (= 0.0 x)))))
-
-(if (not (defined? 'inf?))
- (define-public (inf? x) (= (/ 1.0 x) 0.0)))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; intervals
(if (null? (cdr platform)) #f
(member (string-downcase (cadr platform)) '("95" "98" "me")))))
-(case PLATFORM
- ((windows)
- (define native-getcwd
- getcwd)
-
- (define (slashify x)
- (if (string-index x #\\)
- x
- (string-regexp-substitute
- "//*" "/"
- (string-regexp-substitute "\\\\" "/" x))))
-
- ;; FIXME: this prints a warning.
- (define-public (ly-getcwd)
- (slashify (native-getcwd))))
-
- (else
- (define-public ly-getcwd
- getcwd)))
+(define (slashify x)
+ (if (string-index x #\\)
+ x
+ (string-regexp-substitute
+ "//*" "/"
+ (string-regexp-substitute "\\\\" "/" x))))
+
+(define-public (ly-getcwd)
+ (if (eq? PLATFORM 'windows)
+ (slashify (getcwd))
+ (getcwd)))
(define-public (is-absolute? file-name)
(let ((file-name-length (string-length file-name)))
(call-with-output-string (lambda (p) (format p "uniqueContext~s" unique-counter))))
(define (lyric-combine-music sync music loc)
+ ;; CompletizeExtenderEvent is added following the last lyric in MUSIC
+ ;; to signal to the Extender_engraver that any pending extender should
+ ;; be completed if the lyrics end before the associated voice.
+ (append! (ly:music-property music 'elements)
+ (list (make-music 'CompletizeExtenderEvent)))
(make-music 'LyricCombineMusic
'element music
'associated-context sync
When the markup is formatted, then FUNCTION is called as follows
- (FUNCTION GROB PROPS ARG1 ARG2 ... )
+ (FUNCTION GROB PROPS ARG1 ARG2 ... )
GROB is the current grob, PROPS is a list of alists, and ARG1.. are
the rest of the arguments.
<==>
(markup \"foo\"
#:raise 0.2 #:hbracket #:bold \"bar\"
- #:override '(baseline-skip . 4)
+ #:override '(baseline-skip . 4)
#:bracket #:column (\"baz\" \"bazr\" \"bla\"))
Use `markup*' in a \\notemode context."
-
+
(car (compile-all-markup-expressions `(#:line ,body))))
(defmacro*-public markup* (#:rest body)
"Same as `markup', for use in a \\notes block."
`(ly:export (markup ,@body)))
-
-
+
+
(define (compile-all-markup-expressions expr)
"Return a list of canonical markups expressions, e.g.:
(#:COMMAND1 arg11 arg12 #:COMMAND2 arg21 arg22 arg23)
;;; (markup-command-signature raise-markup)
;;; ==> (#<primitive-procedure number?> #<procedure markup? (obj)>)
;;;
-;;; (markup-command-keyword raise-markup) ==> "scheme0-markup1"
-;;;
+;;; (markup-command-keyword raise-markup) ==> scheme0-markup1
+;;;
(define-public (markup-command-keyword markup-command)
- "Return markup-command's argument keyword, ie a string describing the command
- arguments, eg. \"scheme0markup1\""
+ "Return markup-command's argument keyword, ie a symbol describing the command
+ arguments, eg. scheme0-markup1"
(object-property markup-command 'markup-keyword))
(define-public (markup-command-signature-ref markup-command)
(define-public (markup-command-signature-set! markup-command signature)
"Set markup-command's signature and keyword (as object properties)"
(set-object-property! markup-command 'markup-signature signature)
- (set-object-property! markup-command 'markup-keyword
+ (set-object-property! markup-command 'markup-keyword
(markup-signature-to-keyword signature))
signature)
;; for reasons I don't get,
;; (case func ((markup?) .. )
;; doesn't work.
- (cond
+ (cond
((eq? func markup?) "markup")
((eq? func markup-list?) "markup-list")
(else "scheme"))
(markup-argument-list? (markup-command-signature (car arg))
(cdr arg)))))
-;;
-;;
;;
-;;
+;;
+;;
+;;
(define (markup-thrower-typecheck arg)
"typecheck, and throw an error when something amiss.
;;
;; good enough if you only use make-XXX-markup functions.
-;;
+;;
(define (cheap-markup? x)
(or (string? x)
(and (pair? x)
;;
;; replace by markup-thrower-typecheck for more detailed diagnostics.
-;;
+;;
(define-public markup? cheap-markup?)
;; utility
"DOCME"
(if (and (pair? stencils)
(ly:stencil? (car stencils)))
-
+
(if (and (pair? (cdr stencils))
(ly:stencil? (cadr stencils)))
(let* ((tail (stack-stencil-line space (cdr stencils)))
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 }
-\score {
- \new ChoirStaff <<
- \foo \foo \foo \foo
- \foo \foo \foo \foo
+foo = \new Staff \new Voice \repeat unfold 50 \relative c' { c4 d8[ d16( e]~ e16[ e e) f] g8 }
+\score {
+ \new ChoirStaff <<
+ \foo \foo \foo \foo
+ \foo \foo \foo \foo
>>
\midi {}
cat $a
done
-echo 'running gprof'
+echo 'running gprof'
gprof $exe > profile
exit 0
-I $depth/input/mutopia/W.A.Mozart/ \
$f
- echo 'running gprof'
+ echo 'running gprof'
if test -f gmon.sum ; then
gprof -s $exe gmon.out gmon.sum
else
s = open ('lily/lily-lexer.cc', 'r').read ()
keywords += [w for w in re.findall (r"\s*{\"(.+)\",\s*.*},\s*\n", s)]
-s = open ('scm/markup.scm', 'r').read ()
-keywords += [w for w in re.findall (r"(?m)^\s*\(cons\s*([a-z-]+)-markup", s)]
+# markup commands
+for name in ['ly/toc-init.ly',
+ 'scm/define-markup-commands.scm',
+ 'scm/fret-diagrams.scm',
+ 'scm/harp-pedals.scm']:
+ s = open (name, 'r').read ()
+ keywords += [w for w in re.findall (r"\(define-markup[a-z-]+\s+\(([a-zA-Z-]+)", s)]
# identifiers and keywords
for name in ['ly/chord-modifiers-init.ly',
'ly/scale-definitions-init.ly',
'ly/script-init.ly',
'ly/spanners-init.ly',
+ 'ly/toc-init.ly',
'ly/declarations-init.ly']:
s = open (name, 'r').read ()
keywords += [w for w in re.findall (r"(?m)^\s*\"?([a-zA-Z]+)\"?\s*=", s)]
'ly/english.ly',
'ly/espanol.ly',
'ly/italiano.ly',
+ 'ly/makam.ly',
'ly/nederlands.ly',
'ly/norsk.ly',
'ly/portugues.ly',
'//markup - { _ } -',
'//notes - { _ } -',
'//relative - % { _ } -',
- '//score - { //n /? //simultaneous { //n _ //n } /! //n //paper { } //n /? //midi { } //n /! } //n -',
+ '//score - { //n /? //simultaneous { //n _ //n } /! //n //layout { } //n /? //midi { } //n /! } //n -',
'//simultaneous - { _ } -',
- '//sustainDown - _ //sustainUp -',
+ '//sustainOn - _ //sustainOff -',
'//times - % { _ } -',
'//transpose - % { _ } -',
'']
f.write ('syn match lilyNote \"\\<\\(\\(\\(')
f.write (''.join ([w + '\\|' for w in note_names]))
- f.write ('a\\)\\([,\']\\)\\{,4}\\([?!]\\)\\?\\)\\|s\\|r\\)\\(\\(128\\|64\\|32\\|16\\|8\\|4\\|2\\|1\\|\\\\breve\\|\\\\longa\\|\\\\maxima\\)[.]\\{,8}\\)\\?\\(\\A\\|\\n\\)\"me=e-1\n')
+ f.write ('a\\)\\([,\']\\)\\{,4}\\([?!]\\)\\?\\)\\|s\\|r\\|R\\|q\\)\\(\\(128\\|64\\|32\\|16\\|8\\|4\\|2\\|1\\|\\\\breve\\|\\\\longa\\|\\\\maxima\\)[.]\\{,8}\\)\\?\\(\\A\\|\\n\\)\"me=e-1\n')
self.dir = tempfile.mkdtemp ()
print 'dir is', self.dir
def __del__ (self):
- print 'rm -rf %s' % self.dir
+ print 'rm -rf %s' % self.dir
os.system ('rm -rf %s' % self.dir)
def __call__ (self):
return self.dir
return
def shorten_string (s):
- threshold = 15
+ threshold = 15
if len (s) > 2*threshold:
s = s[:threshold] + '..' + s[-threshold:]
return s
for (p,q) in zip (x1, x2):
dist = max (abs (p-q), dist)
-
+
return dist
def compare_png_images (old, new, dest_dir):
def png_dims (f):
m = re.search ('([0-9]+) x ([0-9]+)', read_pipe ('file %s' % f))
-
+
return tuple (map (int, m.groups ()))
dest = os.path.join (dest_dir, new.replace ('.png', '.compare.jpeg'))
## hmmm. what to do?
system ('touch %(dest)s' % locals ())
return
-
+
dims = (min (dims1[0], dims2[0]),
min (dims1[1], dims2[1]))
return i[0] > i[1]
def interval_length (i):
- return max (i[1]-i[0], 0)
-
+ return max (i[1]-i[0], 0)
+
def interval_union (i1, i2):
return (min (i1[0], i2[0]),
max (i1[1], i2[1]))
def bbox_union (b1, b2):
return (interval_union (b1[X_AXIS], b2[X_AXIS]),
interval_union (b1[Y_AXIS], b2[Y_AXIS]))
-
+
def bbox_intersection (b1, b2):
return (interval_intersect (b1[X_AXIS], b2[X_AXIS]),
interval_intersect (b1[Y_AXIS], b2[Y_AXIS]))
def bbox_diameter (b):
return max (interval_length (b[X_AXIS]),
interval_length (b[Y_AXIS]))
-
+
def difference_area (a, b):
return bbox_area (a) - bbox_area (bbox_intersection (a,b))
def __init__ (self, exp_list):
(self.name, self.origin, bbox_x,
bbox_y, self.output_expression) = tuple (exp_list)
-
+
self.bbox = (bbox_x, bbox_y)
self.centroid = (bbox_x[0] + bbox_x[1], bbox_y[0] + bbox_y[1])
self.bbox[0][1],
self.bbox[1][0],
self.bbox[1][1])
-
+
def axis_centroid (self, axis):
- return apply (sum, self.bbox[axis]) / 2
-
+ return apply (sum, self.bbox[axis]) / 2
+
def centroid_distance (self, other, scale):
- return max_distance (self.centroid, other.centroid) / scale
-
+ return max_distance (self.centroid, other.centroid) / scale
+
def bbox_distance (self, other):
divisor = bbox_area (self.bbox) + bbox_area (other.bbox)
difference_area (other.bbox, self.bbox)) / divisor
else:
return 0.0
-
+
def expression_distance (self, other):
if self.output_expression == other.output_expression:
return 0
def __init__ (self, system1, system2):
self.system1 = system1
self.system2 = system2
-
+
self.link_list_dict = {}
self.back_link_dict = {}
self._geometric_distance = None
self._expression_change_count = None
self._orphan_count = None
-
+
for g in system1.grobs ():
## skip empty bboxes.
if bbox_is_empty (g.bbox):
continue
-
+
closest = system2.closest (g.name, g.centroid)
-
+
self.link_list_dict.setdefault (closest, [])
self.link_list_dict[closest].append (g)
self.back_link_dict[g] = closest
total += d
self._geometric_distance = total
-
+
def calc_orphan_count (self):
count = 0
for (g1, g2) in self.back_link_dict.items ():
if g2 == None:
self.orphans.append ((g1, None))
-
+
count += 1
self._orphan_count = count
-
+
def calc_output_exp_distance (self):
d = 0
for (g1,g2) in self.back_link_dict.items ():
def output_expression_details_string (self):
return ', '.join ([g1.name for g1 in self.expression_changed])
-
+
def geo_details_string (self):
results = [(d, g1,g2) for ((g1, g2), d) in self.geo_distances.items()]
results.sort ()
results.reverse ()
-
+
return ', '.join (['%s: %f' % (g1.name, d) for (d, g1, g2) in results])
def orphan_details_string (self):
if self._geometric_distance == None:
self.calc_geometric_distance ()
return self._geometric_distance
-
+
def orphan_count (self):
if self._orphan_count == None:
self.calc_orphan_count ()
-
+
return self._orphan_count
-
+
def output_expression_change_count (self):
if self._expression_change_count == None:
self.calc_output_exp_distance ()
return self._expression_change_count
-
+
def distance (self):
return (self.output_expression_change_count (),
self.orphan_count (),
self.geometric_distance ())
-
+
def read_signature_file (name):
print 'reading', name
-
+
entries = open (name).read ().split ('\n')
def string_to_tup (s):
- return tuple (map (float, s.split (' ')))
+ return tuple (map (float, s.split (' ')))
def string_to_entry (s):
fields = s.split('@')
fields[3] = string_to_tup (fields[3])
return tuple (fields)
-
+
entries = [string_to_entry (e) for e in entries
if e and not e.startswith ('#')]
def __init__ (self, f1, f2):
self._distance = None
self.file_names = (f1, f2)
-
+
def text_record_string (self):
return '%-30f %-20s\n' % (self.distance (),
self.name ()
+ os.path.splitext (self.file_names[1])[1]
)
-
+
def calc_distance (self):
return 0.0
self._distance = self.calc_distance ()
return self._distance
-
+
def source_file (self):
for ext in ('.ly', '.ly.txt'):
base = os.path.splitext (self.file_names[1])[0]
f = base + ext
if os.path.exists (f):
return f
-
+
return ''
-
+
def name (self):
base = os.path.basename (self.file_names[1])
base = os.path.splitext (base)[0]
base = hash_to_original_name.get (base, base)
base = os.path.splitext (base)[0]
return base
-
+
def extension (self):
return os.path.splitext (self.file_names[1])[1]
def get_cell (self, oldnew):
return ''
-
+
def get_file (self, oldnew):
return self.file_names[oldnew]
-
+
def html_record_string (self, dest_dir):
dist = self.distance()
-
+
details = self.get_distance_details ()
if details:
details_base = os.path.splitext (self.file_names[1])[0]
name = self.name () + self.extension ()
file1 = self.get_file (0)
file2 = self.get_file (1)
-
+
return '''<tr>
<td>
%(dist)f
FileLink.__init__ (self, f1, f2)
self.contents = (self.get_content (self.file_names[0]),
self.get_content (self.file_names[1]))
-
+
def calc_distance (self):
## todo: could use import MIDI to pinpoint
return 0.0
else:
return 100.0;
-
+
def get_content (self, f):
print 'reading', f
s = open (f).read ()
# truncate long lines
str = '\n'.join ([l[:80] for l in str.split ('\n')])
-
+
str = '<font size="-2"><pre>%s</pre></font>' % str
return str
-
+
def calc_distance (self):
if self.contents[0] == self.contents[1]:
d = 0.0
return d
-
+
class TextFileCompareLink (FileCompareLink):
def calc_distance (self):
import difflib
fromfiledate = self.file_names[0],
tofiledate = self.file_names[1]
)
-
+
self.diff_lines = [l for l in diff]
self.diff_lines = self.diff_lines[2:]
-
+
return math.sqrt (float (len ([l for l in self.diff_lines if l[0] in '-+'])))
-
+
def get_cell (self, oldnew):
str = ''
if oldnew == 1:
c = TextFileCompareLink.get_content (self, f)
c = re.sub ("\nProcessing `[^\n]+'\n", '', c)
return c
-
+
class ProfileFileLink (FileCompareLink):
def __init__ (self, f1, f2):
FileCompareLink.__init__ (self, f1, f2)
self.results = [{}, {}]
-
+
def get_cell (self, oldnew):
str = ''
for k in ('time', 'cells'):
self.get_ratio (k))
return '<pre>%s</pre>' % str
-
+
def get_ratio (self, key):
(v1,v2) = (self.results[0].get (key, -1),
self.results[1].get (key, -1))
return 0.0
return (v1 - v2) / float (v1+v2)
-
+
def calc_distance (self):
for oldnew in (0,1):
def note_info (m):
self.results[oldnew][m.group(1)] = float (m.group (2))
-
+
re.sub ('([a-z]+): ([-0-9.]+)\n',
note_info, self.contents[oldnew])
'time': 0.1,
'cells': 5.0,
}
-
+
for k in ('time', 'cells'):
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
-
+
class MidiFileLink (TextFileCompareLink):
def get_content (self, oldnew):
import midi
-
+
data = FileCompareLink.get_content (self, oldnew)
midi = midi.parse (data)
tracks = midi[1]
ev_str = repr (e)
if re.search ('LilyPond [0-9.]+', ev_str):
continue
-
+
str += ' ev %s\n' % `e`
return str
-
+
class SignatureFileLink (FileLink):
for l in self.system_links.values ():
d = max (d, l.geometric_distance ())
orphan_distance += l.orphan_count ()
-
+
return d + orphan_distance
def add_file_compare (self, f1, f2):
- system_index = []
+ system_index = []
def note_system_index (m):
system_index.append (int (m.group (1)))
return ''
-
+
base1 = re.sub ("-([0-9]+).signature", note_system_index, f1)
base2 = re.sub ("-([0-9]+).signature", note_system_index, f2)
self.add_system_link (link, system_index[0])
-
+
def create_images (self, dest_dir):
files_created = [[], []]
if options.local_data_dir:
data_option = ('-slilypond-datadir=%s/share/lilypond/current '
% os.path.dirname(infile))
-
+
mkdir (os.path.split (outfile)[0])
cmd = ('gs -sDEVICE=png16m -dGraphicsAlphaBits=4 -dTextAlphaBits=4 '
' %(data_option)s '
system (cmd)
return files_created
-
+
def link_files_for_html (self, dest_dir):
FileLink.link_files_for_html (self, dest_dir)
to_compare = [[], []]
to_compare = self.create_images (dest_dir)
else:
exts += ['.png', '-page*png']
-
- for ext in exts:
+
+ for ext in exts:
for oldnew in (0,1):
for f in glob.glob (self.base_names[oldnew] + ext):
dst = dest_dir + '/' + f
if f.endswith ('.png'):
to_compare[oldnew].append (f)
-
- if options.compare_images:
+
+ if options.compare_images:
for (old, new) in zip (to_compare[0], to_compare[1]):
compare_png_images (old, new, dest_dir)
name = 'source'
else:
name = '<tt>%s</tt>' % name
-
+
return '''
<a href="%(img)s">
<img src="%(img)s" style="border-style: none; max-width: 500px;">
imgs_str = '\n'.join (['''<a href="%s">
<img src="%s" style="border-style: none; max-width: 500px;">
-</a><br>''' % (img, img)
+</a><br>''' % (img, img)
for img in imgs])
- str = cell (os.path.splitext (self.file_names[oldnew])[0], self.name ())
+ str = cell (os.path.splitext (self.file_names[oldnew])[0], self.name ())
if options.compare_images and oldnew == 1:
str = str.replace ('.png', '.compare.jpeg')
-
+
return str
e = '<td>%d</td>' % c
for d in link.distance ():
e += '<td>%f</td>' % d
-
+
e = '<tr>%s</tr>' % e
html += e
link.geo_details_string ()):
e += "<td>%s</td>" % s
-
+
e = '<tr>%s</tr>' % e
html += e
-
+
original = self.name ()
html = '''<html>
<head>
def compare_signature_files (f1, f2):
s1 = read_signature_file (f1)
s2 = read_signature_file (f2)
-
+
return SystemLink (s1, s2).distance ()
def paired_files (dir1, dir2, pattern):
found = [os.path.split (f)[1] for f in glob.glob (d + '/' + pattern)]
found = dict ((f, 1) for f in found)
files.append (found)
-
+
pairs = []
missing = []
for f in files[0]:
missing.append (f)
return (pairs, files[1].keys (), missing)
-
+
class ComparisonData:
def __init__ (self):
self.result_dict = {}
## ugh: drop the .ly.txt
for (key, val) in self.file_links.items ():
-
+
def note_original (match, ln=val):
key = ln.name ()
hash_to_original_name[key] = match.group (1)
note_original, open (sf).read ())
else:
print 'no source for', val
-
+
def compare_trees (self, dir1, dir2):
self.compare_directories (dir1, dir2)
-
+
(root, dirs, files) = os.walk (dir1).next ()
for d in dirs:
d1 = os.path.join (dir1, d)
if os.path.islink (d1) or os.path.islink (d2):
continue
-
+
if os.path.isdir (d2):
self.compare_trees (d1, d2)
-
+
def compare_directories (self, dir1, dir2):
for ext in ['signature',
'midi',
'gittxt']:
(paired, m1, m2) = paired_files (dir1, dir2, '*.' + ext)
- self.missing += [(dir1, m) for m in m1]
- self.added += [(dir2, m) for m in m2]
+ self.missing += [(dir1, m) for m in m1]
+ self.added += [(dir2, m) for m in m2]
for p in paired:
if (options.max_count
and len (self.file_links) > options.max_count):
continue
-
+
f2 = dir2 + '/' + p
f1 = dir1 + '/' + p
self.compare_files (f1, f2)
'.midi': MidiFileLink,
'.log' : LogFileCompareLink,
'.profile': ProfileFileLink,
- '.gittxt': GitFileCompareLink,
+ '.gittxt': GitFileCompareLink,
}
-
+
if klasses.has_key (ext):
self.compare_general_files (klasses[ext], f1, f2)
file_link = klass (f1, f2)
self.file_links[name] = file_link
-
+
def compare_signature_files (self, f1, f2):
name = os.path.split (f1)[1]
name = re.sub ('-[0-9]+.signature', '', name)
-
+
file_link = None
try:
file_link = self.file_links[name]
str = '\n'.join ([os.path.splitext (link.file_names[1])[0]
for link in changed])
fn = dest_dir + '/changed.txt'
-
+
open_write_file (fn).write (str)
-
+
def thresholded_results (self, threshold):
## todo: support more scores.
results = [(link.distance(), link)
changed = [r for (d,r) in results if d > threshold]
return (changed, below, unchanged)
-
+
def write_text_result_page (self, filename, threshold):
out = None
if filename == '':
(changed, below, unchanged) = self.thresholded_results (threshold)
-
+
for link in changed:
out.write (link.text_record_string ())
out.write ('\n\n')
out.write ('%d below threshold\n' % len (below))
out.write ('%d unchanged\n' % len (unchanged))
-
+
def create_text_result_page (self, dir1, dir2, dest_dir, threshold):
self.write_text_result_page (dest_dir + '/index.txt', threshold)
-
+
def create_html_result_page (self, dir1, dir2, dest_dir, threshold):
dir1 = dir1.replace ('//', '/')
dir2 = dir2.replace ('//', '/')
if below_count:
html += ('<p>%d below threshold</p>' % below_count)
-
+
html += ('<p>%d unchanged</p>' % len (unchanged))
dest_file = dest_dir + '/index.html'
for link in changed:
link.link_files_for_html (dest_dir)
-
+
def print_results (self, threshold):
self.write_text_result_page ('', threshold)
data.compare_trees (dir1, dir2)
data.read_sources ()
-
+
data.print_results (threshold)
if os.path.isdir (dest_dir):
data.write_changed (dest_dir, threshold)
data.create_html_result_page (dir1, dir2, dest_dir, threshold)
data.create_text_result_page (dir1, dir2, dest_dir, threshold)
-
+
################################################################
# TESTING
except OSError, z:
print 'OSError', x, y, z
raise OSError
-
+
def open_write_file (x):
d = os.path.split (x)[0]
mkdir (d)
def system (x):
-
+
print 'invoking', x
stat = os.system (x)
assert stat == 0
def test_paired_files ():
print paired_files (os.environ["HOME"] + "/src/lilypond/scripts/",
os.environ["HOME"] + "/src/lilypond-stable/scripts/build/", '*.py')
-
-
+
+
def test_compare_trees ():
system ('rm -rf dir1 dir2')
system ('mkdir dir1 dir2')
system ('cp 20multipage* dir2')
system ('cp 19multipage-1.signature dir2/20multipage-1.signature')
-
+
system ('mkdir -p dir1/subdir/ dir2/subdir/')
system ('cp 19.sub{-*.signature,.ly,.png,.eps,.log,.profile} dir1/subdir/')
system ('cp 19.sub{-*.signature,.ly,.png,.eps,.log,.profile} dir2/subdir/')
#(ly:set-option (quote no-point-and-click))
\sourcefilename "my-source.ly"
-
+
%(papermod)s
\header { tagline = ##f }
\score {
for d in dicts:
open (d['name'] + '.ly','w').write (ly_template % d)
-
+
names = [d['name'] for d in dicts]
system ('lilypond -ddump-profile -dseparate-log-files -ddump-signatures --png -dbackend=eps ' + ' '.join (names))
-
+
multipage_str = r'''
#(set-default-paper-size "a6")
\score {
- \relative {c1 \pageBreak c1 }
+ \relative c' { c1 \pageBreak c1 }
\layout {}
\midi {}
}
open ('20multipage.ly', 'w').write (multipage_str.replace ('c1', 'd1'))
open ('19multipage.ly', 'w').write ('#(set-global-staff-size 19.5)\n' + multipage_str)
system ('lilypond -dseparate-log-files -ddump-signatures --png 19multipage 20multipage ')
-
+
test_compare_signatures (names)
-
+
def test_compare_signatures (names, timing=False):
import time
if do_clean:
system ('rm -rf ' + dir)
system ('mkdir ' + dir)
-
+
os.chdir (dir)
if do_clean:
test_basic_compare ()
-
+
test_compare_trees ()
-
+
################################################################
#
def main ():
p = optparse.OptionParser ("output-distance - compare LilyPond formatting runs")
p.usage = 'output-distance.py [options] tree1 tree2'
-
+
p.add_option ('', '--test-self',
dest="run_test",
action="store_true",
help='run test method')
-
+
p.add_option ('--max-count',
dest="max_count",
metavar="COUNT",
type="int",
- default=0,
+ default=0,
action="store",
help='only analyze COUNT signature pairs')
if not name:
name = args[0].replace ('/', '')
name = os.path.join (args[1], 'compare-' + shorten_string (name))
-
+
compare_trees (args[0], args[1], name, options.threshold)
if __name__ == '__main__':