]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'master' of /home/jcharles/GIT/Lily/. into translation
authorJean-Charles Malahieude <lilyfan@orange.fr>
Sat, 11 Jun 2016 12:26:38 +0000 (14:26 +0200)
committerJean-Charles Malahieude <lilyfan@orange.fr>
Sat, 11 Jun 2016 12:26:38 +0000 (14:26 +0200)
304 files changed:
Documentation/ca/web/community.itexi
Documentation/contributor/release-work.itexi
Documentation/contributor/source-code.itexi
Documentation/cs/learning/common-notation.itely
Documentation/cs/web/community.itexi
Documentation/de/notation/rhythms.itely
Documentation/de/web/community.itexi
Documentation/es/web/community.itexi
Documentation/es/web/news.itexi
Documentation/fr/learning/common-notation.itely
Documentation/fr/notation/cheatsheet.itely
Documentation/fr/notation/input.itely
Documentation/fr/notation/rhythms.itely
Documentation/fr/web/community.itexi
Documentation/hu/web/community.itexi
Documentation/it/web/community.itexi
Documentation/ja/web/community.itexi
Documentation/misc/announce-v2.0.html
Documentation/music-glossary.tely
Documentation/snippets/contemporary-notation.snippet-list
Documentation/snippets/customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly [new file with mode: 0644]
Documentation/snippets/flat-ties.ly [new file with mode: 0644]
Documentation/snippets/midi.snippet-list
Documentation/snippets/obtaining-2.12-lyrics-spacing-in-newer-versions.ly
Documentation/snippets/percussion.snippet-list
Documentation/snippets/piano-template-with-centered-lyrics.ly
Documentation/snippets/pitches.snippet-list
Documentation/snippets/scheme-language.snippet-list
Documentation/snippets/simultaneous-notes.snippet-list
Documentation/snippets/specific-notation.snippet-list
Documentation/snippets/staff-notation.snippet-list
Documentation/snippets/tweaks-and-overrides.snippet-list
Documentation/snippets/two--partcombine-pairs-on-one-staff.ly [new file with mode: 0644]
Documentation/topdocs/README.texi
Documentation/web/community.itexi
Documentation/web/manuals.itexi
Documentation/web/news-front.itexi
Documentation/web/news.itexi
Documentation/zh/web/community.itexi
VERSION
aclocal.m4
lily/accidental-engraver.cc
lily/all-font-metrics.cc
lily/ambitus-engraver.cc
lily/arpeggio-engraver.cc
lily/auto-beam-engraver.cc
lily/axis-group-engraver.cc
lily/axis-group-interface.cc
lily/balloon-engraver.cc
lily/bar-engraver.cc
lily/bar-number-engraver.cc
lily/beam-collision-engraver.cc
lily/beam-engraver.cc
lily/beam-performer.cc
lily/bend-engraver.cc
lily/book-scheme.cc
lily/box.cc
lily/break-align-engraver.cc
lily/breathing-sign-engraver.cc
lily/callback.cc [deleted file]
lily/chord-name-engraver.cc
lily/chord-tremolo-engraver.cc
lily/clef-engraver.cc
lily/cluster-engraver.cc
lily/collision-engraver.cc
lily/completion-note-heads-engraver.cc
lily/completion-rest-engraver.cc
lily/concurrent-hairpin-engraver.cc
lily/context-def.cc
lily/context-mod.cc
lily/context-property.cc
lily/context.cc
lily/control-track-performer.cc
lily/cue-clef-engraver.cc
lily/custos-engraver.cc
lily/default-bar-line-engraver.cc
lily/dispatcher.cc
lily/dot-column-engraver.cc
lily/dots-engraver.cc
lily/double-percent-repeat-engraver.cc
lily/drum-note-engraver.cc
lily/drum-note-performer.cc
lily/duration.cc
lily/dynamic-align-engraver.cc
lily/dynamic-engraver.cc
lily/dynamic-performer.cc
lily/engraver.cc
lily/episema-engraver.cc
lily/extender-engraver.cc
lily/figured-bass-engraver.cc
lily/figured-bass-position-engraver.cc
lily/fingering-column-engraver.cc
lily/fingering-engraver.cc
lily/font-metric.cc
lily/font-size-engraver.cc
lily/footnote-engraver.cc
lily/forbid-break-engraver.cc
lily/fretboard-engraver.cc
lily/glissando-engraver.cc
lily/grace-engraver.cc
lily/grace-spacing-engraver.cc
lily/grid-line-span-engraver.cc
lily/grid-point-engraver.cc
lily/grob-array.cc
lily/grob-pq-engraver.cc
lily/grob-smob.cc
lily/horizontal-bracket-engraver.cc
lily/hyphen-engraver.cc
lily/include/all-font-metrics.hh
lily/include/book.hh
lily/include/box.hh
lily/include/callback.hh
lily/include/coherent-ligature-engraver.hh
lily/include/context-def.hh
lily/include/context-mod.hh
lily/include/context.hh
lily/include/dispatcher.hh
lily/include/duration.hh
lily/include/engraver.hh
lily/include/font-metric.hh
lily/include/gregorian-ligature-engraver.hh
lily/include/grob-array.hh
lily/include/grob-interface.hh
lily/include/grob.hh
lily/include/input.hh
lily/include/ligature-engraver.hh
lily/include/lily-imports.hh
lily/include/lily-lexer.hh
lily/include/lily-parser.hh
lily/include/lily-proto.hh
lily/include/listener.hh
lily/include/misc.hh
lily/include/moment.hh
lily/include/music-function.hh
lily/include/music-iterator.hh
lily/include/music-output.hh
lily/include/output-def.hh
lily/include/page-marker.hh
lily/include/paper-book.hh
lily/include/paper-column-engraver.hh
lily/include/paper-outputter.hh
lily/include/performer.hh
lily/include/pitch.hh
lily/include/prob.hh
lily/include/protected-scm.hh
lily/include/scale.hh
lily/include/scheme-engraver.hh
lily/include/scm-hash.hh
lily/include/score.hh
lily/include/skyline-pair.hh
lily/include/skyline.hh
lily/include/slur-proto-engraver.hh
lily/include/smobs.hh
lily/include/smobs.tcc
lily/include/source-file.hh
lily/include/spring.hh
lily/include/stencil.hh
lily/include/translator-dispatch-list.hh
lily/include/translator-group.hh
lily/include/translator.hh
lily/include/translator.icc
lily/include/unpure-pure-container.hh
lily/input-smob.cc
lily/instrument-name-engraver.cc
lily/instrument-switch-engraver.cc
lily/keep-alive-together-engraver.cc
lily/key-engraver.cc
lily/key-performer.cc
lily/kievan-ligature-engraver.cc
lily/laissez-vibrer-engraver.cc
lily/ledger-line-engraver.cc
lily/ligature-bracket-engraver.cc
lily/lily-imports.cc
lily/lily-lexer.cc
lily/lily-parser.cc
lily/listener.cc
lily/lookup.cc
lily/lyric-engraver.cc
lily/lyric-performer.cc
lily/mark-engraver.cc
lily/measure-grouping-engraver.cc
lily/melody-engraver.cc
lily/mensural-ligature-engraver.cc
lily/metronome-engraver.cc
lily/midi-control-function-performer.cc
lily/misc.cc
lily/moment.cc
lily/multi-measure-rest-engraver.cc
lily/music-function.cc
lily/music-iterator.cc
lily/music-output.cc
lily/new-fingering-engraver.cc
lily/note-head-line-engraver.cc
lily/note-heads-engraver.cc
lily/note-name-engraver.cc
lily/note-performer.cc
lily/note-spacing-engraver.cc
lily/open-type-font-scheme.cc
lily/ottava-engraver.cc
lily/output-def-scheme.cc
lily/output-property-engraver.cc
lily/page-marker.cc
lily/page-turn-engraver.cc
lily/paper-book.cc
lily/paper-column-engraver.cc
lily/paper-outputter.cc
lily/parenthesis-engraver.cc
lily/parser.yy
lily/part-combine-engraver.cc
lily/percent-repeat-engraver.cc
lily/pfb-scheme.cc
lily/phrasing-slur-engraver.cc
lily/piano-pedal-align-engraver.cc
lily/piano-pedal-engraver.cc
lily/piano-pedal-performer.cc
lily/pitch-squash-engraver.cc
lily/pitch.cc
lily/pitched-trill-engraver.cc
lily/prob.cc
lily/protected-scm.cc
lily/pure-from-neighbor-engraver.cc
lily/repeat-acknowledge-engraver.cc
lily/repeat-tie-engraver.cc
lily/rest-collision-engraver.cc
lily/rest-engraver.cc
lily/rhythmic-column-engraver.cc
lily/scale.cc
lily/scheme-engraver.cc
lily/scm-hash.cc
lily/score-engraver.cc
lily/score-performer.cc
lily/score.cc
lily/script-column-engraver.cc
lily/script-engraver.cc
lily/script-row-engraver.cc
lily/separating-line-group-engraver.cc
lily/skyline-pair.cc
lily/skyline.cc
lily/slash-repeat-engraver.cc
lily/slur-engraver.cc
lily/slur-performer.cc
lily/source-file.cc
lily/spacing-engraver.cc
lily/span-arpeggio-engraver.cc
lily/span-bar-engraver.cc
lily/span-bar-stub-engraver.cc
lily/spanner-break-forbid-engraver.cc
lily/spring-smob.cc
lily/staff-collecting-engraver.cc
lily/staff-performer.cc
lily/staff-symbol-engraver.cc
lily/stanza-number-align-engraver.cc
lily/stanza-number-engraver.cc
lily/stem-engraver.cc
lily/stencil.cc
lily/system-start-delimiter-engraver.cc
lily/tab-note-heads-engraver.cc
lily/tab-staff-symbol-engraver.cc
lily/tab-tie-follow-engraver.cc
lily/tempo-performer.cc
lily/text-engraver.cc
lily/text-spanner-engraver.cc
lily/tie-engraver.cc
lily/tie-performer.cc
lily/time-signature-engraver.cc
lily/time-signature-performer.cc
lily/timing-translator.cc
lily/translator-dispatch-list.cc
lily/translator-group.cc
lily/translator.cc
lily/trill-spanner-engraver.cc
lily/tuplet-engraver.cc
lily/tweak-engraver.cc
lily/undead.cc
lily/unpure-pure-container.cc
lily/vaticana-ligature-engraver.cc
lily/vertical-align-engraver.cc
lily/volta-engraver.cc
ly/Welcome-to-LilyPond-MacOS.ly
ly/Welcome_to_LilyPond.ly
ly/articulate.ly
mf/99-lilypond-fonts.conf.in
mf/feta-flags.mf
po/lilypond.pot
python/musicexp.py
python/musicxml.py
python/musicxml2ly_conversion.py [new file with mode: 0644]
python/utilities.py [new file with mode: 0644]
scm/chord-entry.scm
scm/define-context-properties.scm
scm/define-event-classes.scm
scm/define-music-display-methods.scm
scm/define-note-names.scm
scm/framework-ps.scm
scm/lily.scm
scm/output-ps.scm
scm/output-svg.scm
scripts/build/create-weblinks-itexi.py
scripts/midi2ly.py
scripts/musicxml2ly.py
stepmake/stepmake/executable-rules.make
stepmake/stepmake/test-rules.make
tex/texinfo.tex
vim/lilypond-ftplugin.vim

index ca5d0e41206e7dabaf73123b7011537e2cd2453f..8264c97144c5660539fdaaf97eed37ceb8fe47a3 100644 (file)
@@ -780,7 +780,7 @@ Les proves del lilpond-book d'aquesta versió.
 @itemize
 @item @uref{http://lilypond.org/test, Comparacions entre proves de regressió}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Arxiu de totes les proves de regressió}
 
 @end itemize
index 3869505630435d485154fbee19250a5d8041a8bc..a2e3cb15d5e7e171c7f77c99cca4263e9444d2be 100644 (file)
@@ -612,7 +612,7 @@ Download the test output from lilypond.org (you will need to
 replace @code{2.15.33-1} with the latest build):
 
 @smallexample
-@uref{http://lilypond.org/download/binaries/test-output/lilypond-2.15.33-1.test-output.tar.bz2}
+@uref{http://lilypond.org/downloads/binaries/test-output/lilypond-2.15.33-1.test-output.tar.bz2}
 @end smallexample
 
 Copy the tarball into @file{gub/regtests/}, and tell the build
index 9541fe963a775bcabe1ef4ed841cd6cf9e800bc5..8e07f9fb06309632c717c11225006f8533c17077 100644 (file)
@@ -628,7 +628,7 @@ repository from GitHub.  Ensure that the tarball has the correct Version
 number.
 
 @item
-Copy the tarball to @code{http://lilypond.org/download/gub-sources/lilypad/}.
+Copy the tarball to @code{http://lilypond.org/downloads/gub-sources/lilypad/}.
 You will need to have SSH access to @code{lilypond.org}.  If you do not, contact
 the Release Manager via the lilypond-devel mailing list.
 
index 188dae02d4b8a02c119f93f68dc0ba586fcac756..f9f4f68ae7266435c22eb821f408bf7f75200f26 100644 (file)
@@ -558,7 +558,7 @@ Slovníček: @rglos{grace notes}, @rglos{acciaccatura},
 
 Melodické ozdoby se zadávají příkazem @code{\grace}, ačkoli se také dají
 vytvářet uvozením hudebního výrazu příkazem @code{\appoggiatura} (dlouhý
-příraz, prodleva) a @code{\acciaccatura} (příraz, krátká appogiatura).
+příraz, prodleva) a @code{\acciaccatura} (příraz, krátká appoggiatura).
 
 @lilypond[verbatim,quote]
 \relative {
index 14705906f8b73d62e7e014dfaf8edfae305edcdf..062f780c4858720fd74ee27f30448efe567c14de 100644 (file)
@@ -620,7 +620,7 @@ lilypond-book-Zkoušky této verze.
 @itemize
 @item @uref{http://lilypond.org/test, Porovnání dvou verzí}:
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archiv všech zkoušek regresí}
 
 @end itemize
index a87acd3a5d04ab6e2c6e0e205f8b8ccad092ba4b..8e5c266ae09b2c310060b9e9d91b14f17434bab4 100644 (file)
@@ -3349,7 +3349,7 @@ Referenz der Interna:
 @funindex \grace
 @funindex \slashedGrace
 @funindex \acciaccatura
-@funindex \appoggiature
+@funindex \appoggiatura
 
 @cindex Verzierungen
 @cindex Ziernoten
@@ -3370,7 +3370,7 @@ keine logische Zeit im Takt ein.
 
 Es gibt drei Arten von Verzierungen:
 den Vorschlag (engl. acciaccatura), eine angebundene Verzierungsnote
-mit einem Schrägstrich durch den Hals, und den Vorhalt (engl. appogiatura),
+mit einem Schrägstrich durch den Hals, und den Vorhalt (engl. appoggiatura),
 welcher den Wert der Hauptnote um seinen eigenen Wert verkürzt und
 ohne Schrägstrich notiert wird.  Man kann einen Vorschlag auch mit
 Schrägstrich durch den Hals, aber ohne Legatobogen notieren.  Diese
index eabe6754c40deb6962f6727420c09a9b38a3fd29..de6578eec86abfb082532a160e104ba0de2dbc4f 100644 (file)
@@ -799,7 +799,7 @@ lilypond-book-Tests dieser Version.
 @itemize
 @item @uref{http://lilypond.org/test, Vergleiche zweier Versionen}:
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archiv aller Regressionstests}
 
 @end itemize
index 2e2d994ed3ff120d4c3e7f8761122c633b7c5f14..cdbf9c870dfb1973e884fa8fee694c7139338fa2 100644 (file)
@@ -788,7 +788,7 @@ Las pruebas de lilypond-book de esta versión.
 @itemize
 @item @uref{http://lilypond.org/test, Comparaciones entre pruebas de regresión}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archivo de todas las pruebas de regresión}
 
 @end itemize
@@ -1059,7 +1059,7 @@ Carl Sorensen
 Para barras de corchea normales, de pentagrama cruzado,
 interrumpidas y en ángulo.  El barrado debería depender del
 contexto y de las notas vecinas (véase la sección 2.2 de
-@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon,_Jean-Pierre%29,
+@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon%2C_Jean-Pierre%29,
 este libro}).  Si es posible, reducir el tiempo de cálculo del
 barrado.
 
index 9f2bc23ea2c3f0a24e9d4b296efadf6c68122d08..60497e625bfb2ca434cbeab92438e9c804759e8c 100644 (file)
@@ -3467,7 +3467,7 @@ and lots of updates for the translations.
 
 Release 2.11.28 is now available as a binary installer for
 FreeBSD x86_64.  Download
-@uref{http://lilypond.org/download/binaries/freebsd-64/,the installer} and
+@uref{http://lilypond.org/downloads/binaries/freebsd-64/,the installer} and
 do @emph{sh lilypond-2.11.28-1.freebsd-64.sh} in a command window.
 @newsEnd
 
@@ -4360,11 +4360,11 @@ to the @ref{Descargas antiguas} get them!
 Starting with 2.7.26, the development team has been working on the
 installers. We're proud to announce another version of these: they are
 now available for
-@uref{http://lilypond.org/download/binaries/linux-x86/,
+@uref{http://lilypond.org/downloads/binaries/linux-x86/,
 Linux/x86},
-@uref{http://lilypond.org/download/binaries/darwin-ppc/,
+@uref{http://lilypond.org/downloads/binaries/darwin-ppc/,
 MacOS X} and
-@uref{http://lilypond.org/download/binaries/mingw/,
+@uref{http://lilypond.org/downloads/binaries/mingw/,
 Windows}.
 @newsEnd
 
index 43b221956b17bcb1deeadd4bcdd6b7a8eaf949ff..909ec9b7abc373b9ad715d420065a10e7f540239 100644 (file)
@@ -715,7 +715,7 @@ que deux ; un @notation{triolet} portera donc une fraction de 3/2.
 Glossaire musicologique :
 @rglosnamed{grace notes,ornements},
 @rglosnamed{acciaccatura,acciaccature},
-@rglosnamed{appoggiatura,appogiature}.
+@rglosnamed{appoggiatura,appoggiature}.
 
 Des @notation{notes d'ornement} s'obtiennent en appliquant la commande
 @code{\grace}, @code{\appoggiatura} ou @code{\acciaccatura} à une
index 37bd09c7650038d6c2b442cef6bb8e58790db50a..b147dcd852458c978c5c408b9458b07d6bbbe623 100644 (file)
@@ -240,7 +240,7 @@ f8 c2 d e
 
 
 @item @code{\grace}
-@tab appogiatures
+@tab appoggiatures
 @tab
 @lilypond[relative=2]
 \set Staff.initialTimeSignatureVisibility = #all-invisible
index f0665906f40b22962bf3024ea510025b01f65c43..040e7eb79b5df8ddb2f5568c934329b70e876625 100644 (file)
@@ -3036,7 +3036,7 @@ En combinaison avec le script @file{articulate}, d'autres éléments
 seront aussi reportés en MIDI :
 
 @itemize
-@item les appogiatures -- celles-ci prendront la moitié de la valeur,
+@item les appoggiatures -- celles-ci prendront la moitié de la valeur,
 dépourvue de point, de la note qui les suit --  par exemple,
 
 @example
index c23e2bfc865242fa53dc76f43b1e8294b522446d..197f40b1fde977d9dfdec77ca2d788b08216f9bb 100644 (file)
@@ -3635,8 +3635,8 @@ désactivés dans cette même expression.
 @seealso
 Glossaire musicologique :
 @rglosnamed{grace notes,ornements},
-@rglosnamed{acciaccatura,acciacature},
-@rglosnamed{appoggiatura,appogiature}.
+@rglosnamed{acciaccatura,acciaccature},
+@rglosnamed{appoggiatura,appoggiature}.
 
 Manuel de notation :
 @ref{Barres de ligature manuelles},
index 7a44948fc30070d0e11ec505ea7377f3279180e7..98cf3dc3b03c29e4c744c06581342a94c15ac691 100644 (file)
@@ -824,7 +824,7 @@ Test de lilypond-book} relatifs à ce niveau de mise à jour
 @item @uref{http://lilypond.org/test,
 Comparaison entre différentes versions}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archive de tous les tests de régression}
 
 @end itemize
@@ -1092,7 +1092,7 @@ LilyPond
 Une ligature, qu'elle soit rectiligne, passe d'une portée à l'autre,
 discontinue ou coudée, devrait dépendre du contexte et des notes
 adjacentes (voir
-@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon,_Jean-Pierre%29,
+@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon%2C_Jean-Pierre%29,
 la section 2.2 de cet article}).  Dans la mesure du possible, raccourcir
 le temps de calcul nécessaire à la génération des ligatures.
 
index 864020d948f0e8cc337aa57617dd15174196d4ed..73efbec681b5a4ad86974676b1e3ea6bd3177c39 100644 (file)
@@ -652,7 +652,7 @@ A lilypond-book tesztjei.
 @itemize
 @item @uref{http://lilypond.org/test, Összehasonlítás}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archívum}
 
 @end itemize
index 53e1dba95551bf640624930797e3018ae0fcd0d6..3ff3be32bb2d14671528eb4aba0c8a4cbe36ee97 100644 (file)
@@ -760,7 +760,7 @@ I collaudi lilypond-book per questa versione.
 @itemize
 @item @uref{http://lilypond.org/test, Confronto tra i collaudi di regressione}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archivio di tutti i collaudi di regressione}
 
 @end itemize
index 212c7d401e99209a8743195e5d66820529f2c385..8be2657353efa65c9e4f7781e702c3eb6e625f59 100644 (file)
@@ -770,7 +770,7 @@ LilyPond の開発手法はかなり複雑です。@c
 @itemize
 @item @uref{http://lilypond.org/test, バージョン間での回帰テストの比較}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 すべての回帰テストのアーカイブ}
 
 @end itemize
@@ -1027,7 +1027,7 @@ Carl Sorensen
 
 For regular, cross-staff, broken and kneed beams.  Beaming should depend
 on context and neighbor notes (see section 2.2 of
-@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon,_Jean-Pierre%29,
+@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon%2C_Jean-Pierre%29,
 this book}).  If possible also reduce beaming-computation time.
 
 @strong{Difficulty:} medium
index 8b72cf4a26dbbf978a3bf8742c21dc4c67b6e58b..6551a677bbbb7c8cef948632894087d0513f57c6 100644 (file)
@@ -153,7 +153,7 @@ and <code>\appoggiatura</code>,
             \acciaccatura g8 f4
           </pre>
 
-     <p>Both reflect the traditional meanings of acciaccatura and appogiatura,
+     <p>Both reflect the traditional meanings of acciaccatura and appoggiatura,
 and both insert insert a slur from the first grace note to the main
 note.
 
index 300c9c18a834715a1d38ff7efcbb8f366e338f7e..0b03549d88afda126a825907d7f216c221ad33ab 100644 (file)
@@ -3030,7 +3030,7 @@ D: doppelter Vorschlag,
 NL: dubbele voorslag,
 DK: dobbelt forslag,
 S: dubbelslag,
-FI: kaksoisappogiatura, kaksoisetuhele.
+FI: kaksoisappoggiatura, kaksoisetuhele.
 
 @seealso
 @ref{appoggiatura}.
index 098532b9612292a9a54bd76b2c7df02b1abf9026..b12e5980dd81307fd6a8ecd3161a32864da7acf1 100644 (file)
@@ -4,6 +4,7 @@ clusters.ly
 contemporary-glissando.ly
 double-glissando.ly
 flat-flags-and-beam-nibs.ly
+flat-ties.ly
 flute-slap-notation.ly
 heavily-customized-polymetric-time-signatures.ly
 laissez-vibrer-ties.ly
diff --git a/Documentation/snippets/customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly b/Documentation/snippets/customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly
new file mode 100644 (file)
index 0000000..0d2a8ce
--- /dev/null
@@ -0,0 +1,151 @@
+%% DO NOT EDIT this file manually; it is automatically
+%% generated from LSR http://lsr.di.unimi.it
+%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
+%% and then run scripts/auxiliar/makelsr.py
+%%
+%% This file is in the public domain.
+\version "2.18.0"
+
+\header {
+  lsrtags = "midi, percussion, pitches, specific-notation"
+
+  texidoc = "
+If you want to use customized drum-pitch-names for an own drum-style
+with proper output for layout and midi, follow the steps as
+demonstrated in the code below. In short:
+
+* define the names * define the appearence * tell LilyPond to use it
+for layout * assign pitches to the names * tell LilyPond to use them
+for midi
+
+"
+  doctitle = "Customize drumPitchNames drumStyleTable and drumPitchTable in layout and midi"
+} % begin verbatim
+
+%% This snippet tries to amend
+%% NR 2.5.1 Common notation for percussion - Custom percussion staves
+%% http://lilypond.org/doc/v2.18/Documentation/notation/common-notation-for-percussion#custom-percussion-staves
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% To use custom drum-pitch-names for your score and midi you need to follow
+%% this route:
+%%
+%%%%%%%%%%%%
+%% LAYOUT:
+%%%%%%%%%%%%
+%%
+%% (1) Define a name and put it in `drumPitchNames'
+%%     This can be done at toplevel with
+%%         drumPitchNames #'my-name  = #'my-name
+%%     or shorter:
+%%         drumPitchNames.my-name  = #'my-name
+%%     It's possible to add an alias as well.
+%% (2) Define how it should be printed
+%%     Therefore put them into a toplevel-list, where each entry should look:
+%%         (my-name
+%%           note-head-style-or-default
+%%             articulation-string-or-#f
+%%               staff-position)
+%%     Example:
+%%         #(define my-style
+%%           '(
+%%             (my-name default "tenuto" -1)
+%%             ; ...
+%%             ))
+%% (3) Tell LilyPond to use this custom-definitions, with
+%%         drumStyleTable = #(alist->hash-table my-style)
+%%     in a \layout or \with
+%%
+%%     Now we're done for layout, here a short, but complete example:
+%%         \new DrumStaff
+%%           \with { drumStyleTable = #(alist->hash-table my-style) }
+%%           \drummode { my-name }
+%%
+%%%%%%%%%%%%
+%% MIDI:
+%%%%%%%%%%%%
+%%
+%% (1) Again at toplvel, assign a pitch to your custom-note-name
+%%         midiDrumPitches #'my-name = #(ly:make-pitch -1 4 FLAT)
+%%     or shorter:
+%%         midiDrumPitches.my-name = ges
+%%     Note that you have to use the name, which is in drumPitchNames, no alias
+%% (2) Tell LilyPond to use this pitch(es), with
+%%         drumPitchTable = #(alist->hash-table midiDrumPitches)
+%%
+%%     Example:
+%%         \score {
+%%            \new DrumStaff
+%%             \with {
+%%               drumStyleTable = #(alist->hash-table my-style)
+%%               drumPitchTable = #(alist->hash-table midiDrumPitches)
+%%             }
+%%             \drummode { my-name4 }
+%%           \layout {}
+%%           \midi {}
+%%         }
+%%
+%%%%%%%%%%%%
+%% TESTING
+%%%%%%%%%%%%
+%%
+%% To test whether all is fine, run the following sequence in terminal:
+%%         lilypond my-file.ly
+%%         midi2ly my-file.midi
+%%         gedit my-file-midi.ly
+%%
+%% Which will do:
+%% 1. create pdf and midi
+%% 2. transform the midi back to a .ly-file
+%%    (note: midi2ly is not always good in correctly identifying enharmonic pitches)
+%% 3. open this file in gedit (or use another editor)
+%% Now watch what you've got.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% FULL EXAMPLE
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+drumPitchNames.dbass      = #'dbass
+drumPitchNames.dba        = #'dbass  % 'db is in use already
+drumPitchNames.dbassmute  = #'dbassmute
+drumPitchNames.dbm        = #'dbassmute
+drumPitchNames.do         = #'dopen
+drumPitchNames.dopenmute  = #'dopenmute
+drumPitchNames.dom        = #'dopenmute
+drumPitchNames.dslap      = #'dslap
+drumPitchNames.ds         = #'dslap
+drumPitchNames.dslapmute  = #'dslapmute
+drumPitchNames.dsm        = #'dslapmute
+
+#(define djembe
+  '((dbass      default  #f         -2)
+    (dbassmute  default  "stopped"  -2)
+    (dopen      default  #f          0)
+    (dopenmute  default  "stopped"   0)
+    (dslap      default  #f          2)
+    (dslapmute  default  "stopped"   2)))
+
+midiDrumPitches.dbass = g
+midiDrumPitches.dbassmute = fis
+midiDrumPitches.dopen =  a
+midiDrumPitches.dopenmute = gis
+midiDrumPitches.dslap =  b
+midiDrumPitches.dslapmute = ais
+
+one = \drummode { r4 dba4 do ds r dbm dom dsm }
+
+\score {
+   \new DrumStaff
+    \with {
+      \override StaffSymbol.line-count =  #3
+      instrumentName = #"Djembe "
+      drumStyleTable = #(alist->hash-table djembe)
+      drumPitchTable = #(alist->hash-table midiDrumPitches)
+    }
+    \one
+  \layout {}
+  \midi {}
+}
diff --git a/Documentation/snippets/flat-ties.ly b/Documentation/snippets/flat-ties.ly
new file mode 100644 (file)
index 0000000..db63fb4
--- /dev/null
@@ -0,0 +1,117 @@
+%% DO NOT EDIT this file manually; it is automatically
+%% generated from LSR http://lsr.di.unimi.it
+%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
+%% and then run scripts/auxiliar/makelsr.py
+%%
+%% This file is in the public domain.
+\version "2.18.0"
+
+\header {
+  lsrtags = "contemporary-notation, scheme-language, staff-notation, tweaks-and-overrides"
+
+  texidoc = "
+The function takes the default @code{Tie.stencil} as an argument,
+calculating the result relying on the extents of this default. Further
+tweaking is possible by overriding @code{Tie.details.height-limit} or
+with @code{\\shape}. It's also possible to change the custom-definition
+on the fly.
+
+"
+  doctitle = "Flat Ties"
+} % begin verbatim
+
+%% http://lsr.di.unimi.it/LSR/Item?id=1031
+
+#(define ((flared-tie coords) grob)
+
+  (define (pair-to-list pair)
+     (list (car pair) (cdr pair)))
+
+  (define (normalize-coords goods x y dir)
+    (map
+      (lambda (coord)
+        ;(coord-scale coord (cons x (* y dir)))
+        (cons (* x (car coord)) (* y dir (cdr coord))))
+      goods))
+
+  (define (my-c-p-s points thick)
+    (make-connected-path-stencil
+      points
+      thick
+      1.0
+      1.0
+      #f
+      #f))
+
+  ;; outer let to trigger suicide
+  (let ((sten (ly:tie::print grob)))
+    (if (grob::is-live? grob)
+        (let* ((layout (ly:grob-layout grob))
+               (line-thickness (ly:output-def-lookup layout 'line-thickness))
+               (thickness (ly:grob-property grob 'thickness 0.1))
+               (used-thick (* line-thickness thickness))
+               (dir (ly:grob-property grob 'direction))
+               (xex (ly:stencil-extent sten X))
+               (yex (ly:stencil-extent sten Y))
+               (lenx (interval-length xex))
+               (leny (interval-length yex))
+               (xtrans (car xex))
+               (ytrans (if (> dir 0)(car yex) (cdr yex)))
+               (uplist
+                 (map pair-to-list
+                      (normalize-coords coords lenx (* leny 2) dir))))
+
+   (ly:stencil-translate
+       (my-c-p-s uplist used-thick)
+     (cons xtrans ytrans)))
+   '())))
+
+#(define flare-tie
+  (flared-tie '((0 . 0)(0.1 . 0.2) (0.9 . 0.2) (1.0 . 0.0))))
+
+\layout {
+  \context {
+    \Voice
+    \override Tie.stencil = #flare-tie
+  }
+}
+
+\paper { ragged-right = ##f }
+
+\relative c' {
+  a4~a
+  \override Tie.height-limit = 4
+  a'4~a
+  a'4~a
+  <a,, c e a c e a c e>~ q
+
+  \break
+
+  a'4~a
+  \once \override Tie.details.height-limit = 14
+  a4~a
+
+  \break
+
+  a4~a
+  \once \override Tie.details.height-limit = 0.5
+  a4~a
+
+  \break
+
+  a4~a
+  \shape #'((0 . 0) (0 . 0.4) (0 . 0.4) (0 . 0)) Tie
+  a4~a
+
+  \break
+
+  a4~a
+  \once \override Tie.stencil =
+    #(flared-tie '((0 . 0)(0.1 . 0.4) (0.9 . 0.4) (1.0 . 0.0)))
+  a4~a
+
+  a4~a
+  \once \override Tie.stencil =
+    #(flared-tie '((0 . 0)(0.06 . 0.1) (0.94 . 0.1) (1.0 . 0.0)))
+  a4~a
+}
index ecc73acb4ec684a3a281941deb1d7cc73b8cc445..243a5a03a077a3f4c6cfbddfe3d30480faca3651 100644 (file)
@@ -1,5 +1,6 @@
 changing-midi-output-to-one-channel-per-voice.ly
 changing-the-tempo-without-a-metronome-mark.ly
 creating-custom-dynamics-in-midi-output.ly
+customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly
 demo-midiinstruments.ly
 replacing-default-midi-instrument-equalization.ly
index 1b294569e36e422ffde26d600bb93215525f6a25..de3e108a48ddd409f42afcee13e1ec400e16a6d2 100644 (file)
@@ -49,7 +49,7 @@ bassMusic = \relative c {
 }
 
 words = \lyricmode {
-  Great is Thy faith- ful- ness,
+  Great is Thy faith -- ful -- ness,
 }
 
 \score {
index 5a29fb2c15ba4277b065119f7803ae21c2b6efb8..edef3b78e2c16030d4d2501963dcbbf36d4bb1f0 100644 (file)
@@ -1,4 +1,5 @@
 adding-drum-parts.ly
+customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly
 heavily-customized-polymetric-time-signatures.ly
 jazz-combo-template.ly
 percussion-beaters.ly
index d1f05af6dcf6d13257a4f06c86539221883519f3..008535e304ef6cdf50082a81294bccd01b208260 100644 (file)
@@ -38,20 +38,11 @@ text = \lyricmode {
 }
 
 \score {
-  \new GrandStaff <<
+  \new PianoStaff <<
     \new Staff = upper { \new Voice = "singer" \upper }
     \new Lyrics \lyricsto "singer" \text
     \new Staff = lower { \lower }
   >>
-  \layout {
-    \context {
-      \GrandStaff
-      \accepts "Lyrics"
-    }
-    \context {
-      \Lyrics
-      \consists "Bar_engraver"
-    }
-  }
+  \layout { }
   \midi { }
 }
index 7410307eb56c51fd12a96bef68c36872d8668d93..ce27407d6774da7489cab95ac2d3a8f3698b3473 100644 (file)
@@ -12,6 +12,7 @@ clefs-can-be-transposed-by-arbitrary-amounts.ly
 coloring-notes-depending-on-their-pitch.ly
 creating-a-sequence-of-notes-on-various-pitches.ly
 creating-custom-key-signatures.ly
+customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly
 forcing-a-clef-symbol-to-be-displayed.ly
 generating-random-notes.ly
 hiding-accidentals-on-tied-notes-at-the-start-of-a-new-system.ly
index 2513ba46821897a6c08c4b9fcd31f2ebf82ee258..a963aea6be9089a9804e0b2f30b2484975d7e58a 100644 (file)
@@ -11,6 +11,7 @@ customizing-the-position-and-number-of-dots-in-repeat-sign-bar-lines.ly
 displaying-grob-ancestry.ly
 drawing-boxes-around-grobs.ly
 drawing-circles-around-various-objects.ly
+flat-ties.ly
 generating-random-notes.ly
 generating-whole-scores-also-book-parts-in-scheme-without-using-the-parser.ly
 outputting-the-version-number.ly
index c2be0bb2e3db035d22068fe9b09b930e74390bf8..cd3e01f1de44b8af34317100b364052adc55ed29 100644 (file)
@@ -9,3 +9,4 @@ forcing-horizontal-shift-of-notes.ly
 making-an-object-invisible-with-the-transparent-property.ly
 moving-dotted-notes-in-polyphony.ly
 suppressing-warnings-for-clashing-note-columns.ly
+two--partcombine-pairs-on-one-staff.ly
index b372f9879f5fdb373bc50a5524c0dd0186add950..bc43d7d3ba6e1594b5f4fcbf8ac5ba2130d78eae 100644 (file)
@@ -15,6 +15,7 @@ contemporary-glissando.ly
 controlling-the-placement-of-chord-fingerings.ly
 creating-blank-staves.ly
 custodes.ly
+customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly
 demo-midiinstruments.ly
 embedding-native-postscript-in-a--markup-block.ly
 engravers-one-by-one.ly
index 0322a423b049fc0f76149c9d0682a6a62e8d47b2..bfb3706161f78a4ce689d99cc3e14f4862298ff2 100644 (file)
@@ -16,6 +16,7 @@ cross-staff-stems.ly
 display-bracket-with-only-one-staff-in-a-system.ly
 extending-a-trillspanner.ly
 extending-glissandi-across-repeats.ly
+flat-ties.ly
 forcing-measure-width-to-adapt-to-metronomemarks-width.ly
 glissandi-can-skip-grobs.ly
 how-to-print-two-rehearsal-marks-above-and-below-the-same-barline-method-1.ly
@@ -43,6 +44,7 @@ tick-bar-lines.ly
 time-signature-in-parentheses---method-3.ly
 time-signature-in-parentheses.ly
 tweaking-clef-properties.ly
+two--partcombine-pairs-on-one-staff.ly
 use-square-bracket-at-the-start-of-a-staff-group.ly
 using-autochange-with-more-than-one-voice.ly
 vertical-aligned-staffgroups-without-connecting-systemstartbar.ly
index ed848f2c0a4941d07a3cefb7e3ec2ea32cad677d..b0bf51340d84c1233da34532774be4cb0e5ae1c6 100644 (file)
@@ -42,6 +42,7 @@ dynamics-text-spanner-postfix.ly
 extending-a-trillspanner.ly
 extending-glissandi-across-repeats.ly
 fine-tuning-pedal-brackets.ly
+flat-ties.ly
 forcing-horizontal-shift-of-notes.ly
 fret-diagrams-explained-and-developed.ly
 generating-custom-flags.ly
diff --git a/Documentation/snippets/two--partcombine-pairs-on-one-staff.ly b/Documentation/snippets/two--partcombine-pairs-on-one-staff.ly
new file mode 100644 (file)
index 0000000..da3d7b3
--- /dev/null
@@ -0,0 +1,101 @@
+%% DO NOT EDIT this file manually; it is automatically
+%% generated from LSR http://lsr.di.unimi.it
+%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
+%% and then run scripts/auxiliar/makelsr.py
+%%
+%% This file is in the public domain.
+\version "2.19.22"
+
+\header {
+  lsrtags = "simultaneous-notes, staff-notation"
+
+  texidoc = "
+The @code{\\partcombine} function takes two music expressions each
+containing a part, and distributes them among four @code{Voice}s named
+@qq{two} @qq{one} @qq{solo} and @qq{chords} depending on when and how
+the parts merged into a common voice.   The voices output from
+@code{\\partcombine} can have their layout properties adjusted in the
+usual way.  Here we define extensions of @code{\\partcombine} to make
+it easier to put four voices on a staff.
+
+soprano = @{ d'4 | cis'  b  e'  d'8 cis' | cis'2 b @} alto = @{ fis4 |
+e8 fis gis ais b4 b | b ais fis2 @} tenor = @{ a8 b | cis' dis' e'4 b8
+cis' d'4 | gis cis' dis'2 @} bass = @{ fis8 gis | a4 gis g fis | eis
+fis b,2 @}
+
+\\new Staff <<
+  \\key b\\minor
+  \\clef alto
+  \\partial 4
+  \\transpose b b'
+  \\partcombineUp \\soprano \\alto
+  \\partcombineDown \\tenor \\bass >>
+
+"
+  doctitle = "Two \\partcombine pairs on one staff"
+} % begin verbatim
+
+\layout {
+  \context {
+    \Staff
+    \accepts "VoiceBox"
+  }
+  \context {
+    \name "VoiceBox"
+    \type "Engraver_group"
+    \defaultchild "Voice"
+    \accepts "Voice"
+  }
+}
+
+partcombineUp =
+#(define-music-function (partOne partTwo)
+  (ly:music? ly:music?)
+"Take the music in @var{partOne} and @var{partTwo} and return
+a @code{VoiceBox} named @q{Up} containing @code{Voice}s
+that contain @var{partOne} and @var{partTwo} merged into one
+voice where feasible.  This variant sets the default voicing
+in the output to use upward stems."
+#{
+  \new VoiceBox = "Up" <<
+    \context Voice = "one" { \voiceOne }
+    \context Voice = "two" { \voiceThree }
+    \context Voice = "shared" { \voiceOne }
+    \context Voice = "solo" { \voiceOne }
+    \partcombine #partOne #partTwo
+  >>
+#})
+
+partcombineDown = #
+(define-music-function (partOne partTwo)
+  (ly:music? ly:music?)
+"Take the music in @var{partOne} and @var{partTwo} and return
+a @code{VoiceBox} named @q{Down} containing @code{Voice}s
+that contain @var{partOne} and @var{partTwo} merged into one
+voice where feasible.  This variant sets the default voicing
+in the output to use downward stems."
+#{
+  \new VoiceBox = "Down" <<
+    \set VoiceBox.soloText = #"Solo III"
+    \set VoiceBox.soloIIText = #"Solo IV"
+    \context Voice ="one" { \voiceFour }
+    \context Voice ="two" { \voiceTwo }
+    \context Voice ="shared" { \voiceFour }
+    \context Voice ="solo" { \voiceFour }
+    \partcombine #partOne #partTwo
+  >>
+#})
+
+soprano = { d'4 | cis'  b  e'  d'8 cis' | cis'2 b }
+alto = { fis4 | e8 fis gis ais b4 b | b ais fis2 }
+tenor = { a8 b | cis' dis' e'4 b8 cis' d'4 | gis cis' dis'2 }
+bass = { fis8 gis | a4 gis g fis | eis fis b,2 }
+
+\new Staff <<
+  \key b\minor
+  \clef alto
+  \partial 4
+  \transpose b b'
+  \partcombineUp \soprano \alto
+  \partcombineDown \tenor \bass
+>>
index e282c32fba41326ebbb1a7e86bdd536857a23dfa..4dce2a313f6dcae354f46ad572507cb5733f1bb8 100644 (file)
@@ -24,7 +24,7 @@ denotes a stable version.  For development versions 'y' is odd.
 @section Downloading
 
 The primary download site for sourcecode is
-@uref{http://lilypond.org/download/}.
+@uref{http://lilypond.org/downloads/}.
 
 @section Compilation
 
index 5013b4d954681fdd5a44b45ee1e802450b6c4153..31b400fa893909c31ff9e907bce19cc34c8f651a 100644 (file)
@@ -761,7 +761,7 @@ This release's lilypond-book tests.
 @itemize
 @item @uref{http://lilypond.org/test, Comparisons between regression tests}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archive of all regression tests}
 
 @end itemize
@@ -1016,7 +1016,7 @@ Carl Sorensen
 
 For regular, cross-staff, broken and kneed beams.  Beaming should depend
 on context and neighbor notes (see section 2.2 of
-@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon,_Jean-Pierre%29,
+@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon%2C_Jean-Pierre%29,
 this book}).  If possible also reduce beaming-computation time.
 
 @strong{Difficulty:} medium
index e741a960eaa3831bdd43d9fe184ab9ac987537ba..07ccb42aa963ae2b0490ede8a34cb9c6bf6e0c91 100644 (file)
@@ -133,7 +133,7 @@ translation status for non-English readers.
 user-created examples, hints and tips.
 
 @item
-@uref{http://benlemon.me/blog/music/lilypond/operation-lilypond/,Video Tutorials}:
+@uref{http://bit.ly/LilyPondBeginners,Video Tutorials}:
 Ben Lemon, a LilyPond user, has created a range of video tutorials on
 his blog and which are aimed at new users.
 
index e7c6d228db9bf67065cf71a5be4a879ad91601e0..675244a21385af5870e545715f3ecc986d7c7ac1 100644 (file)
@@ -9,10 +9,10 @@
 @c used for news about the upcoming release; see CG 10.2
 
 @newsItem
-@subheading LilyPond 2.19.41 released  @emph{May 1, 2016}
+@subheading LilyPond 2.19.43 released  @emph{June 8, 2016}
 
 We are happy to announce the release of LilyPond
-2.19.41.  This release includes a number of enhancements, and contains some
+2.19.43.  This release includes a number of enhancements, and contains some
 work in progress.  You will have access to the very latest features, but
 some may be incomplete, and you may encounter bugs and crashes.  If you
 require a stable version of Lilypond, we recommend using the 2.18
@@ -138,115 +138,3 @@ Jean-Charles Malahieude, Till Paala, Yoshiki Sawada
 and numerous other contributors.
 
 @newsEnd
-
-@newsItem
-@subheading LilyPond blog.  @emph{June 2, 2013}
-
-Janek Warchoł has created a LilyPond blog.  You can find it at
-@uref{http://lilypondblog.org/, lilypondblog.org}!
-
-@newsEnd
-
-@newsItem
-@subheading LilyPond 2.16.2 released!  @emph{January 4, 2013}
-
-We are happy to announce the release of LilyPond 2.16.2. This release is mainly
-to correct a problem with lilypond-book running on Windows. We recommend that
-only people requiring this functionality upgrade to this version.
-
-@newsEnd
-
-@newsItem
-@subheading The LilyPond Report #28.  @emph{November 12, 2012}
-
-The @uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?The-LilyPond-Report-28, October
-issue of the @emph{LilyPond Report}} focuses on the
-@uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?LilyPond-meeting-in-Waltrop,
-meeting of LilyPond developers and users} in Waltrop, Germany last
-August.  Of course, there are also some musings on LilyPond
-triggered by the release of 2.16.0 and 2.17.0 occuring from that
-venue.
-
-There are also two monthly financial reports from David Kastrup
-whose work on LilyPond is
-@uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?The-LilyPond-Report-24#an_urgent_request_for_funding,
-solely paid for} by financial contributions from other developer
-and users (thank you!), and a report about experiences from
-@uref{http://scorio.com, a web-based music typesetting service}
-using LilyPond internally.
-
-Come @uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?The-LilyPond-Report-28, read
-LilyPond Report 28} now; comments and contributions are warmly
-encouraged!
-@newsEnd
-
-@newsItem
-@subheading LilyPond 2.16.1 released!  @emph{November 9, 2012}
-
-We are happy to announce the release of LilyPond 2.16.1. This has a number of
-updates to the previous stable version, and should cause no problems. We
-recommend that everybody upgrade to this version.
-@newsEnd
-
-@newsItem
-@subheading Lilypond 2.16.0 released!  @emph{August 24, 2012}
-
-We are proud to announce the release of GNU LilyPond 2.16.1.
-LilyPond is a music engraving program, devoted to producing the
-highest-quality sheet music possible.  It brings the aesthetics of
-traditionally engraved music to computer printouts.
-
-Many improvements have been made in the past year since the previous
-main stable version. A few major improvements are:
-
-@itemize
-@item
-Support for kievan square notation
-@item
-User and programming interfaces have greatly improved
-@item
-Music functions have become quite more versatile
-@end itemize
-
-A full list of new features is given in:
-
-@example
-@uref{http://lilypond.org/doc/v2.16/Documentation/changes/index.html}
-@end example
-
-Happy music typesetting!  LilyPond 2.16 was brought to you by...
-
-Main development team:
-
-Bertrand Bordage, Trevor Daniels, Colin Hall, Phil Holmes, Ian Hulin,
-Reinhold Kainhofer, David Kastrup, Jonathan Kulp, Werner Lemberg,
-John Mandereau, Patrick McCarty, Joe Neeman, Han-Wen Nienhuys,
-Jan Nieuwenhuizen, Graham Percival, Mark Polesky, Neil Puttock,
-Mike Solomon, Carl Sorensen, Francisco Vila, Valentin Villenave,
-Jan Warchoł
-
-Programming contributors:
-
-Aleksandr Andreev, Sven Axelsson, Peter Chubb, Karin Hoethker,
-Marc Hohl, David Nalesnik, Justin Ohmie, Benkő Pál, Julien Rioux, Patrick Schmidt,
-Adam Spiers, Heikki Taurainen, Piers Titus van der Torren,
-Jan-Peter Voigt, Janek Warchol
-
-Documentation contributors:
-
-James Lowe, Pavel Roskin, Alberto Simoes, Stefan Weil
-
-Bug squad:
-
-Colin Campbell, Eluze, Phil Holmes, Marek Klein, Ralph Palmer,
-James Lowe
-
-Support:
-
-Colin Campbell, Christian Hitz, Phil Holmes
-
-Translation contributors:
-
-Jean-Charles Malahieude, Till Paala, Yoshiki Sawada
-
-@newsEnd
index 9095620830db213dc116ae45706b25ca8598d816..fbabbd846e324499d911c3f58a031f11ea7989f8 100644 (file)
@@ -26,6 +26,30 @@ NOTE:
   * don't duplicate entries from news-front.itexi
 @end ignore
 
+@newsItem
+@subheading LilyPond 2.19.42 released  @emph{May 15, 2016}
+
+We are happy to announce the release of LilyPond
+2.19.42.  This release includes a number of enhancements, and contains some
+work in progress.  You will have access to the very latest features, but
+some may be incomplete, and you may encounter bugs and crashes.  If you
+require a stable version of Lilypond, we recommend using the 2.18
+version.
+
+@newsEnd
+
+@newsItem
+@subheading LilyPond 2.19.41 released  @emph{May 1, 2016}
+
+We are happy to announce the release of LilyPond
+2.19.41.  This release includes a number of enhancements, and contains some
+work in progress.  You will have access to the very latest features, but
+some may be incomplete, and you may encounter bugs and crashes.  If you
+require a stable version of Lilypond, we recommend using the 2.18
+version.
+
+@newsEnd
+
 @newsItem
 @subheading LilyPond 2.19.40 released  @emph{April 17, 2016}
 
@@ -707,6 +731,14 @@ a stable version of Lilypond, we recommend using the 2.16 version.
 
 @newsEnd
 
+@newsItem
+@subheading LilyPond blog.  @emph{June 2, 2013}
+
+Janek Warchoł has created a LilyPond blog.  You can find it at
+@uref{http://lilypondblog.org/, lilypondblog.org}!
+
+@newsEnd
+
 @newsItem
 @subheading LilyPond 2.17.19 released!  @emph{May 26, 2013}
 
@@ -818,6 +850,15 @@ a stable version of Lilypond, we recommend using the 2.16 version.
 
 @newsEnd
 
+@newsItem
+@subheading LilyPond 2.16.2 released!  @emph{January 4, 2013}
+
+We are happy to announce the release of LilyPond 2.16.2. This release is mainly
+to correct a problem with lilypond-book running on Windows. We recommend that
+only people requiring this functionality upgrade to this version.
+
+@newsEnd
+
 @newsItem
 @subheading LilyPond 2.17.9 released!  @emph{December 15, 2012}
 
@@ -852,6 +893,30 @@ a stable version of Lilypond, we recommend using the 2.16 version.
 @newsEnd
 
 
+@newsItem
+@subheading The LilyPond Report #28.  @emph{November 12, 2012}
+
+The @uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?The-LilyPond-Report-28, October
+issue of the @emph{LilyPond Report}} focuses on the
+@uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?LilyPond-meeting-in-Waltrop,
+meeting of LilyPond developers and users} in Waltrop, Germany last
+August.  Of course, there are also some musings on LilyPond
+triggered by the release of 2.16.0 and 2.17.0 occuring from that
+venue.
+
+There are also two monthly financial reports from David Kastrup
+whose work on LilyPond is
+@uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?The-LilyPond-Report-24#an_urgent_request_for_funding,
+solely paid for} by financial contributions from other developer
+and users (thank you!), and a report about experiences from
+@uref{http://scorio.com, a web-based music typesetting service}
+using LilyPond internally.
+
+Come @uref{http://web.archive.org/web/20110325004849/http://news.lilynet.net/?The-LilyPond-Report-28, read
+LilyPond Report 28} now; comments and contributions are warmly
+encouraged!
+@newsEnd
+
 @newsItem
 @subheading LilyPond 2.16.1 released!  @emph{November 9, 2012}
 
@@ -942,7 +1007,7 @@ highest-quality sheet music possible.  It brings the aesthetics of
 traditionally engraved music to computer printouts.
 
 Many improvements have been made in the past year since the previous
-main stable version. A few major improvements are: 
+main stable version. A few major improvements are:
 
 @itemize
 @item
@@ -950,7 +1015,7 @@ Support for kievan square notation
 @item
 User and programming interfaces have greatly improved
 @item
-Music functions have become quite more versatile 
+Music functions have become quite more versatile
 @end itemize
 
 A full list of new features is given in:
@@ -992,7 +1057,7 @@ Colin Campbell, Christian Hitz, Phil Holmes
 
 Translation contributors:
 
-Jean-Charles Malahieude, Till Paala, Yoshiki Sawada 
+Jean-Charles Malahieude, Till Paala, Yoshiki Sawada
 
 @newsEnd
 
@@ -3308,7 +3373,7 @@ and lots of updates for the translations.
 
 Release 2.11.28 is now available as a binary installer for
 FreeBSD x86_64.  Download
-@uref{http://lilypond.org/download/binaries/freebsd-64/,the installer} and
+@uref{http://lilypond.org/downloads/binaries/freebsd-64/,the installer} and
 do @emph{sh lilypond-2.11.28-1.freebsd-64.sh} in a command window.
 @newsEnd
 
@@ -4201,11 +4266,11 @@ to the @ref{Old downloads} get them!
 Starting with 2.7.26, the development team has been working on the
 installers. We're proud to announce another version of these: they are
 now available for
-@uref{http://lilypond.org/download/binaries/linux-x86/,
+@uref{http://lilypond.org/downloads/binaries/linux-x86/,
 Linux/x86},
-@uref{http://lilypond.org/download/binaries/darwin-ppc/,
+@uref{http://lilypond.org/downloads/binaries/darwin-ppc/,
 MacOS X} and
-@uref{http://lilypond.org/download/binaries/mingw/,
+@uref{http://lilypond.org/downloads/binaries/mingw/,
 Windows}.
 @newsEnd
 
index 58d63f0e6fec8e643cbe8b7d9269c4e4c0e2ba05..5e3efa38cab44aa5dc1e06db618bf49d6bf1bfc3 100644 (file)
@@ -766,7 +766,7 @@ This release's lilypond-book tests.
 @itemize
 @item @uref{http://lilypond.org/test, Comparisons between regression tests}
 
-@item @uref{http://lilypond.org/download/binaries/test-output/,
+@item @uref{http://lilypond.org/downloads/binaries/test-output/,
 Archive of all regression tests}
 
 @end itemize
diff --git a/VERSION b/VERSION
index a71d765f26d3ce5df4d309cc52a75e2751df3145..f18fd1a1d691befcba07dd999722e15a44979297 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1,7 +1,7 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=2
 MINOR_VERSION=19
-PATCH_LEVEL=42
+PATCH_LEVEL=44
 MY_PATCH_LEVEL=
 VERSION_STABLE=2.18.2
-VERSION_DEVEL=2.19.41
+VERSION_DEVEL=2.19.43
index 0037c58ca807c403a206647415ed64ef8c00bf05..ed47b8350efe006c1bf6443d775b79bd282ebece 100644 (file)
@@ -281,11 +281,9 @@ AC_DEFUN(STEPMAKE_CXX, [
     STEPMAKE_OPTIONAL_REQUIRED(CXX, c++, $1)
 
     CXXFLAGS="$CXXFLAGS $OPTIMIZE"
-    LD='$(CXX)'
 
     AC_SUBST(CXX)
     AC_SUBST(CXXFLAGS)
-    AC_SUBST(LD)
 ])
 
 
index f9d2e15cd4c0e298f9c6a9fbcb3caea2a93fe172..1be735b0ed2dab1d7478370fb38d2daa59bf4be9 100644 (file)
@@ -511,11 +511,16 @@ Accidental_engraver::process_music ()
     update_local_key_signature (sig);
 }
 
-ADD_ACKNOWLEDGER (Accidental_engraver, arpeggio);
-ADD_ACKNOWLEDGER (Accidental_engraver, finger);
-ADD_ACKNOWLEDGER (Accidental_engraver, rhythmic_head);
-ADD_END_ACKNOWLEDGER (Accidental_engraver, tie);
-ADD_ACKNOWLEDGER (Accidental_engraver, note_column);
+
+void
+Accidental_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Accidental_engraver, arpeggio);
+  ADD_ACKNOWLEDGER (Accidental_engraver, finger);
+  ADD_ACKNOWLEDGER (Accidental_engraver, rhythmic_head);
+  ADD_END_ACKNOWLEDGER (Accidental_engraver, tie);
+  ADD_ACKNOWLEDGER (Accidental_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Accidental_engraver,
                 /* doc */
index a560a25940b5dbd065d50ed6ad8d81f6af6b6782..ab4f2a4ce4e3a09651b674a8f9598e2cdd6699f5 100644 (file)
@@ -27,8 +27,6 @@
 #include "scm-hash.hh"
 #include "warn.hh"
 
-const char * const All_font_metrics::type_p_name_ = 0;
-
 Index_to_charcode_map const *
 All_font_metrics::get_index_to_charcode_map (const string &filename,
                                              int face_index,
index 9ceea9387c59eb09a380fd23ebeaf4b84d9601c9..665c83a4cc51c6b5648df8ee06565aaf6f9a093e 100644 (file)
@@ -40,7 +40,7 @@ class Ambitus_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Ambitus_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (note_head);
+  void acknowledge_note_head (Grob_info);
 
   void process_music ();
   void stop_translation_timestep ();
@@ -218,7 +218,12 @@ Ambitus_engraver::finalize ()
     }
 }
 
-ADD_ACKNOWLEDGER (Ambitus_engraver, note_head);
+void
+Ambitus_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Ambitus_engraver, note_head);
+}
+
 ADD_TRANSLATOR (Ambitus_engraver,
                 /* doc */
                 "Create an ambitus.",
index e191470161d99070b8f03597168b82e2b3eadcb2..d308a430686a6dc085685b4ac1f68304eb6621fe 100644 (file)
@@ -43,7 +43,7 @@ public:
 protected:
   void process_music ();
   void stop_translation_timestep ();
-  DECLARE_TRANSLATOR_LISTENER (arpeggio);
+  void listen_arpeggio (Stream_event *);
 private:
   Item *arpeggio_;
   Stream_event *arpeggio_event_;
@@ -55,7 +55,6 @@ Arpeggio_engraver::Arpeggio_engraver ()
   arpeggio_event_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Arpeggio_engraver, arpeggio);
 void Arpeggio_engraver::listen_arpeggio (Stream_event *ev)
 {
   ASSIGN_EVENT_ONCE (arpeggio_event_, ev);
@@ -109,9 +108,15 @@ Arpeggio_engraver::stop_translation_timestep ()
   arpeggio_event_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Arpeggio_engraver, stem);
-ADD_ACKNOWLEDGER (Arpeggio_engraver, rhythmic_head);
-ADD_ACKNOWLEDGER (Arpeggio_engraver, note_column);
+
+void
+Arpeggio_engraver::boot ()
+{
+  ADD_LISTENER (Arpeggio_engraver, arpeggio);
+  ADD_ACKNOWLEDGER (Arpeggio_engraver, stem);
+  ADD_ACKNOWLEDGER (Arpeggio_engraver, rhythmic_head);
+  ADD_ACKNOWLEDGER (Arpeggio_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Arpeggio_engraver,
                 /* doc */
index 37872577387bd1750a5e30d24558e45b7ea1c8a8..a7a92d9d6dfac2f8196b3d10a60f547765ab3ebf 100644 (file)
@@ -45,12 +45,13 @@ protected:
   virtual void finalize ();
   virtual void derived_mark () const;
 
-  DECLARE_ACKNOWLEDGER (rest);
-  DECLARE_ACKNOWLEDGER (beam);
-  DECLARE_ACKNOWLEDGER (bar_line);
-  DECLARE_ACKNOWLEDGER (breathing_sign);
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_TRANSLATOR_LISTENER (beam_forbid);
+public:
+  void acknowledge_rest (Grob_info);
+  void acknowledge_beam (Grob_info);
+  void acknowledge_bar_line (Grob_info);
+  void acknowledge_breathing_sign (Grob_info);
+  void acknowledge_stem (Grob_info);
+  void listen_beam_forbid (Stream_event *);
 
 private:
   virtual bool test_moment (Direction, Moment, Moment);
@@ -160,7 +161,6 @@ Auto_beam_engraver::Auto_beam_engraver ()
   beam_settings_ = SCM_EOL;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Auto_beam_engraver, beam_forbid);
 void
 Auto_beam_engraver::listen_beam_forbid (Stream_event *ev)
 {
@@ -541,11 +541,17 @@ Auto_beam_engraver::process_acknowledged ()
   process_acknowledged_count_++;
 }
 
-ADD_ACKNOWLEDGER (Auto_beam_engraver, stem);
-ADD_ACKNOWLEDGER (Auto_beam_engraver, bar_line);
-ADD_ACKNOWLEDGER (Auto_beam_engraver, beam);
-ADD_ACKNOWLEDGER (Auto_beam_engraver, breathing_sign);
-ADD_ACKNOWLEDGER (Auto_beam_engraver, rest);
+void
+Auto_beam_engraver::boot ()
+{
+  ADD_LISTENER (Auto_beam_engraver, beam_forbid);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, stem);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, bar_line);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, beam);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, breathing_sign);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, rest);
+}
+
 ADD_TRANSLATOR (Auto_beam_engraver,
                 /* doc */
                 "Generate beams based on measure characteristics and observed"
@@ -574,7 +580,7 @@ ADD_TRANSLATOR (Auto_beam_engraver,
 class Grace_auto_beam_engraver : public Auto_beam_engraver
 {
   TRANSLATOR_DECLARATIONS (Grace_auto_beam_engraver);
-  DECLARE_TRANSLATOR_LISTENER (beam_forbid);
+  TRANSLATOR_INHERIT (Auto_beam_engraver);
 
 private:
   Moment last_grace_start_; // Full starting time of last grace group
@@ -591,13 +597,6 @@ Grace_auto_beam_engraver::Grace_auto_beam_engraver ()
   // not considered.
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Grace_auto_beam_engraver, beam_forbid);
-void
-Grace_auto_beam_engraver::listen_beam_forbid (Stream_event *ev)
-{
-  Auto_beam_engraver::listen_beam_forbid (ev);
-}
-
 bool
 Grace_auto_beam_engraver::is_same_grace_state (Moment, Moment)
 {
@@ -637,11 +636,17 @@ Grace_auto_beam_engraver::test_moment (Direction dir, Moment test_mom, Moment)
   return !test_mom.grace_part_;
 }
 
-ADD_ACKNOWLEDGER (Grace_auto_beam_engraver, stem);
-ADD_ACKNOWLEDGER (Grace_auto_beam_engraver, bar_line);
-ADD_ACKNOWLEDGER (Grace_auto_beam_engraver, beam);
-ADD_ACKNOWLEDGER (Grace_auto_beam_engraver, breathing_sign);
-ADD_ACKNOWLEDGER (Grace_auto_beam_engraver, rest);
+void
+Grace_auto_beam_engraver::boot ()
+{
+  ADD_LISTENER (Auto_beam_engraver, beam_forbid);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, stem);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, bar_line);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, beam);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, breathing_sign);
+  ADD_ACKNOWLEDGER (Auto_beam_engraver, rest);
+}
+
 ADD_TRANSLATOR (Grace_auto_beam_engraver,
                 /* doc */
                 "Generates one autobeam group across an entire grace phrase. "
index 3a9b0d67752d58fcaa5d52886426c73e65659e97..2bc4858479898f905cc3799aba21074a2111038a 100644 (file)
@@ -43,7 +43,7 @@ protected:
   void process_music ();
   virtual void initialize ();
   virtual void finalize ();
-  DECLARE_ACKNOWLEDGER (grob);
+  void acknowledge_grob (Grob_info);
   void process_acknowledged ();
   virtual Spanner *get_spanner ();
   virtual void add_element (Grob *);
@@ -165,7 +165,12 @@ Axis_group_engraver::add_element (Grob *e)
   Axis_group_interface::add_element (staffline_, e);
 }
 
-ADD_ACKNOWLEDGER (Axis_group_engraver, grob);
+
+void
+Axis_group_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Axis_group_engraver, grob);
+}
 
 ADD_TRANSLATOR (Axis_group_engraver,
                 /* doc */
index 52520280f2eba2cbe2cf0d9718991c1156df5f4f..38a193caf63dfc4659dc10a1245d2c9ab2785c69 100644 (file)
@@ -81,7 +81,7 @@ Axis_group_interface::has_axis (Grob *me, Axis a)
 {
   SCM axes = me->get_property ("axes");
 
-  return (SCM_BOOL_F != scm_memq (scm_from_int (a), axes));
+  return scm_is_true (scm_memq (scm_from_int (a), axes));
 }
 
 Interval
index 980aa9223154ff967c4c7157349c25204b36577a..4f0f136db05b8ca6f5edf72bfd9ead489859b34f 100644 (file)
@@ -28,8 +28,8 @@ class Balloon_engraver : public Engraver
 {
   TRANSLATOR_DECLARATIONS (Balloon_engraver);
 
-  DECLARE_TRANSLATOR_LISTENER (annotate_output);
-  DECLARE_ACKNOWLEDGER (grob);
+  void listen_annotate_output (Stream_event *);
+  void acknowledge_grob (Grob_info);
   vector<Stream_event *> events_;
 
   void stop_translation_timestep ();
@@ -37,7 +37,6 @@ class Balloon_engraver : public Engraver
   void balloonify (Grob *, Stream_event *);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Balloon_engraver, annotate_output);
 void
 Balloon_engraver::listen_annotate_output (Stream_event *ev)
 {
@@ -85,7 +84,13 @@ Balloon_engraver::acknowledge_grob (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Balloon_engraver, grob);
+
+void
+Balloon_engraver::boot ()
+{
+  ADD_LISTENER (Balloon_engraver, annotate_output);
+  ADD_ACKNOWLEDGER (Balloon_engraver, grob);
+}
 
 ADD_TRANSLATOR (Balloon_engraver,
                 /* doc */
index 397743b4b07b87d8fd4cf49f1384d49aa8ce15e4..8feb63dd134fa873d229fc4e3f4b10ecd98ca9c6 100644 (file)
@@ -38,7 +38,7 @@ protected:
   void stop_translation_timestep ();
   void process_acknowledged ();
 
-  DECLARE_END_ACKNOWLEDGER (spanner);
+  void acknowledge_end_spanner (Grob_info);
 
 private:
   void create_bar ();
@@ -108,7 +108,12 @@ Bar_engraver::acknowledge_end_spanner (Grob_info gi)
     spanners_.push_back (dynamic_cast<Spanner *> (g));
 }
 
-ADD_END_ACKNOWLEDGER (Bar_engraver, spanner);
+
+void
+Bar_engraver::boot ()
+{
+  ADD_END_ACKNOWLEDGER (Bar_engraver, spanner);
+}
 
 ADD_TRANSLATOR (Bar_engraver,
                 /* doc */
index 144076439c6e27fb787a6d50251cf3c2e7ea7ab0..1af5f19da1777115acda72facd0dd63d630a1c68 100644 (file)
@@ -45,14 +45,13 @@ protected:
 
 protected:
   void stop_translation_timestep ();
-  DECLARE_TRANSLATOR_LISTENER (alternative);
-  DECLARE_ACKNOWLEDGER (break_alignment);
+  void listen_alternative (Stream_event *);
+  void acknowledge_break_alignment (Grob_info);
   void process_music ();
   void create_items ();
   TRANSLATOR_DECLARATIONS (Bar_number_engraver);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Bar_number_engraver, alternative);
 void
 Bar_number_engraver::listen_alternative (Stream_event *ev)
 {
@@ -177,7 +176,13 @@ Bar_number_engraver::create_items ()
   text_ = make_item ("BarNumber", SCM_EOL);
 }
 
-ADD_ACKNOWLEDGER (Bar_number_engraver, break_alignment);
+
+void
+Bar_number_engraver::boot ()
+{
+  ADD_LISTENER (Bar_number_engraver, alternative);
+  ADD_ACKNOWLEDGER (Bar_number_engraver, break_alignment);
+}
 
 ADD_TRANSLATOR (Bar_number_engraver,
                 /* doc */
index 151ffacf16eab597378664eeb3d84a74f7ce5229..31f96b72b17b4f406d2f87720b6af847bab55f23 100644 (file)
@@ -30,15 +30,15 @@ protected:
   vector<Grob_info> beams_;
   vector<Grob_info> covered_grobs_;
 
-  DECLARE_ACKNOWLEDGER (note_head);
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (accidental);
-  DECLARE_ACKNOWLEDGER (clef);
-  DECLARE_ACKNOWLEDGER (clef_modifier);
-  DECLARE_ACKNOWLEDGER (key_signature);
-  DECLARE_ACKNOWLEDGER (time_signature);
-  DECLARE_ACKNOWLEDGER (beam);
-  DECLARE_ACKNOWLEDGER (flag);
+  void acknowledge_note_head (Grob_info);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_accidental (Grob_info);
+  void acknowledge_clef (Grob_info);
+  void acknowledge_clef_modifier (Grob_info);
+  void acknowledge_key_signature (Grob_info);
+  void acknowledge_time_signature (Grob_info);
+  void acknowledge_beam (Grob_info);
+  void acknowledge_flag (Grob_info);
 
   virtual void finalize ();
 
@@ -193,15 +193,20 @@ Beam_collision_engraver::acknowledge_beam (Grob_info i)
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Beam_collision_engraver, note_head);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, stem);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, accidental);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, clef);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, key_signature);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, time_signature);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, clef_modifier);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, flag);
-ADD_ACKNOWLEDGER (Beam_collision_engraver, beam);
+
+void
+Beam_collision_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, note_head);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, stem);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, accidental);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, clef);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, key_signature);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, time_signature);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, clef_modifier);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, flag);
+  ADD_ACKNOWLEDGER (Beam_collision_engraver, beam);
+}
 
 ADD_TRANSLATOR (Beam_collision_engraver,
                 /* doc */
index e6ca4caf16d58586556a288fb7c915bb8e06659c..277d1b0a0eae6a6de6dfcd9ff46f3a8ef9f26d22 100644 (file)
@@ -38,8 +38,8 @@
 class Beam_engraver : public Engraver
 {
 public:
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (rest);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_rest (Grob_info);
 
 protected:
   Stream_event *start_ev_;
@@ -77,7 +77,7 @@ protected:
   virtual bool valid_start_point ();
   virtual bool valid_end_point ();
 
-  DECLARE_TRANSLATOR_LISTENER (beam);
+  void listen_beam (Stream_event *);
 public:
   TRANSLATOR_DECLARATIONS (Beam_engraver);
 };
@@ -112,7 +112,6 @@ Beam_engraver::Beam_engraver ()
   prev_start_ev_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Beam_engraver, beam);
 void
 Beam_engraver::listen_beam (Stream_event *ev)
 {
@@ -312,8 +311,14 @@ Beam_engraver::acknowledge_stem (Grob_info info)
   Beam::add_stem (beam_, stem);
 }
 
-ADD_ACKNOWLEDGER (Beam_engraver, stem);
-ADD_ACKNOWLEDGER (Beam_engraver, rest);
+
+void
+Beam_engraver::boot ()
+{
+  ADD_LISTENER (Beam_engraver, beam);
+  ADD_ACKNOWLEDGER (Beam_engraver, stem);
+  ADD_ACKNOWLEDGER (Beam_engraver, rest);
+}
 
 ADD_TRANSLATOR (Beam_engraver,
                 /* doc */
@@ -337,8 +342,8 @@ class Grace_beam_engraver : public Beam_engraver
 {
 public:
   TRANSLATOR_DECLARATIONS (Grace_beam_engraver);
-
-  DECLARE_TRANSLATOR_LISTENER (beam);
+  TRANSLATOR_INHERIT (Beam_engraver);
+  void listen_beam (Stream_event *);
 
 protected:
   virtual bool valid_start_point ();
@@ -366,7 +371,6 @@ Grace_beam_engraver::valid_end_point ()
 /*
   Ugh, C&P code.
  */
-IMPLEMENT_TRANSLATOR_LISTENER (Grace_beam_engraver, beam);
 void
 Grace_beam_engraver::listen_beam (Stream_event *ev)
 {
@@ -378,8 +382,14 @@ Grace_beam_engraver::listen_beam (Stream_event *ev)
     stop_ev_ = ev;
 }
 
-ADD_ACKNOWLEDGER (Grace_beam_engraver, stem);
-ADD_ACKNOWLEDGER (Grace_beam_engraver, rest);
+
+void
+Grace_beam_engraver::boot ()
+{
+  ADD_LISTENER (Grace_beam_engraver, beam);
+  ADD_ACKNOWLEDGER (Beam_engraver, stem);
+  ADD_ACKNOWLEDGER (Beam_engraver, rest);
+}
 
 ADD_TRANSLATOR (Grace_beam_engraver,
                 /* doc */
index a6e78d67c7f2353515b263f749f6ece4951c9d2a..0970e8b5e74831d5767b2e8367f7d00eb8c55fff 100644 (file)
@@ -35,7 +35,7 @@ protected:
   void start_translation_timestep ();
   void process_music ();
   void set_melisma (bool);
-  DECLARE_TRANSLATOR_LISTENER (beam);
+  void listen_beam (Stream_event *);
 private:
   Stream_event *start_ev_;
   Stream_event *now_stop_ev_;
@@ -80,7 +80,6 @@ Beam_performer::start_translation_timestep ()
   now_stop_ev_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Beam_performer, beam);
 void
 Beam_performer::listen_beam (Stream_event *ev)
 {
@@ -92,6 +91,12 @@ Beam_performer::listen_beam (Stream_event *ev)
     now_stop_ev_ = ev;
 }
 
+void
+Beam_performer::boot ()
+{
+  ADD_LISTENER (Beam_performer, beam);
+}
+
 ADD_TRANSLATOR (Beam_performer,
                 /* doc */
                 "",
index 44b0f21eaaa6820b96d7fc24e274db9c107b82f6..83c98a94e082a612a18d6c30c3d3935e090b7285 100644 (file)
@@ -29,10 +29,10 @@ class Bend_engraver : public Engraver
 {
 public:
   TRANSLATOR_DECLARATIONS (Bend_engraver);
-  DECLARE_ACKNOWLEDGER (note_head);
+  void acknowledge_note_head (Grob_info);
 
 protected:
-  DECLARE_TRANSLATOR_LISTENER (bend_after);
+  void listen_bend_after (Stream_event *);
   void finalize ();
   void process_music ();
   void stop_translation_timestep ();
@@ -115,7 +115,6 @@ Bend_engraver::Bend_engraver ()
   fall_event_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Bend_engraver, bend_after);
 void
 Bend_engraver::listen_bend_after (Stream_event *ev)
 {
@@ -133,7 +132,13 @@ Bend_engraver::process_music ()
     }
 }
 
-ADD_ACKNOWLEDGER (Bend_engraver, note_head);
+
+void
+Bend_engraver::boot ()
+{
+  ADD_LISTENER (Bend_engraver, bend_after);
+  ADD_ACKNOWLEDGER (Bend_engraver, note_head);
+}
 
 ADD_TRANSLATOR (Bend_engraver,
                 /* doc */
index cf35a7c1bdf0adcdc87a0eac3a68545c401c9b78..af0cb6263221e745f6b5d27d2dce49ba6fa9668c 100644 (file)
@@ -178,4 +178,4 @@ LY_DEFINE (ly_book_scores, "ly:book-scores",
 }
 
 
-const char Book::type_p_name_[] = "ly:book?";
+const char * const Book::type_p_name_ = "ly:book?";
index 629b8010fae6b2ab9b429399e463952d5ed2aa04..6569493419da6a66c44077feab15ea5297c46ee9 100644 (file)
@@ -133,4 +133,4 @@ Box::print ()
 /****************************************************************/
 
 
-const char Box::type_p_name_[] = "ly:box?";
+const char * const Box::type_p_name_ = "ly:box?";
index f9090c8e0829718e61a594437d185ac3e235d771..55a638da870283b10b8446695221264a581c8991 100644 (file)
@@ -40,8 +40,8 @@ protected:
   virtual void derived_mark () const;
 public:
   TRANSLATOR_DECLARATIONS (Break_align_engraver);
-  DECLARE_ACKNOWLEDGER (break_aligned);
-  DECLARE_ACKNOWLEDGER (break_alignable);
+  void acknowledge_break_aligned (Grob_info);
+  void acknowledge_break_alignable (Grob_info);
 };
 
 void
@@ -155,8 +155,13 @@ Break_align_engraver::add_to_group (SCM align_name, Item *item)
   Axis_group_interface::add_element (group, item);
 }
 
-ADD_ACKNOWLEDGER (Break_align_engraver, break_aligned);
-ADD_ACKNOWLEDGER (Break_align_engraver, break_alignable);
+void
+Break_align_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Break_align_engraver, break_aligned);
+  ADD_ACKNOWLEDGER (Break_align_engraver, break_alignable);
+}
+
 ADD_TRANSLATOR (Break_align_engraver,
                 /* doc */
                 "Align grobs with corresponding @code{break-align-symbols}"
index 34b296d10b248028416c87286138c4073c6583af..ade1b15f297ea1dd4f32a1bfc1437c51fce8935e 100644 (file)
@@ -39,7 +39,7 @@ protected:
   void process_music ();
   void stop_translation_timestep ();
 
-  DECLARE_TRANSLATOR_LISTENER (breathing);
+  void listen_breathing (Stream_event *);
 private:
   Stream_event *breathing_sign_event_;
   Grob *breathing_sign_;
@@ -51,7 +51,6 @@ Breathing_sign_engraver::Breathing_sign_engraver ()
   breathing_sign_event_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Breathing_sign_engraver, breathing);
 void
 Breathing_sign_engraver::listen_breathing (Stream_event *ev)
 {
@@ -74,6 +73,12 @@ Breathing_sign_engraver::stop_translation_timestep ()
   breathing_sign_event_ = 0;
 }
 
+void
+Breathing_sign_engraver::boot ()
+{
+  ADD_LISTENER (Breathing_sign_engraver, breathing);
+}
+
 ADD_TRANSLATOR (Breathing_sign_engraver,
                 /* doc */
                 "Create a breathing sign.",
diff --git a/lily/callback.cc b/lily/callback.cc
deleted file mode 100644 (file)
index 5310295..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-  This file is part of LilyPond, the GNU music typesetter.
-
-  Copyright (C) 2016  David Kastrup <dak@gnu.org>
-
-  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/>.
-*/
-
-#include "callback.hh"
-
-const char * const Callback_wrapper::type_p_name_ = 0;
index db8493e2a5a6648478caf455e780dc104d15c65f..3a14ff4b07f44168ce5117712d7e99e73812cc91 100644 (file)
@@ -39,8 +39,8 @@ protected:
   void stop_translation_timestep ();
   void process_music ();
   virtual void finalize ();
-  DECLARE_TRANSLATOR_LISTENER (note);
-  DECLARE_TRANSLATOR_LISTENER (rest);
+  void listen_note (Stream_event *);
+  void listen_rest (Stream_event *);
 private:
   vector<Stream_event *> notes_;
 
@@ -143,14 +143,12 @@ Chord_name_engraver::process_music ()
   context ()->set_property ("lastChord", markup);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Chord_name_engraver, note);
 void
 Chord_name_engraver::listen_note (Stream_event *ev)
 {
   notes_.push_back (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Chord_name_engraver, rest);
 void
 Chord_name_engraver::listen_rest (Stream_event *ev)
 {
@@ -168,6 +166,13 @@ Chord_name_engraver::stop_translation_timestep ()
   The READs description is not strictly accurate:
   which properties are read depend on the chord naming function active.
 */
+void
+Chord_name_engraver::boot ()
+{
+  ADD_LISTENER (Chord_name_engraver, note);
+  ADD_LISTENER (Chord_name_engraver, rest);
+}
+
 ADD_TRANSLATOR (Chord_name_engraver,
                 /* doc */
                 "Catch note and rest events and generate the appropriate chordname.",
index 3855c350d73e8e15b7e0faaa37d008ed902b0d6a..7a17c1350e36567857acb983eeda04695df3827f 100644 (file)
@@ -62,8 +62,8 @@ protected:
 protected:
   virtual void finalize ();
   void process_music ();
-  DECLARE_TRANSLATOR_LISTENER (tremolo_span);
-  DECLARE_ACKNOWLEDGER (stem);
+  void listen_tremolo_span (Stream_event *);
+  void acknowledge_stem (Grob_info);
 };
 
 Chord_tremolo_engraver::Chord_tremolo_engraver ()
@@ -73,7 +73,6 @@ Chord_tremolo_engraver::Chord_tremolo_engraver ()
   previous_stem_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Chord_tremolo_engraver, tremolo_span);
 void
 Chord_tremolo_engraver::listen_tremolo_span (Stream_event *ev)
 {
@@ -158,7 +157,13 @@ Chord_tremolo_engraver::acknowledge_stem (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Chord_tremolo_engraver, stem);
+void
+Chord_tremolo_engraver::boot ()
+{
+  ADD_LISTENER (Chord_tremolo_engraver, tremolo_span);
+  ADD_ACKNOWLEDGER (Chord_tremolo_engraver, stem);
+}
+
 ADD_TRANSLATOR (Chord_tremolo_engraver,
                 /* doc */
                 "Generate beams for tremolo repeats.",
index 940a18d2010849e27ecf73b66f99361aa6a3260c..00b3c3e55a736ef930d8d048afe30c2d74869df3 100644 (file)
@@ -39,7 +39,7 @@ public:
 protected:
   void stop_translation_timestep ();
   void process_music ();
-  DECLARE_ACKNOWLEDGER (bar_line);
+  void acknowledge_bar_line (Grob_info);
 
   virtual void derived_mark () const;
 private:
@@ -203,7 +203,12 @@ Clef_engraver::stop_translation_timestep ()
     }
 }
 
-ADD_ACKNOWLEDGER (Clef_engraver, bar_line);
+void
+Clef_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Clef_engraver, bar_line);
+}
+
 ADD_TRANSLATOR (Clef_engraver,
                 /* doc */
                 "Determine and set reference point for pitches.",
index bb5ed0dc54da0b6f79b430afb227b2bb35682ab7..0c84d1cb650019a32607e4744588715ea3b4d09e 100644 (file)
@@ -34,8 +34,8 @@ class Cluster_spanner_engraver : public Engraver
 
 protected:
   TRANSLATOR_DECLARATIONS (Cluster_spanner_engraver);
-  DECLARE_TRANSLATOR_LISTENER (cluster_note);
-  DECLARE_ACKNOWLEDGER (note_column);
+  void listen_cluster_note (Stream_event *);
+  void acknowledge_note_column (Grob_info);
   void stop_translation_timestep ();
   virtual void process_music ();
   virtual void finalize ();
@@ -81,7 +81,6 @@ Cluster_spanner_engraver::typeset_grobs ()
   beacon_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Cluster_spanner_engraver, cluster_note);
 void
 Cluster_spanner_engraver::listen_cluster_note (Stream_event *ev)
 {
@@ -142,7 +141,13 @@ Cluster_spanner_engraver::acknowledge_note_column (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Cluster_spanner_engraver, note_column);
+void
+Cluster_spanner_engraver::boot ()
+{
+  ADD_LISTENER (Cluster_spanner_engraver, cluster_note);
+  ADD_ACKNOWLEDGER (Cluster_spanner_engraver, note_column);
+}
+
 ADD_TRANSLATOR (Cluster_spanner_engraver,
                 /* doc */
                 "Engrave a cluster using @code{Spanner} notation.",
index d1eb2dd3c0a4b49bc29a7f4553468c43b677420c..ca6a52d320a09dde5c5ff326611bfe4309ded81b 100644 (file)
@@ -31,7 +31,7 @@ class Collision_engraver : public Engraver
   vector<Grob *> note_columns_;
 
 protected:
-  DECLARE_ACKNOWLEDGER (note_column);
+  void acknowledge_note_column (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
 public:
@@ -78,7 +78,12 @@ Collision_engraver::Collision_engraver ()
   col_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Collision_engraver, note_column);
+
+void
+Collision_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Collision_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Collision_engraver,
                 /* doc */
index 34a985d32da3cd1b16f2dda5e7bb2ff5a93fd5b2..ef3a5012a26cbc5a77d192904ffb216d5082c4ab 100644 (file)
@@ -80,7 +80,7 @@ protected:
   void start_translation_timestep ();
   void process_music ();
   void stop_translation_timestep ();
-  DECLARE_TRANSLATOR_LISTENER (note);
+  void listen_note (Stream_event *);
 };
 
 void
@@ -89,7 +89,6 @@ Completion_heads_engraver::initialize ()
   is_first_ = false;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Completion_heads_engraver, note);
 void
 Completion_heads_engraver::listen_note (Stream_event *ev)
 {
@@ -307,6 +306,12 @@ Completion_heads_engraver::Completion_heads_engraver ()
   tie_column_ = 0;
 }
 
+void
+Completion_heads_engraver::boot ()
+{
+  ADD_LISTENER (Completion_heads_engraver, note);
+}
+
 ADD_TRANSLATOR (Completion_heads_engraver,
                 /* doc */
                 "This engraver replaces @code{Note_heads_engraver}.  It plays"
index 8f809fde7021f9cd7cc9a175602ef6cbc1435b61..2b5693916e96ee25e02d0d1ff9a4882e50b51b1d 100644 (file)
@@ -76,7 +76,7 @@ protected:
   void start_translation_timestep ();
   void process_music ();
   void stop_translation_timestep ();
-  DECLARE_TRANSLATOR_LISTENER (rest);
+  void listen_rest (Stream_event *);
 };
 
 void
@@ -85,7 +85,6 @@ Completion_rest_engraver::initialize ()
   is_first_ = false;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Completion_rest_engraver, rest);
 void
 Completion_rest_engraver::listen_rest (Stream_event *ev)
 {
@@ -258,6 +257,12 @@ Completion_rest_engraver::Completion_rest_engraver ()
 {
 }
 
+void
+Completion_rest_engraver::boot ()
+{
+  ADD_LISTENER (Completion_rest_engraver, rest);
+}
+
 ADD_TRANSLATOR (Completion_rest_engraver,
                 /* doc */
                 "This engraver replaces @code{Rest_engraver}.  It plays"
index aa167b7de40a55120e4179d3d8c1a4ca05582bcd..3fdf6524c243f6745fa93883b7b46223528c1ca7 100644 (file)
@@ -34,8 +34,8 @@ public:
   TRANSLATOR_DECLARATIONS (Concurrent_hairpin_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (hairpin);
-  DECLARE_END_ACKNOWLEDGER (hairpin);
+  void acknowledge_hairpin (Grob_info);
+  void acknowledge_end_hairpin (Grob_info);
 
   void stop_translation_timestep ();
   void finalize ();
@@ -100,8 +100,13 @@ Concurrent_hairpin_engraver::finalize ()
   hairpins_hanging_out_.resize (0);
 }
 
-ADD_ACKNOWLEDGER (Concurrent_hairpin_engraver, hairpin);
-ADD_END_ACKNOWLEDGER (Concurrent_hairpin_engraver, hairpin);
+
+void
+Concurrent_hairpin_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Concurrent_hairpin_engraver, hairpin);
+  ADD_END_ACKNOWLEDGER (Concurrent_hairpin_engraver, hairpin);
+}
 
 ADD_TRANSLATOR (Concurrent_hairpin_engraver,
                 /* doc */
index 3258297b49539e2af7ed329eba280fc1b4192e6c..402bd80b6e8baf329b52b07c16275751f8c0b95b 100644 (file)
@@ -82,7 +82,7 @@ Context_def::~Context_def ()
 {
 }
 
-const char Context_def::type_p_name_[] = "ly:context-def?";
+const char * const Context_def::type_p_name_ = "ly:context-def?";
 
 int
 Context_def::print_smob (SCM port, scm_print_state *) const
index a533da2cbd05f4f2e990263e6396d2a4fb536491..892d692bbf8f6c2a89ff1d7288929cf8a8891e95 100644 (file)
@@ -34,7 +34,7 @@ Context_mod::Context_mod (SCM mod_list)
   mods_ = scm_reverse (mod_list);
 }
 
-const char Context_mod::type_p_name_[] = "ly:context-mod?";
+const char * const Context_mod::type_p_name_ = "ly:context-mod?";
 
 int
 Context_mod::print_smob (SCM port, scm_print_state *) const
index e0acae14557319223f253df2655caf80950796c0..6e22b2f808211b28aaa7acedad6afba52f9829f6 100644 (file)
@@ -66,7 +66,7 @@ class Grob_properties : public Simple_smob<Grob_properties>
 {
 public:
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   friend class Grob_property_info;
   friend SCM ly_make_grob_properties (SCM);
@@ -97,7 +97,7 @@ private:
     cooked_ (alist), cooked_from_ (alist), nested_ (0) { }
 };
 
-const char Grob_properties::type_p_name_[] = "ly:grob-properties?";
+const char * const Grob_properties::type_p_name_ = "ly:grob-properties?";
 
 SCM
 Grob_properties::mark_smob () const
index a6b1da6a3609787625c7546905cf61a2935d6bf2..7de61c5796fd291739c8f8e700a8132f58e1b2a8 100644 (file)
@@ -49,9 +49,13 @@ Context::check_removal ()
       ctx->check_removal ();
       if (ctx->is_removable ())
         {
-          recurse_over_translators (ctx, &Translator::finalize,
-                                    &Translator_group::finalize,
-                                    UP);
+          recurse_over_translators
+            (ctx,
+             Callback0_wrapper::make_smob
+             <Translator, &Translator::finalize> (),
+             Callback0_wrapper::make_smob
+             <Translator_group, &Translator_group::finalize> (),
+             UP);
           send_stream_event (ctx, "RemoveContext", 0, 0);
         }
     }
@@ -775,7 +779,7 @@ Context::mark_smob () const
   return properties_scm_;
 }
 
-const char Context::type_p_name_[] = "ly:context?";
+const char * const Context::type_p_name_ = "ly:context?";
 
 Global_context *
 Context::get_global_context () const
index 82beebe122fb002066f0fede1a4303c67fcbadd7..db6efe649ed5b3fa15c6155d51e8d8084e51b14f 100644 (file)
@@ -66,6 +66,12 @@ Control_track_performer::initialize ()
   add_text (Audio_text::TEXT, id_string);
 }
 
+void
+Control_track_performer::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Control_track_performer,
                 /* doc */
                 "",
index 383c9a1b1f7c33c2150a30c8e2e8fc6444d93408..53640afadc17264e62e765b6a1f238d592e5e548 100644 (file)
@@ -41,7 +41,7 @@ public:
 protected:
   void stop_translation_timestep ();
   void process_music ();
-  DECLARE_ACKNOWLEDGER (bar_line);
+  void acknowledge_bar_line (Grob_info);
 
   virtual void derived_mark () const;
 private:
@@ -209,7 +209,12 @@ Cue_clef_engraver::stop_translation_timestep ()
     }
 }
 
-ADD_ACKNOWLEDGER (Cue_clef_engraver, bar_line);
+void
+Cue_clef_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Cue_clef_engraver, bar_line);
+}
+
 ADD_TRANSLATOR (Cue_clef_engraver,
                 /* doc */
                 "Determine and set reference point for pitches in cued voices.",
index 5893dc205b731d84d6e8b3901d992b23bac4b6a9..a21ad4eb787ee8c9a4a91047abad40ffaa802601 100644 (file)
@@ -39,8 +39,8 @@ class Custos_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Custos_engraver);
   void start_translation_timestep ();
-  DECLARE_ACKNOWLEDGER (bar);
-  DECLARE_ACKNOWLEDGER (note_head);
+  void acknowledge_bar (Grob_info);
+  void acknowledge_note_head (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
   virtual void finalize ();
@@ -142,8 +142,13 @@ Custos_engraver::finalize ()
   custodes_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Custos_engraver, bar);
-ADD_ACKNOWLEDGER (Custos_engraver, note_head);
+
+void
+Custos_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Custos_engraver, bar);
+  ADD_ACKNOWLEDGER (Custos_engraver, note_head);
+}
 
 ADD_TRANSLATOR (Custos_engraver,
                 /* doc */
index 4eeb23036774feb4373e67bdad6e5577918678ba..a8b9898276c518ea263b3663e67d1df37b7bcdc5 100644 (file)
@@ -37,6 +37,12 @@ public:
 
 #include "translator.icc"
 
+void
+Default_bar_line_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Default_bar_line_engraver,
                 /* doc */
                 "This engraver determines what kind of automatic bar lines"
index 8f938d6f91a8bcd86a3721128bf0ba5c11920619..b1b076759f83b8a7e1a655d84054957b84afb4c5 100644 (file)
@@ -23,7 +23,7 @@
 #include "warn.hh"
 #include "lily-imports.hh"
 
-const char Dispatcher::type_p_name_[] = "ly:dispatcher?";
+const char * const Dispatcher::type_p_name_ = "ly:dispatcher?";
 
 Dispatcher::~Dispatcher ()
 {
index c646ed038cde099d9169ff488e34e125c5a48081..c5c80015249791f858e82ba1499e820122be975a 100644 (file)
@@ -32,7 +32,7 @@ public:
 
 protected:
 
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
+  void acknowledge_rhythmic_head (Grob_info);
 
   void stop_translation_timestep ();
 };
@@ -61,7 +61,12 @@ Dot_column_engraver::acknowledge_rhythmic_head (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Dot_column_engraver, rhythmic_head);
+void
+Dot_column_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Dot_column_engraver, rhythmic_head);
+}
+
 ADD_TRANSLATOR (Dot_column_engraver,
                 /* doc */
                 "Engrave dots on dotted notes shifted to the right of the"
index 5465f460f6077e61d46fa4de53ffadbfe90b9495..cbd6c718a9e944bcc70b245b64b88045575c4ed6 100644 (file)
@@ -27,7 +27,7 @@
 
 class Dots_engraver : public Engraver
 {
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
+  void acknowledge_rhythmic_head (Grob_info);
   TRANSLATOR_DECLARATIONS (Dots_engraver);
 };
 
@@ -56,7 +56,12 @@ Dots_engraver::acknowledge_rhythmic_head (Grob_info gi)
     }
 }
 
-ADD_ACKNOWLEDGER (Dots_engraver, rhythmic_head);
+
+void
+Dots_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Dots_engraver, rhythmic_head);
+}
 
 ADD_TRANSLATOR (Dots_engraver,
                 "Create @ref{Dots} objects for"
index d85648293ece82b38ed4f8a327ff8d2492783be1..d1717f8314a96f68b67cb85367f8a79910673767 100644 (file)
@@ -38,7 +38,7 @@ protected:
   // moment (global time) where percent started
   Moment start_mom_;
 
-  DECLARE_TRANSLATOR_LISTENER (double_percent);
+  void listen_double_percent (Stream_event *);
 
   void process_music ();
 };
@@ -48,7 +48,6 @@ Double_percent_repeat_engraver::Double_percent_repeat_engraver ()
   percent_event_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Double_percent_repeat_engraver, double_percent);
 void
 Double_percent_repeat_engraver::listen_double_percent (Stream_event *ev)
 {
@@ -95,6 +94,12 @@ Double_percent_repeat_engraver::process_music ()
     }
 }
 
+void
+Double_percent_repeat_engraver::boot ()
+{
+  ADD_LISTENER (Double_percent_repeat_engraver, double_percent);
+}
+
 ADD_TRANSLATOR (Double_percent_repeat_engraver,
                 /* doc */
                 "Make double measure repeats.",
index 09a58fa24b873722f89bddc8310cc41ed529f1ef..16b089cb703cca7877766b9e16ed202929357fbb 100644 (file)
@@ -43,9 +43,9 @@ public:
 
 protected:
   void process_music ();
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_TRANSLATOR_LISTENER (note);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_note_column (Grob_info);
+  void listen_note (Stream_event *);
   void stop_translation_timestep ();
 };
 
@@ -53,7 +53,6 @@ Drum_notes_engraver::Drum_notes_engraver ()
 {
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Drum_notes_engraver, note);
 void
 Drum_notes_engraver::listen_note (Stream_event *ev)
 {
@@ -140,8 +139,14 @@ Drum_notes_engraver::stop_translation_timestep ()
   events_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Drum_notes_engraver, stem);
-ADD_ACKNOWLEDGER (Drum_notes_engraver, note_column);
+
+void
+Drum_notes_engraver::boot ()
+{
+  ADD_LISTENER (Drum_notes_engraver, note);
+  ADD_ACKNOWLEDGER (Drum_notes_engraver, stem);
+  ADD_ACKNOWLEDGER (Drum_notes_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Drum_notes_engraver,
                 /* doc */
index 0285de650478c880493963c576389112057058c5..93f648f3d765b4047afc23803e1e6eb8eda3a840 100644 (file)
@@ -33,7 +33,7 @@ public:
 protected:
   void stop_translation_timestep ();
   void process_music ();
-  DECLARE_TRANSLATOR_LISTENER (note);
+  void listen_note (Stream_event *);
 private:
   vector<Stream_event *> note_evs_;
 };
@@ -96,13 +96,18 @@ Drum_note_performer::stop_translation_timestep ()
   note_evs_.clear ();
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Drum_note_performer, note);
 void
 Drum_note_performer::listen_note (Stream_event *ev)
 {
   note_evs_.push_back (ev);
 }
 
+void
+Drum_note_performer::boot ()
+{
+  ADD_LISTENER (Drum_note_performer, note);
+}
+
 ADD_TRANSLATOR (Drum_note_performer,
                 /* doc */
                 "Play drum notes.",
index 0b1001954072852ea366ad18c257aa19ef0fb4e0..0c6fa4dd5f55c89b5fe628276c04b47acc3f7cc4 100644 (file)
@@ -136,7 +136,7 @@ Duration::to_string () const
   return s;
 }
 
-const char Duration::type_p_name_[] = "ly:duration?";
+const char * const Duration::type_p_name_ = "ly:duration?";
 
 
 int
index 0abb39a7f2614b5bd0ab79e488b2159e46890f14..c276e217593e7b209e1cce5f47b15a8610dd8e1b 100644 (file)
 class Dynamic_align_engraver : public Engraver
 {
   TRANSLATOR_DECLARATIONS (Dynamic_align_engraver);
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (dynamic);
-  DECLARE_ACKNOWLEDGER (footnote_spanner);
-  DECLARE_END_ACKNOWLEDGER (dynamic);
+  void acknowledge_rhythmic_head (Grob_info);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_dynamic (Grob_info);
+  void acknowledge_footnote_spanner (Grob_info);
+  void acknowledge_end_dynamic (Grob_info);
 
 protected:
   virtual void stop_translation_timestep ();
@@ -64,11 +64,6 @@ Dynamic_align_engraver::Dynamic_align_engraver ()
   current_dynamic_spanner_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
-ADD_ACKNOWLEDGER (Dynamic_align_engraver, rhythmic_head);
-ADD_ACKNOWLEDGER (Dynamic_align_engraver, stem);
-ADD_ACKNOWLEDGER (Dynamic_align_engraver, footnote_spanner);
-ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
 
 void
 Dynamic_align_engraver::create_line_spanner (Grob *cause)
@@ -232,6 +227,16 @@ Dynamic_align_engraver::stop_translation_timestep ()
   support_.clear ();
 }
 
+void
+Dynamic_align_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
+  ADD_ACKNOWLEDGER (Dynamic_align_engraver, rhythmic_head);
+  ADD_ACKNOWLEDGER (Dynamic_align_engraver, stem);
+  ADD_ACKNOWLEDGER (Dynamic_align_engraver, footnote_spanner);
+  ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
+}
+
 ADD_TRANSLATOR (Dynamic_align_engraver,
                 /* doc */
                 "Align hairpins and dynamic texts on a horizontal line.",
index edfd35fcb5912652b08a46dd3548da3cc5866ac6..5d4ef33de3aee6f282176fd92d3f82baf23966dc 100644 (file)
 class Dynamic_engraver : public Engraver
 {
   TRANSLATOR_DECLARATIONS (Dynamic_engraver);
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
-  DECLARE_TRANSLATOR_LISTENER (span_dynamic);
-  DECLARE_TRANSLATOR_LISTENER (break_span);
+  void acknowledge_note_column (Grob_info);
+  void listen_absolute_dynamic (Stream_event *);
+  void listen_span_dynamic (Stream_event *);
+  void listen_break_span (Stream_event *);
 
 protected:
   virtual void process_music ();
@@ -69,14 +69,12 @@ Dynamic_engraver::Dynamic_engraver ()
   end_new_spanner_ = false;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_engraver, absolute_dynamic);
 void
 Dynamic_engraver::listen_absolute_dynamic (Stream_event *ev)
 {
   ASSIGN_EVENT_ONCE (script_event_, ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_engraver, span_dynamic);
 void
 Dynamic_engraver::listen_span_dynamic (Stream_event *ev)
 {
@@ -85,7 +83,6 @@ Dynamic_engraver::listen_span_dynamic (Stream_event *ev)
   ASSIGN_EVENT_ONCE (accepted_spanevents_drul_[d], ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_engraver, break_span);
 void
 Dynamic_engraver::listen_break_span (Stream_event *event)
 {
@@ -278,7 +275,15 @@ Dynamic_engraver::acknowledge_note_column (Grob_info info)
     finished_spanner_->set_bound (RIGHT, info.grob ());
 }
 
-ADD_ACKNOWLEDGER (Dynamic_engraver, note_column);
+void
+Dynamic_engraver::boot ()
+{
+  ADD_LISTENER (Dynamic_engraver, absolute_dynamic);
+  ADD_LISTENER (Dynamic_engraver, span_dynamic);
+  ADD_LISTENER (Dynamic_engraver, break_span);
+  ADD_ACKNOWLEDGER (Dynamic_engraver, note_column);
+}
+
 ADD_TRANSLATOR (Dynamic_engraver,
                 /* doc */
                 "Create hairpins, dynamic texts and dynamic text spanners.",
index 6a6f8b8cf9acefceb7235547568556133609388e..46a8a446d35af8c3a32e949c34f59ed962e520c1 100644 (file)
@@ -33,9 +33,9 @@ protected:
   void process_music ();
   Real equalize_volume (Real);
 
-  DECLARE_TRANSLATOR_LISTENER (decrescendo);
-  DECLARE_TRANSLATOR_LISTENER (crescendo);
-  DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
+  void listen_decrescendo (Stream_event *);
+  void listen_crescendo (Stream_event *);
+  void listen_absolute_dynamic (Stream_event *);
 private:
   Stream_event *script_event_;
   Drul_array<Stream_event *> span_events_;
@@ -206,7 +206,6 @@ Dynamic_performer::stop_translation_timestep ()
     = span_events_[RIGHT] = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, decrescendo);
 void
 Dynamic_performer::listen_decrescendo (Stream_event *r)
 {
@@ -215,7 +214,6 @@ Dynamic_performer::listen_decrescendo (Stream_event *r)
   grow_dir_[d] = SMALLER;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, crescendo);
 void
 Dynamic_performer::listen_crescendo (Stream_event *r)
 {
@@ -224,7 +222,6 @@ Dynamic_performer::listen_crescendo (Stream_event *r)
   grow_dir_[d] = BIGGER;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_performer, absolute_dynamic);
 void
 Dynamic_performer::listen_absolute_dynamic (Stream_event *r)
 {
@@ -232,6 +229,14 @@ Dynamic_performer::listen_absolute_dynamic (Stream_event *r)
     script_event_ = r;
 }
 
+void
+Dynamic_performer::boot ()
+{
+  ADD_LISTENER (Dynamic_performer, decrescendo);
+  ADD_LISTENER (Dynamic_performer, crescendo);
+  ADD_LISTENER (Dynamic_performer, absolute_dynamic);
+}
+
 ADD_TRANSLATOR (Dynamic_performer,
                 /* doc */
                 "",
index 25ae579bd7dbcd59f844b28c05b51d1db54e9d4a..5a1486927a3f696a9d503b99ab5dce2fb61ff2dd 100644 (file)
@@ -175,20 +175,3 @@ ly_is_grob_cause (SCM obj)
 {
   return unsmob<Grob> (obj) || unsmob<Stream_event> (obj) || scm_is_null (obj);
 }
-
-#include "translator.icc"
-
-ADD_TRANSLATOR (Engraver,
-                /* doc */
-                "Base class for engravers.  Does nothing, so it is not used.",
-
-                /* create */
-                "",
-
-                /* read */
-                "",
-
-                /* write */
-                ""
-               );
-
index a62ed3726f8bd9c2269e4c8f73148dba80528d0b..d2fc2f398f9ac8856a0ef4b69cf2e5d3392edb20 100644 (file)
@@ -33,9 +33,9 @@ public:
   TRANSLATOR_DECLARATIONS (Episema_engraver);
 protected:
   virtual void finalize ();
-  DECLARE_TRANSLATOR_LISTENER (episema);
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_ACKNOWLEDGER (note_head);
+  void listen_episema (Stream_event *);
+  void acknowledge_note_column (Grob_info);
+  void acknowledge_note_head (Grob_info);
   void stop_translation_timestep ();
   void process_music ();
 
@@ -56,7 +56,6 @@ Episema_engraver::Episema_engraver ()
   event_drul_.set (0, 0);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Episema_engraver, episema);
 void
 Episema_engraver::listen_episema (Stream_event *ev)
 {
@@ -161,8 +160,14 @@ Episema_engraver::acknowledge_note_head (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Episema_engraver, note_column);
-ADD_ACKNOWLEDGER (Episema_engraver, note_head);
+
+void
+Episema_engraver::boot ()
+{
+  ADD_LISTENER (Episema_engraver, episema);
+  ADD_ACKNOWLEDGER (Episema_engraver, note_column);
+  ADD_ACKNOWLEDGER (Episema_engraver, note_head);
+}
 
 ADD_TRANSLATOR (Episema_engraver,
                 /* doc */
index 3f3ef3b3ff3941527362496a43e9f2a3f964274a..39fa7788dedb87fa6a4ff5344c865f9c963383c3 100644 (file)
@@ -43,9 +43,9 @@ public:
   TRANSLATOR_DECLARATIONS (Extender_engraver);
 
 protected:
-  DECLARE_TRANSLATOR_LISTENER (extender);
-  DECLARE_TRANSLATOR_LISTENER (completize_extender);
-  DECLARE_ACKNOWLEDGER (lyric_syllable);
+  void listen_extender (Stream_event *);
+  void listen_completize_extender (Stream_event *);
+  void acknowledge_lyric_syllable (Grob_info);
 
   virtual void finalize ();
 
@@ -60,7 +60,6 @@ Extender_engraver::Extender_engraver ()
   ev_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender);
 void
 Extender_engraver::listen_extender (Stream_event *ev)
 {
@@ -73,7 +72,6 @@ Extender_engraver::listen_extender (Stream_event *ev)
   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 */)
 {
@@ -180,7 +178,14 @@ Extender_engraver::finalize ()
     }
 }
 
-ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
+void
+Extender_engraver::boot ()
+{
+  ADD_LISTENER (Extender_engraver, extender);
+  ADD_LISTENER (Extender_engraver, completize_extender);
+  ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
+}
+
 ADD_TRANSLATOR (Extender_engraver,
                 /* doc */
                 "Create lyric extenders.",
index 2ed07e3e836fc410e2cddb846b332b9e2d3bab2a..9785f3fef47e763efc7acc2da7636ed7e20a7b72 100644 (file)
@@ -122,8 +122,8 @@ protected:
   Moment stop_moment_;
   bool have_rest_;
 
-  DECLARE_TRANSLATOR_LISTENER (rest);
-  DECLARE_TRANSLATOR_LISTENER (bass_figure);
+  void listen_rest (Stream_event *);
+  void listen_bass_figure (Stream_event *);
 
   virtual void derived_mark () const;
 
@@ -180,14 +180,12 @@ Figured_bass_engraver::stop_translation_timestep ()
     clear_spanners ();
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Figured_bass_engraver, rest);
 void
 Figured_bass_engraver::listen_rest (Stream_event *)
 {
   have_rest_ = true;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Figured_bass_engraver, bass_figure);
 void
 Figured_bass_engraver::listen_bass_figure (Stream_event *ev)
 {
@@ -504,6 +502,13 @@ Figured_bass_engraver::add_brackets ()
     }
 }
 
+void
+Figured_bass_engraver::boot ()
+{
+  ADD_LISTENER (Figured_bass_engraver, rest);
+  ADD_LISTENER (Figured_bass_engraver, bass_figure);
+}
+
 ADD_TRANSLATOR (Figured_bass_engraver,
                 /* doc */
                 "Make figured bass numbers.",
index c1df4623e6271a610fc6bc8df3f373418c7e6e74..66fabb1ffb6d4a0a316aeccb31bec741bfefd759 100644 (file)
@@ -36,12 +36,12 @@ class Figured_bass_position_engraver : public Engraver
   vector<Grob *> support_;
   vector<Grob *> span_support_;
 protected:
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_ACKNOWLEDGER (slur);
-  DECLARE_END_ACKNOWLEDGER (slur);
-  DECLARE_END_ACKNOWLEDGER (tie);
-  DECLARE_ACKNOWLEDGER (bass_figure_alignment);
-  DECLARE_END_ACKNOWLEDGER (bass_figure_alignment);
+  void acknowledge_note_column (Grob_info);
+  void acknowledge_slur (Grob_info);
+  void acknowledge_end_slur (Grob_info);
+  void acknowledge_end_tie (Grob_info);
+  void acknowledge_bass_figure_alignment (Grob_info);
+  void acknowledge_end_bass_figure_alignment (Grob_info);
 
   virtual void finalize ();
   void start_spanner ();
@@ -138,13 +138,18 @@ Figured_bass_position_engraver::acknowledge_bass_figure_alignment (Grob_info inf
   start_spanner ();
 }
 
-ADD_ACKNOWLEDGER (Figured_bass_position_engraver, note_column);
-ADD_ACKNOWLEDGER (Figured_bass_position_engraver, slur);
-ADD_END_ACKNOWLEDGER (Figured_bass_position_engraver, slur);
 
-ADD_END_ACKNOWLEDGER (Figured_bass_position_engraver, tie);
-ADD_ACKNOWLEDGER (Figured_bass_position_engraver, bass_figure_alignment);
-ADD_END_ACKNOWLEDGER (Figured_bass_position_engraver, bass_figure_alignment);
+
+void
+Figured_bass_position_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Figured_bass_position_engraver, note_column);
+  ADD_ACKNOWLEDGER (Figured_bass_position_engraver, slur);
+  ADD_END_ACKNOWLEDGER (Figured_bass_position_engraver, slur);
+  ADD_END_ACKNOWLEDGER (Figured_bass_position_engraver, tie);
+  ADD_ACKNOWLEDGER (Figured_bass_position_engraver, bass_figure_alignment);
+  ADD_END_ACKNOWLEDGER (Figured_bass_position_engraver, bass_figure_alignment);
+}
 
 ADD_TRANSLATOR (Figured_bass_position_engraver,
                 /* doc */
index 1c5b904809809c81f09022b68638edab7c39637d..a2a37143b37a81efc59482fda913b1b7c7eddf20 100644 (file)
@@ -37,7 +37,7 @@ class Fingering_column_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Fingering_column_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (finger);
+  void acknowledge_finger (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
 };
@@ -101,7 +101,12 @@ Fingering_column_engraver::process_acknowledged ()
     }
 }
 
-ADD_ACKNOWLEDGER (Fingering_column_engraver, finger);
+void
+Fingering_column_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Fingering_column_engraver, finger);
+}
+
 ADD_TRANSLATOR (Fingering_column_engraver,
                 /* doc */
                 "Find potentially colliding scripts and put them into a"
index d5b4102d8bf844bd3ef8cbb28aa71a357bb673aa..8de44e96984ed22d18a504a1d5fe41bc9118d8bc 100644 (file)
@@ -38,16 +38,15 @@ public:
 protected:
   void stop_translation_timestep ();
   void process_music ();
-  DECLARE_TRANSLATOR_LISTENER (fingering);
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (flag);
+  void listen_fingering (Stream_event *);
+  void acknowledge_rhythmic_head (Grob_info);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_flag (Grob_info);
 
 private:
   void make_script (Direction, Stream_event *, int);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Fingering_engraver, fingering);
 void
 Fingering_engraver::listen_fingering (Stream_event *ev)
 {
@@ -141,9 +140,15 @@ Fingering_engraver::Fingering_engraver ()
 {
 }
 
-ADD_ACKNOWLEDGER (Fingering_engraver, rhythmic_head);
-ADD_ACKNOWLEDGER (Fingering_engraver, stem);
-ADD_ACKNOWLEDGER (Fingering_engraver, flag);
+
+void
+Fingering_engraver::boot ()
+{
+  ADD_LISTENER (Fingering_engraver, fingering);
+  ADD_ACKNOWLEDGER (Fingering_engraver, rhythmic_head);
+  ADD_ACKNOWLEDGER (Fingering_engraver, stem);
+  ADD_ACKNOWLEDGER (Fingering_engraver, flag);
+}
 
 ADD_TRANSLATOR (Fingering_engraver,
                 /* doc */
index f2b6a0e1476c2e669a1917d47f8d17343960ac37..c9daa95f3edf2000d39fb47a5d856a8df505073a 100644 (file)
@@ -112,7 +112,7 @@ Font_metric::print_smob (SCM port, scm_print_state *) const
   return 1;
 }
 
-const char Font_metric::type_p_name_[] = "ly:font-metric?";
+const char * const Font_metric::type_p_name_ = "ly:font-metric?";
 
 SCM
 Font_metric::font_file_name () const
index b9250358dd2197a48356529db9aa5db9954f9bdb..4dfd24d01444a561a2485f6001aeb9f14f57c8d3 100644 (file)
@@ -25,7 +25,7 @@ class Font_size_engraver : public Engraver
 
   TRANSLATOR_DECLARATIONS (Font_size_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (font);
+  void acknowledge_font (Grob_info);
   void process_music ();
   Real size;
 private:
@@ -61,7 +61,12 @@ Font_size_engraver::acknowledge_font (Grob_info gi)
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Font_size_engraver, font);
+void
+Font_size_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Font_size_engraver, font);
+}
+
 ADD_TRANSLATOR (Font_size_engraver,
                 /* doc */
                 "Put @code{fontSize} into @code{font-size} grob property.",
index 636379125f73b36caf936bbddba4fc632244f0e8..e80d9b64cec69b8016a4a2aca5cb5bdfb4f924f5 100644 (file)
@@ -33,8 +33,8 @@ class Footnote_engraver : public Engraver
 {
   TRANSLATOR_DECLARATIONS (Footnote_engraver);
 
-  DECLARE_ACKNOWLEDGER (grob);
-  DECLARE_END_ACKNOWLEDGER (grob);
+  void acknowledge_grob (Grob_info);
+  void acknowledge_end_grob (Grob_info);
 
   vector<Drul_array<Spanner *> > annotated_spanners_;
 
@@ -114,8 +114,13 @@ Footnote_engraver::acknowledge_end_grob (Grob_info info)
       }
 }
 
-ADD_ACKNOWLEDGER (Footnote_engraver, grob);
-ADD_END_ACKNOWLEDGER (Footnote_engraver, grob);
+
+void
+Footnote_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Footnote_engraver, grob);
+  ADD_END_ACKNOWLEDGER (Footnote_engraver, grob);
+}
 
 ADD_TRANSLATOR (Footnote_engraver,
                 /* doc */
index db0e254739c3cc5d7cee1a1eecaa1ada39adcb68..9cfdef24c82566634160bc4d22ba655e2be1e9e2 100644 (file)
@@ -58,6 +58,12 @@ Forbid_line_break_engraver::start_translation_timestep ()
     }
 }
 
+void
+Forbid_line_break_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Forbid_line_break_engraver,
                 /* doc */
                 "Forbid line breaks when note heads are still playing at some"
index 2ce799bf0f94b4516b90086bcd0f194fe17196bf..18843fc87c6d3c2d9829c6b29f1f337d85cd14f2 100644 (file)
@@ -48,9 +48,9 @@ protected:
   void stop_translation_timestep ();
   void process_music ();
   virtual void derived_mark () const;
-  DECLARE_TRANSLATOR_LISTENER (note);
-  DECLARE_TRANSLATOR_LISTENER (string_number);
-  DECLARE_TRANSLATOR_LISTENER (fingering);
+  void listen_note (Stream_event *);
+  void listen_string_number (Stream_event *);
+  void listen_fingering (Stream_event *);
 
 private:
   SCM last_placements_;
@@ -68,21 +68,18 @@ Fretboard_engraver::Fretboard_engraver ()
   last_placements_ = SCM_BOOL_F;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Fretboard_engraver, note);
 void
 Fretboard_engraver::listen_note (Stream_event *ev)
 {
   note_events_.push_back (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Fretboard_engraver, string_number);
 void
 Fretboard_engraver::listen_string_number (Stream_event *ev)
 {
   tabstring_events_.push_back (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Fretboard_engraver, fingering);
 void
 Fretboard_engraver::listen_fingering (Stream_event *ev)
 {
@@ -128,6 +125,14 @@ Fretboard_engraver::stop_translation_timestep ()
   fingering_events_.clear ();
 }
 
+void
+Fretboard_engraver::boot ()
+{
+  ADD_LISTENER (Fretboard_engraver, note);
+  ADD_LISTENER (Fretboard_engraver, string_number);
+  ADD_LISTENER (Fretboard_engraver, fingering);
+}
+
 ADD_TRANSLATOR (Fretboard_engraver,
                 /* doc */
                 "Generate fret diagram from one or more events of type"
index c7744d1f4b2db3288cbbb252f12ccd0e4b9d4824..878e7f88b355539a7f29e1cf75aa3e3e701108be 100644 (file)
@@ -35,8 +35,8 @@ public:
   TRANSLATOR_DECLARATIONS (Glissando_engraver);
 
 protected:
-  DECLARE_TRANSLATOR_LISTENER (glissando);
-  DECLARE_ACKNOWLEDGER (note_column);
+  void listen_glissando (Stream_event *);
+  void acknowledge_note_column (Grob_info);
   virtual void finalize ();
 
   void stop_translation_timestep ();
@@ -60,7 +60,6 @@ Glissando_engraver::Glissando_engraver ()
   stop_glissandi_ = false;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Glissando_engraver, glissando);
 void
 Glissando_engraver::listen_glissando (Stream_event *ev)
 {
@@ -170,7 +169,13 @@ Glissando_engraver::finalize ()
     kill_me_[i]->suicide ();
 }
 
-ADD_ACKNOWLEDGER (Glissando_engraver, note_column);
+void
+Glissando_engraver::boot ()
+{
+  ADD_LISTENER (Glissando_engraver, glissando);
+  ADD_ACKNOWLEDGER (Glissando_engraver, note_column);
+}
+
 ADD_TRANSLATOR (Glissando_engraver,
                 /* doc */
                 "Engrave glissandi.",
index 5279cab4c0fb2ed3fa7f2dd03bc4846a84d998a0..57ccb1e0fa4d18202fff38f18cc002a38b0f77f8 100644 (file)
@@ -157,6 +157,12 @@ Grace_engraver::derived_mark () const
   Engraver::derived_mark ();
 }
 
+void
+Grace_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Grace_engraver,
                 /* doc */
                 "Set font size and other properties for grace notes.",
index 5da9c90b5cc40b16f177261373e99c2096fdb0b3..445d2b0f81a7504c44df39d87efbeebd1b4be4ba 100644 (file)
@@ -77,6 +77,12 @@ Grace_spacing_engraver::stop_translation_timestep ()
     grace_spacing_ = 0;
 }
 
+void
+Grace_spacing_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Grace_spacing_engraver,
                 "Bookkeeping of shortest starting and playing notes in grace"
                 " note runs.",
index a61f61df789162cd495cca4b73e202a995784019..efecf676228f01de4c5d225f68231d5a7b3f749c 100644 (file)
@@ -31,7 +31,7 @@ class Grid_line_span_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Grid_line_span_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (grid_point);
+  void acknowledge_grid_point (Grob_info);
   void stop_translation_timestep ();
 };
 
@@ -70,7 +70,12 @@ Grid_line_span_engraver::stop_translation_timestep ()
   lines_.resize (0);
 }
 
-ADD_ACKNOWLEDGER (Grid_line_span_engraver, grid_point);
+void
+Grid_line_span_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Grid_line_span_engraver, grid_point);
+}
+
 ADD_TRANSLATOR (Grid_line_span_engraver,
                 /* doc */
                 "This engraver makes cross-staff lines: It catches all normal"
index f4361957874aadb5cd71e7f0d3b69776a11662a6..d67fb191b6463605ae35440913b6bd7d6deab823 100644 (file)
@@ -48,6 +48,12 @@ Grid_point_engraver::Grid_point_engraver ()
 {
 }
 
+void
+Grid_point_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Grid_point_engraver,
                 /* doc */
                 "Generate grid points.",
index ec0ee43e1895f92eb21f16f616110f5e1ed2ed0e..f5228dfd7148d91296dac7765b8b197cb162f34c 100644 (file)
@@ -116,7 +116,7 @@ Grob_array::filter_map_assign (const Grob_array &src,
     filter_map (map_fun);
 }
 
-const char Grob_array::type_p_name_[] = "ly:grob-array?";
+const char * const Grob_array::type_p_name_ = "ly:grob-array?";
 
 
 SCM
index 45b4ff2b359d7aca819c4ab074145eb9df430e4a..25392a43556d8746b6742cded90cb9e30da521a9 100644 (file)
@@ -42,7 +42,7 @@ public:
   TRANSLATOR_DECLARATIONS (Grob_pq_engraver);
 protected:
   virtual void initialize ();
-  DECLARE_ACKNOWLEDGER (grob);
+  void acknowledge_grob (Grob_info);
   void start_translation_timestep ();
   void stop_translation_timestep ();
   void process_acknowledged ();
@@ -148,7 +148,12 @@ Grob_pq_engraver::start_translation_timestep ()
     context ()->set_property ("busyGrobs", busy);
 }
 
-ADD_ACKNOWLEDGER (Grob_pq_engraver, grob);
+void
+Grob_pq_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Grob_pq_engraver, grob);
+}
+
 ADD_TRANSLATOR (Grob_pq_engraver,
                 /* doc */
                 "Administrate when certain grobs (e.g., note heads) stop"
index 066b700a252004ac86f809d721208c1f243fa8d9..72949973b1acf777fb88295945c7cf44e7f6e489 100644 (file)
@@ -23,7 +23,7 @@
 #include "warn.hh"
 
 
-const char Grob::type_p_name_[] = "ly:grob?";
+const char * const Grob::type_p_name_ = "ly:grob?";
 
 SCM
 Grob::mark_smob () const
index cd46817904db5726a5ed2dee7026b4fd1a2649e6..d50146a2d0ddaf0061104d33252b73166d36077b 100644 (file)
@@ -39,8 +39,8 @@ public:
 
   void stop_translation_timestep ();
   void process_music ();
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_TRANSLATOR_LISTENER (note_grouping);
+  void acknowledge_note_column (Grob_info);
+  void listen_note_grouping (Stream_event *);
 };
 
 Horizontal_bracket_engraver::Horizontal_bracket_engraver ()
@@ -49,7 +49,6 @@ Horizontal_bracket_engraver::Horizontal_bracket_engraver ()
   push_count_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Horizontal_bracket_engraver, note_grouping);
 void
 Horizontal_bracket_engraver::listen_note_grouping (Stream_event *ev)
 {
@@ -109,7 +108,13 @@ Horizontal_bracket_engraver::stop_translation_timestep ()
   events_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Horizontal_bracket_engraver, note_column);
+void
+Horizontal_bracket_engraver::boot ()
+{
+  ADD_LISTENER (Horizontal_bracket_engraver, note_grouping);
+  ADD_ACKNOWLEDGER (Horizontal_bracket_engraver, note_column);
+}
+
 ADD_TRANSLATOR (Horizontal_bracket_engraver,
                 /* doc */
                 "Create horizontal brackets over notes for musical analysis"
index be436655561f8421eac94c40d32c1b7950796839..19ff388963d2273934eb9a5356b1da005557aefe 100644 (file)
@@ -42,8 +42,8 @@ public:
 
 protected:
 
-  DECLARE_ACKNOWLEDGER (lyric_syllable);
-  DECLARE_TRANSLATOR_LISTENER (hyphen);
+  void acknowledge_lyric_syllable (Grob_info);
+  void listen_hyphen (Stream_event *);
 
   virtual void finalize ();
 
@@ -74,7 +74,6 @@ Hyphen_engraver::acknowledge_lyric_syllable (Grob_info i)
     finished_hyphen_->set_bound (RIGHT, item);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Hyphen_engraver, hyphen);
 void
 Hyphen_engraver::listen_hyphen (Stream_event *ev)
 {
@@ -155,7 +154,13 @@ Hyphen_engraver::stop_translation_timestep ()
   ev_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Hyphen_engraver, lyric_syllable);
+
+void
+Hyphen_engraver::boot ()
+{
+  ADD_LISTENER (Hyphen_engraver, hyphen);
+  ADD_ACKNOWLEDGER (Hyphen_engraver, lyric_syllable);
+}
 
 ADD_TRANSLATOR (Hyphen_engraver,
                 /* doc */
index f206a3b95d7ec375f6a864c44a8aab7b43170e05..a2d090a6dfd71c7567447e5ff75dd87ece76f756 100644 (file)
@@ -48,7 +48,6 @@ class All_font_metrics : public Smob<All_font_metrics>
 
   All_font_metrics (All_font_metrics const &);
 public:
-  static const char * const type_p_name_; // = 0
   SCM mark_smob () const;
 
   Index_to_charcode_map const *get_index_to_charcode_map (const string &filename,
index 3ea6c2c550b0346db2e77d88903df91735c6a2b4..0a71a6b9e442a6901b82028d45c83ca09831a945 100644 (file)
@@ -30,7 +30,7 @@ class Book : public Smob<Book>
 {
 public:
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Book ();
   SCM header_;
   Output_def *paper_;
index 7d5745d6965b757123606d33b4b25edf64dc1779..d4a8655a429b0cf965364132871cf2b7f9c3b054 100644 (file)
@@ -12,7 +12,7 @@
 class Box : public Simple_smob<Box>
 {
 public:
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   Interval interval_a_[NO_AXES];
 public:
index b797baf062e7ba235ec9d8e8c793fd817d9b6973..671140673f5df0dd242c5ac883ff0b274128bb29 100644 (file)
@@ -44,10 +44,10 @@ class Callback_wrapper : public Simple_smob<Callback_wrapper>
   // this involves an adjustment of the this pointer from Smob_core to
   // the scope containing the callback.
   SCM (*trampoline_) (SCM, SCM);
-  Callback_wrapper (SCM (*trampoline) (SCM, SCM)) : trampoline_ (trampoline)
+  Callback_wrapper (SCM (*trampoline) (SCM, SCM))
+    : trampoline_ (trampoline)
   { } // Private constructor, use only in make_smob
 public:
-  static const char * const type_p_name_; // = 0
   LY_DECLARE_SMOB_PROC (&Callback_wrapper::call, 2, 0, 0)
   SCM call (SCM target, SCM arg)
   {
@@ -66,5 +66,121 @@ public:
   }
 };
 
+class Callback2_wrapper : public Simple_smob<Callback2_wrapper>
+{
+  // See Callback_wrapper for the details.  Callback2_wrapper just
+  // supports an additional SCM argument as compared to
+  // Callback_wrapper but is otherwise identical.
+  SCM (*trampoline_) (SCM, SCM, SCM);
+  Callback2_wrapper (SCM (*trampoline) (SCM, SCM, SCM))
+    : trampoline_ (trampoline)
+  { } // Private constructor, use only in make_smob
+public:
+  LY_DECLARE_SMOB_PROC (&Callback2_wrapper::call, 3, 0, 0)
+  SCM call (SCM target, SCM arg1, SCM arg2)
+  {
+    return trampoline_ (target, arg1, arg2);
+  }
+
+  template <SCM (*trampoline) (SCM, SCM, SCM)>
+  static SCM make_smob ()
+  {
+    static SCM res =
+      scm_permanent_object (Callback2_wrapper (trampoline).smobbed_copy ());
+    return res;
+  }
+};
+
+class Callback0_wrapper : public Simple_smob<Callback0_wrapper>
+{
+  // See Callback_wrapper for the details.  Callback0_wrapper does not
+  // pass arguments but is otherwise identical to Callback_wrapper.
+  SCM (*trampoline_) (SCM);
+  Callback0_wrapper (SCM (*trampoline) (SCM))
+    : trampoline_ (trampoline)
+  { } // Private constructor, use only in make_smob
+public:
+  LY_DECLARE_SMOB_PROC (&Callback0_wrapper::call, 1, 0, 0)
+  SCM call (SCM target)
+  {
+    return trampoline_ (target);
+  }
+
+  template <SCM (*trampoline) (SCM)>
+  static SCM make_smob ()
+  {
+    static SCM res =
+      scm_permanent_object (Callback0_wrapper (trampoline).smobbed_copy ());
+    return res;
+  }
+  // Since there are no arguments at all, we might as well provide
+  // default trampolines
+  template <class T, SCM (T::*p)()>
+  static SCM trampoline (SCM target)
+  {
+    T *t = LY_ASSERT_SMOB (T, target, 1);
+    return (t->*p) ();
+  }
+
+  template <class T, void (T::*p)()>
+  static SCM trampoline (SCM target)
+  {
+    T *t = LY_ASSERT_SMOB (T, target, 1);
+    (t->*p) ();
+    return SCM_UNSPECIFIED;
+  }
+
+  template <class T, SCM (T::*p)()>
+  static SCM make_smob ()
+  {
+    return make_smob<trampoline<T, p> > ();
+  }
+
+  template <class T, void (T::*p)()>
+  static SCM make_smob ()
+  {
+    return make_smob<trampoline<T, p> > ();
+  }
+};
+
+// The following will usually be used unsmobbified, relying on its
+// constituents being protected independently.
+
+class Method_instance : public Simple_smob<Method_instance>
+{
+  SCM method_, instance_;
+public:
+  LY_DECLARE_SMOB_PROC (&Method_instance::call, 0, 0, 1)
+  SCM call (SCM rest)
+  {
+    return scm_apply_1 (method_, instance_, rest);
+  }
+
+  Method_instance (SCM method, SCM instance)
+    : method_ (method), instance_ (instance)
+  { }
+  Method_instance (SCM method, Smob_core *instance)
+    : method_ (method), instance_ (instance->self_scm ())
+  { }
+  SCM method () const { return method_; }
+  SCM instance () const { return instance_; }
+  SCM operator () () const
+  {
+    return scm_call_1 (method_, instance_);
+  }
+  SCM operator () (SCM arg) const
+  {
+    return scm_call_2 (method_, instance_, arg);
+  }
+  SCM operator () (SCM arg1, SCM arg2) const
+  {
+    return scm_call_3 (method_, instance_, arg1, arg2);
+  }
+  SCM mark_smob () const
+  {
+    scm_gc_mark (method_);
+    return instance_;
+  }
+};
 
 #endif
index 19e731815af44cd598e1170f68335e3609f7913d..78bfef8897e626c20daaf07353f3b6243c8f5348 100644 (file)
@@ -26,6 +26,8 @@ class Coherent_ligature_engraver : public Ligature_engraver
 public:
   // no TRANSLATOR_DECLARATIONS (Coherent_ligature_engraver) needed
   // since this class is abstract
+  TRANSLATOR_INHERIT (Ligature_engraver);
+  DECLARE_TRANSLATOR_CALLBACKS (Coherent_ligature_engraver);
 
 protected:
   virtual void build_ligature (Spanner *ligature,
index c49fee1e305a6ada60a051ac52400a0e7044bfae..b068e204c02e345d50bf2343def2e95a68941c27 100644 (file)
@@ -35,7 +35,7 @@ struct Context_def : public Smob<Context_def>
 {
   SCM mark_smob () const;
   int print_smob (SCM, scm_print_state *) const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Context_def ();
 private:
   /*
index c9f0caa8fbb9c32228b28ae56a0df1c14ad37deb..81b1f34e36c47189b543eda186e84dbf66e6fb98 100644 (file)
@@ -38,7 +38,7 @@ struct Context_mod : public Simple_smob<Context_mod>
 {
   SCM mark_smob () const;
   int print_smob (SCM, scm_print_state *) const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   SCM mods_;
 public:
index 130a304f935ea694c71d3f9d773ad1aed98e365d..468f612061707734ee3865faf8937cba06ea92ec 100644 (file)
@@ -33,7 +33,7 @@ class Context : public Smob<Context>
 public:
   SCM mark_smob () const;
   int print_smob (SCM, scm_print_state *) const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Context ();
 private:
   Scheme_hash_table *properties_dict () const;
index f0eb30ba6dc41d8d8ad392e362d6ec480a7fa49d..98a8626fd8f04f370c632209b053c40d77bb0953 100644 (file)
@@ -29,7 +29,7 @@ class Dispatcher : public Smob<Dispatcher>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Dispatcher ();
 private:
   /* Hash table. Each event-class maps to a list of listeners. */
index 7a57cf53af6a4ff5dd333266173374a89bac9591..6233fc1b2d4fdff1c897cc33c040e8145fbf457e 100644 (file)
@@ -29,7 +29,7 @@ struct Duration : public Simple_smob<Duration>
 {
   static SCM equal_p (SCM, SCM);
   int print_smob (SCM, scm_print_state *) const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   Duration ();
   Duration (int, int);
   Duration (Rational, bool scale);
index 956f49365b6cc17d4e65c8734d4ec4227cb2bb3d..928f6a969dbddad717c25856351b53b9fba4f5d5 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef ENGRAVER_HH
 #define ENGRAVER_HH
 
+#include "callback.hh"
+#include "grob.hh"
 #include "grob-info.hh"
 #include "translator.hh"
 
@@ -46,6 +48,17 @@ protected:
   Engraver_group *get_daddy_engraver () const;
 
 public:
+  template <class T, void (T::*callback)(Grob_info)>
+  static SCM ack_trampoline (SCM target, SCM grob, SCM source_engraver)
+  {
+    T *t = LY_ASSERT_SMOB (T, target, 1);
+    Grob *g = LY_ASSERT_SMOB (Grob, grob, 2);
+    Engraver *e = LY_ASSERT_SMOB (Engraver, source_engraver, 3);
+
+    (t->*callback) (Grob_info (e, g));
+    return SCM_UNSPECIFIED;
+  }
+
   /**
      Announce element. Default: pass on to daddy. Utility
   */
@@ -64,7 +77,9 @@ public:
   /**
      override other ctor
   */
-  TRANSLATOR_DECLARATIONS (Engraver);
+  DECLARE_CLASSNAME (Engraver);
+  DECLARE_TRANSLATOR_CALLBACKS (Engraver);
+  Engraver ();
 };
 
 #define make_item(x, cause) internal_make_item (ly_symbol2scm (x), cause, x, __FILE__, __LINE__, __FUNCTION__)
index d74c8157ca9f50003aa1777d9cb35ed3d8923b19..e385a1e7af7ad603a9bb043b0c7fa4dcb6b9a995 100644 (file)
@@ -35,7 +35,7 @@ class Font_metric : public Smob<Font_metric>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Font_metric ();
 private:
   DECLARE_CLASSNAME (Font_metric);
index 5aea42662b29bd909471a9469b216ba097c222c1..d7011bda99f975ec540ac1d3b9b48b68d5005649 100644 (file)
@@ -26,13 +26,15 @@ class Gregorian_ligature_engraver : public Coherent_ligature_engraver
   Stream_event *pes_or_flexa_req_;
 
 public:
+  void listen_pes_or_flexa (Stream_event *ev);
   // no TRANSLATOR_DECLARATIONS (Gregorian_ligature_engraver) needed
   // since this class is abstract
 
+  TRANSLATOR_INHERIT(Coherent_ligature_engraver);
+  DECLARE_TRANSLATOR_CALLBACKS (Gregorian_ligature_engraver);
 protected:
   Gregorian_ligature_engraver ();
 
-  virtual void listen_pes_or_flexa (Stream_event *ev);
   virtual void build_ligature (Spanner *ligature,
                                vector<Grob_info> const &primitives);
   virtual void transform_heads (Spanner *ligature,
index 1a755fe66196c2bdbbf301c2217a068d06a010b0..ca925b42917621842afd3ce2fc5512a21662ff5d 100644 (file)
@@ -29,7 +29,7 @@ class Grob_array : public Simple_smob<Grob_array>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   vector<Grob *> grobs_;
   bool ordered_;
index 9c3eadb4b06b7deccf252f2cabfbe65f4cc91fa1..bde5f5263d4130091afbd44a803501ee9fc9da69 100644 (file)
@@ -21,6 +21,7 @@
 #define INTERFACE_HH
 
 #include "lily-guile.hh"
+#include "protected-scm.hh"
 
 class Grob;
 
@@ -57,14 +58,14 @@ private:
   friend bool has_interface(Grob *);
 
 private:
-  static SCM interface_symbol_;
+  static Protected_scm interface_symbol_;
   static char const *cxx_name_;
   static char const *description_;
   static char const *variables_;
 };
 
 template <class Interface>
-SCM Grob_interface<Interface>::interface_symbol_;
+Protected_scm Grob_interface<Interface>::interface_symbol_;
 
 #endif /* INTERFACE_HH */
 
index db51e02e73cb0a0c5ec6ce1f4e91d56d5bc69bbe..a9408f09a2ac1cbc6beb21a9766526c3d3af5914 100644 (file)
@@ -32,7 +32,7 @@ class Grob : public Smob<Grob>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Grob ();
 private:
   DECLARE_CLASSNAME (Grob);
index b77db2d66f547051ca07fd51cdb615dfbc34126d..aab0d117a66a561b7f6a0cea4c727a97b64d3e24 100644 (file)
@@ -32,7 +32,7 @@ class Input : public Simple_smob<Input>
   char const *end_;
   Source_file *source_file_;
 public:
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   int print_smob (SCM, scm_print_state *) const;
   static SCM equal_p (SCM, SCM);
   SCM mark_smob () const;
index 6f53331a4e5493627debd1ebea1bc48952f28726..1f8fd8b85f37d574160e4fcb0d99f4143c74e3f9 100644 (file)
@@ -30,9 +30,6 @@ protected:
   void stop_translation_timestep ();
   virtual void finalize ();
 
-  DECLARE_ACKNOWLEDGER (rest);
-  DECLARE_ACKNOWLEDGER (ligature_head);
-  virtual void listen_ligature (Stream_event *ev);
   void process_music ();
   virtual Spanner *create_ligature_spanner () = 0;
   virtual void typeset_ligature (Spanner *ligature,
@@ -41,8 +38,12 @@ protected:
   SCM brew_ligature_primitive_proc;
 
 public:
+  void acknowledge_rest (Grob_info);
+  void acknowledge_ligature_head (Grob_info);
+  void listen_ligature (Stream_event *ev);
   // no TRANSLATOR_DECLARATIONS (Ligature_engraver) needed since this
   // class is abstract
+  DECLARE_TRANSLATOR_CALLBACKS (Ligature_engraver);
 
 private:
   Drul_array<Stream_event *> events_drul_;
index 97982895f50c851ef1b993c157956fdf9fb771b6..d930f69cf940527ddd9eba2703ecf5920e220d34 100644 (file)
@@ -58,8 +58,10 @@ namespace Lily {
   extern Variable beat_structure;
   extern Variable calc_repeat_slash_count;
   extern Variable car_less;
+  extern Variable chordmodifiers;
   extern Variable construct_chord_elements;
   extern Variable default_time_signature_settings;
+  extern Variable drum_pitch_names;
   extern Variable grob_compose_function;
   extern Variable grob_offset_function;
   extern Variable hash_table_to_alist;
@@ -91,6 +93,7 @@ namespace Lily {
 #endif
   extern Variable f_parser;
   extern Variable percussion_p;
+  extern Variable pitchnames;
   extern Variable pure_chain_offset_callback;
   extern Variable remove_stencil_warnings;
   extern Variable scale_layout;
index 0e001ec187a76aae50ecf7aec3e312349df280a3..626d24efa64ba2242afe7a1a5ab697941a3043e4 100644 (file)
@@ -36,7 +36,7 @@ class Lily_lexer : public Smob<Lily_lexer>, public Includable_lexer
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Lily_lexer ();
 private:
   int lookup_keyword (const string&);
index b08df7c7a4ab487f5329b6f4f981a1b2c68f234b..e4ff2969b92ce8143326b8a4a7889ee0ee64169e 100644 (file)
@@ -36,7 +36,7 @@ class Lily_parser : public Smob<Lily_parser>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Lily_parser ();
   Lily_lexer *lexer_;
   Sources *sources_;
index f574b39c3f25c0ecb69523bbce3bef8437d28742..ee3946e0fd02921167b4a3f57d142bee0a64d017 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "flower-proto.hh"
 
-class Acknowledge_information;
 class All_font_metrics;
 class Audio_column;
 class Audio_control_function_value_change;
@@ -59,7 +58,6 @@ class Dot_column;
 class Dot_configuration;
 class Dot_formatting_problem;
 class Engraver;
-class Engraver;
 class Engraver_group;
 class Event;
 class Event_chord;
index b9042ba301ac79f715b197ed22d159bbb47943df..a13fdc66e14e141d28917e4ffa46d72494b7e740 100644 (file)
@@ -96,7 +96,7 @@ private:
   SCM callback_;
   SCM target_;
 public:
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 
   Listener (SCM callback, SCM target)
     : callback_ (callback), target_ (target) { }
index 7226aceef8d7a5d31d3530c8a7c88bd78148a578..174b2f4c01663be76fed63778e558d03cf708d6f 100644 (file)
@@ -27,7 +27,26 @@ using namespace std;
 #include "interval.hh"
 
 double log_2 (double x);
-int intlog2 (int d);
+
+/*
+  Return the 2-log, rounded down
+*/
+template <class T>
+int
+intlog2 (T d)
+{
+  if (d <= 0)
+    error ("intlog2 with negative argument: " + ::to_string (d));
+  int i = 0;
+  while ((d != 1))
+    {
+      d /= 2;
+      i++;
+    }
+
+  assert (! (d / 2));
+  return i;
+}
 
 inline int
 sign (int i)
index d84a992b40e73eb6b649476ffb14481558f259d4..c29032f99dc6f56d32fc087b2dcecfaccda7fe16 100644 (file)
@@ -32,7 +32,7 @@ class Moment : public Simple_smob<Moment>
 public:
   static SCM equal_p (SCM, SCM);
   int print_smob (SCM, scm_print_state *) const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   Moment ();
   Moment (int m);
 
index f2c349a3e1cdfd1f2bb6572c3c54c727b973bfe4..80239a61aaefe202f8282c78f453564a55b31b36 100644 (file)
@@ -27,7 +27,7 @@
 class Music_function : public Smob2<Music_function>
 {
 public:
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   int print_smob (SCM, scm_print_state *) const;
   SCM get_signature () const { return scm1 (); }
   SCM get_function () const { return scm2 (); }
index 810d230aac279b447a0c7bd989a1093141567221..bb095df71869e84bbd25d84042cd30adab580e79 100644 (file)
@@ -63,7 +63,7 @@ class Music_iterator : public Smob<Music_iterator>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Music_iterator ();
 protected:
   Moment music_length_;
index dc1111b78ac58b9070f5ecb352baac9d522d2ca4..208c01a831e9f2f2920dd5b1407e15aed4a76668 100644 (file)
@@ -31,7 +31,7 @@ class Music_output : public Smob<Music_output>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Music_output ();
 private:
   DECLARE_CLASSNAME (Music_output);
index 5de672e67addf202f1609017da8d0d838272bb81..8c188f2707872e0d8ea62bf8d5d71e41fca0b6bc 100644 (file)
@@ -51,7 +51,7 @@ class Output_def : public Smob<Output_def>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Output_def ();
   VIRTUAL_COPY_CONSTRUCTOR (Output_def, Output_def);
 
index 02233d30a6d804d06bfa8d420e6e4187944007df..33f3a38c06151c9c46d4b851dedea23f6572d89c 100644 (file)
@@ -27,7 +27,7 @@ class Page_marker : public Smob<Page_marker>
 {
 public:
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Page_marker ();
 private:
   SCM symbol_; /* either 'page-turn-permission or 'page-break-permission */
index b105cdb3de50d5763909b3d38ef900de8468a286..9530c94b7076fb5a9137253adbcd8732a6900836 100644 (file)
@@ -31,7 +31,7 @@ class Paper_book : public Smob<Paper_book>
 {
 public:
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Paper_book ();
 private:
   SCM systems_;
index 1279ff17c990c527db9eaba102eba4aa859357cf..a176fc48ebf6a667d894eb352f2e9e62851c52b6 100644 (file)
@@ -42,12 +42,12 @@ protected:
   virtual void initialize ();
   virtual void finalize ();
 
-  DECLARE_TRANSLATOR_LISTENER (break);
-  DECLARE_TRANSLATOR_LISTENER (label);
+  void listen_break (Stream_event *);
+  void listen_label (Stream_event *);
 
-  DECLARE_ACKNOWLEDGER (item);
-  DECLARE_ACKNOWLEDGER (note_spacing);
-  DECLARE_ACKNOWLEDGER (staff_spacing);
+  void acknowledge_item (Grob_info);
+  void acknowledge_note_spacing (Grob_info);
+  void acknowledge_staff_spacing (Grob_info);
 
   System *system_;
   vector<Stream_event *> break_events_;
index 8683b4c6d10dd5f04531e40691c3bad00228890f..cd1a5e2c92fb4ffb34a0581f85398750c1276d28 100644 (file)
@@ -33,7 +33,6 @@
 class Paper_outputter : public Smob<Paper_outputter>
 {
 public:
-  static const char * const type_p_name_; // = 0
   SCM mark_smob () const;
   virtual ~Paper_outputter ();
 private:
index a640e240aa27449065dad6564fd6e7b524f955a0..70354fdbf2d845f9fe2a571339170b2c0681b43b 100644 (file)
@@ -30,7 +30,7 @@
 class Performer : public Translator
 {
 public:
-  VIRTUAL_COPY_CONSTRUCTOR (Translator, Performer);
+  DECLARE_CLASSNAME (Performer);
   friend class Performer_group;
   Performer_group *get_daddy_performer () const;
 
index daade82e81994b5e06ca2d2103fbe58cc4bd1d04..dad2bc1246727c5fc4f5dc016b78c7f2c788347b 100644 (file)
@@ -38,7 +38,7 @@ public:
   static SCM equal_p (SCM, SCM);
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   int octave_;
   int notename_;
index cb850555fb414983ff0024c502fd66a0da920336..a9a485b5502642924d8610e352ec7b2967b3d2d6 100644 (file)
@@ -38,7 +38,7 @@ public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
   static SCM equal_p (SCM, SCM);
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Prob ();
 private:
   DECLARE_CLASSNAME (Prob);
index 48a26b15c995a4d948a5c4974dd9da02f414cb71..0115cb9f9ff6e2d388dd2fc714ec5639cdcc180c 100644 (file)
@@ -46,13 +46,14 @@ class Protected_scm
   static SCM list_;
   static SCM last_;
   Protected_scm (Protected_scm const &);
+  void protectify (SCM);
 public:
   Protected_scm ();
   Protected_scm (SCM);
-  ~Protected_scm ();
   Protected_scm &operator = (SCM);
   Protected_scm &operator = (Protected_scm const &);
-  operator SCM () const;
+  operator const SCM & () const;
+  operator SCM & ();
 };
 
 #endif /* PROTECTED_SCM_HH */
index 7c990e503419ce7db183489fae7ce90c0074d092..19cd175c797fd7d9e63a5ac79dbb8c73696c1fa0 100644 (file)
@@ -26,7 +26,6 @@
 
 struct Scale : public Smob<Scale>
 {
-  static const char * const type_p_name_; // = 0
   virtual ~Scale ();
   Scale (vector<Rational> const &);
   Scale (Scale const &);
index 3cd691578fa5b4b2b83f1ac9ecf5b0007dd979de..59cab571fbe4058a9f6b8b33dc663c5d464438ba 100644 (file)
@@ -34,11 +34,6 @@ public:
 protected:
   ~Scheme_engraver ();
 
-  void stop_translation_timestep ();
-  void start_translation_timestep ();
-  void process_music ();
-  void process_acknowledged ();
-
   virtual void initialize ();
   virtual void finalize ();
   virtual void derived_mark () const;
@@ -46,29 +41,28 @@ protected:
   virtual bool must_be_last () const;
 
 private:
-  void acknowledge_grob_by_hash (Grob_info info, SCM iface_function_hash);
-  void init_acknowledgers (SCM alist, SCM *hash);
+  virtual SCM get_acknowledger (SCM sym, Direction start_end)
+  {
+    return generic_get_acknowledger
+      (sym, interface_acknowledger_hash_[start_end]);
+  }
 
-  DECLARE_ACKNOWLEDGER (grob);
-  DECLARE_END_ACKNOWLEDGER (grob);
+  SCM init_acknowledgers (SCM alist);
+  // For now no description.  In future, something derived from the
+  // definition might make sense.
+  SCM translator_description () const { return SCM_EOL; }
 
   bool must_be_last_;
 
-  SCM acknowledge_grob_function_;
-  SCM stop_translation_timestep_function_;
-  SCM start_translation_timestep_function_;
-  SCM process_music_function_;
-  SCM process_acknowledged_function_;
   SCM initialize_function_;
   SCM finalize_function_;
+  SCM precomputable_methods_ [TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
 
   // hashq table of interface-symbol -> scheme-function
-  SCM interface_acknowledger_hash_;
-  SCM interface_end_acknowledger_hash_;
+  Drul_array<SCM> interface_acknowledger_hash_;
 
   // Alist of listened-symbol . scheme-function
   SCM per_instance_listeners_;
 };
 
 #endif /* SCHEME_ENGRAVER_HH */
-
index 241f316c4ec3dd622ed493936a5dcf63b36f3447..3453904f7152cf3c8cfe60b652fca9892803637a 100644 (file)
@@ -46,7 +46,6 @@
 class Scheme_hash_table : public Smob1<Scheme_hash_table>
 {
 public:
-  static const char * const type_p_name_; // = 0
   int print_smob (SCM, scm_print_state *) const;
   bool try_retrieve (SCM key, SCM *val);
   bool contains (SCM key) const;
index b3ece8960a813245139822c999120a85d668899a..a5918242f14d6bf534508461801c0dc3e4134d85 100644 (file)
@@ -31,7 +31,7 @@ class Score : public Smob<Score>
 {
 public:
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Score ();
 private:
   SCM music_;
index 6d7cea0ac248d917091bea19bb05cba6d0abf72c..f7946c1851d50123979a6dd2623e62b90609ae32 100644 (file)
@@ -25,7 +25,7 @@
 class Skyline_pair : public Simple_smob<Skyline_pair>
 {
 public:
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   Drul_array<Skyline> skylines_;
 
index 21693420c88419fd0fc8834eb3e7e749d4fafb6d..43feb407615ebff249454d8b3a132296f2e07d99 100644 (file)
@@ -51,7 +51,7 @@ struct Building
 class Skyline : public Simple_smob<Skyline>
 {
 public:
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   list<Building> buildings_;
   Direction sky_;
index c11926b21a9bc8841b4b6e9ba5cdc115cdbbd412..97ed1a6637bbf78877020d18678a7169a988cde6 100644 (file)
@@ -54,17 +54,6 @@ protected:
   const char* event_name_;
   virtual SCM event_symbol () = 0;
 
-  DECLARE_ACKNOWLEDGER (inline_accidental);
-  DECLARE_ACKNOWLEDGER (fingering);
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_ACKNOWLEDGER (script);
-  DECLARE_ACKNOWLEDGER (dots);
-  DECLARE_ACKNOWLEDGER (text_script);
-  DECLARE_END_ACKNOWLEDGER (tie);
-  DECLARE_ACKNOWLEDGER (tuplet_number);
-
-  void listen_note (Stream_event *ev);
-  void listen_slur (Stream_event *ev, Stream_event *note = 0);
   void acknowledge_extra_object (Grob_info);
   void stop_translation_timestep ();
   void process_music ();
@@ -78,8 +67,22 @@ protected:
   virtual void derived_mark () const;
 
 public:
+  void acknowledge_inline_accidental (Grob_info);
+  void acknowledge_fingering (Grob_info);
+  void acknowledge_note_column (Grob_info);
+  void acknowledge_script (Grob_info);
+  void acknowledge_dots (Grob_info);
+  void acknowledge_text_script (Grob_info);
+  void acknowledge_end_tie (Grob_info);
+  void acknowledge_tuplet_number (Grob_info);
+  void listen_note (Stream_event *ev);
+  void listen_slur (Stream_event *ev, Stream_event *note);
+  // You'd think the following is the same as defaulting `note' to 0,
+  // but template resolution for trampolines disagrees.  Huh.
+  void listen_slur (Stream_event *ev) { listen_slur (ev, 0); }
   // no TRANSLATOR_DECLARATIONS (Slur_proto_engraver) needed since this
   // class is abstract
+  DECLARE_TRANSLATOR_CALLBACKS (Slur_proto_engraver);
 };
 
 #endif // SLUR_PROTO_ENGRAVER_HH
index 889d86a8cab3a342b374593a7a6afa1879d98f9f..7ef46b23e41106eb444907d665cd1a6aecac80c8 100644 (file)
     debugging purposes.  If the class does not define this function,
     the output will be #<Classname> when printing.
 
-  - a static const type_p_name_[] string set to something like
+  - a static const * const type_p_name_ string set to something like
     "ly:grob?".  When provided, an accordingly named function for
     checking for the given smob type will be available in Scheme.
 
@@ -177,6 +177,7 @@ private:
   // Most default functions are do-nothings.  void init() will
   // recognize their address when not overriden and will then refrain
   // altogether from passing the the respective callbacks to GUILE.
+
   SCM mark_smob (void) const;
   static SCM mark_trampoline (SCM); // Used for calling mark_smob
   static size_t free_smob (SCM obj);
@@ -185,11 +186,10 @@ private:
   static int print_trampoline (SCM, SCM, scm_print_state *);
   static void smob_proc_init (scm_t_bits) { };
 
-  // type_p_name_ has to be defined in the Super class, either with a
-  // static const char [] string or as a null pointer of type const
-  // char *.  We used to provide a default here for convenience, but
-  // battling the various conflicting C++ standards was too much of a
-  // hassle.
+  // Define type_p_name_ in the Super class as a const char * const.
+  // Without such definition it defaults to 0, producing no predicate.
+
+  static const char * const type_p_name_; // = 0
 
   // LY_DECLARE_SMOB_PROC is used in the Super class definition for
   // making a smob callable like a function.  Its first argument is a
index b8dfc1f67fdb6027b897fa78b2dbb19964eb3312..818c0900a56bac154476b49282eae6bf529241b8 100644 (file)
@@ -113,6 +113,9 @@ Scm_init Smob_base<Super>::scm_init_ (init);
 template <class Super>
 string Smob_base<Super>::smob_name_;
 
+template <class Super>
+const char * const Smob_base<Super>::type_p_name_ = 0;
+
 template <class Super>
 void Smob_base<Super>::init ()
 {
index 6686389289e3cc04909d7aff588a38a719115cc7..fc5bf2f54111c83b1bcf35aa8f9c7d5bd3526549 100644 (file)
@@ -40,7 +40,7 @@ class Source_file : public Smob<Source_file>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Source_file ();
 private:
   vector<char const *> newline_locations_;
index fd01ca048cf7bc0ce53506c8b058dae13b244702..d4ebee23cd05f3680b9bfcfe3bb036061a6af92a 100644 (file)
@@ -27,7 +27,7 @@ class Spring : public Simple_smob<Spring>
 {
 public:
   static SCM equal_p (SCM, SCM);
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   Real distance_;
   Real min_distance_;
index 6ccb9252bb18a224f5a38ff36b53bda6c30cd94b..8af67c0f766f039184e6ba00500d43044a58a0e7 100644 (file)
@@ -59,7 +59,7 @@ class Stencil : public Simple_smob<Stencil>
 {
 public:
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   Box dim_;
   SCM expr_;
index 6fd03beecf050ce363338430753fb2a22991ac10..b6124572fc53d6f694fb7fae2a32cbbe0b83d248 100644 (file)
 #define TRANSLATOR_DISPATCH_LIST_HH
 
 #include "lily-proto.hh"
+#include "callback.hh"
 #include "std-vector.hh"
 #include "smobs.hh"
 #include "translator.hh"
 
-struct Engraver_dispatch_entry
-{
-  Engraver *engraver_;
-  Translator::Grob_info_callback function_;
-};
-
 class Engraver_dispatch_list : public Simple_smob<Engraver_dispatch_list>
 {
-  vector<Engraver_dispatch_entry> dispatch_entries_;
+  vector<Method_instance> dispatch_entries_;
 public:
-  static const char * const type_p_name_; // = 0
   void apply (Grob_info);
   SCM static create (SCM trans_list,
                      SCM iface_list, Direction);
index d90c2929de2d3d93a5271fae07250108c5b730f1..d4500ef2b4e170a4312b35746fc01a47d4d8429f 100644 (file)
 #ifndef TRANSLATOR_GROUP_HH
 #define TRANSLATOR_GROUP_HH
 
+#include "callback.hh"
 #include "listener.hh"
 #include "translator.hh"
 
-typedef void (Translator:: *Translator_method) (void);
-typedef void (Translator_group:: *Translator_group_method) (void);
-typedef void (*Translator_group_void_method) (Translator_group *);
-
-struct Translator_method_binding
-{
-  Translator *translator_;
-  Translator::Callback method_;
-
-  Translator_method_binding ()
-  {
-  }
-  Translator_method_binding (Translator *tr, Translator::Callback ptr)
-  {
-    translator_ = tr;
-    method_ = ptr;
-  }
-  void invoke ()
-  {
-    if (method_)
-      (translator_->*method_) ();
-  }
-};
-
 class Translator_group : public Smob<Translator_group>
 {
 public:
   SCM mark_smob () const;
   int print_smob (SCM, scm_print_state *) const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Translator_group ();
 private:
   void precompute_method_bindings ();
-  vector<Translator_method_binding>
+  vector<Method_instance>
   precomputed_method_bindings_[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
 
-  Translator_group_void_method
-  precomputed_self_method_bindings_[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
-
   SCM protected_events_;
 
   void create_child_translator (SCM);
@@ -80,12 +54,9 @@ public:
   void stop_translation_timestep ();
   void start_translation_timestep ();
 
-  virtual void fetch_precomputable_methods (Translator_group_void_method[]);
-
   Translator_group ();
 
   void precomputed_translator_foreach (Translator_precompute_index);
-  void call_precomputed_self_method (Translator_precompute_index);
 
   Context *context () const { return context_; }
 protected:
@@ -97,8 +68,8 @@ protected:
 };
 
 SCM names_to_translators (SCM namelist, Context *tg);
-void recurse_over_translators (Context *c, Translator_method ptr,
-                               Translator_group_method ptr2, Direction);
+void recurse_over_translators (Context *c, SCM tr_method,
+                               SCM tr_group_method, Direction);
 void precomputed_recurse_over_translators (Context *c, Translator_precompute_index idx, Direction dir);
 Translator_group *get_translator_group (SCM sym);
 
index 118220772ab72b758ea467f67e616bbff6946230..dd0659bf50866ec4a9e03e86565deffc0299f7dd 100644 (file)
@@ -23,6 +23,7 @@
 #include "global-ctor.hh"
 #include "lily-proto.hh"
 #include "virtual-methods.hh"
+#include "callback.hh"
 #include "input.hh"             // for error reporting
 #include "smobs.hh"
 #include "std-vector.hh"
 #define TRANSLATOR_FAMILY_DECLARATIONS(NAME)                            \
   public:                                                               \
   VIRTUAL_COPY_CONSTRUCTOR (Translator, NAME);                          \
-  static Drul_array<vector<Acknowledge_information> > acknowledge_static_array_drul_; \
-  virtual void fetch_precomputable_methods (Callback methods[]);        \
-  static Grob_info_callback static_get_acknowledger (SCM sym);          \
-  static Grob_info_callback static_get_end_acknowledger(SCM);           \
-  virtual Grob_info_callback get_acknowledger (SCM sym)                 \
-  {                                                                     \
-    return static_get_acknowledger (sym);                               \
-  }                                                                     \
-  virtual Grob_info_callback get_end_acknowledger (SCM sym)             \
-  {                                                                     \
-    return static_get_end_acknowledger (sym);                           \
-  }                                                                     \
+  virtual void fetch_precomputable_methods (SCM methods[]);             \
+  DECLARE_TRANSLATOR_CALLBACKS (NAME);                                  \
+  TRANSLATOR_INHERIT (Translator);                                      \
+  /* end #define */
+
+#define TRANSLATOR_INHERIT(BASE)                                        \
+  using BASE::method_finder
+
+#define DECLARE_TRANSLATOR_CALLBACKS(NAME)                              \
+  template <void (NAME::*mf)()>                                         \
+  static SCM method_finder () { return method_find_base<NAME, mf> (); } \
   /* end #define */
 
 /*
 */
 
 #define TRANSLATOR_DECLARATIONS(NAME)                                   \
-  TRANSLATOR_FAMILY_DECLARATIONS(NAME)                                  \
+  public:                                                               \
+  TRANSLATOR_FAMILY_DECLARATIONS (NAME);                                \
+  static Drul_array<Protected_scm> acknowledge_static_array_drul_;      \
   static SCM static_description_;                                       \
   static Protected_scm listener_list_;                                  \
+  static SCM static_get_acknowledger (SCM sym, Direction start_end);    \
+  virtual SCM get_acknowledger (SCM sym, Direction start_end)           \
+  {                                                                     \
+    return static_get_acknowledger (sym, start_end);                    \
+  }                                                                     \
 public:                                                                 \
   NAME ();                                                              \
+  static void boot ();                                                  \
   virtual SCM static_translator_description () const;                   \
   virtual SCM translator_description () const;                          \
   virtual SCM get_listener_list () const                                \
@@ -66,15 +74,6 @@ public:                                                                 \
   }                                                                     \
   /* end #define */
 
-#define DECLARE_TRANSLATOR_LISTENER(m)                  \
-public:                                                 \
-inline void listen_ ## m (Stream_event *);              \
-/* Should be private */                                 \
-static void _internal_declare_ ## m ();
-
-#define DECLARE_ACKNOWLEDGER(x) public : void acknowledge_ ## x (Grob_info); protected:
-#define DECLARE_END_ACKNOWLEDGER(x) public : void acknowledge_end_ ## x (Grob_info); protected:
-
 enum Translator_precompute_index
 {
   START_TRANSLATION_TIMESTEP,
@@ -90,14 +89,9 @@ enum Translator_precompute_index
 class Translator : public Smob<Translator>
 {
 public:
-  // We don't make Grob_info_callback specific to Engraver since we
-  // otherwise get into a circular mess with regard to the definitions
-  // as the timing of Engraver is exercised from within Translator
-  typedef void (Translator::*Grob_info_callback) (Grob_info);
-  typedef void (Translator::*Callback) (void);
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
   virtual ~Translator ();
 private:
   void init ();
@@ -105,6 +99,7 @@ private:
 public:
   Context *context () const { return daddy_context_; }
 
+  Translator ();
   Translator (Translator const &);
 
   SCM internal_get_property (SCM symbol) const;
@@ -128,7 +123,12 @@ public:
   Context *get_score_context () const;
   Global_context *get_global_context () const;
 
-  TRANSLATOR_DECLARATIONS (Translator);
+  DECLARE_CLASSNAME (Translator);
+  virtual Translator *clone () const = 0;
+  virtual void fetch_precomputable_methods (SCM methods[]) = 0;
+  virtual SCM get_listener_list () const = 0;
+  virtual SCM translator_description () const = 0;
+  virtual SCM get_acknowledger (SCM sym, Direction start_end) = 0;
 
 protected:                      // should be private.
   Context *daddy_context_;
@@ -146,6 +146,16 @@ protected:                      // should be private.
     return SCM_UNSPECIFIED;
   }
 
+  template <class T, void (T::*mf)()>
+  static SCM
+  method_find_base () { return Callback0_wrapper::make_smob<T, mf> (); }
+
+  // Fallback for non-overriden callbacks for which &T::x degrades to
+  // &Translator::x
+  template <void (Translator::*)()>
+  static SCM
+  method_finder () { return SCM_UNDEFINED; }
+
   virtual void derived_mark () const;
   static SCM event_class_symbol (const char *ev_class);
   SCM static_translator_description (const char *grobs,
@@ -157,22 +167,13 @@ protected:                      // should be private.
   friend class Translator_group;
 };
 
-struct Acknowledge_information
-{
-  SCM symbol_;
-  Translator::Grob_info_callback function_;
-
-  Acknowledge_information ()
-  {
-    symbol_ = SCM_EOL;
-    function_ = 0;
-  }
-};
-
-
 void add_translator (Translator *trans);
 
 Translator *get_translator (SCM s);
+
+SCM
+generic_get_acknowledger (SCM sym, SCM ack_hash);
+
 Moment get_event_length (Stream_event *s, Moment now);
 Moment get_event_length (Stream_event *s);
 
index 250a92313724f9ab1a7afb0778085dcb7f9eb73b..b649a1a197884aa7a86ce51d616eff51e3640675 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "callback.hh"
 #include "std-vector.hh"
-#include "translator.hh"
+#include "engraver.hh"
 
 /*
   TODO: derive "foo-bar-interface" from Foo_bar classname.
@@ -35,6 +35,7 @@
   SCM T::static_description_ = SCM_EOL;                                 \
   static void _ ## T ## _adder ()                                       \
   {                                                                     \
+    T::boot ();                                                         \
     T *t = new T;                                                       \
     T::static_description_ =                                            \
       scm_permanent_object (t->static_translator_description ());       \
   {                                                                     \
     return static_description_;                                         \
   }                                                                     \
-  ADD_GLOBAL_CTOR (_ ## T ## _adder); \
+  ADD_GLOBAL_CTOR (_ ## T ## _adder);                                   \
   /* end define */
 
 #define DEFINE_TRANSLATOR_LISTENER_LIST(T) \
-  Protected_scm T::listener_list_ (SCM_EOL);    \
-  /* end define */
+  Protected_scm T::listener_list_ (SCM_EOL)
 
 #define DEFINE_ACKNOWLEDGERS(classname) \
-  Drul_array< vector<Acknowledge_information> > classname::acknowledge_static_array_drul_;      \
-  Translator::Grob_info_callback                                        \
-  classname::static_get_acknowledger (SCM sym)                          \
-  {                                                                     \
-    return generic_get_acknowledger (sym, &acknowledge_static_array_drul_[START]);      \
-  }                                                                     \
-  Translator::Grob_info_callback                                        \
-  classname::static_get_end_acknowledger (SCM sym)                      \
+  Drul_array<Protected_scm> classname::acknowledge_static_array_drul_;  \
+  SCM                                                                   \
+  classname::static_get_acknowledger (SCM sym, Direction start_end)     \
   {                                                                     \
-    return generic_get_acknowledger (sym, &acknowledge_static_array_drul_[STOP]);       \
+    return generic_get_acknowledger                                     \
+      (sym, acknowledge_static_array_drul_[start_end]);                 \
   }                                                                     \
   /* end define */
 
     return Translator::static_translator_description (grobs, desc, listener_list_, read, write); \
   }
 
-#define ADD_TRANSLATOR_FAMILY(classname)                                \
-  IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS (classname);                    \
-  DEFINE_ACKNOWLEDGERS(classname)                                       \
-
 #define ADD_TRANSLATOR(classname, desc, grobs, read, write)             \
-  ADD_TRANSLATOR_FAMILY (classname)                                     \
+  IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS (classname);                    \
+  DEFINE_ACKNOWLEDGERS(classname);                                      \
   ADD_THIS_TRANSLATOR (classname);                                      \
-  DEFINE_TRANSLATOR_DOC(classname, desc, grobs, read, write)            \
-  DEFINE_TRANSLATOR_LISTENER_LIST(classname)                            \
+  DEFINE_TRANSLATOR_DOC(classname, desc, grobs, read, write);           \
+  DEFINE_TRANSLATOR_LISTENER_LIST(classname);
 
 #define IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS(T)                        \
   void                                                                  \
-  T::fetch_precomputable_methods (Translator::Callback ptrs[])         \
+  T::fetch_precomputable_methods (SCM ptrs[])                           \
   {                                                                     \
     ptrs[START_TRANSLATION_TIMESTEP] =                                  \
-      (&T::start_translation_timestep                                  \
-       == &Translator::start_translation_timestep)                     \
-      ? 0                                                              \
-      : static_cast<Callback> (&T::start_translation_timestep);                \
+      method_finder <&T::start_translation_timestep> ();                \
                                                                        \
     ptrs[STOP_TRANSLATION_TIMESTEP] =                                  \
-      (& T::stop_translation_timestep == & Translator::stop_translation_timestep) \
-      ? 0                                                              \
-      : static_cast<Callback> (&T::stop_translation_timestep);         \
-                                                                       \
+      method_finder <&T::stop_translation_timestep> ();                 \
+                                                                        \
     ptrs[PROCESS_MUSIC] =                                              \
-      (&T::process_music == &Translator::process_music)                        \
-      ? 0                                                              \
-      : static_cast<Callback> (&T::process_music);                     \
+      method_finder <&T::process_music> ();                             \
                                                                        \
     ptrs[PROCESS_ACKNOWLEDGED] =                                       \
-      (&T::process_acknowledged == &Translator::process_acknowledged)  \
-      ? 0                                                              \
-      : static_cast<Callback> (&T::process_acknowledged);              \
+      method_finder <&T::process_acknowledged> ();                      \
   }
 
-void add_acknowledger (Translator::Grob_info_callback ptr,
+void add_acknowledger (SCM ptr,
                        char const *func_name,
-                       vector<Acknowledge_information> *ack_array);
-
-Translator::Grob_info_callback
-generic_get_acknowledger (SCM sym,
-                          vector<Acknowledge_information> const *ack_array);
+                       SCM &ack_hash);
 
 #define ADD_ACKNOWLEDGER(CLASS, NAME)                                   \
-  void CLASS ## NAME ## _ack_adder ()                                   \
-  {                                                                     \
-    add_acknowledger (static_cast<Translator::Grob_info_callback> (&CLASS::acknowledge_ ## NAME), #NAME, &CLASS::acknowledge_static_array_drul_[START]); \
-  }                                                                     \
-  ADD_SCM_INIT_FUNC (CLASS ## NAME ## _ack_adder_initclass, CLASS ## NAME ## _ack_adder);
+  add_acknowledger (Callback2_wrapper::make_smob                        \
+                    <ack_trampoline<CLASS, &CLASS::acknowledge_ ## NAME> > (), \
+                    #NAME, acknowledge_static_array_drul_[START])
 
-#define ADD_END_ACKNOWLEDGER(CLASS, NAME)                                       \
-  void CLASS ## NAME ## _end_ack_adder ()                                       \
-  {                                                                     \
-    add_acknowledger (static_cast<Translator::Grob_info_callback> (&CLASS::acknowledge_end_ ## NAME), #NAME, &CLASS::acknowledge_static_array_drul_[STOP]); \
-  }                                                                     \
-  ADD_SCM_INIT_FUNC (CLASS ## NAME ## _end_ack_adder_initclass, CLASS ## NAME ## _end_ack_adder);
+#define ADD_END_ACKNOWLEDGER(CLASS, NAME)                               \
+  add_acknowledger (Callback2_wrapper::make_smob                        \
+                    <ack_trampoline<CLASS, &CLASS::acknowledge_end_ ## NAME> > (), \
+                    #NAME, acknowledge_static_array_drul_[STOP])
 
 /*
   Implement the method cl::listen_##m, and make it listen to stream
   events of class m.
  */
-#define IMPLEMENT_TRANSLATOR_LISTENER(cl, m)            \
-void                                                    \
-cl :: _internal_declare_ ## m ()                        \
-{                                                       \
+#define ADD_LISTENER(cl, m)                                             \
   listener_list_ = scm_acons                                            \
     (event_class_symbol (#m),                                           \
      Callback_wrapper::make_smob                                        \
-     <trampoline <cl, &cl::listen_ ## m> > (), listener_list_);         \
-}                                                                       \
-                                                                        \
-ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m);
+     <trampoline <cl, &cl::listen_ ## m> > (), listener_list_)
 
 #endif /* TRANSLATOR_ICC */
index 92974fe8f069d6e5e199916db70f50f166cb1bfd..7accff9a8843fcdb788595a8d7821fd86d80cd85 100644 (file)
@@ -26,7 +26,7 @@
 class Unpure_pure_container : public Smob2<Unpure_pure_container>
 {
 public:
-  static const char type_p_name_ [];
+  static const char * const type_p_name_;
   SCM unpure_part () const { return scm1 (); }
   // A container that has the same callback for both 'pure' and 'unpure' lookups
   // and which ignores the 'start' and 'end' columnns.
index f9de264277307556a0eec0c3ea296a030f5aa0e9..6f5fc18a54fb116a58dc2c1db13cf227c472704c 100644 (file)
@@ -25,7 +25,7 @@
 /* Dummy input location for use if real one is missing.  */
 Input dummy_input_global;
 
-const char Input::type_p_name_[] = "ly:input-location?";
+const char * const Input::type_p_name_ = "ly:input-location?";
 
 SCM
 Input::mark_smob () const
index d339fbce612e94c19638c33ed0da5c532b07f89b..ec37d6bcbffc2b18d638e76cf1ead798526e8e47 100644 (file)
@@ -43,7 +43,7 @@ protected:
   vector<Grob *> backup_axis_groups_;
 
   virtual void finalize ();
-  DECLARE_ACKNOWLEDGER (axis_group);
+  void acknowledge_axis_group (Grob_info);
   void process_music ();
   void start_spanner ();
   void consider_start_spanner ();
@@ -173,7 +173,12 @@ Instrument_name_engraver::stop_spanner ()
   text_spanner_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Instrument_name_engraver, axis_group);
+
+void
+Instrument_name_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Instrument_name_engraver, axis_group);
+}
 
 ADD_TRANSLATOR (Instrument_name_engraver,
                 /* doc */
index 67a58c7e6fca4ebec53bc57ec8f61b409fa12769..59cbb4f13cd4102eee7d9cc00af1844f55eb70b1 100644 (file)
@@ -75,6 +75,12 @@ Instrument_switch_engraver::stop_translation_time_step ()
   text_ = 0;
 }
 
+void
+Instrument_switch_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Instrument_switch_engraver,
                 /* doc */
                 "Create a cue text for taking instrument.",
index 79fedc96df05e2976660b766605ae4d28271bad5..9b1cbe4a23a412b95cb8797e6f7dd8fdc7656704 100644 (file)
@@ -31,7 +31,7 @@ class Keep_alive_together_engraver: public Engraver
 
 public:
   TRANSLATOR_DECLARATIONS (Keep_alive_together_engraver);
-  DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
+  void acknowledge_hara_kiri_group_spanner (Grob_info);
 
   virtual void finalize ();
 };
@@ -88,7 +88,12 @@ Keep_alive_together_engraver::finalize ()
     }
 }
 
-ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner);
+
+void
+Keep_alive_together_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner);
+}
 
 ADD_TRANSLATOR (Keep_alive_together_engraver,
                 /* doc */
index 971f55317295e8a56387a6f508dc8a41f20cd96a..8c907dc7cccb0a4da9ed48ceaf6093a68916278c 100644 (file)
@@ -46,9 +46,9 @@ protected:
   void stop_translation_timestep ();
   void process_music ();
 
-  DECLARE_TRANSLATOR_LISTENER (key_change);
-  DECLARE_ACKNOWLEDGER (clef);
-  DECLARE_ACKNOWLEDGER (bar_line);
+  void listen_key_change (Stream_event *);
+  void acknowledge_clef (Grob_info);
+  void acknowledge_bar_line (Grob_info);
 };
 
 void
@@ -120,7 +120,6 @@ Key_engraver::create_key (bool is_default)
     }
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Key_engraver, key_change);
 void
 Key_engraver::listen_key_change (Stream_event *ev)
 {
@@ -212,8 +211,14 @@ Key_engraver::initialize ()
   context ()->set_property ("tonic", p.smobbed_copy ());
 }
 
-ADD_ACKNOWLEDGER (Key_engraver, clef);
-ADD_ACKNOWLEDGER (Key_engraver, bar_line);
+
+void
+Key_engraver::boot ()
+{
+  ADD_LISTENER (Key_engraver, key_change);
+  ADD_ACKNOWLEDGER (Key_engraver, clef);
+  ADD_ACKNOWLEDGER (Key_engraver, bar_line);
+}
 
 ADD_TRANSLATOR (Key_engraver,
                 /* doc */
index 06666ac53257083095af1323b62df7ec531d0dfa..219454115a04dc673f2ce903d04d2be68afded22 100644 (file)
@@ -36,7 +36,7 @@ protected:
   void process_music ();
   void stop_translation_timestep ();
 
-  DECLARE_TRANSLATOR_LISTENER (key_change);
+  void listen_key_change (Stream_event *);
 private:
   Stream_event *key_ev_;
   Audio_key *audio_;
@@ -98,7 +98,6 @@ Key_performer::stop_translation_timestep ()
     }
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Key_performer, key_change);
 void
 Key_performer::listen_key_change (Stream_event *ev)
 {
@@ -106,6 +105,12 @@ Key_performer::listen_key_change (Stream_event *ev)
     key_ev_ = ev;
 }
 
+void
+Key_performer::boot ()
+{
+  ADD_LISTENER (Key_performer, key_change);
+}
+
 ADD_TRANSLATOR (Key_performer,
                 /* doc */
                 "",
index 25582c6a395ebccaede5622c680ce4814663e576..cdb51de3adb49e3a9e521a0ca9ac9315b6cb8b10 100644 (file)
@@ -36,22 +36,15 @@ protected:
   virtual Spanner *create_ligature_spanner ();
   virtual void build_ligature (Spanner *ligature,
                                vector<Grob_info> const &primitives);
-  DECLARE_TRANSLATOR_LISTENER (ligature);
 
 public:
   TRANSLATOR_DECLARATIONS (Kievan_ligature_engraver);
+  TRANSLATOR_INHERIT (Coherent_ligature_engraver);
 
 private:
   void fold_up_primitives (vector<Grob_info> const &primitives, Real padding, Real &min_length);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Kievan_ligature_engraver, ligature);
-void
-Kievan_ligature_engraver::listen_ligature (Stream_event *ev)
-{
-  Ligature_engraver::listen_ligature (ev);
-}
-
 Kievan_ligature_engraver::Kievan_ligature_engraver ()
 {
 
@@ -135,8 +128,14 @@ Kievan_ligature_engraver::build_ligature (Spanner *ligature,
 
 }
 
-ADD_ACKNOWLEDGER (Kievan_ligature_engraver, rest);
-ADD_ACKNOWLEDGER (Kievan_ligature_engraver, ligature_head);
+
+void
+Kievan_ligature_engraver::boot ()
+{
+  ADD_LISTENER (Ligature_engraver, ligature);
+  ADD_ACKNOWLEDGER (Ligature_engraver, rest);
+  ADD_ACKNOWLEDGER (Ligature_engraver, ligature_head);
+}
 
 ADD_TRANSLATOR (Kievan_ligature_engraver,
                 /* doc */
index 6e57a7e9df6b92e7cb7fec9b30daea722a460a75..e84ea36bca7b72cbbe263b3361afdd0813a6f642 100644 (file)
@@ -32,9 +32,9 @@ class Laissez_vibrer_engraver : public Engraver
   vector<Grob *> lv_ties_;
 
   void stop_translation_timestep ();
-  DECLARE_ACKNOWLEDGER (note_head);
+  void acknowledge_note_head (Grob_info);
 protected:
-  DECLARE_TRANSLATOR_LISTENER (laissez_vibrer);
+  void listen_laissez_vibrer (Stream_event *);
 public:
   TRANSLATOR_DECLARATIONS (Laissez_vibrer_engraver);
 };
@@ -53,7 +53,6 @@ Laissez_vibrer_engraver::stop_translation_timestep ()
   lv_ties_.clear ();
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Laissez_vibrer_engraver, laissez_vibrer);
 void
 Laissez_vibrer_engraver::listen_laissez_vibrer (Stream_event *ev)
 {
@@ -104,7 +103,13 @@ Laissez_vibrer_engraver::acknowledge_note_head (Grob_info inf)
   lv_ties_.push_back (lv_tie);
 }
 
-ADD_ACKNOWLEDGER (Laissez_vibrer_engraver, note_head);
+void
+Laissez_vibrer_engraver::boot ()
+{
+  ADD_LISTENER (Laissez_vibrer_engraver, laissez_vibrer);
+  ADD_ACKNOWLEDGER (Laissez_vibrer_engraver, note_head);
+}
+
 ADD_TRANSLATOR (Laissez_vibrer_engraver,
                 /* doc */
                 "Create laissez vibrer items.",
index 8e871c1abf868c5ee53f34ffb82eaa5a4f2e6039..869720cca4f8811a835c7ec00af5dd717348c706 100644 (file)
@@ -36,8 +36,8 @@ protected:
   virtual void finalize ();
   void process_music ();
 
-  DECLARE_ACKNOWLEDGER (ledgered);
-  DECLARE_ACKNOWLEDGER (staff_symbol);
+  void acknowledge_ledgered (Grob_info);
+  void acknowledge_staff_symbol (Grob_info);
 
   void start_spanner ();
   void stop_spanner ();
@@ -120,8 +120,13 @@ Ledger_line_engraver::acknowledge_ledgered (Grob_info s)
   ledgered_grobs_.push_back (s.grob ());
 }
 
-ADD_ACKNOWLEDGER (Ledger_line_engraver, ledgered);
-ADD_ACKNOWLEDGER (Ledger_line_engraver, staff_symbol);
+void
+Ledger_line_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Ledger_line_engraver, ledgered);
+  ADD_ACKNOWLEDGER (Ledger_line_engraver, staff_symbol);
+}
+
 ADD_TRANSLATOR (Ledger_line_engraver,
                 /* doc */
                 "Create the spanner to draw ledger lines, and notices"
index bc3d379c22e01c83197afb6d41d1e998b1c6a625..4919071d97b92a05c01bdc960f8cc7a3e8d2002e 100644 (file)
@@ -33,9 +33,9 @@ class Ligature_bracket_engraver : public Engraver
 protected:
   virtual void process_music ();
   virtual void stop_translation_timestep ();
-  DECLARE_ACKNOWLEDGER (rest);
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_TRANSLATOR_LISTENER (ligature);
+  void acknowledge_rest (Grob_info);
+  void acknowledge_note_column (Grob_info);
+  void listen_ligature (Stream_event *);
 public:
   TRANSLATOR_DECLARATIONS (Ligature_bracket_engraver);
 
@@ -46,7 +46,6 @@ private:
   Stream_event *previous_start_event_;
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Ligature_bracket_engraver, ligature);
 void
 Ligature_bracket_engraver::listen_ligature (Stream_event *ev)
 {
@@ -116,8 +115,14 @@ Ligature_bracket_engraver::stop_translation_timestep ()
   finished_ligature_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Ligature_bracket_engraver, rest);
-ADD_ACKNOWLEDGER (Ligature_bracket_engraver, note_column);
+
+void
+Ligature_bracket_engraver::boot ()
+{
+  ADD_LISTENER (Ligature_bracket_engraver, ligature);
+  ADD_ACKNOWLEDGER (Ligature_bracket_engraver, rest);
+  ADD_ACKNOWLEDGER (Ligature_bracket_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Ligature_bracket_engraver,
                 /* doc */
index adc9124fb7dc948c613515dff9c2a585a9350987..62e58b603c1ff36e8c150fbf920c9e6bae711965 100644 (file)
@@ -52,8 +52,10 @@ namespace Lily {
   Variable beat_structure ("beat-structure");
   Variable calc_repeat_slash_count ("calc-repeat-slash-count");
   Variable car_less ("car<");
+  Variable chordmodifiers ("chordmodifiers");
   Variable construct_chord_elements ("construct-chord-elements");
   Variable default_time_signature_settings ("default-time-signature-settings");
+  Variable drum_pitch_names ("drumPitchNames");
   Variable grob_compose_function ("grob::compose-function");
   Variable grob_offset_function ("grob::offset-function");
   Variable hash_table_to_alist ("hash-table->alist");
@@ -85,6 +87,7 @@ namespace Lily {
 #endif
   Variable f_parser ("%parser");
   Variable percussion_p ("percussion?");
+  Variable pitchnames ("pitchnames");
   Variable pure_chain_offset_callback ("pure-chain-offset-callback");
   Variable remove_stencil_warnings ("remove-stencil-warnings");
   Variable scale_layout ("scale-layout");
index 221d048cc00aa9a0f67f2f963b5932a43475328d..6db0e653e5480d224427df3488bd12ae5c1a3bb5 100644 (file)
@@ -369,7 +369,7 @@ Lily_lexer::add_lexed_char (int count)
 }
 
 
-const char Lily_lexer::type_p_name_[] = "ly:lily-lexer?";
+const char * const Lily_lexer::type_p_name_ = "ly:lily-lexer?";
 
 SCM
 Lily_lexer::mark_smob () const
index 31889742843cd750355ad2d4d64131233db438e4..d2499d4c4134c1453cc0a9b1a8618282df26da33 100644 (file)
@@ -200,7 +200,7 @@ Lily_parser::parser_error (Input const &i, const string &s)
   error_level_ = 1;
 }
 
-const char Lily_parser::type_p_name_[] = "ly:lily-parser?";
+const char * const Lily_parser::type_p_name_ = "ly:lily-parser?";
 
 /****************************************************************
   OUTPUT-DEF
index 2a8d28d8cbb6daa0d287eeccded86624f75fbb9d..836f8cdc6f1b450829ff7337befa4bbc3763db33 100644 (file)
@@ -19,4 +19,4 @@
 
 #include "listener.hh"
 
-const char Listener::type_p_name_[] = "ly:listener?";
+const char * const Listener::type_p_name_ = "ly:listener?";
index b6d13fc3568646eebcc70abe8f080dca2c7f54ad..3e592516c588bc765cdfe451931bd56da2122e8b 100644 (file)
@@ -246,9 +246,9 @@ Lookup::round_filled_polygon (vector<Offset> const &points,
      applies to the given polygon.  However, this is quite complicated
      to check. */
 
+#ifdef DEBUG
   const Real epsilon = 0.01;
 
-#ifdef DEBUG
   /* remove consecutive duplicate points */
   for (vsize i = 0; i < points.size (); i++)
     {
index cdee61517e333f4c6a554c973b27c11555d8835c..08c9306693a303f83ed31dc1c51c62c013d08422 100644 (file)
@@ -36,7 +36,7 @@ class Lyric_engraver : public Engraver
 protected:
   void stop_translation_timestep ();
   void process_music ();
-  DECLARE_TRANSLATOR_LISTENER (lyric);
+  void listen_lyric (Stream_event *);
 
 public:
   TRANSLATOR_DECLARATIONS (Lyric_engraver);
@@ -56,7 +56,6 @@ Lyric_engraver::Lyric_engraver ()
   event_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Lyric_engraver, lyric);
 void
 Lyric_engraver::listen_lyric (Stream_event *ev)
 {
@@ -194,6 +193,12 @@ Lyric_engraver::stop_translation_timestep ()
   event_ = 0;
 }
 
+void
+Lyric_engraver::boot ()
+{
+  ADD_LISTENER (Lyric_engraver, lyric);
+}
+
 ADD_TRANSLATOR (Lyric_engraver,
                 /* doc */
                 "Engrave text for lyrics.",
index 0ad69ae0536b2efa17d95663dc2f4e0c818704d7..6a25d62a3f99e44fd8fbff912e20b0e2e70e61d0 100644 (file)
@@ -30,7 +30,7 @@ protected:
 
   void stop_translation_timestep ();
   void process_music ();
-  DECLARE_TRANSLATOR_LISTENER (lyric);
+  void listen_lyric (Stream_event *);
 private:
   vector<Stream_event *> events_;
   Audio_text *audio_;
@@ -67,13 +67,18 @@ Lyric_performer::stop_translation_timestep ()
   events_.clear ();
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Lyric_performer, lyric);
 void
 Lyric_performer::listen_lyric (Stream_event *event)
 {
   events_.push_back (event);
 }
 
+void
+Lyric_performer::boot ()
+{
+  ADD_LISTENER (Lyric_performer, lyric);
+}
+
 ADD_TRANSLATOR (Lyric_performer,
                 /* doc */
                 "",
index 7db0a781cc8d993807ac51af519218ef0b48d42d..a849ec11ce0dddd77f57c586efc0db2c8a68a3f7 100644 (file)
@@ -54,8 +54,8 @@ protected:
   void stop_translation_timestep ();
   virtual void finalize ();
 
-  DECLARE_TRANSLATOR_LISTENER (mark);
-  DECLARE_ACKNOWLEDGER (break_alignment);
+  void listen_mark (Stream_event *);
+  void acknowledge_break_alignment (Grob_info);
 };
 
 Mark_engraver::Mark_engraver ()
@@ -111,7 +111,6 @@ Mark_engraver::create_items (Stream_event *ev)
   text_ = make_item ("RehearsalMark", ev->self_scm ());
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Mark_engraver, mark);
 void
 Mark_engraver::listen_mark (Stream_event *ev)
 {
@@ -157,7 +156,13 @@ Mark_engraver::process_music ()
     }
 }
 
-ADD_ACKNOWLEDGER (Mark_engraver, break_alignment);
+
+void
+Mark_engraver::boot ()
+{
+  ADD_LISTENER (Mark_engraver, mark);
+  ADD_ACKNOWLEDGER (Mark_engraver, break_alignment);
+}
 
 ADD_TRANSLATOR (Mark_engraver,
                 /* doc */
index e7fc3c6726cb874513b016b23c874976bfa03bfb..2ab7a7bcc6092d8aa4fb5fc7ab6c029f652924eb 100644 (file)
@@ -36,7 +36,7 @@ protected:
 
   void process_music ();
   virtual void finalize ();
-  DECLARE_ACKNOWLEDGER (note_column);
+  void acknowledge_note_column (Grob_info);
 };
 
 void
@@ -119,7 +119,12 @@ Measure_grouping_engraver::Measure_grouping_engraver ()
   grouping_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Measure_grouping_engraver, note_column);
+void
+Measure_grouping_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Measure_grouping_engraver, note_column);
+}
+
 ADD_TRANSLATOR (Measure_grouping_engraver,
                 /* doc */
                 "Create @code{MeasureGrouping} to indicate beat subdivision.",
index 2d982056d33d22f438fdb30a800e081bf6f8150f..a97d13755f08e777948a70394ebbd15f7c2e437b 100644 (file)
@@ -29,8 +29,8 @@ class Melody_engraver : public Engraver
   Grob *stem_;
 protected:
 
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (slur);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_slur (Grob_info);
   TRANSLATOR_DECLARATIONS (Melody_engraver);
   void stop_translation_timestep ();
   void process_acknowledged ();
@@ -93,8 +93,13 @@ Melody_engraver::acknowledge_stem (Grob_info info)
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Melody_engraver, stem);
-ADD_ACKNOWLEDGER (Melody_engraver, slur);
+
+void
+Melody_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Melody_engraver, stem);
+  ADD_ACKNOWLEDGER (Melody_engraver, slur);
+}
 
 ADD_TRANSLATOR (Melody_engraver,
                 /* doc */
index ac1eb1f10af267f215b2385e723ff0ab361bf071..41652a1006775c65227a29917b502ab578f02684 100644 (file)
@@ -59,10 +59,10 @@ protected:
   virtual Spanner *create_ligature_spanner ();
   virtual void build_ligature (Spanner *ligature,
                                vector<Grob_info> const &primitives);
-  DECLARE_TRANSLATOR_LISTENER (ligature);
 
 public:
   TRANSLATOR_DECLARATIONS (Mensural_ligature_engraver);
+  TRANSLATOR_INHERIT (Coherent_ligature_engraver);
 
 private:
   void transform_heads (vector<Grob_info> const &primitives);
@@ -73,13 +73,6 @@ private:
                            Real &min_length);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Mensural_ligature_engraver, ligature);
-void
-Mensural_ligature_engraver::listen_ligature (Stream_event *ev)
-{
-  Ligature_engraver::listen_ligature (ev);
-}
-
 Mensural_ligature_engraver::Mensural_ligature_engraver ()
 {
   brew_ligature_primitive_proc
@@ -495,8 +488,14 @@ Mensural_ligature_engraver::build_ligature (Spanner *ligature,
     ligature->set_property ("minimum-length", scm_from_double (min_length));
 }
 
-ADD_ACKNOWLEDGER (Mensural_ligature_engraver, rest);
-ADD_ACKNOWLEDGER (Mensural_ligature_engraver, ligature_head);
+
+void
+Mensural_ligature_engraver::boot ()
+{
+  ADD_LISTENER (Ligature_engraver, ligature);
+  ADD_ACKNOWLEDGER (Ligature_engraver, rest);
+  ADD_ACKNOWLEDGER (Ligature_engraver, ligature_head);
+}
 
 ADD_TRANSLATOR (Mensural_ligature_engraver,
                 /* doc */
index e1de3e23e0f48692e536060357856741152f65ee..241a2da44aa0a7b990504dadc2765b97b59825c3 100644 (file)
@@ -46,11 +46,11 @@ protected:
   void stop_translation_timestep ();
   void process_music ();
 
-  DECLARE_ACKNOWLEDGER (break_aligned);
-  DECLARE_ACKNOWLEDGER (break_alignment);
-  DECLARE_ACKNOWLEDGER (grob);
+  void acknowledge_break_aligned (Grob_info);
+  void acknowledge_break_alignment (Grob_info);
+  void acknowledge_grob (Grob_info);
 
-  DECLARE_TRANSLATOR_LISTENER (tempo_change);
+  void listen_tempo_change (Stream_event *);
 };
 
 Metronome_mark_engraver::Metronome_mark_engraver ()
@@ -61,7 +61,6 @@ Metronome_mark_engraver::Metronome_mark_engraver ()
   tempo_ev_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Metronome_mark_engraver, tempo_change);
 void
 Metronome_mark_engraver::listen_tempo_change (Stream_event *ev)
 {
@@ -168,9 +167,15 @@ Metronome_mark_engraver::process_music ()
     }
 }
 
-ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_aligned);
-ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_alignment);
-ADD_ACKNOWLEDGER (Metronome_mark_engraver, grob);
+
+void
+Metronome_mark_engraver::boot ()
+{
+  ADD_LISTENER (Metronome_mark_engraver, tempo_change);
+  ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_aligned);
+  ADD_ACKNOWLEDGER (Metronome_mark_engraver, break_alignment);
+  ADD_ACKNOWLEDGER (Metronome_mark_engraver, grob);
+}
 
 ADD_TRANSLATOR (Metronome_mark_engraver,
                 /* doc */
index 90ea063f736d1c3af3a884ba7cc5858506d1ff7e..a112e6bceffb7daaaf54d9340a265dab20dbbb87 100644 (file)
@@ -113,6 +113,12 @@ Midi_control_function_performer::announce_function_value_change (SCM sev)
     }
 }
 
+void
+Midi_control_function_performer::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Midi_control_function_performer,
                 /* doc */
                 "",
index b930fd521a50e4eb2c93d69736591cac7a7b402e..6cafa2b50b3669fac258e5d2b1d3e51cdb737db1 100644 (file)
 #include "offset.hh"
 #include "warn.hh"
 
-/*
-  Return the 2-log, rounded down
-*/
-int
-intlog2 (int d)
-{
-  if (d <= 0)
-    error ("intlog2 with negative argument: " + ::to_string (d));
-  int i = 0;
-  while ((d != 1))
-    {
-      d /= 2;
-      i++;
-    }
-
-  assert (! (d / 2));
-  return i;
-}
-
 double
 log_2 (double x)
 {
index 81ab30e3aebebfe5bde60d265e31f94d257efdf7..20c1f58a0b51cdef2e0c5e42e16c4dced7014e7d 100644 (file)
@@ -44,7 +44,7 @@ Moment::Moment (Rational m)
 }
 
 
-const char Moment::type_p_name_[] = "ly:moment?";
+const char * const Moment::type_p_name_ = "ly:moment?";
 
 
 int
index 274746b84597d35ab272cd8048dbb6e0c37b3be4..04ef91fc881a5744ae84615bdf2aadfe042738c5 100644 (file)
@@ -40,8 +40,8 @@ public:
 protected:
   void process_music ();
   void start_translation_timestep ();
-  DECLARE_TRANSLATOR_LISTENER (multi_measure_rest);
-  DECLARE_TRANSLATOR_LISTENER (multi_measure_text);
+  void listen_multi_measure_rest (Stream_event *);
+  void listen_multi_measure_text (Stream_event *);
 
 private:
   void add_bound_item_to_grobs (Item *);
@@ -74,7 +74,6 @@ Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
 {
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Multi_measure_rest_engraver, multi_measure_rest);
 void
 Multi_measure_rest_engraver::listen_multi_measure_rest (Stream_event *ev)
 {
@@ -91,7 +90,6 @@ Multi_measure_rest_engraver::listen_multi_measure_rest (Stream_event *ev)
   clear_lapsed_events (now);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Multi_measure_rest_engraver, multi_measure_text);
 void
 Multi_measure_rest_engraver::listen_multi_measure_text (Stream_event *ev)
 {
@@ -245,6 +243,13 @@ Multi_measure_rest_engraver::start_translation_timestep ()
   clear_lapsed_events (now_mom ());
 }
 
+void
+Multi_measure_rest_engraver::boot ()
+{
+  ADD_LISTENER (Multi_measure_rest_engraver, multi_measure_rest);
+  ADD_LISTENER (Multi_measure_rest_engraver, multi_measure_text);
+}
+
 ADD_TRANSLATOR (Multi_measure_rest_engraver,
                 /* doc */
                 "Engrave multi-measure rests that are produced with"
index 969d5ff7b538cb6abf82a3c2d750072d9bd3c83b..c252291736cae35e659efc07ea6659742f2e0947 100644 (file)
@@ -24,7 +24,7 @@
 #include "fluid.hh"
 #include "lily-imports.hh"
 
-const char Music_function::type_p_name_[] = "ly:music-function?";
+const char * const Music_function::type_p_name_ = "ly:music-function?";
 
 /* Print a textual represenation of the smob to a given port.  */
 int
index b89e92c28ec968f2f13bfbfff070a440d891ce7f..a7a06ff0d82a1ba88ac1f1a67a4346f2fc00ceb0 100644 (file)
@@ -190,7 +190,7 @@ Music_iterator::get_music () const
 
 /****************************************************************/
 
-const char Music_iterator::type_p_name_[] = "ly:iterator?";
+const char * const Music_iterator::type_p_name_ = "ly:iterator?";
 
 SCM
 Music_iterator::mark_smob () const
index 7b89b853f6c29c332aad8292c3f828912db3ff1d..9e8cc9ff9a5bcf3353588f0996afabdf73ded7ee 100644 (file)
@@ -39,7 +39,7 @@ Music_output::derived_mark () const
 {
 }
 
-const char Music_output::type_p_name_[] = "ly:music-output?";
+const char * const Music_output::type_p_name_ = "ly:music-output?";
 
 SCM
 Music_output::mark_smob () const
index 3ecad3a89e3d10cefca9de2fd65ffe161ee3842e..75eccf69fc2cb44edb69d4cc63861332f6d8f578 100644 (file)
@@ -71,9 +71,9 @@ public:
   TRANSLATOR_DECLARATIONS (New_fingering_engraver);
 protected:
   void stop_translation_timestep ();
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
-  DECLARE_ACKNOWLEDGER (inline_accidental);
-  DECLARE_ACKNOWLEDGER (stem);
+  void acknowledge_rhythmic_head (Grob_info);
+  void acknowledge_inline_accidental (Grob_info);
+  void acknowledge_stem (Grob_info);
   void add_fingering (Grob *, SCM,
                       vector<Finger_tuple> *,
                       Stream_event *, Stream_event *);
@@ -371,9 +371,14 @@ New_fingering_engraver::New_fingering_engraver ()
   stem_ = 0;
 }
 
-ADD_ACKNOWLEDGER (New_fingering_engraver, rhythmic_head);
-ADD_ACKNOWLEDGER (New_fingering_engraver, inline_accidental);
-ADD_ACKNOWLEDGER (New_fingering_engraver, stem);
+
+void
+New_fingering_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (New_fingering_engraver, rhythmic_head);
+  ADD_ACKNOWLEDGER (New_fingering_engraver, inline_accidental);
+  ADD_ACKNOWLEDGER (New_fingering_engraver, stem);
+}
 
 ADD_TRANSLATOR (New_fingering_engraver,
                 /* doc */
index 4b21bb27673a5bf62fee58851947c79e3ebe5024..b09fe6636139ebe3a658decf524086b04437057c 100644 (file)
@@ -39,7 +39,7 @@ public:
   TRANSLATOR_DECLARATIONS (Note_head_line_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
+  void acknowledge_rhythmic_head (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
 
@@ -106,7 +106,12 @@ Note_head_line_engraver::stop_translation_timestep ()
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Note_head_line_engraver, rhythmic_head);
+void
+Note_head_line_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Note_head_line_engraver, rhythmic_head);
+}
+
 ADD_TRANSLATOR (Note_head_line_engraver,
                 /* doc */
                 "Engrave a line between two note heads in a staff"
index 6322dfa2b9f7ed72b5a8bdfd9af6109fa62fa9b5..5839a827eb3129045c9e5330d41dacf203ab0d67 100644 (file)
@@ -41,7 +41,7 @@ public:
   TRANSLATOR_DECLARATIONS (Note_heads_engraver);
 
 protected:
-  DECLARE_TRANSLATOR_LISTENER (note);
+  void listen_note (Stream_event *);
   void process_music ();
   void stop_translation_timestep ();
 };
@@ -50,7 +50,6 @@ Note_heads_engraver::Note_heads_engraver ()
 {
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Note_heads_engraver, note);
 void
 Note_heads_engraver::listen_note (Stream_event *ev)
 {
@@ -121,6 +120,12 @@ Note_heads_engraver::stop_translation_timestep ()
   note_evs_.clear ();
 }
 
+void
+Note_heads_engraver::boot ()
+{
+  ADD_LISTENER (Note_heads_engraver, note);
+}
+
 ADD_TRANSLATOR (Note_heads_engraver,
                 /* doc */
                 "Generate note heads.",
index 3ae9840e0d4090e2e30c6287bda48d5f982008d1..2b8fa87000c8331f6c6a02e137a176e95fb83636 100644 (file)
@@ -30,12 +30,11 @@ public:
   TRANSLATOR_DECLARATIONS (Note_name_engraver);
 
   vector<Stream_event *> events_;
-  DECLARE_TRANSLATOR_LISTENER (note);
+  void listen_note (Stream_event *);
   void process_music ();
   void stop_translation_timestep ();
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Note_name_engraver, note);
 void
 Note_name_engraver::listen_note (Stream_event *ev)
 {
@@ -74,6 +73,12 @@ Note_name_engraver::Note_name_engraver ()
 {
 }
 
+void
+Note_name_engraver::boot ()
+{
+  ADD_LISTENER (Note_name_engraver, note);
+}
+
 ADD_TRANSLATOR (Note_name_engraver,
                 /* doc */
                 "Print pitches as words.",
index aa46440006c21140b3f12828b3e97c5ef6ba2ae0..468210d20d0852f26a7d576dfc483defe42a277f 100644 (file)
@@ -35,15 +35,16 @@ protected:
   void stop_translation_timestep ();
   void process_music ();
 
-  DECLARE_TRANSLATOR_LISTENER (note);
-  DECLARE_TRANSLATOR_LISTENER (breathing);
+  void listen_note (Stream_event *);
+  void listen_breathing (Stream_event *);
+  void listen_tie (Stream_event *);
+  void listen_articulation (Stream_event *);
 private:
-  vector<Stream_event *> note_evs_;
+  vector<Stream_event *> note_evs_, script_evs_;
   vector<Audio_note *> notes_;
 
   vector<Audio_note *> last_notes_;
   Moment last_start_;
-
 };
 
 void
@@ -68,6 +69,10 @@ Note_performer::process_music ()
           Stream_event *tie_event = 0;
           Moment len = get_event_length (n, now_mom ());
           int velocity = 0;
+
+          for (vsize j = script_evs_.size (); j--;)
+            articulations = scm_cons (script_evs_[j]->self_scm (), articulations);
+
           for (SCM s = articulations; scm_is_pair (s); s = scm_cdr (s))
             {
               Stream_event *ev = unsmob<Stream_event> (scm_car (s));
@@ -124,16 +129,27 @@ Note_performer::stop_translation_timestep ()
 
   notes_.clear ();
   note_evs_.clear ();
+  script_evs_.clear ();
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Note_performer, note)
 void
 Note_performer::listen_note (Stream_event *ev)
 {
   note_evs_.push_back (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Note_performer, breathing)
+void
+Note_performer::listen_tie (Stream_event *ev)
+{
+  script_evs_.push_back (ev);
+}
+
+void
+Note_performer::listen_articulation (Stream_event *ev)
+{
+  script_evs_.push_back (ev);
+}
+
 void
 Note_performer::listen_breathing (Stream_event *ev)
 {
@@ -157,6 +173,15 @@ Note_performer::listen_breathing (Stream_event *ev)
       }
 }
 
+void
+Note_performer::boot ()
+{
+  ADD_LISTENER (Note_performer, note);
+  ADD_LISTENER (Note_performer, breathing);
+  ADD_LISTENER (Note_performer, tie);
+  ADD_LISTENER (Note_performer, articulation);
+}
+
 ADD_TRANSLATOR (Note_performer,
                 /* doc */
                 "",
index f0bca862d98585972abaf03ade23d336de06243f..414e1ee7610cee80c76e1ead38768c21e9fbd5cb 100644 (file)
@@ -40,8 +40,8 @@ class Note_spacing_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Note_spacing_engraver);
 protected:
 
-  DECLARE_ACKNOWLEDGER (rhythmic_grob);
-  DECLARE_ACKNOWLEDGER (note_column);
+  void acknowledge_rhythmic_grob (Grob_info);
+  void acknowledge_note_column (Grob_info);
   void stop_translation_timestep ();
   virtual void finalize ();
   virtual void derived_mark () const;
@@ -135,8 +135,13 @@ Note_spacing_engraver::stop_translation_timestep ()
 
 }
 
-ADD_ACKNOWLEDGER (Note_spacing_engraver, note_column);
-ADD_ACKNOWLEDGER (Note_spacing_engraver, rhythmic_grob);
+
+void
+Note_spacing_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Note_spacing_engraver, note_column);
+  ADD_ACKNOWLEDGER (Note_spacing_engraver, rhythmic_grob);
+}
 
 ADD_TRANSLATOR (Note_spacing_engraver,
                 /* doc */
index 79370fa698dffa4b3eeea8d997c53163ee7ffe4f..365ccb1a630f83756980b2d9fc9f2a40eba96008 100644 (file)
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include "international.hh"
 #include "modified-font-metric.hh"
 #include "open-type-font.hh"
+#include "freetype.hh"
+
+#ifdef FT_FONT_FORMATS_H
+/* FreeType 2.6+ */
+#include FT_FONT_FORMATS_H
+#else
+/* FreeType 2.5.5 and earlier */
+#include FT_XFREE86_H
+#define FT_Get_Font_Format FT_Get_X11_Font_Format
+#endif
 
 LY_DEFINE (ly_font_sub_fonts, "ly:font-sub-fonts", 1, 0, 0,
            (SCM font),
@@ -115,3 +126,49 @@ LY_DEFINE (ly_otf_glyph_list, "ly:otf-glyph-list", 1, 0, 0,
 
   return otf->glyph_list ();
 }
+
+LY_DEFINE (ly_get_font_format, "ly:get-font-format",
+           1, 1, 0, (SCM font_file_name, SCM idx),
+           "Get the font format for @var{font_file_name},"
+           " returning it as a symbol.  The optional"
+           " @var{idx} argument is useful for TrueType Collections (TTC) and"
+           " OpenType/CFF collections (OTC) only;"
+           " it specifies the font index within the TTC/OTC."
+           " The default value of @var{idx} is@tie{}0.")
+{
+  LY_ASSERT_TYPE (scm_is_string, font_file_name, 1);
+
+  int i = 0;
+  if (!SCM_UNBNDP (idx))
+    {
+      LY_ASSERT_TYPE (scm_is_integer, idx, 2);
+      i = scm_to_int (idx);
+      if (i < 0)
+        {
+          warning (_ ("font index must be non-negative, using index 0"));
+          i = 0;
+        }
+    }
+
+  string file_name = ly_scm2string (font_file_name);
+
+  FT_Face face;
+  /* check whether font index is valid */
+  if (i > 0)
+    {
+      face = open_ft_face (file_name, -1);
+      if (i >= face->num_faces)
+        {
+          warning (_f ("font index %d too large for font `%s', using index 0",
+                       i, file_name.c_str ()));
+          i = 0;
+        }
+      FT_Done_Face (face);
+    }
+
+  face = open_ft_face (file_name, i);
+  SCM asscm = scm_from_ascii_symbol (FT_Get_Font_Format (face));
+  FT_Done_Face (face);
+
+  return asscm;
+}
index d236ed779d28439768480e21fedaa41af7efb490..e681e73af6b65a661454712f47a4b535a72f6328 100644 (file)
@@ -32,7 +32,7 @@ public:
 protected:
   virtual void finalize ();
 
-  DECLARE_ACKNOWLEDGER (note_column);
+  void acknowledge_note_column (Grob_info);
 
   void process_music ();
   void stop_translation_timestep ();
@@ -136,7 +136,12 @@ Ottava_spanner_engraver::finalize ()
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Ottava_spanner_engraver, note_column);
+
+void
+Ottava_spanner_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Ottava_spanner_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Ottava_spanner_engraver,
                 /* doc */
index e78eff0673375d921eaeeb6cecf3cf0ffcb5f240..65673c8a9ec71a6238104e70621f1313b224f810 100644 (file)
@@ -101,8 +101,8 @@ LY_DEFINE (ly_output_description, "ly:output-description",
     {
       Context_def *td = unsmob<Context_def> (scm_cdar (s));
       SCM key = scm_caar (s);
-      if (td && key == td->get_context_name ())
-       ell = scm_cons (scm_cons (key, td->to_alist ()), ell);
+      if (td && scm_is_eq (key, td->get_context_name ()))
+        ell = scm_cons (scm_cons (key, td->to_alist ()), ell);
     }
   return ell;
 }
@@ -132,7 +132,7 @@ LY_DEFINE (ly_output_find_context_def, "ly:output-find-context-def",
 }
 
 const char
-Output_def::type_p_name_[] = "ly:output-def?";
+* const Output_def::type_p_name_ = "ly:output-def?";
 
 LY_DEFINE (ly_paper_outputscale, "ly:paper-outputscale",
           1, 0, 0, (SCM def),
@@ -195,7 +195,7 @@ LY_DEFINE (ly_paper_fonts, "ly:paper-fonts",
     }
 
   SCM alist2 = SCM_EOL;
-  if (scm_hash_table_p (tab2) == SCM_BOOL_T)
+  if (scm_is_true (scm_hash_table_p (tab2)))
     {
       // strip original-fonts/pango-font-descriptions
       alist2 = scm_append (ly_alist_vals (ly_hash2alist (tab2)));
index c14a6ee563b11c3e1f09cd6210ed7f7fa8eb1255..7a0fa2d3c3389484cb94f03c6f798f0a1e6b866c 100644 (file)
@@ -31,13 +31,12 @@ class Output_property_engraver : public Engraver
 protected:
   vector<Stream_event*> props_;
   
-  DECLARE_ACKNOWLEDGER (grob);
-  DECLARE_TRANSLATOR_LISTENER (apply_output);
+  void acknowledge_grob (Grob_info);
+  void listen_apply_output (Stream_event *);
 
   void stop_translation_timestep ();
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Output_property_engraver, apply_output);
 void
 Output_property_engraver::listen_apply_output (Stream_event *ev)
 {
@@ -78,7 +77,13 @@ Output_property_engraver::Output_property_engraver ()
 {
 }
 
-ADD_ACKNOWLEDGER (Output_property_engraver, grob);
+void
+Output_property_engraver::boot ()
+{
+  ADD_LISTENER (Output_property_engraver, apply_output);
+  ADD_ACKNOWLEDGER (Output_property_engraver, grob);
+}
+
 ADD_TRANSLATOR (Output_property_engraver,
                /* doc */
                "Apply a procedure to any grob acknowledged.",
index 02b9c4ad19e82c6a00b2a970ea5d098881820ed5..af62bdc95e27409ce44c14eea4bd4740ffe5f956 100644 (file)
@@ -40,7 +40,7 @@ Page_marker::~Page_marker ()
 {
 }
 
-const char Page_marker::type_p_name_[] = "ly:page-marker?";
+const char * const Page_marker::type_p_name_ = "ly:page-marker?";
 
 SCM
 Page_marker::mark_smob () const
index dd90ba71cf196afea1691f7d348f9c550ce129d3..c77dc9b2a5de516ad7cf827c7793c8e310dc3cb2 100644 (file)
@@ -97,8 +97,8 @@ class Page_turn_engraver : public Engraver
   Grob *breakable_column (Page_turn_event const &);
 
 protected:
-  DECLARE_TRANSLATOR_LISTENER (break);
-  DECLARE_ACKNOWLEDGER (note_head);
+  void listen_break (Stream_event *);
+  void acknowledge_note_head (Grob_info);
 
 public:
   TRANSLATOR_DECLARATIONS (Page_turn_engraver);
@@ -168,7 +168,6 @@ Page_turn_engraver::acknowledge_note_head (Grob_info gi)
   note_end_ = now_mom () + dur_ptr->get_length ();
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Page_turn_engraver, break);
 void
 Page_turn_engraver::listen_break (Stream_event *ev)
 {
@@ -342,7 +341,13 @@ Page_turn_engraver::finalize ()
     }
 }
 
-ADD_ACKNOWLEDGER (Page_turn_engraver, note_head);
+
+void
+Page_turn_engraver::boot ()
+{
+  ADD_LISTENER (Page_turn_engraver, break);
+  ADD_ACKNOWLEDGER (Page_turn_engraver, note_head);
+}
 
 ADD_TRANSLATOR (Page_turn_engraver,
                 /* doc */
index e23ef527772cbe2dc61d192ab2485673e8d0f7ab..3a672198b538df5a880c19b1032db80adb1af946 100644 (file)
@@ -53,7 +53,7 @@ Paper_book::~Paper_book ()
 {
 }
 
-const char Paper_book::type_p_name_[] = "ly:paper-book?";
+const char * const Paper_book::type_p_name_ = "ly:paper-book?";
 
 SCM
 Paper_book::mark_smob () const
index 7c44f173d70226f540b266bd24c7c28dfc8d8a76..8cb99ecbb6f1f259fc047677014db523f240ecb5 100644 (file)
@@ -142,14 +142,12 @@ Paper_column_engraver::set_columns (Paper_column *new_command,
   system_->add_column (musical_column_);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Paper_column_engraver, break);
 void
 Paper_column_engraver::listen_break (Stream_event *ev)
 {
   break_events_.push_back (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Paper_column_engraver, label);
 void
 Paper_column_engraver::listen_label (Stream_event *ev)
 {
@@ -301,9 +299,16 @@ Paper_column_engraver::start_translation_timestep ()
     }
 }
 
-ADD_ACKNOWLEDGER (Paper_column_engraver, item);
-ADD_ACKNOWLEDGER (Paper_column_engraver, note_spacing);
-ADD_ACKNOWLEDGER (Paper_column_engraver, staff_spacing);
+
+void
+Paper_column_engraver::boot ()
+{
+  ADD_LISTENER (Paper_column_engraver, break);
+  ADD_LISTENER (Paper_column_engraver, label);
+  ADD_ACKNOWLEDGER (Paper_column_engraver, item);
+  ADD_ACKNOWLEDGER (Paper_column_engraver, note_spacing);
+  ADD_ACKNOWLEDGER (Paper_column_engraver, staff_spacing);
+}
 
 ADD_TRANSLATOR (Paper_column_engraver,
                 /* doc */
index 471a36a41a4572eb1941eb83ad4a27b244cb3c26..a72ea59ccdef770d8f70c32f942a42ee4fe8a6d9 100644 (file)
@@ -40,8 +40,6 @@ using namespace std;
 #include "lily-imports.hh"
 
 
-const char * const Paper_outputter::type_p_name_ = 0;
-
 Paper_outputter::Paper_outputter (SCM port, const string &format)
 {
   file_ = port;
index 1479aa4c0be887d711ae4d2b46c3b1e1cdb78f8c..dcbd506a4a5326ec6fd8524f13fd5298ac07a453 100644 (file)
@@ -32,7 +32,7 @@ class Parenthesis_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Parenthesis_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (grob);
+  void acknowledge_grob (Grob_info);
 };
 
 Parenthesis_engraver::Parenthesis_engraver ()
@@ -72,7 +72,12 @@ Parenthesis_engraver::acknowledge_grob (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Parenthesis_engraver, grob);
+void
+Parenthesis_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Parenthesis_engraver, grob);
+}
+
 ADD_TRANSLATOR (Parenthesis_engraver,
                 /* doc */
                 "Parenthesize objects whose music cause has the"
index b8849e8f4acaa79447fe0a81daa4d6e0d8a218d3..1695aea6259d838f12655f412692210e251eeb4e 100644 (file)
@@ -387,8 +387,7 @@ prec levels in different prods */
 start_symbol:
        lilypond
        | EMBEDDED_LILY {
-               SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::pitchnames);
        } embedded_lilypond {
                parser->lexer_->pop_state ();
                 *retval = $3;
@@ -824,8 +823,7 @@ context_mod_arg:
        embedded_scm
        |
        {
-               SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::pitchnames);
        }
        composite_music
        {
@@ -1282,8 +1280,7 @@ output_def_body:
        {
                if (scm_is_pair ($1))
                        $1 = scm_car ($1);
-               SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::pitchnames);
        } music_or_context_def
        {
                parser->lexer_->pop_state ();
@@ -1455,8 +1452,7 @@ simple_music:
 context_modification:
         WITH
        {
-               SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::pitchnames);
        } '{' context_mod_list '}'
         {
                 parser->lexer_->pop_state ();
@@ -2530,15 +2526,13 @@ mode_changed_music:
 
 mode_changing_head:
        NOTEMODE {
-               SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::pitchnames);
 
                $$ = ly_symbol2scm ("notes");
        }
        | DRUMMODE
                {
-               SCM nn = parser->lexer_->lookup_identifier ("drumPitchNames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::drum_pitch_names);
 
                $$ = ly_symbol2scm ("drums");
        }
@@ -2548,10 +2542,9 @@ mode_changing_head:
                $$ = ly_symbol2scm ("figures");
        }
        | CHORDMODE {
-               SCM nn = parser->lexer_->lookup_identifier ("chordmodifiers");
-               parser->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
-               nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_chord_state (nn);
+               parser->lexer_->chordmodifier_tab_ =
+                       alist_to_hashq (Lily::chordmodifiers);
+               parser->lexer_->push_chord_state (Lily::pitchnames);
                $$ = ly_symbol2scm ("chords");
 
        }
@@ -2563,8 +2556,7 @@ mode_changing_head:
 
 mode_changing_head_with_context:
        DRUMS {
-               SCM nn = parser->lexer_->lookup_identifier ("drumPitchNames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::drum_pitch_names);
 
                $$ = ly_symbol2scm ("DrumStaff");
        }
@@ -2574,10 +2566,9 @@ mode_changing_head_with_context:
                $$ = ly_symbol2scm ("FiguredBass");
        }
        | CHORDS {
-               SCM nn = parser->lexer_->lookup_identifier ("chordmodifiers");
-               parser->lexer_->chordmodifier_tab_ = alist_to_hashq (nn);
-               nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_chord_state (nn);
+               parser->lexer_->chordmodifier_tab_ =
+                       alist_to_hashq (Lily::chordmodifiers);
+               parser->lexer_->push_chord_state (Lily::pitchnames);
                $$ = ly_symbol2scm ("ChordNames");
        }
        | LYRICS
@@ -3861,8 +3852,7 @@ markup_uncomposed_list:
                $$ = $2;
        }
        | SCORELINES {
-               SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::pitchnames);
        } '{' score_body '}' {
                Score *sc = unsmob<Score> ($4);
                sc->origin ()->set_spot (@$);
@@ -3975,8 +3965,7 @@ simple_markup:
                $$ = make_simple_markup ($1);
        }
        | SCORE {
-               SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
-               parser->lexer_->push_note_state (nn);
+               parser->lexer_->push_note_state (Lily::pitchnames);
        } '{' score_body '}' {
                Score *sc = unsmob<Score> ($4);
                sc->origin ()->set_spot (@$);
index eaae218c1b17a1700a10a394960b1000c1abffac..33c10f59660cb77ff2a674656168ae7d1d19a951 100644 (file)
@@ -34,11 +34,11 @@ class Part_combine_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Part_combine_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (note_head);
-  DECLARE_ACKNOWLEDGER (stem);
+  void acknowledge_note_head (Grob_info);
+  void acknowledge_stem (Grob_info);
 
-  DECLARE_TRANSLATOR_LISTENER (part_combine);
-  DECLARE_TRANSLATOR_LISTENER (note);
+  void listen_part_combine (Stream_event *);
+  void listen_note (Stream_event *);
   void process_music ();
   void stop_translation_timestep ();
   void create_item (Stream_event *ev);
@@ -51,7 +51,6 @@ private:
   Stream_event *waiting_event_;
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Part_combine_engraver, part_combine);
 void
 Part_combine_engraver::listen_part_combine (Stream_event *ev)
 {
@@ -61,7 +60,6 @@ Part_combine_engraver::listen_part_combine (Stream_event *ev)
   waiting_event_ = new_event_;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Part_combine_engraver, note);
 void
 Part_combine_engraver::listen_note (Stream_event *)
 {
@@ -137,8 +135,15 @@ Part_combine_engraver::stop_translation_timestep ()
   note_found_ = false;
 }
 
-ADD_ACKNOWLEDGER (Part_combine_engraver, note_head);
-ADD_ACKNOWLEDGER (Part_combine_engraver, stem);
+void
+Part_combine_engraver::boot ()
+{
+  ADD_LISTENER (Part_combine_engraver, part_combine);
+  ADD_LISTENER (Part_combine_engraver, note);
+  ADD_ACKNOWLEDGER (Part_combine_engraver, note_head);
+  ADD_ACKNOWLEDGER (Part_combine_engraver, stem);
+}
+
 ADD_TRANSLATOR (Part_combine_engraver,
                 /* doc */
                 "Part combine engraver for orchestral scores: Print markings"
index 895e06981ec6483c1cfcdb7f1b460f41a625c52e..b620cdccb561d49fc684917d58116b3be5a1c534 100644 (file)
@@ -50,7 +50,7 @@ protected:
   Moment command_moment_;
 
   virtual void finalize ();
-  DECLARE_TRANSLATOR_LISTENER (percent);
+  void listen_percent (Stream_event *);
 
   void start_translation_timestep ();
   void stop_translation_timestep ();
@@ -85,7 +85,6 @@ Percent_repeat_engraver::start_translation_timestep ()
     }
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Percent_repeat_engraver, percent);
 void
 Percent_repeat_engraver::listen_percent (Stream_event *ev)
 {
@@ -169,6 +168,12 @@ Percent_repeat_engraver::stop_translation_timestep ()
 {
 }
 
+void
+Percent_repeat_engraver::boot ()
+{
+  ADD_LISTENER (Percent_repeat_engraver, percent);
+}
+
 ADD_TRANSLATOR (Percent_repeat_engraver,
                 /* doc */
                 "Make whole measure repeats.",
index 4a1351547230abd68d06c72ad882778c09be4f88..f708c098a09329511805f27a1d6f8db4a1409112 100644 (file)
@@ -1,4 +1,5 @@
 
+#include "international.hh"
 #include "program-option.hh"
 #include "source-file.hh"
 #include "memory-stream.hh"
@@ -29,20 +30,50 @@ LY_DEFINE (ly_pfb_2_pfa, "ly:pfb->pfa",
 }
 
 LY_DEFINE (ly_otf_2_cff, "ly:otf->cff",
-           1, 0, 0, (SCM otf_file_name),
+           1, 1, 0, (SCM otf_file_name, SCM idx),
            "Convert the contents of an OTF file to a CFF file,"
-           " returning it as a string.")
+           " returning it as a string.  The optional"
+           " @var{idx} argument is useful for OpenType/CFF collections (OTC)"
+           " only; it specifies the font index within the OTC.  The default"
+           " value of @var{idx} is@tie{}0.")
 {
   LY_ASSERT_TYPE (scm_is_string, otf_file_name, 1);
 
+  int i = 0;
+  if (!SCM_UNBNDP (idx))
+    {
+      LY_ASSERT_TYPE (scm_is_integer, idx, 2);
+      i = scm_to_int (idx);
+      if (i < 0)
+        {
+          warning (_ ("font index must be non-negative, using index 0"));
+          i = 0;
+        }
+    }
+
   string file_name = ly_scm2string (otf_file_name);
   debug_output ("[" + file_name); // start message on a new line
 
-  FT_Face face = open_ft_face (file_name, 0 /* index */);
+  FT_Face face;
+  /* check whether font index is valid */
+  if (i > 0)
+    {
+      face = open_ft_face (file_name, -1);
+      if (i >= face->num_faces)
+        {
+          warning (_f ("font index %d too large for font `%s', using index 0",
+                       i, file_name.c_str ()));
+          i = 0;
+        }
+      FT_Done_Face (face);
+    }
+
+  face = open_ft_face (file_name, i);
   string table = get_otf_table (face, "CFF ");
 
   SCM asscm = scm_from_latin1_stringn ((char *) table.data (),
                                        table.length ());
+  FT_Done_Face (face);
 
   debug_output ("]", false);
 
index 479be1df22cdf87e9d02e47c18d5c72cc0733dcf..ee7a96a2d773e492c8172f0ef77bd5ba67373cab 100644 (file)
 class Phrasing_slur_engraver : public Slur_proto_engraver
 {
 protected:
-  DECLARE_TRANSLATOR_LISTENER (phrasing_slur);
-  DECLARE_TRANSLATOR_LISTENER (note);
-  DECLARE_ACKNOWLEDGER (slur);
+  void listen_phrasing_slur (Stream_event *);
+  void acknowledge_slur (Grob_info);
 
 public:
   SCM event_symbol ();
   TRANSLATOR_DECLARATIONS (Phrasing_slur_engraver);
+  TRANSLATOR_INHERIT (Slur_proto_engraver);
 };
 
 Phrasing_slur_engraver::Phrasing_slur_engraver () :
@@ -55,36 +55,35 @@ Phrasing_slur_engraver::event_symbol ()
   return ly_symbol2scm ("phrasing-slur-event");
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Phrasing_slur_engraver, phrasing_slur);
 void
 Phrasing_slur_engraver::listen_phrasing_slur (Stream_event *ev)
 {
   Slur_proto_engraver::listen_slur (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Phrasing_slur_engraver, note);
 void
-Phrasing_slur_engraver::listen_note (Stream_event *ev)
+Phrasing_slur_engraver::acknowledge_slur (Grob_info info)
 {
-  Slur_proto_engraver::listen_note (ev);
+  acknowledge_extra_object (info);
 }
 
+
 void
-Phrasing_slur_engraver::acknowledge_slur (Grob_info info)
+Phrasing_slur_engraver::boot ()
 {
-  acknowledge_extra_object (info);
+  ADD_LISTENER (Phrasing_slur_engraver, phrasing_slur);
+  ADD_LISTENER (Slur_proto_engraver, note);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, inline_accidental);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, fingering);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, note_column);
+  ADD_ACKNOWLEDGER (Phrasing_slur_engraver, slur);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, script);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, dots);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, text_script);
+  ADD_END_ACKNOWLEDGER (Slur_proto_engraver, tie);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, tuplet_number);
 }
 
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, inline_accidental);
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, fingering)
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, note_column);
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, slur);
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, script);
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, dots);
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, text_script);
-ADD_END_ACKNOWLEDGER (Phrasing_slur_engraver, tie);
-ADD_ACKNOWLEDGER (Phrasing_slur_engraver, tuplet_number);
-
 ADD_TRANSLATOR (Phrasing_slur_engraver,
                 /* doc */
                 "Print phrasing slurs.  Similar to @ref{Slur_engraver}.",
index 7134a6cfc7797d895491db906a751d502bfc3295..7c120a1bc19f861cea5c14a7603326d629a5469b 100644 (file)
@@ -76,11 +76,11 @@ public:
 protected:
   virtual void finalize ();
 
-  DECLARE_ACKNOWLEDGER (piano_pedal_script);
-  DECLARE_ACKNOWLEDGER (piano_pedal_bracket);
-  DECLARE_ACKNOWLEDGER (note_column);
+  void acknowledge_piano_pedal_script (Grob_info);
+  void acknowledge_piano_pedal_bracket (Grob_info);
+  void acknowledge_note_column (Grob_info);
 
-  DECLARE_END_ACKNOWLEDGER (piano_pedal_bracket);
+  void acknowledge_end_piano_pedal_bracket (Grob_info);
 
   void stop_translation_timestep ();
   void start_translation_timestep ();
@@ -248,11 +248,16 @@ Piano_pedal_align_engraver::finalize ()
     }
 }
 
-ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, note_column);
-ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
-ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_script);
 
-ADD_END_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
+
+void
+Piano_pedal_align_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, note_column);
+  ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
+  ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_script);
+  ADD_END_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
+}
 
 ADD_TRANSLATOR (Piano_pedal_align_engraver,
                 /* doc */
index 2fb99407d50c7c9a7061fb832d89d662ce38b27d..cbdf5244d11e223d3c8aea157ac0d8acee5daf8d 100644 (file)
@@ -123,9 +123,9 @@ public:
 protected:
   virtual void initialize ();
   virtual void finalize ();
-  DECLARE_TRANSLATOR_LISTENER (sustain);
-  DECLARE_TRANSLATOR_LISTENER (una_corda);
-  DECLARE_TRANSLATOR_LISTENER (sostenuto);
+  void listen_sustain (Stream_event *);
+  void listen_una_corda (Stream_event *);
+  void listen_sostenuto (Stream_event *);
   void stop_translation_timestep ();
   void process_music ();
 
@@ -205,7 +205,6 @@ Piano_pedal_engraver::initialize ()
   info_list_[NUM_PEDAL_TYPES].type_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver, sostenuto);
 void
 Piano_pedal_engraver::listen_sostenuto (Stream_event *ev)
 {
@@ -213,7 +212,6 @@ Piano_pedal_engraver::listen_sostenuto (Stream_event *ev)
   ASSIGN_EVENT_ONCE (info_list_[SOSTENUTO].event_drul_[d], ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver, sustain);
 void
 Piano_pedal_engraver::listen_sustain (Stream_event *ev)
 {
@@ -221,7 +219,6 @@ Piano_pedal_engraver::listen_sustain (Stream_event *ev)
   ASSIGN_EVENT_ONCE (info_list_[SUSTAIN].event_drul_[d], ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_engraver, una_corda);
 void
 Piano_pedal_engraver::listen_una_corda (Stream_event *ev)
 {
@@ -479,6 +476,14 @@ Piano_pedal_engraver::typeset_all (Pedal_info *p)
     }
 }
 
+void
+Piano_pedal_engraver::boot ()
+{
+  ADD_LISTENER (Piano_pedal_engraver, sostenuto);
+  ADD_LISTENER (Piano_pedal_engraver, sustain);
+  ADD_LISTENER (Piano_pedal_engraver, una_corda);
+}
+
 ADD_TRANSLATOR (Piano_pedal_engraver,
                 /* doc */
                 "Engrave piano pedal symbols and brackets.",
index 49ec0dd7feb042ea052de8a6b01069b59366187b..a8273980e924d61ca558444ec949475102b6c536 100644 (file)
@@ -48,9 +48,9 @@ protected:
   void process_music ();
   void stop_translation_timestep ();
   void start_translation_timestep ();
-  DECLARE_TRANSLATOR_LISTENER (sustain);
-  DECLARE_TRANSLATOR_LISTENER (una_corda);
-  DECLARE_TRANSLATOR_LISTENER (sostenuto);
+  void listen_sustain (Stream_event *);
+  void listen_una_corda (Stream_event *);
+  void listen_sostenuto (Stream_event *);
 private:
   vector<Audio_piano_pedal *> audios_;
   Pedal_info info_alist_[NUM_PEDAL_TYPES];
@@ -146,7 +146,6 @@ Piano_pedal_performer::start_translation_timestep ()
     }
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_performer, sostenuto);
 void
 Piano_pedal_performer::listen_sostenuto (Stream_event *r)
 {
@@ -154,7 +153,6 @@ Piano_pedal_performer::listen_sostenuto (Stream_event *r)
   info_alist_[SOSTENUTO].event_drul_[d] = r;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_performer, sustain);
 void
 Piano_pedal_performer::listen_sustain (Stream_event *r)
 {
@@ -162,7 +160,6 @@ Piano_pedal_performer::listen_sustain (Stream_event *r)
   info_alist_[SUSTAIN].event_drul_[d] = r;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Piano_pedal_performer, una_corda);
 void
 Piano_pedal_performer::listen_una_corda (Stream_event *r)
 {
@@ -170,6 +167,14 @@ Piano_pedal_performer::listen_una_corda (Stream_event *r)
   info_alist_[UNA_CORDA].event_drul_[d] = r;
 }
 
+void
+Piano_pedal_performer::boot ()
+{
+  ADD_LISTENER (Piano_pedal_performer, sostenuto);
+  ADD_LISTENER (Piano_pedal_performer, sustain);
+  ADD_LISTENER (Piano_pedal_performer, una_corda);
+}
+
 ADD_TRANSLATOR (Piano_pedal_performer,
                 /* doc */
                 "",
index d9796ff0e0789feb3c5d842228b8c4be968282da..0750c594950e7dd7ce5f9bcea9166345a1b9875f 100644 (file)
@@ -28,7 +28,7 @@ class Pitch_squash_engraver : public Engraver
 {
 public:
   TRANSLATOR_DECLARATIONS (Pitch_squash_engraver);
-  DECLARE_ACKNOWLEDGER (note_head);
+  void acknowledge_note_head (Grob_info);
 };
 
 void
@@ -44,7 +44,12 @@ Pitch_squash_engraver::Pitch_squash_engraver ()
 }
 
 #include "translator.icc"
-ADD_ACKNOWLEDGER (Pitch_squash_engraver, note_head);
+void
+Pitch_squash_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Pitch_squash_engraver, note_head);
+}
+
 ADD_TRANSLATOR (Pitch_squash_engraver,
                 /* doc */
                 "Set the vertical position of note heads to"
index e34562fecc5571fe83ab21b5c3b5df677ffb36d9..9e46bba70e6ff1d2360a66292427f312b4b5f5c8 100644 (file)
@@ -218,7 +218,7 @@ Pitch::down_to (int notename)
   notename_ = notename;
 }
 
-const char Pitch::type_p_name_[] = "ly:pitch?";
+const char * const Pitch::type_p_name_ = "ly:pitch?";
 
 SCM
 Pitch::mark_smob () const
index 30d734346e53df7565c419817a9637ad1524afc0..1ec4da9aebdd26c07c31725230d8f20d650937b0 100644 (file)
@@ -38,11 +38,11 @@ public:
   TRANSLATOR_DECLARATIONS (Pitched_trill_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (note_head);
-  DECLARE_ACKNOWLEDGER (dots);
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (flag);
-  DECLARE_ACKNOWLEDGER (trill_spanner);
+  void acknowledge_note_head (Grob_info);
+  void acknowledge_dots (Grob_info);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_flag (Grob_info);
+  void acknowledge_trill_spanner (Grob_info);
   void stop_translation_timestep ();
 
 private:
@@ -169,11 +169,16 @@ Pitched_trill_engraver::stop_translation_timestep ()
   trill_accidental_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Pitched_trill_engraver, note_head);
-ADD_ACKNOWLEDGER (Pitched_trill_engraver, dots);
-ADD_ACKNOWLEDGER (Pitched_trill_engraver, stem);
-ADD_ACKNOWLEDGER (Pitched_trill_engraver, flag);
-ADD_ACKNOWLEDGER (Pitched_trill_engraver, trill_spanner);
+
+void
+Pitched_trill_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Pitched_trill_engraver, note_head);
+  ADD_ACKNOWLEDGER (Pitched_trill_engraver, dots);
+  ADD_ACKNOWLEDGER (Pitched_trill_engraver, stem);
+  ADD_ACKNOWLEDGER (Pitched_trill_engraver, flag);
+  ADD_ACKNOWLEDGER (Pitched_trill_engraver, trill_spanner);
+}
 
 ADD_TRANSLATOR (Pitched_trill_engraver,
                 /* doc */
index 938f10686164e33d98460e5d1d2bc682b341e90e..d05a33e4f3aa60387ad40a612deaf01a6d952a54 100644 (file)
@@ -24,7 +24,7 @@
 #include "profile.hh"
 
 
-const char Prob::type_p_name_[] = "ly:prob?";
+const char * const Prob::type_p_name_ = "ly:prob?";
 
 SCM
 Prob::equal_p (SCM sa, SCM sb)
index 225c64dc60fc220bf03910f25575a539a3ecbdfd..75091e19015ce3d78e87dd208be3fae1cf2b9f73 100644 (file)
@@ -37,18 +37,20 @@ Protected_scm::Protected_scm (SCM s)
   assert (SCM_IMP (s));
 }
 
-// For static objects, this will be called at program exit.  With the
-// state of the memory system unknown, we refrain from any cleanup
-// actions outside of the object memory itself.
+SCM Protected_scm::list_ = SCM_EOL;
+SCM Protected_scm::last_ = SCM_EOL;
 
-Protected_scm::~Protected_scm ()
+void
+Protected_scm::protectify (SCM s)
 {
-  object_ = SCM_UNDEFINED;
+  s = scm_list_1 (s);
+  if (SCM_CONSP (last_))
+    SCM_SETCDR (last_, s);
+  else
+    list_ = scm_permanent_object (s);
+  last_ = object_ = s;
 }
 
-SCM Protected_scm::list_ = SCM_EOL;
-SCM Protected_scm::last_ = SCM_EOL;
-
 Protected_scm &
 Protected_scm::operator = (SCM s)
 {
@@ -57,14 +59,7 @@ Protected_scm::operator = (SCM s)
   else if (SCM_IMP (s))
     object_ = s;
   else
-    {
-      s = scm_list_1 (s);
-      if (SCM_CONSP (last_))
-        SCM_SETCDR (last_, s);
-      else
-        list_ = scm_permanent_object (s);
-      last_ = object_ = s;
-    }
+    protectify (s);
 
   return *this;
 }
@@ -75,7 +70,17 @@ Protected_scm::operator = (Protected_scm const &s)
   return *this = (SCM) s;
 }
 
-Protected_scm::operator SCM () const
+Protected_scm::operator SCM const & () const
 {
-  return SCM_CONSP (object_) ? SCM_CAR (object_) : object_;
+  return SCM_CONSP (object_) ? *SCM_CARLOC (object_) : object_;
+}
+
+Protected_scm::operator SCM & ()
+{
+  // The reference may be used to overwrite an immediate value with a
+  // non-immediate one, so we _have_ to create full protection.
+  if (!SCM_CONSP (object_))
+    protectify (object_);
+
+  return *SCM_CARLOC (object_);
 }
index e147f53ccadb3a5da4663b83cf59616d518911f4..3bd0fa1091482d4e12a9f32707492c0630e9823b 100644 (file)
@@ -36,8 +36,8 @@ class Pure_from_neighbor_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Pure_from_neighbor_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (pure_from_neighbor);
-  DECLARE_ACKNOWLEDGER (item);
+  void acknowledge_pure_from_neighbor (Grob_info);
+  void acknowledge_item (Grob_info);
   void finalize ();
 };
 
@@ -136,8 +136,13 @@ Pure_from_neighbor_engraver::finalize ()
   pure_relevants_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, item);
-ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, pure_from_neighbor);
+void
+Pure_from_neighbor_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, item);
+  ADD_ACKNOWLEDGER (Pure_from_neighbor_engraver, pure_from_neighbor);
+}
+
 ADD_TRANSLATOR (Pure_from_neighbor_engraver,
                 /* doc */
                 "Coordinates items that get their pure heights from their neighbors.",
index 67477b1f01df6cd589a7d24559132d1e12f64466..d11b633fd5cb4b92ffb32af56f83c340056892bd 100644 (file)
@@ -135,6 +135,12 @@ Repeat_acknowledge_engraver::process_music ()
     }
 }
 
+void
+Repeat_acknowledge_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Repeat_acknowledge_engraver,
                 /* doc */
                 "Acknowledge repeated music, and convert the contents of"
index 4eea8e5800ae271fe103da8241a225a1790386c0..fb2c8bb58465ca0c80ebc3d6f0de9cfa13652dcf 100644 (file)
@@ -32,8 +32,8 @@ class Repeat_tie_engraver : public Engraver
   vector<Grob *> semi_ties_;
 
   void stop_translation_timestep ();
-  DECLARE_ACKNOWLEDGER (note_head);
-  DECLARE_TRANSLATOR_LISTENER (repeat_tie);
+  void acknowledge_note_head (Grob_info);
+  void listen_repeat_tie (Stream_event *);
 
 public:
   TRANSLATOR_DECLARATIONS (Repeat_tie_engraver);
@@ -53,7 +53,6 @@ Repeat_tie_engraver::stop_translation_timestep ()
   semi_ties_.clear ();
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Repeat_tie_engraver, repeat_tie);
 void
 Repeat_tie_engraver::listen_repeat_tie (Stream_event *ev)
 {
@@ -88,7 +87,13 @@ Repeat_tie_engraver::acknowledge_note_head (Grob_info inf)
 
 }
 
-ADD_ACKNOWLEDGER (Repeat_tie_engraver, note_head);
+void
+Repeat_tie_engraver::boot ()
+{
+  ADD_LISTENER (Repeat_tie_engraver, repeat_tie);
+  ADD_ACKNOWLEDGER (Repeat_tie_engraver, note_head);
+}
+
 ADD_TRANSLATOR (Repeat_tie_engraver,
                 /* doc */
                 "Create repeat ties.",
index a70641cfd05e522d3f67e7bc3c8addb4d06d18bb..56a6783fbfa34d338eac0366b6ecf5e9a90d864d 100644 (file)
@@ -94,6 +94,12 @@ Rest_collision_engraver::stop_translation_timestep ()
   rest_collision_ = 0;
 }
 
+void
+Rest_collision_engraver::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Rest_collision_engraver,
                 /* doc */
                 "Handle collisions of rests.",
index b40aeee8a3738e0b43c7080d60e2f715d932b662..d691c2e98c7f9e2001706845c9ca3cf15b590df1 100644 (file)
@@ -37,7 +37,7 @@ class Rest_engraver : public Engraver
 protected:
   void start_translation_timestep ();
   void process_music ();
-  DECLARE_TRANSLATOR_LISTENER (rest);
+  void listen_rest (Stream_event *);
 public:
   TRANSLATOR_DECLARATIONS (Rest_engraver);
 };
@@ -80,13 +80,18 @@ Rest_engraver::process_music ()
     }
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Rest_engraver, rest);
 void
 Rest_engraver::listen_rest (Stream_event *ev)
 {
   ASSIGN_EVENT_ONCE (rest_event_, ev);
 }
 
+void
+Rest_engraver::boot ()
+{
+  ADD_LISTENER (Rest_engraver, rest);
+}
+
 ADD_TRANSLATOR (Rest_engraver,
                 /* doc */
                 "Engrave rests.",
index 28a06f79b0672dfa88e341c65fad3682448b8ce9..04281231d52825410a3606900a52f36147b31d5b 100644 (file)
@@ -61,9 +61,9 @@ class Rhythmic_column_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Rhythmic_column_engraver);
 protected:
 
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (flag);
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_flag (Grob_info);
+  void acknowledge_rhythmic_head (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
 };
@@ -134,9 +134,14 @@ Rhythmic_column_engraver::stop_translation_timestep ()
   flag_ = 0;
 }
 
-ADD_ACKNOWLEDGER (Rhythmic_column_engraver, stem);
-ADD_ACKNOWLEDGER (Rhythmic_column_engraver, flag);
-ADD_ACKNOWLEDGER (Rhythmic_column_engraver, rhythmic_head);
+
+void
+Rhythmic_column_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Rhythmic_column_engraver, stem);
+  ADD_ACKNOWLEDGER (Rhythmic_column_engraver, flag);
+  ADD_ACKNOWLEDGER (Rhythmic_column_engraver, rhythmic_head);
+}
 
 ADD_TRANSLATOR (Rhythmic_column_engraver,
                 /* doc */
index d6f566b9ed57517d28ae1ef2859d25438deff275..02c1dc5f8e2daca09b480ac977049c66e70d68e3 100644 (file)
@@ -90,8 +90,6 @@ LY_DEFINE (ly_set_default_scale, "ly:set-default-scale",
   return SCM_UNSPECIFIED;
 }
 
-const char * const Scale::type_p_name_ = 0;
-
 int
 Scale::step_count () const
 {
index ec4197641bfcba78386ee3b11c9becd6e24cf762..c322a6d25515239cea12fd1545a596145612f113 100644 (file)
 
 #include "translator.icc"
 
+#include "scm-hash.hh"
+
 Scheme_engraver::Scheme_engraver (SCM definition)
 {
-  stop_translation_timestep_function_ = SCM_EOL;
-  start_translation_timestep_function_ = SCM_EOL;
-  process_music_function_ = SCM_EOL;
-  process_acknowledged_function_ = SCM_EOL;
   initialize_function_ = SCM_EOL;
   finalize_function_ = SCM_EOL;
 
-  interface_acknowledger_hash_ = SCM_EOL;
-  interface_end_acknowledger_hash_ = SCM_EOL;
+  interface_acknowledger_hash_.set (SCM_EOL, SCM_EOL);
 
   must_be_last_ = false;
   per_instance_listeners_ = SCM_EOL;
+  for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
+    precomputable_methods_[i] = SCM_UNDEFINED;
 
   init_from_scheme (definition);
 }
@@ -47,12 +46,12 @@ Scheme_engraver::~Scheme_engraver ()
 {
 }
 
-// Extracts the value if callable, if not return #f.
+// Extracts the value if callable, if not return SCM_UNDEFINED;
 static SCM
 callable (SCM symbol, SCM defn)
 {
   SCM val = ly_assoc_get (symbol, defn, SCM_BOOL_F);
-  return ly_is_procedure (val) ? val : SCM_BOOL_F;
+  return ly_is_procedure (val) ? val : SCM_UNDEFINED;
 }
 
 bool
@@ -61,28 +60,35 @@ Scheme_engraver::must_be_last () const
   return must_be_last_;
 }
 
+void
+Scheme_engraver::fetch_precomputable_methods (SCM ptrs[])
+{
+  for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
+    ptrs[i] = precomputable_methods_[i];
+}
+
 void
 Scheme_engraver::init_from_scheme (SCM definition)
 {
-  start_translation_timestep_function_ = callable (ly_symbol2scm ("start-translation-timestep"),
-                                                   definition);
-  stop_translation_timestep_function_ = callable (ly_symbol2scm ("stop-translation-timestep"),
-                                                  definition);
-  process_music_function_ = callable (ly_symbol2scm ("process-music"), definition);
-  process_acknowledged_function_ = callable (ly_symbol2scm ("process-acknowledged"),
-                                             definition);
+  precomputable_methods_[START_TRANSLATION_TIMESTEP]
+    = callable (ly_symbol2scm ("start-translation-timestep"), definition);
+  precomputable_methods_[STOP_TRANSLATION_TIMESTEP]
+    = callable (ly_symbol2scm ("stop-translation-timestep"), definition);
+  precomputable_methods_[PROCESS_MUSIC]
+    = callable (ly_symbol2scm ("process-music"), definition);
+  precomputable_methods_[PROCESS_ACKNOWLEDGED]
+    = callable (ly_symbol2scm ("process-acknowledged"), definition);
   initialize_function_ = callable (ly_symbol2scm ("initialize"), definition);
   finalize_function_ = callable (ly_symbol2scm ("finalize"), definition);
 
-  SCM listeners = ly_assoc_get (ly_symbol2scm ("listeners"), definition, SCM_EOL);
-
-  per_instance_listeners_ = SCM_EOL;
+  SCM p = ly_assoc_get (ly_symbol2scm ("listeners"), definition, SCM_EOL);
+  SCM listeners = SCM_EOL;
 
   must_be_last_ = to_boolean (ly_assoc_get (ly_symbol2scm ("must-be-last"),
                                             definition,
                                             SCM_BOOL_F));
 
-  for (SCM p = listeners; scm_is_pair (p); p = scm_cdr (p))
+  for (; scm_is_pair (p); p = scm_cdr (p))
     {
       SCM event_class = scm_caar (p);
       SCM proc = scm_cdar (p);
@@ -93,26 +99,35 @@ Scheme_engraver::init_from_scheme (SCM definition)
       // We should check the arity of the function?
 
       // Record for later lookup.
-      per_instance_listeners_ = scm_acons (event_class, proc, per_instance_listeners_);
+      listeners = scm_acons (event_class, proc, listeners);
     }
 
-  init_acknowledgers (ly_assoc_get (ly_symbol2scm ("acknowledgers"),
-                                    definition, SCM_EOL),
-                      &interface_acknowledger_hash_);
+  SCM hash1 =
+    init_acknowledgers (ly_assoc_get (ly_symbol2scm ("acknowledgers"),
+                                      definition, SCM_EOL));
+  SCM hash2 =
+    init_acknowledgers (ly_assoc_get (ly_symbol2scm ("end-acknowledgers"),
+                                      definition, SCM_EOL));
 
-  init_acknowledgers (ly_assoc_get (ly_symbol2scm ("end-acknowledgers"),
-                                    definition, SCM_EOL),
-                      &interface_end_acknowledger_hash_);
+  per_instance_listeners_ = listeners;
+  interface_acknowledger_hash_.set (hash1, hash2);
+
+  // It's not defined whether Scheme_engraver::derived_mark is already
+  // active while the construction is underway, so we make sure we
+  // keep a version of everything on the stack that is not still
+  // covered by `definition'.
+
+  scm_remember_upto_here_2 (definition, listeners);
+  scm_remember_upto_here_2 (hash1, hash2);
 
   // TODO: hook up description, props read/written, grobs created
   // etc. to provide automatic documentation.
 }
 
-void
-Scheme_engraver::init_acknowledgers (SCM alist,
-                                     SCM *hash)
+SCM
+Scheme_engraver::init_acknowledgers (SCM alist)
 {
-  *hash = scm_c_make_hash_table (7);
+  SCM hash = Scheme_hash_table::make_smob ();
   for (SCM p = alist; scm_is_pair (p); p = scm_cdr (p))
     {
       SCM iface = scm_caar (p);
@@ -121,79 +136,40 @@ Scheme_engraver::init_acknowledgers (SCM alist,
       if (!(ly_is_procedure (proc) && ly_is_symbol (iface)))
         continue;
 
-      scm_hashq_set_x (*hash, iface, proc);
+      unsmob<Scheme_hash_table>(hash)->set (iface, proc);
     }
+  return hash;
 }
 
-// This is the easy way to do it, at the cost of too many invocations
-// of Scheme_engraver::acknowledge_grob.  The clever dispatching of
-// acknowledgers is hardwired to have 1 method per engraver per
-// grob-type, which doesn't work for this case.
-void
-Scheme_engraver::acknowledge_grob (Grob_info info)
+SCM
+Scheme_engraver::get_listener_list () const
 {
-  acknowledge_grob_by_hash (info, interface_acknowledger_hash_);
+  return per_instance_listeners_;
 }
 
 void
-Scheme_engraver::acknowledge_end_grob (Grob_info info)
+Scheme_engraver::initialize ()
 {
-  acknowledge_grob_by_hash (info, interface_end_acknowledger_hash_);
+  if (!SCM_UNBNDP (initialize_function_))
+    scm_call_1 (initialize_function_, self_scm ());
 }
 
 void
-Scheme_engraver::acknowledge_grob_by_hash (Grob_info info,
-                                           SCM iface_function_hash)
-{
-  SCM meta = info.grob ()->get_property ("meta");
-  SCM ifaces = scm_cdr (scm_assoc (ly_symbol2scm ("interfaces"), meta));
-  for (SCM s = ifaces; scm_is_pair (s); s = scm_cdr (s))
-    {
-      SCM func = scm_hashq_ref (iface_function_hash,
-                                scm_car (s), SCM_BOOL_F);
-
-      if (ly_is_procedure (func))
-        scm_call_3 (func, self_scm (), info.grob ()->self_scm (),
-                    info.origin_translator ()->self_scm ());
-    }
-}
-
-SCM
-Scheme_engraver::get_listener_list () const
+Scheme_engraver::finalize ()
 {
-  return per_instance_listeners_;
+  if (!SCM_UNBNDP (finalize_function_))
+    scm_call_1 (finalize_function_, self_scm ());
 }
 
-#define DISPATCH(what)                                  \
-  void                                                  \
-  Scheme_engraver::what ()                              \
-  {                                                     \
-    if (what ## _function_ != SCM_BOOL_F)               \
-      scm_call_1 (what ## _function_, self_scm ());     \
-  }
-
-DISPATCH (start_translation_timestep);
-DISPATCH (stop_translation_timestep);
-DISPATCH (initialize);
-DISPATCH (finalize);
-DISPATCH (process_music);
-DISPATCH (process_acknowledged);
-
 void
 Scheme_engraver::derived_mark () const
 {
-  scm_gc_mark (start_translation_timestep_function_);
-  scm_gc_mark (stop_translation_timestep_function_);
+  for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
+    scm_gc_mark (precomputable_methods_[i]);
+
   scm_gc_mark (initialize_function_);
   scm_gc_mark (finalize_function_);
-  scm_gc_mark (process_music_function_);
-  scm_gc_mark (process_acknowledged_function_);
   scm_gc_mark (per_instance_listeners_);
-  scm_gc_mark (interface_acknowledger_hash_);
-  scm_gc_mark (interface_end_acknowledger_hash_);
+  scm_gc_mark (interface_acknowledger_hash_[START]);
+  scm_gc_mark (interface_acknowledger_hash_[STOP]);
 }
-
-ADD_ACKNOWLEDGER (Scheme_engraver, grob);
-ADD_END_ACKNOWLEDGER (Scheme_engraver, grob);
-
-ADD_TRANSLATOR_FAMILY (Scheme_engraver);
index 3eb40ada7bfe929576fc50cb1c081d368951b488..0b1e0b4e2532a7cc481ba4a794270aa3caa44799 100644 (file)
@@ -21,8 +21,6 @@
 
 #include <cassert>
 
-const char * const Scheme_hash_table::type_p_name_ = 0;
-
 SCM
 Scheme_hash_table::make_smob ()
 {
@@ -69,9 +67,13 @@ Scheme_hash_table::set (SCM k, SCM v)
 SCM
 Scheme_hash_table::get (SCM k) const
 {
-  /* SCM_UNSPECIFIED will stick out like a sore thumb, hopefully.
+  /* SCM_UNDEFINED is the default for unset elements, but
+     scm_hashq_ref cannot return it, so we do it a bit more awkwardly.
   */
-  return scm_hashq_ref (hash_tab (), k, SCM_UNSPECIFIED);
+  SCM handle = scm_hashq_get_handle (hash_tab (), k);
+  if (scm_is_pair (handle))
+    return scm_cdr (handle);
+  return SCM_UNDEFINED;
 }
 
 void
index 3e4fb973152f691fce87f9d2bed7052227d13820..88ea4af86f34003dd605dad337c56d7e7f1174b1 100644 (file)
@@ -58,9 +58,11 @@ Score_engraver::prepare (SCM)
 void
 Score_engraver::finish (SCM)
 {
-  recurse_over_translators (context (), &Translator::finalize,
-                            &Translator_group::finalize,
-                            UP);
+  recurse_over_translators
+    (context (),
+     Callback0_wrapper::make_smob<Translator, &Translator::finalize> (),
+     Callback0_wrapper::make_smob<Translator_group, &Translator_group::finalize> (),
+     UP);
 }
 
 #define MUSIC_FONT "emmentaler-20"
index 4ea42ed14315fcf4b72a860cf4de9efc2cc1c4f1..b44bb489f5b9ccec4b8c46eb97775ac9278eae25 100644 (file)
@@ -118,10 +118,11 @@ Score_performer::finish (SCM)
   SCM channel_mapping = context ()->get_property ("midiChannelMapping");
   bool use_ports = scm_is_eq (channel_mapping, ly_symbol2scm ("voice"));
   performance_->ports_ = use_ports;
-  recurse_over_translators (context (),
-                            &Translator::finalize,
-                            &Translator_group::finalize,
-                            UP);
+  recurse_over_translators
+    (context (),
+     Callback0_wrapper::make_smob<Translator, &Translator::finalize> (),
+     Callback0_wrapper::make_smob<Translator_group, &Translator_group::finalize> (),
+     UP);
 }
 
 void
index da48e8f1031c3a5230f2c073b9bd2b0ff4166442..d10023dd8506b5103bed7a09ef673a074cff8574 100644 (file)
@@ -59,7 +59,7 @@ Score::~Score ()
 {
 }
 
-const char Score::type_p_name_[] = "ly:score?";
+const char * const Score::type_p_name_ = "ly:score?";
 
 SCM
 Score::mark_smob () const
index dc34098664d19f6d8ae59ea7d460813d508775de..6310f3b5403e5b56a98d984f3b3e735bb0c42cc4 100644 (file)
@@ -35,7 +35,7 @@ class Script_column_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Script_column_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (side_position);
+  void acknowledge_side_position (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
 };
@@ -77,7 +77,12 @@ Script_column_engraver::process_acknowledged ()
     script_column_ = make_item ("ScriptColumn", SCM_EOL);
 }
 
-ADD_ACKNOWLEDGER (Script_column_engraver, side_position);
+void
+Script_column_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Script_column_engraver, side_position);
+}
+
 ADD_TRANSLATOR (Script_column_engraver,
                 /* doc */
                 "Find potentially colliding scripts and put them into a"
index 62c3de482cd359256d824135fd0420d29455bd91..8a7b122f1fb0c0be00bab174937f95d627f0206a 100644 (file)
@@ -54,14 +54,14 @@ protected:
   void stop_translation_timestep ();
   void process_music ();
 
-  DECLARE_TRANSLATOR_LISTENER (articulation);
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
-  DECLARE_ACKNOWLEDGER (stem);
-  DECLARE_ACKNOWLEDGER (stem_tremolo);
-  DECLARE_ACKNOWLEDGER (tie);
-  DECLARE_END_ACKNOWLEDGER (tie);
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_ACKNOWLEDGER (inline_accidental);
+  void listen_articulation (Stream_event *);
+  void acknowledge_rhythmic_head (Grob_info);
+  void acknowledge_stem (Grob_info);
+  void acknowledge_stem_tremolo (Grob_info);
+  void acknowledge_tie (Grob_info);
+  void acknowledge_end_tie (Grob_info);
+  void acknowledge_note_column (Grob_info);
+  void acknowledge_inline_accidental (Grob_info);
 
 public:
   TRANSLATOR_DECLARATIONS (Script_engraver);
@@ -71,7 +71,6 @@ Script_engraver::Script_engraver ()
 {
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Script_engraver, articulation);
 void
 Script_engraver::listen_articulation (Stream_event *ev)
 {
@@ -275,13 +274,19 @@ Script_engraver::stop_translation_timestep ()
   scripts_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Script_engraver, rhythmic_head);
-ADD_ACKNOWLEDGER (Script_engraver, stem);
-ADD_ACKNOWLEDGER (Script_engraver, tie);
-ADD_END_ACKNOWLEDGER (Script_engraver, tie);
-ADD_ACKNOWLEDGER (Script_engraver, note_column);
-ADD_ACKNOWLEDGER (Script_engraver, stem_tremolo);
-ADD_ACKNOWLEDGER (Script_engraver, inline_accidental);
+
+void
+Script_engraver::boot ()
+{
+  ADD_LISTENER (Script_engraver, articulation);
+  ADD_ACKNOWLEDGER (Script_engraver, rhythmic_head);
+  ADD_ACKNOWLEDGER (Script_engraver, stem);
+  ADD_ACKNOWLEDGER (Script_engraver, tie);
+  ADD_END_ACKNOWLEDGER (Script_engraver, tie);
+  ADD_ACKNOWLEDGER (Script_engraver, note_column);
+  ADD_ACKNOWLEDGER (Script_engraver, stem_tremolo);
+  ADD_ACKNOWLEDGER (Script_engraver, inline_accidental);
+}
 
 ADD_TRANSLATOR (Script_engraver,
                 /* doc */
index 35b5038020f34431faa1819ff09b36611868ce16..20af8d1cbb20326dd041db1461b2facaf4dc89ce 100644 (file)
@@ -39,8 +39,8 @@ class Script_row_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Script_row_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (accidental_placement);
-  DECLARE_ACKNOWLEDGER (side_position);
+  void acknowledge_accidental_placement (Grob_info);
+  void acknowledge_side_position (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
 };
@@ -89,8 +89,13 @@ Script_row_engraver::process_acknowledged ()
     script_row_ = make_item ("ScriptRow", SCM_EOL);
 }
 
-ADD_ACKNOWLEDGER (Script_row_engraver, accidental_placement);
-ADD_ACKNOWLEDGER (Script_row_engraver, side_position);
+void
+Script_row_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Script_row_engraver, accidental_placement);
+  ADD_ACKNOWLEDGER (Script_row_engraver, side_position);
+}
+
 ADD_TRANSLATOR (Script_row_engraver,
                 /* doc */
                 "Determine order in horizontal side position elements.",
index 08069afda8858634692b5d73ea8d99d92e025371..5eb1407a31787a4babd78271edffd528570f9dc4 100644 (file)
@@ -59,8 +59,8 @@ protected:
   Spacings current_spacings_;
   Spacings last_spacings_;
 
-  DECLARE_ACKNOWLEDGER (item);
-  DECLARE_ACKNOWLEDGER (break_aligned);
+  void acknowledge_item (Grob_info);
+  void acknowledge_break_aligned (Grob_info);
   void stop_translation_timestep ();
   void start_translation_timestep ();
 
@@ -153,8 +153,13 @@ Separating_line_group_engraver::stop_translation_timestep ()
   break_aligned_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Separating_line_group_engraver, item);
-ADD_ACKNOWLEDGER (Separating_line_group_engraver, break_aligned);
+
+void
+Separating_line_group_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Separating_line_group_engraver, item);
+  ADD_ACKNOWLEDGER (Separating_line_group_engraver, break_aligned);
+}
 
 ADD_TRANSLATOR (Separating_line_group_engraver,
                 /* doc */
index b3c2b96df4ad9d4e34eb4641a8eef63a91a58db8..bab43494a6c68564cbae3886b64a543749a72c5f 100644 (file)
@@ -120,7 +120,7 @@ Skyline_pair::operator [] (Direction d) const
   return skylines_[d];
 }
 
-const char Skyline_pair::type_p_name_[] = "ly:skyline-pair?";
+const char * const Skyline_pair::type_p_name_ = "ly:skyline-pair?";
 
 
 MAKE_SCHEME_CALLBACK (Skyline_pair, skyline, 2);
index f46b2f3e84c401437e6136fbb7808b63a51c398d..6ef2069c39b50b0acb7273c06928c3e509cf4729 100644 (file)
@@ -802,7 +802,7 @@ Skyline::clear ()
 
 /****************************************************************/
 
-const char Skyline::type_p_name_[] = "ly:skyline?";
+const char * const Skyline::type_p_name_ = "ly:skyline?";
 
 MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Skyline, get_touching_point, 3, 1, "")
 SCM
index f9f0bfb76a0adbe3ea3b926da899b895b31d8500..b1bdf9c0dac4746b26634d7bb4da9690073a98f9 100644 (file)
@@ -35,7 +35,7 @@ public:
 protected:
   Stream_event *slash_;
 protected:
-  DECLARE_TRANSLATOR_LISTENER (repeat_slash);
+  void listen_repeat_slash (Stream_event *);
   void process_music ();
 };
 
@@ -44,7 +44,6 @@ Slash_repeat_engraver::Slash_repeat_engraver ()
   slash_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Slash_repeat_engraver, repeat_slash);
 void
 Slash_repeat_engraver::listen_repeat_slash (Stream_event *ev)
 {
@@ -65,6 +64,12 @@ Slash_repeat_engraver::process_music ()
     }
 }
 
+void
+Slash_repeat_engraver::boot ()
+{
+  ADD_LISTENER (Slash_repeat_engraver, repeat_slash);
+}
+
 ADD_TRANSLATOR (Slash_repeat_engraver,
                 /* doc */
                 "Make beat repeats.",
index 581136791d932daff6148c2ad80d2b82366c095b..2ea4595fc1b0b2544219aac915c1e4e647ed0a58 100644 (file)
@@ -35,13 +35,10 @@ class Slur_engraver : public Slur_proto_engraver
 {
   virtual void set_melisma (bool);
 
-protected:
-  DECLARE_TRANSLATOR_LISTENER (slur);
-  DECLARE_TRANSLATOR_LISTENER (note);
-
 public:
   SCM event_symbol ();
   TRANSLATOR_DECLARATIONS (Slur_engraver);
+  TRANSLATOR_INHERIT (Slur_proto_engraver);
 };
 
 Slur_engraver::Slur_engraver () :
@@ -56,34 +53,27 @@ Slur_engraver::event_symbol ()
   return ly_symbol2scm ("slur-event");
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Slur_engraver, slur);
-void
-Slur_engraver::listen_slur (Stream_event *ev)
-{
-  Slur_proto_engraver::listen_slur (ev);
-}
-
-IMPLEMENT_TRANSLATOR_LISTENER (Slur_engraver, note);
 void
-Slur_engraver::listen_note (Stream_event *ev)
+Slur_engraver::set_melisma (bool m)
 {
-  Slur_proto_engraver::listen_note (ev);
+  context ()->set_property ("slurMelismaBusy", ly_bool2scm (m));
 }
 
 void
-Slur_engraver::set_melisma (bool m)
+Slur_engraver::boot ()
 {
-  context ()->set_property ("slurMelismaBusy", ly_bool2scm (m));
+  ADD_LISTENER (Slur_proto_engraver, slur);
+  ADD_LISTENER (Slur_proto_engraver, note);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, inline_accidental);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, fingering);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, note_column);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, script);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, text_script);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, dots);
+  ADD_END_ACKNOWLEDGER (Slur_proto_engraver, tie);
+  ADD_ACKNOWLEDGER (Slur_proto_engraver, tuplet_number);
 }
 
-ADD_ACKNOWLEDGER (Slur_engraver, inline_accidental);
-ADD_ACKNOWLEDGER (Slur_engraver, fingering);
-ADD_ACKNOWLEDGER (Slur_engraver, note_column);
-ADD_ACKNOWLEDGER (Slur_engraver, script);
-ADD_ACKNOWLEDGER (Slur_engraver, text_script);
-ADD_ACKNOWLEDGER (Slur_engraver, dots);
-ADD_END_ACKNOWLEDGER (Slur_engraver, tie);
-ADD_ACKNOWLEDGER (Slur_engraver, tuplet_number);
 ADD_TRANSLATOR (Slur_engraver,
                 /* doc */
                 "Build slur grobs from slur events.",
index 222a9d75faa7eb487802e17cef96c96ac36ce466..47fed784fe6c64335b1b926f033a372599405cbf 100644 (file)
@@ -40,7 +40,7 @@ protected:
   void process_music ();
   void set_melisma (bool);
 
-  DECLARE_TRANSLATOR_LISTENER (slur);
+  void listen_slur (Stream_event *);
 private:
   Stream_event *start_ev_;
   Stream_event *now_stop_ev_;
@@ -83,7 +83,6 @@ Slur_performer::start_translation_timestep ()
   now_stop_ev_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Slur_performer, slur);
 void
 Slur_performer::listen_slur (Stream_event *ev)
 {
@@ -95,6 +94,12 @@ Slur_performer::listen_slur (Stream_event *ev)
     now_stop_ev_ = ev;
 }
 
+void
+Slur_performer::boot ()
+{
+  ADD_LISTENER (Slur_performer, slur);
+}
+
 ADD_TRANSLATOR (Slur_performer,
                 /* doc */
                 "",
index 5a94927a7ffb549977f5b284f5fda18f3bdf91a6..14fdf2beb3b6ef4c10ff835c60deeca2a5811157 100644 (file)
@@ -362,7 +362,7 @@ Source_file::get_port () const
 /****************************************************************/
 
 
-const char Source_file::type_p_name_[] = "ly:source-file?";
+const char * const Source_file::type_p_name_ = "ly:source-file?";
 
 SCM
 Source_file::mark_smob () const
index cc5b1e31d1c2f6c92365933702744c385bfcf0c0..d77a55b757af67725ac237d49eeffdcb129fb793 100644 (file)
@@ -76,11 +76,11 @@ class Spacing_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Spacing_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (staff_spacing);
-  DECLARE_ACKNOWLEDGER (note_spacing);
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
-  DECLARE_ACKNOWLEDGER (rhythmic_grob);
-  DECLARE_TRANSLATOR_LISTENER (spacing_section);
+  void acknowledge_staff_spacing (Grob_info);
+  void acknowledge_note_spacing (Grob_info);
+  void acknowledge_rhythmic_head (Grob_info);
+  void acknowledge_rhythmic_grob (Grob_info);
+  void listen_spacing_section (Stream_event *);
 
   void start_translation_timestep ();
   void stop_translation_timestep ();
@@ -99,7 +99,6 @@ Spacing_engraver::Spacing_engraver ()
   start_section_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Spacing_engraver, spacing_section);
 void
 Spacing_engraver::listen_spacing_section (Stream_event *ev)
 {
@@ -261,10 +260,16 @@ Spacing_engraver::start_translation_timestep ()
     stopped_durations_.push_back (playing_durations_.get ());
 }
 
-ADD_ACKNOWLEDGER (Spacing_engraver, staff_spacing);
-ADD_ACKNOWLEDGER (Spacing_engraver, note_spacing);
-ADD_ACKNOWLEDGER (Spacing_engraver, rhythmic_head);
-ADD_ACKNOWLEDGER (Spacing_engraver, rhythmic_grob);
+
+void
+Spacing_engraver::boot ()
+{
+  ADD_LISTENER (Spacing_engraver, spacing_section);
+  ADD_ACKNOWLEDGER (Spacing_engraver, staff_spacing);
+  ADD_ACKNOWLEDGER (Spacing_engraver, note_spacing);
+  ADD_ACKNOWLEDGER (Spacing_engraver, rhythmic_head);
+  ADD_ACKNOWLEDGER (Spacing_engraver, rhythmic_grob);
+}
 
 ADD_TRANSLATOR (Spacing_engraver,
                 /* doc */
index f66c8770b52333c9bbc23c19d9d3c01bbeb510a8..9cece4a6fe336bd26d050168fa974f4c8db67737 100644 (file)
@@ -37,8 +37,8 @@ class Span_arpeggio_engraver : public Engraver
 {
 public:
   TRANSLATOR_DECLARATIONS (Span_arpeggio_engraver);
-  DECLARE_ACKNOWLEDGER (arpeggio);
-  DECLARE_ACKNOWLEDGER (note_column);
+  void acknowledge_arpeggio (Grob_info);
+  void acknowledge_note_column (Grob_info);
 
 protected:
   void process_acknowledged ();
@@ -125,8 +125,13 @@ Span_arpeggio_engraver::stop_translation_timestep ()
   note_columns_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Span_arpeggio_engraver, arpeggio);
-ADD_ACKNOWLEDGER (Span_arpeggio_engraver, note_column);
+void
+Span_arpeggio_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Span_arpeggio_engraver, arpeggio);
+  ADD_ACKNOWLEDGER (Span_arpeggio_engraver, note_column);
+}
+
 ADD_TRANSLATOR (Span_arpeggio_engraver,
                 /* doc */
                 "Make arpeggios that span multiple staves.",
index 63c245e70cbcb32f4620b4e8ecd4fd9a9ae4b8c7..e74528535bfa0f2dd48dd8b0834e38bace2fd6b1 100644 (file)
@@ -41,7 +41,7 @@ class Span_bar_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Span_bar_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (bar_line);
+  void acknowledge_bar_line (Grob_info);
   void stop_translation_timestep ();
   void process_acknowledged ();
 };
@@ -94,7 +94,12 @@ Span_bar_engraver::stop_translation_timestep ()
   bars_.resize (0);
 }
 
-ADD_ACKNOWLEDGER (Span_bar_engraver, bar_line);
+void
+Span_bar_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Span_bar_engraver, bar_line);
+}
+
 ADD_TRANSLATOR (Span_bar_engraver,
                 /* doc */
                 "Make cross-staff bar lines: It catches all normal bar lines"
index 304564398f0841c7832aa8d5412f6b8e04a30459..a0c10f8594ae1165cbe74fcdd3b077ad94c0cd86 100644 (file)
@@ -55,8 +55,8 @@ class Span_bar_stub_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (span_bar);
-  DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
+  void acknowledge_span_bar (Grob_info);
+  void acknowledge_hara_kiri_group_spanner (Grob_info);
   void process_acknowledged ();
   void stop_translation_timestep ();
   virtual void derived_mark () const;
@@ -175,8 +175,13 @@ Span_bar_stub_engraver::stop_translation_timestep ()
   axis_groups_ = axis_groups;
 }
 
-ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
-ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
+void
+Span_bar_stub_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
+  ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
+}
+
 ADD_TRANSLATOR (Span_bar_stub_engraver,
                 /* doc */
                 "Make stubs for span bars in all contexts that the span bars cross.",
index 4a47aade98c241b060165500b24d66340bfd9123..8d64b40ce8134672fcc1e53dfa28daedbfcfab4a 100644 (file)
@@ -31,8 +31,8 @@ class Spanner_break_forbid_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Spanner_break_forbid_engraver);
   vector<Spanner *> running_spanners_;
 protected:
-  DECLARE_ACKNOWLEDGER (unbreakable_spanner);
-  DECLARE_END_ACKNOWLEDGER (unbreakable_spanner);
+  void acknowledge_unbreakable_spanner (Grob_info);
+  void acknowledge_end_unbreakable_spanner (Grob_info);
 
   void process_music ();
 };
@@ -66,8 +66,13 @@ Spanner_break_forbid_engraver::Spanner_break_forbid_engraver ()
 {
 }
 
-ADD_END_ACKNOWLEDGER (Spanner_break_forbid_engraver, unbreakable_spanner);
-ADD_ACKNOWLEDGER (Spanner_break_forbid_engraver, unbreakable_spanner);
+void
+Spanner_break_forbid_engraver::boot ()
+{
+  ADD_END_ACKNOWLEDGER (Spanner_break_forbid_engraver, unbreakable_spanner);
+  ADD_ACKNOWLEDGER (Spanner_break_forbid_engraver, unbreakable_spanner);
+}
+
 ADD_TRANSLATOR (Spanner_break_forbid_engraver,
                 /* doc */
                 "Forbid breaks in certain spanners.",
index 77b01bb158d56152e6c8dd027a788ba7788c7636..a389df2efdb5921a60b56814a7a2c2f210bb495f 100644 (file)
@@ -66,4 +66,4 @@ LY_DEFINE (ly_spring_set_inverse_stretch_strength_x, "ly:spring-set-inverse-stre
   return s->smobbed_copy ();
 }
 
-const char Spring::type_p_name_[] = "ly:spring?";
+const char * const Spring::type_p_name_ = "ly:spring?";
index 2ff2b79cafcb68b1f9c4a6cf19bb7aab9792bd9f..88680943d3d0937139645d0a6a8cf075f1e24bce 100644 (file)
@@ -26,8 +26,8 @@ class Staff_collecting_engraver : public Engraver
 {
 public:
   TRANSLATOR_DECLARATIONS (Staff_collecting_engraver);
-  DECLARE_ACKNOWLEDGER (staff_symbol);
-  DECLARE_END_ACKNOWLEDGER (staff_symbol);
+  void acknowledge_staff_symbol (Grob_info);
+  void acknowledge_end_staff_symbol (Grob_info);
 };
 
 Staff_collecting_engraver::Staff_collecting_engraver ()
@@ -54,8 +54,13 @@ Staff_collecting_engraver::acknowledge_end_staff_symbol (Grob_info gi)
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Staff_collecting_engraver, staff_symbol);
-ADD_END_ACKNOWLEDGER (Staff_collecting_engraver, staff_symbol);
+
+void
+Staff_collecting_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Staff_collecting_engraver, staff_symbol);
+  ADD_END_ACKNOWLEDGER (Staff_collecting_engraver, staff_symbol);
+}
 
 ADD_TRANSLATOR (Staff_collecting_engraver,
                 /* doc */
index 26781f0dcd5b53529d6f1ba986b011cdfc73a09a..3a05cbd0e25213673aa5577c55c7eb7d3fe5feaf 100644 (file)
@@ -79,6 +79,12 @@ map<string, int> Staff_performer::static_channel_map_;
 int Staff_performer::channel_count_ = 0;
 int Staff_performer::staff_performer_count_ = 0;
 
+void
+Staff_performer::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Staff_performer,
                 /* doc */
                 "",
index cad91e76c3e958d318ff50305432b536549a41dc..c8f528f0f541c6d6536bbff52e6a0474e2d4966b 100644 (file)
@@ -42,8 +42,8 @@ protected:
 
   void stop_translation_timestep ();
   virtual ~Staff_symbol_engraver ();
-  DECLARE_ACKNOWLEDGER (grob);
-  DECLARE_TRANSLATOR_LISTENER (staff_span);
+  void acknowledge_grob (Grob_info);
+  void listen_staff_span (Stream_event *);
   virtual void finalize ();
   void process_music ();
   virtual void derived_mark () const;
@@ -76,7 +76,6 @@ Staff_symbol_engraver::Staff_symbol_engraver ()
   span_events_.set (0, 0);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Staff_symbol_engraver, staff_span);
 void
 Staff_symbol_engraver::listen_staff_span (Stream_event *ev)
 {
@@ -163,7 +162,13 @@ Staff_symbol_engraver::acknowledge_grob (Grob_info s)
     }
 }
 
-ADD_ACKNOWLEDGER (Staff_symbol_engraver, grob);
+
+void
+Staff_symbol_engraver::boot ()
+{
+  ADD_LISTENER (Staff_symbol_engraver, staff_span);
+  ADD_ACKNOWLEDGER (Staff_symbol_engraver, grob);
+}
 
 ADD_TRANSLATOR (Staff_symbol_engraver,
                 /* doc */
index c32653abe07adaa01f471255c0c2e7b2dcaa18ca..39eae99831fb5c5c4f1ae353691523cd9e7aadd5 100644 (file)
@@ -35,8 +35,8 @@ protected:
   vector<Grob *> lyrics_;
   vector<Grob *> stanza_numbers_;
 
-  DECLARE_ACKNOWLEDGER (lyric_syllable);
-  DECLARE_ACKNOWLEDGER (stanza_number);
+  void acknowledge_lyric_syllable (Grob_info);
+  void acknowledge_stanza_number (Grob_info);
   void stop_translation_timestep ();
 };
 
@@ -69,8 +69,13 @@ Stanza_number_align_engraver::stop_translation_timestep ()
   lyrics_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Stanza_number_align_engraver, lyric_syllable);
-ADD_ACKNOWLEDGER (Stanza_number_align_engraver, stanza_number);
+
+void
+Stanza_number_align_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Stanza_number_align_engraver, lyric_syllable);
+  ADD_ACKNOWLEDGER (Stanza_number_align_engraver, stanza_number);
+}
 
 ADD_TRANSLATOR (Stanza_number_align_engraver,
                 /* doc */
index 892bae633c35b4845abe4a439a0dad83fc9dbdfe..0a4539e8f1679059ee81676ca5e8d08797473152 100644 (file)
@@ -32,7 +32,7 @@ public:
   void process_music ();
   virtual void derived_mark () const;
   void stop_translation_timestep ();
-  DECLARE_ACKNOWLEDGER (lyric_syllable);
+  void acknowledge_lyric_syllable (Grob_info);
 };
 
 void
@@ -83,7 +83,12 @@ Stanza_number_engraver::stop_translation_timestep ()
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Stanza_number_engraver, lyric_syllable);
+void
+Stanza_number_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Stanza_number_engraver, lyric_syllable);
+}
+
 ADD_TRANSLATOR (Stanza_number_engraver,
                 /* doc */
                 "Engrave stanza numbers.",
index 2f2eaf82daedf380d0b53cd1505be4ff1ca9016f..8907c34bc3bcfd68b1e5375fa86d950f7d6d9eb1 100644 (file)
@@ -48,9 +48,9 @@ class Stem_engraver : public Engraver
 protected:
   void make_stem (Grob_info, bool);
 
-  DECLARE_TRANSLATOR_LISTENER (tremolo);
-  DECLARE_TRANSLATOR_LISTENER (tuplet_span);
-  DECLARE_ACKNOWLEDGER (rhythmic_head);
+  void listen_tremolo (Stream_event *);
+  void listen_tuplet_span (Stream_event *);
+  void acknowledge_rhythmic_head (Grob_info);
   void stop_translation_timestep ();
   void finalize ();
   void kill_unused_flags ();
@@ -212,7 +212,6 @@ Stem_engraver::stop_translation_timestep ()
   tremolo_ev_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Stem_engraver, tuplet_span);
 void
 Stem_engraver::listen_tuplet_span (Stream_event *ev)
 {
@@ -226,14 +225,20 @@ Stem_engraver::listen_tuplet_span (Stream_event *ev)
     }
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Stem_engraver, tremolo);
 void
 Stem_engraver::listen_tremolo (Stream_event *ev)
 {
   ASSIGN_EVENT_ONCE (tremolo_ev_, ev);
 }
 
-ADD_ACKNOWLEDGER (Stem_engraver, rhythmic_head);
+
+void
+Stem_engraver::boot ()
+{
+  ADD_LISTENER (Stem_engraver, tuplet_span);
+  ADD_LISTENER (Stem_engraver, tremolo);
+  ADD_ACKNOWLEDGER (Stem_engraver, rhythmic_head);
+}
 
 ADD_TRANSLATOR (Stem_engraver,
                 /* doc */
index 3da186954132a5cfc3940471e116671bac07faf0..0cf49296f0b460f444eaad29b7941b2ab99d248e 100644 (file)
@@ -44,7 +44,7 @@ Stencil::mark_smob () const
   return expr_;
 }
 
-const char Stencil::type_p_name_[] = "ly:stencil?";
+const char * const Stencil::type_p_name_ = "ly:stencil?";
 
 Interval
 Stencil::extent (Axis a) const
index 7eadbb0eec3ca70d0cfec80e8685b888f33f5273..2979e11a1918ed653e06108490ee190dab613cd3 100644 (file)
@@ -169,8 +169,8 @@ public:
 protected:
   Bracket_nesting_group *nesting_;
 
-  DECLARE_ACKNOWLEDGER (system_start_delimiter);
-  DECLARE_ACKNOWLEDGER (staff_symbol);
+  void acknowledge_system_start_delimiter (Grob_info);
+  void acknowledge_staff_symbol (Grob_info);
 
   void process_music ();
   virtual void finalize ();
@@ -229,8 +229,13 @@ System_start_delimiter_engraver::acknowledge_system_start_delimiter (Grob_info i
   nesting_->add_support (inf.grob ());
 }
 
-ADD_ACKNOWLEDGER (System_start_delimiter_engraver, staff_symbol);
-ADD_ACKNOWLEDGER (System_start_delimiter_engraver, system_start_delimiter);
+
+void
+System_start_delimiter_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (System_start_delimiter_engraver, staff_symbol);
+  ADD_ACKNOWLEDGER (System_start_delimiter_engraver, system_start_delimiter);
+}
 
 ADD_TRANSLATOR (System_start_delimiter_engraver,
                 /* doc */
index 4d47d77982a33d4ae34dff062a2862f0e11ed395..4294a2e5fe5279ff19a4df3e2031d8a77598de93 100644 (file)
@@ -49,9 +49,9 @@ public:
   TRANSLATOR_DECLARATIONS (Tab_note_heads_engraver);
 
 protected:
-  DECLARE_TRANSLATOR_LISTENER (note);
-  DECLARE_TRANSLATOR_LISTENER (string_number);
-  DECLARE_TRANSLATOR_LISTENER (fingering);
+  void listen_note (Stream_event *);
+  void listen_string_number (Stream_event *);
+  void listen_fingering (Stream_event *);
   void process_music ();
 
   void stop_translation_timestep ();
@@ -61,21 +61,18 @@ Tab_note_heads_engraver::Tab_note_heads_engraver ()
 {
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Tab_note_heads_engraver, note);
 void
 Tab_note_heads_engraver::listen_note (Stream_event *ev)
 {
   note_events_.push_back (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Tab_note_heads_engraver, string_number);
 void
 Tab_note_heads_engraver::listen_string_number (Stream_event *ev)
 {
   tabstring_events_.push_back (ev);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Tab_note_heads_engraver, fingering);
 void
 Tab_note_heads_engraver::listen_fingering (Stream_event *ev)
 {
@@ -142,6 +139,14 @@ Tab_note_heads_engraver::stop_translation_timestep ()
   fingering_events_.clear ();
 }
 
+void
+Tab_note_heads_engraver::boot ()
+{
+  ADD_LISTENER (Tab_note_heads_engraver, note);
+  ADD_LISTENER (Tab_note_heads_engraver, string_number);
+  ADD_LISTENER (Tab_note_heads_engraver, fingering);
+}
+
 ADD_TRANSLATOR (Tab_note_heads_engraver,
                 /* doc */
                 "Generate one or more tablature note heads from event of type"
index be0b343de38d674cfcde27c148a29d4e95cff73f..cde9e82bbb20373d6edc10427a38ffa8f4716802 100644 (file)
@@ -25,7 +25,7 @@ class Tab_staff_symbol_engraver : public Engraver
 public:
   TRANSLATOR_DECLARATIONS (Tab_staff_symbol_engraver);
 protected:
-  DECLARE_ACKNOWLEDGER (staff_symbol);
+  void acknowledge_staff_symbol (Grob_info);
 };
 
 void
@@ -42,7 +42,12 @@ Tab_staff_symbol_engraver::Tab_staff_symbol_engraver ()
 
 #include "translator.icc"
 
-ADD_ACKNOWLEDGER (Tab_staff_symbol_engraver, staff_symbol);
+void
+Tab_staff_symbol_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Tab_staff_symbol_engraver, staff_symbol);
+}
+
 ADD_TRANSLATOR (Tab_staff_symbol_engraver,
                 /* doc */
                 "Create a tablature staff symbol, but look at"
index b26bf0f6f6a9a45f52d30e8c9927c6f0750fdcc0..58c5203ef089a41ccb413a8c3040db0fbe50690b 100644 (file)
@@ -44,9 +44,9 @@ public:
   TRANSLATOR_DECLARATIONS (Tab_tie_follow_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (glissando);
-  DECLARE_ACKNOWLEDGER (slur);
-  DECLARE_ACKNOWLEDGER (tab_note_head);
+  void acknowledge_glissando (Grob_info);
+  void acknowledge_slur (Grob_info);
+  void acknowledge_tab_note_head (Grob_info);
 
   void stop_translation_timestep ();
 };
@@ -110,9 +110,14 @@ Tab_tie_follow_engraver::stop_translation_timestep ()
   note_heads_.clear ();
 }
 
-ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, slur);
-ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, glissando);
-ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, tab_note_head);
+
+void
+Tab_tie_follow_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, slur);
+  ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, glissando);
+  ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, tab_note_head);
+}
 
 ADD_TRANSLATOR (Tab_tie_follow_engraver,
                 /* doc */
index b17e9202cbab8097392ec1a53cb5b440315f35ac..683f133d6466c28ae3774448777f9e397f3fe4b4 100644 (file)
@@ -85,6 +85,12 @@ Tempo_performer::stop_translation_timestep ()
     }
 }
 
+void
+Tempo_performer::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Tempo_performer,
                 /* doc */
                 "",
index 2a12e75a7aa90937235ab1577574daffe11141f6..982b61a287461559c024b87911696bdf69b1870c 100644 (file)
@@ -42,11 +42,10 @@ protected:
   void stop_translation_timestep ();
   void process_music ();
 
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_TRANSLATOR_LISTENER (text_script);
+  void acknowledge_note_column (Grob_info);
+  void listen_text_script (Stream_event *);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Text_engraver, text_script);
 void
 Text_engraver::listen_text_script (Stream_event *ev)
 {
@@ -110,7 +109,13 @@ Text_engraver::Text_engraver ()
 {
 }
 
-ADD_ACKNOWLEDGER (Text_engraver, note_column);
+
+void
+Text_engraver::boot ()
+{
+  ADD_LISTENER (Text_engraver, text_script);
+  ADD_ACKNOWLEDGER (Text_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Text_engraver,
                 /* doc */
index 249fdce04a30820016bee93d980236bee636ef00..f63e19a0593083f9fbb1d869d24ea05696d30823 100644 (file)
@@ -34,8 +34,8 @@ public:
   TRANSLATOR_DECLARATIONS (Text_spanner_engraver);
 protected:
   virtual void finalize ();
-  DECLARE_TRANSLATOR_LISTENER (text_span);
-  DECLARE_ACKNOWLEDGER (note_column);
+  void listen_text_span (Stream_event *);
+  void acknowledge_note_column (Grob_info);
   void stop_translation_timestep ();
   void process_music ();
 
@@ -55,7 +55,6 @@ Text_spanner_engraver::Text_spanner_engraver ()
   event_drul_.set (0, 0);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Text_spanner_engraver, text_span);
 void
 Text_spanner_engraver::listen_text_span (Stream_event *ev)
 {
@@ -156,7 +155,13 @@ Text_spanner_engraver::acknowledge_note_column (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Text_spanner_engraver, note_column);
+
+void
+Text_spanner_engraver::boot ()
+{
+  ADD_LISTENER (Text_spanner_engraver, text_span);
+  ADD_ACKNOWLEDGER (Text_spanner_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Text_spanner_engraver,
                 /* doc */
index 56fb4a337ddce22c9653c16d74635e25501e277a..2a016b31be8a08317422b17faa22b39cd5d84684 100644 (file)
@@ -84,8 +84,8 @@ protected:
   void process_acknowledged ();
   void stop_translation_timestep ();
   void start_translation_timestep ();
-  DECLARE_ACKNOWLEDGER (note_head);
-  DECLARE_TRANSLATOR_LISTENER (tie);
+  void acknowledge_note_head (Grob_info);
+  void listen_tie (Stream_event *);
   void process_music ();
   void typeset_tie (Spanner *);
   void report_unterminated_tie (Head_event_tuple const &);
@@ -101,7 +101,6 @@ Tie_engraver::Tie_engraver ()
   event_processed_ = false;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Tie_engraver, tie);
 void
 Tie_engraver::listen_tie (Stream_event *ev)
 {
@@ -385,7 +384,13 @@ Tie_engraver::typeset_tie (Spanner *her)
   her->set_bound (RIGHT, right_head);
 }
 
-ADD_ACKNOWLEDGER (Tie_engraver, note_head);
+void
+Tie_engraver::boot ()
+{
+  ADD_LISTENER (Tie_engraver, tie);
+  ADD_ACKNOWLEDGER (Tie_engraver, note_head);
+}
+
 ADD_TRANSLATOR (Tie_engraver,
                 /* doc */
                 "Generate ties between note heads of equal pitch.",
index b1aa15ffeb645451287259cbbf0dc41ad29568e2..e93b3e6b0c6047fea2c2de8d33705b9a3098e0c4 100644 (file)
@@ -51,7 +51,7 @@ protected:
   void start_translation_timestep ();
   virtual void acknowledge_audio_element (Audio_element_info);
   void process_music ();
-  DECLARE_TRANSLATOR_LISTENER (tie);
+  void listen_tie (Stream_event *);
 public:
   TRANSLATOR_DECLARATIONS (Tie_performer);
 };
@@ -61,7 +61,6 @@ Tie_performer::Tie_performer ()
   event_ = 0;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Tie_performer, tie);
 void
 Tie_performer::listen_tie (Stream_event *ev)
 {
@@ -184,6 +183,12 @@ Tie_performer::stop_translation_timestep ()
   now_tied_heads_.clear ();
 }
 
+void
+Tie_performer::boot ()
+{
+  ADD_LISTENER (Tie_performer, tie);
+}
+
 ADD_TRANSLATOR (Tie_performer,
                 /* doc */
                 "Generate ties between note heads of equal pitch.",
index df6ae6dd1bb70521736f5dd5f56e68f5ed219660..d57b35bf6eae9bb95c04d2d0d1dde3d85c9f6764 100644 (file)
@@ -43,7 +43,7 @@ protected:
   void process_music ();
 public:
   TRANSLATOR_DECLARATIONS (Time_signature_engraver);
-  DECLARE_TRANSLATOR_LISTENER (time_signature);
+  void listen_time_signature (Stream_event *);
 };
 
 void
@@ -60,7 +60,6 @@ Time_signature_engraver::Time_signature_engraver ()
   last_time_fraction_ = SCM_BOOL_F;
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Time_signature_engraver, time_signature);
 void
 Time_signature_engraver::listen_time_signature (Stream_event *ev)
 {
@@ -116,6 +115,12 @@ Time_signature_engraver::stop_translation_timestep ()
   time_cause_ = SCM_EOL;
 }
 
+void
+Time_signature_engraver::boot ()
+{
+  ADD_LISTENER (Time_signature_engraver, time_signature);
+}
+
 ADD_TRANSLATOR (Time_signature_engraver,
                 /* doc */
                 "Create a @ref{TimeSignature} whenever"
index d9c25554fd7c637e8ecdd793047de78b1c81a6d1..3a3bbd2ca328de3c563bdc5314483c0bcea50d90 100644 (file)
@@ -81,6 +81,12 @@ Time_signature_performer::stop_translation_timestep ()
 
 #include "translator.icc"
 
+void
+Time_signature_performer::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Time_signature_performer,
                 /* doc */
                 "",
index 9bd7e758d8aed170fdba587b1955a792d08ef59d..4716eceb24c489d05ff30feb19a304a449f80f2f 100644 (file)
@@ -223,6 +223,12 @@ Timing_translator::start_translation_timestep ()
 
 #include "translator.icc"
 
+void
+Timing_translator::boot ()
+{
+
+}
+
 ADD_TRANSLATOR (Timing_translator,
                 /* doc */
                 "This engraver adds the alias @code{Timing} to its containing"
index 41d5a171827ceb5bdf065d3eaf5eeebd0bcf1884..eeee8d24831c1417b844919ccc282818864b1b9e 100644 (file)
 #include "engraver.hh"
 
 
-const char * const Engraver_dispatch_list::type_p_name_ = 0;
-
 void
 Engraver_dispatch_list::apply (Grob_info gi)
 {
-  Translator *origin = gi.origin_translator ();
+  SCM origin = gi.origin_translator ()->self_scm ();
+  SCM grob = gi.grob ()->self_scm ();
   for (vsize i = 0; i < dispatch_entries_.size (); i++)
     {
-      Engraver_dispatch_entry const &e (dispatch_entries_[i]);
-      if (e.engraver_ == origin)
+      Method_instance const &e (dispatch_entries_[i]);
+      if (scm_is_eq (e.instance (), origin))
         continue;
 
-      (e.engraver_->*e.function_) (gi);
+      e (grob, origin);
     }
 }
 
@@ -44,32 +43,21 @@ Engraver_dispatch_list::create (SCM trans_list,
   SCM retval = Engraver_dispatch_list ().smobbed_copy ();
   Engraver_dispatch_list *list = unsmob<Engraver_dispatch_list> (retval);
 
-  Engraver_dispatch_entry entry;
-  bool found = false;
   for (SCM s = trans_list; scm_is_pair (s); s = scm_cdr (s))
     {
-      Engraver *eng
-        = unsmob<Engraver> (scm_car (s));
+      Engraver *eng = unsmob<Engraver> (scm_car (s));
 
       if (!eng)
         continue;
 
-      entry.engraver_ = eng;
       for (SCM i = iface_list; scm_is_pair (i); i = scm_cdr (i))
         {
-          Translator::Grob_info_callback ptr
-            = (start_end == START)
-              ? eng->get_acknowledger (scm_car (i))
-              : eng->get_end_acknowledger (scm_car (i));
+          SCM ptr = eng->get_acknowledger (scm_car (i), start_end);
 
-          if (ptr)
-            {
-              entry.function_ = ptr;
-              list->dispatch_entries_.push_back (entry);
-              found = true;
-            }
+          if (!SCM_UNBNDP (ptr))
+            list->dispatch_entries_.push_back (Method_instance (ptr, eng));
         }
     }
 
-  return found ? retval : SCM_EOL;
+  return list->dispatch_entries_.empty () ? SCM_EOL : retval;
 }
index e3f8cba3e8c7393b6a0ed493164c231842fb2541..a9f1690f62998712b5bfe0a7470c437f838025f1 100644 (file)
 #include "warn.hh"
 
 void
-translator_each (SCM list, Translator_method method)
+translator_each (SCM list, SCM method)
 {
   for (SCM p = list; scm_is_pair (p); p = scm_cdr (p))
-    (unsmob<Translator> (scm_car (p))->*method) ();
+    scm_call_1 (method, scm_car (p));
 }
 
 void
@@ -219,10 +219,11 @@ Translator_group::create_child_translator (SCM sev)
   g->connect_to_context (new_context);
   g->unprotect ();
 
-  recurse_over_translators (new_context,
-                            &Translator::initialize,
-                            &Translator_group::initialize,
-                            DOWN);
+  recurse_over_translators
+    (new_context,
+     Callback0_wrapper::make_smob<Translator, &Translator::initialize> (),
+     Callback0_wrapper::make_smob<Translator_group, &Translator_group::initialize> (),
+     DOWN);
 }
 
 SCM
@@ -240,7 +241,6 @@ precomputed_recurse_over_translators (Context *c, Translator_precompute_index id
   if (tg && dir == DOWN)
     {
       tg->precomputed_translator_foreach (idx);
-      tg->call_precomputed_self_method (idx);
     }
 
   for (SCM s = c->children_contexts (); scm_is_pair (s);
@@ -250,20 +250,19 @@ precomputed_recurse_over_translators (Context *c, Translator_precompute_index id
   if (tg && dir == UP)
     {
       tg->precomputed_translator_foreach (idx);
-      tg->call_precomputed_self_method (idx);
     }
 }
 
 void
-recurse_over_translators (Context *c, Translator_method ptr,
-                          Translator_group_method tg_ptr, Direction dir)
+recurse_over_translators (Context *c, SCM ptr,
+                          SCM tg_ptr, Direction dir)
 {
-  Translator_group *tg
-    = dynamic_cast<Translator_group *> (c->implementation ());
+  Translator_group *tg = c->implementation ();
+  SCM tg_scm = tg ? tg->self_scm () : SCM_UNDEFINED;
 
   if (tg && dir == DOWN)
     {
-      (tg->*tg_ptr) ();
+      scm_call_1 (tg_ptr, tg_scm);
       translator_each (tg->get_simple_trans_list (), ptr);
     }
 
@@ -276,7 +275,7 @@ recurse_over_translators (Context *c, Translator_method ptr,
       translator_each (tg->get_simple_trans_list (),
                        ptr);
 
-      (tg->*tg_ptr) ();
+      scm_call_1 (tg_ptr, tg_scm);
     }
 }
 
@@ -299,40 +298,25 @@ Translator_group::precompute_method_bindings ()
   for (SCM s = simple_trans_list_; scm_is_pair (s); s = scm_cdr (s))
     {
       Translator *tr = unsmob<Translator> (scm_car (s));
-      Translator::Callback ptrs[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
+      SCM ptrs[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
       tr->fetch_precomputable_methods (ptrs);
 
       assert (tr);
       for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
         {
-          if (ptrs[i])
-            precomputed_method_bindings_[i].push_back (Translator_method_binding (tr, ptrs[i]));
+          if (!SCM_UNBNDP (ptrs[i]))
+            precomputed_method_bindings_[i].push_back (Method_instance (ptrs[i], tr));
         }
     }
 
-  fetch_precomputable_methods (precomputed_self_method_bindings_);
 }
 
 void
 Translator_group::precomputed_translator_foreach (Translator_precompute_index idx)
 {
-  vector<Translator_method_binding> &bindings (precomputed_method_bindings_[idx]);
+  vector<Method_instance> &bindings (precomputed_method_bindings_[idx]);
   for (vsize i = 0; i < bindings.size (); i++)
-    bindings[i].invoke ();
-}
-
-void
-Translator_group::fetch_precomputable_methods (Translator_group_void_method ptrs[])
-{
-  for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
-    ptrs[i] = 0;
-}
-
-void
-Translator_group::call_precomputed_self_method (Translator_precompute_index idx)
-{
-  if (precomputed_self_method_bindings_[idx])
-    (*precomputed_self_method_bindings_[idx]) (this);
+    bindings[i]();
 }
 
 Translator_group::~Translator_group ()
@@ -340,7 +324,7 @@ Translator_group::~Translator_group ()
 }
 
 
-const char Translator_group::type_p_name_[] = "ly:translator-group?";
+const char * const Translator_group::type_p_name_ = "ly:translator-group?";
 
 int
 Translator_group::print_smob (SCM port, scm_print_state *) const
index 370f7771c0dcf2a95148ee964b97f4ccd00eb284..bdc55f0f05467a4d4cb5fd56b548deb9995329c2 100644 (file)
@@ -207,7 +207,7 @@ Translator::get_score_context () const
   return daddy_context_->get_score_context ();
 }
 
-const char Translator::type_p_name_[] = "ly:translator?";
+const char * const Translator::type_p_name_ = "ly:translator?";
 
 bool
 Translator::must_be_last () const
@@ -230,34 +230,29 @@ Translator::print_smob (SCM port, scm_print_state *) const
 }
 
 void
-add_acknowledger (Translator::Grob_info_callback ptr,
+add_acknowledger (SCM ptr,
                   char const *func_name,
-                  vector<Acknowledge_information> *ack_array)
+                  SCM &ack_hash)
 {
-  Acknowledge_information inf;
-  inf.function_ = ptr;
+  if (SCM_UNBNDP (ack_hash))
+    ack_hash = Scheme_hash_table::make_smob ();
 
   string interface_name (func_name);
 
   interface_name = replace_all (&interface_name, '_', '-');
   interface_name += "-interface";
 
-  /*
-    this is only called during program init, so safe to use scm_gc_protect_object ()
-  */
-  inf.symbol_ = scm_gc_protect_object (ly_symbol2scm (interface_name.c_str ()));
-  ack_array->push_back (inf);
+  unsmob<Scheme_hash_table> (ack_hash)
+    ->set (ly_symbol2scm (interface_name.c_str ()), ptr);
 }
 
-Translator::Grob_info_callback
-generic_get_acknowledger (SCM sym, vector<Acknowledge_information> const *ack_array)
+SCM
+generic_get_acknowledger (SCM sym, SCM ack_hash)
 {
-  for (vsize i = 0; i < ack_array->size (); i++)
-    {
-      if (ack_array->at (i).symbol_ == sym)
-        return ack_array->at (i).function_;
-    }
-  return 0;
+  if (SCM_UNBNDP (ack_hash))
+    return SCM_UNDEFINED;
+
+  return unsmob<Scheme_hash_table> (ack_hash)->get (sym);
 }
 
 Moment
@@ -318,16 +313,4 @@ internal_event_assignment (Stream_event **old_ev, Stream_event *new_ev, const ch
     }
 }
 
-ADD_TRANSLATOR (Translator,
-                /* doc */
-                "Base class.  Not instantiated.",
-
-                /* create */
-                "",
-
-                /* read */
-                "",
-
-                /* write */
-                ""
-               );
+// Base class.  Not instantiated.  No ADD_TRANSLATOR call.
index eb36aff7e6d465c6040f0ad9f2fea6f1fd8a1004..6634b5ea43be9cee202f9772cdeb79f00f6f765a 100644 (file)
@@ -41,8 +41,8 @@ public:
   TRANSLATOR_DECLARATIONS (Trill_spanner_engraver);
 protected:
   virtual void finalize ();
-  DECLARE_TRANSLATOR_LISTENER (trill_span);
-  DECLARE_ACKNOWLEDGER (note_column);
+  void listen_trill_span (Stream_event *);
+  void acknowledge_note_column (Grob_info);
 
   void stop_translation_timestep ();
   void process_music ();
@@ -63,7 +63,6 @@ Trill_spanner_engraver::Trill_spanner_engraver ()
   event_drul_.set (0, 0);
 }
 
-IMPLEMENT_TRANSLATOR_LISTENER (Trill_spanner_engraver, trill_span);
 void
 Trill_spanner_engraver::listen_trill_span (Stream_event *ev)
 {
@@ -152,7 +151,13 @@ Trill_spanner_engraver::finalize ()
     }
 }
 
-ADD_ACKNOWLEDGER (Trill_spanner_engraver, note_column);
+
+void
+Trill_spanner_engraver::boot ()
+{
+  ADD_LISTENER (Trill_spanner_engraver, trill_span);
+  ADD_ACKNOWLEDGER (Trill_spanner_engraver, note_column);
+}
 
 ADD_TRANSLATOR (Trill_spanner_engraver,
                 /* doc */
index 369389200fe95e4e8dd97dea1b1c44dc2f273430..92e018aeceae7ed2f9475c0e7e20c226c806ca0d 100644 (file)
@@ -63,17 +63,16 @@ protected:
   vector<Tuplet_description> stopped_tuplets_;
   vector<Spanner *> last_tuplets_;
 
-  DECLARE_ACKNOWLEDGER (note_column);
-  DECLARE_ACKNOWLEDGER (script);
-  DECLARE_ACKNOWLEDGER (finger);
-  DECLARE_ACKNOWLEDGER (string_number);
-  DECLARE_TRANSLATOR_LISTENER (tuplet_span);
+  void acknowledge_note_column (Grob_info);
+  void acknowledge_script (Grob_info);
+  void acknowledge_finger (Grob_info);
+  void acknowledge_string_number (Grob_info);
+  void listen_tuplet_span (Stream_event *);
   virtual void finalize ();
   void start_translation_timestep ();
   void process_music ();
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Tuplet_engraver, tuplet_span);
 void
 Tuplet_engraver::listen_tuplet_span (Stream_event *ev)
 {
@@ -272,10 +271,16 @@ Tuplet_engraver::Tuplet_engraver ()
 {
 }
 
-ADD_ACKNOWLEDGER (Tuplet_engraver, note_column);
-ADD_ACKNOWLEDGER (Tuplet_engraver, script);
-ADD_ACKNOWLEDGER (Tuplet_engraver, finger);
-ADD_ACKNOWLEDGER (Tuplet_engraver, string_number);
+void
+Tuplet_engraver::boot ()
+{
+  ADD_LISTENER (Tuplet_engraver, tuplet_span);
+  ADD_ACKNOWLEDGER (Tuplet_engraver, note_column);
+  ADD_ACKNOWLEDGER (Tuplet_engraver, script);
+  ADD_ACKNOWLEDGER (Tuplet_engraver, finger);
+  ADD_ACKNOWLEDGER (Tuplet_engraver, string_number);
+}
+
 ADD_TRANSLATOR (Tuplet_engraver,
                 /* doc */
                 "Catch tuplet events and generate appropriate bracket.",
index 81138b3670ebd749b84f360b06ca99ac5eb13195..5f97b1e4cbdb11a84bfb469f864e31a01f2b8d0c 100644 (file)
@@ -29,7 +29,7 @@ class Tweak_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Tweak_engraver);
 
 protected:
-  DECLARE_ACKNOWLEDGER (grob);
+  void acknowledge_grob (Grob_info);
 };
 
 Tweak_engraver::Tweak_engraver ()
@@ -81,7 +81,12 @@ Tweak_engraver::acknowledge_grob (Grob_info info)
     }
 }
 
-ADD_ACKNOWLEDGER (Tweak_engraver, grob);
+void
+Tweak_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Tweak_engraver, grob);
+}
+
 ADD_TRANSLATOR (Tweak_engraver,
                 /* doc */
                 "Read the @code{tweaks} property from the originating event,"
index a328c66cafd0e6e376da5b4a7a4765752ea2a759..4aed7a60237f12b21d35e7f0eb5fb4aa122dc939 100644 (file)
@@ -24,7 +24,7 @@ class Undead : public Simple_smob<Undead>
 public:
   int print_smob (SCM, scm_print_state *) const;
   SCM mark_smob () const;
-  static const char type_p_name_[];
+  static const char * const type_p_name_;
 private:
   SCM object_;
 public:
@@ -51,7 +51,7 @@ Undead::print_smob (SCM port, scm_print_state *) const
   return 1;
 }
 
-const char Undead::type_p_name_[] = "ly:undead?";
+const char * const Undead::type_p_name_ = "ly:undead?";
 
 LY_DEFINE (ly_make_undead, "ly:make-undead",
            1, 0, 0, (SCM object),
index 7a7d6d48d16d3c139aca38ad9f0f38f307b5debb..143b2fd47de4c118e4b1818e94a9bc8c4779e01a 100644 (file)
@@ -25,7 +25,6 @@
 class Unpure_pure_call : public Smob1<Unpure_pure_call>
 {
 public:
-  static const char * const type_p_name_; // = 0
   // Smob procedures unfortunately can only take at most 3 SCM
   // arguments.  Otherwise we could use a "3, 0, 1" call signature and
   // not require an argument count check of our own.
@@ -38,8 +37,6 @@ public:
   }
 };
 
-const char * const Unpure_pure_call::type_p_name_ = 0;
-
 SCM
 Unpure_pure_container::pure_part () const
 {
@@ -48,7 +45,7 @@ Unpure_pure_container::pure_part () const
     : scm2 ();
 }
 
-const char Unpure_pure_container::type_p_name_[] = "ly:unpure-pure-container?";
+const char * const Unpure_pure_container::type_p_name_ = "ly:unpure-pure-container?";
 
 LY_DEFINE (ly_make_unpure_pure_container, "ly:make-unpure-pure-container",
            1, 1, 0, (SCM unpure, SCM pure),
index 2d94c03892238855068ac6a8e735c7b4acf7bb2f..ddd138687270d377305013ca6a80ece7ffdd5a21 100644 (file)
@@ -77,29 +77,13 @@ private:
 
 public:
   TRANSLATOR_DECLARATIONS (Vaticana_ligature_engraver);
-
+  TRANSLATOR_INHERIT (Gregorian_ligature_engraver);
 protected:
   virtual Spanner *create_ligature_spanner ();
   virtual void transform_heads (Spanner *ligature,
                                 vector<Grob_info> const &primitives);
-  DECLARE_TRANSLATOR_LISTENER (pes_or_flexa);
-  DECLARE_TRANSLATOR_LISTENER (ligature);
 };
 
-IMPLEMENT_TRANSLATOR_LISTENER (Vaticana_ligature_engraver, pes_or_flexa);
-void
-Vaticana_ligature_engraver::listen_pes_or_flexa (Stream_event *ev)
-{
-  Gregorian_ligature_engraver::listen_pes_or_flexa (ev);
-}
-
-IMPLEMENT_TRANSLATOR_LISTENER (Vaticana_ligature_engraver, ligature);
-void
-Vaticana_ligature_engraver::listen_ligature (Stream_event *ev)
-{
-  Ligature_engraver::listen_ligature (ev);
-}
-
 Vaticana_ligature_engraver::Vaticana_ligature_engraver ()
 {
   brew_ligature_primitive_proc
@@ -741,8 +725,15 @@ Vaticana_ligature_engraver::transform_heads (Spanner *ligature,
 #endif
 }
 
-ADD_ACKNOWLEDGER (Vaticana_ligature_engraver, rest);
-ADD_ACKNOWLEDGER (Vaticana_ligature_engraver, ligature_head);
+void
+Vaticana_ligature_engraver::boot ()
+{
+  ADD_LISTENER (Gregorian_ligature_engraver, pes_or_flexa);
+  ADD_LISTENER (Ligature_engraver, ligature);
+  ADD_ACKNOWLEDGER (Ligature_engraver, rest);
+  ADD_ACKNOWLEDGER (Ligature_engraver, ligature_head);
+}
+
 ADD_TRANSLATOR (Vaticana_ligature_engraver,
                 /* doc */
                 "Handle ligatures by glueing special ligature heads"
index 6a47809fd728d64fe33f03020bae8440cfb79d30..0226173a2e115ec81d153212a5c3317cee6755c2 100644 (file)
@@ -37,7 +37,7 @@ class Vertical_align_engraver : public Engraver
 
 public:
   TRANSLATOR_DECLARATIONS (Vertical_align_engraver);
-  DECLARE_ACKNOWLEDGER (axis_group);
+  void acknowledge_axis_group (Grob_info);
 
 protected:
   virtual void derived_mark () const;
@@ -48,7 +48,12 @@ protected:
   bool top_level_;
 };
 
-ADD_ACKNOWLEDGER (Vertical_align_engraver, axis_group);
+void
+Vertical_align_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Vertical_align_engraver, axis_group);
+}
+
 ADD_TRANSLATOR (Vertical_align_engraver,
                 /* doc */
                 "Catch groups (staves, lyrics lines, etc.) and stack them"
index bd198cbb67faad5c395bd1567133d6413019c938..2f95ac7ac11b861216e75a77d7d63857f6373fab 100644 (file)
@@ -43,7 +43,7 @@ public:
   TRANSLATOR_DECLARATIONS (Volta_engraver);
 protected:
 
-  DECLARE_ACKNOWLEDGER (bar_line);
+  void acknowledge_bar_line (Grob_info);
 
   virtual void derived_mark () const;
   void stop_translation_timestep ();
@@ -189,7 +189,12 @@ Volta_engraver::stop_translation_timestep ()
 /*
   TODO: should attach volta to paper-column if no bar is found.
 */
-ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
+void
+Volta_engraver::boot ()
+{
+  ADD_ACKNOWLEDGER (Volta_engraver, bar_line);
+}
+
 ADD_TRANSLATOR (Volta_engraver,
                 /* doc */
                 "Make volta brackets.",
index 87ae51855d57677710dd6b12b8d0a4c0fc8ba4ee..972b6abd4ae68498697a324dc0d4878e7a598da2 100644 (file)
@@ -23,7 +23,7 @@ That's it.  For more information, visit http://lilypond.org .
 
 %}
 
-\version "2.19.41"  % necessary for upgrading to future LilyPond versions.
+\version "2.19.43"  % necessary for upgrading to future LilyPond versions.
 
 \header{
   title = "A scale in LilyPond"
index 526bb56eb466dd245097399c68fdbba72aa876d5..8f3351a7051f042de990fa9828519bf179bd1789 100644 (file)
@@ -32,7 +32,7 @@ Good luck with LilyPond!  Happy engraving.
 
 %}
 
-\version "2.19.41"  % necessary for upgrading to future LilyPond versions.
+\version "2.19.43"  % necessary for upgrading to future LilyPond versions.
 
 \header{
   title = "A scale in LilyPond"
index 78acdbfe1f76da6ed22f49cc1a14ffc2cab3393a..0414bd926b89418e9a5d966de31fe81e2ef24b54 100644 (file)
@@ -54,7 +54,7 @@
 %     portato        ac:portatoFactor (default 3/4)
 %     tenuto         ac:tenutoFactor (default 1/1 - by default, notes marked
 %                                     tenuto are not shortened)
-% * Appogiaturas are made to take half the value of the note following,
+% * Appoggiaturas are made to take half the value of the note following,
 %   without taking dots into account (so in \appoggiatura c8 d2. the c
 %   will take the time of a crotchet).
 % * Trills and turns are expanded. The algorithm tries to choose notes
index 83f8b5376e3575a2f3af4cb451cde4e467ee8791..0831bf062cabf6d3547f6d592691d7b21d5773a7 100644 (file)
     </rejectfont>
   </selectfont>
 
+  <!--
+      LilyPond cannot handle OpenType/CFF Collection (OTC) fonts
+      (NotoSansCJK.ttc and SourceHanSans.ttc etc.).
+      This settings is a workaround that ignores some major OTC fonts
+      for avoiding errors.
+      TODO: Add OTC fonts support and remove this settings
+  -->
+
+  <selectfont>
+    <rejectfont>
+      <!--
+         Noto Sans CJK
+         https://www.google.com/get/noto/help/cjk/
+
+         `CJK OTF fonts with different default language' and
+         `Region specific OTF subsets' can be used.
+         Their file names are `NotoSans*.otf'.
+      -->
+      <glob>*/NotoSansCJK*.ttc</glob>
+
+      <!--
+         Source Han Sans
+         https://github.com/adobe-fonts/source-han-sans
+
+         `Language-specific OTFs' and
+         `Region-specific Subset OTFs' can be used.
+         Their file names are `SourceHanSans*.otf'.
+      -->
+      <glob>*/SourceHanSans*.ttc</glob>
+
+      <!--
+         Source Han Code JP
+         https://github.com/adobe-fonts/source-han-code-jp
+
+         `OTF' can be used.
+         Their file names are `SourceHanCodeJP-*.otf'.
+      -->
+      <glob>*/SourceHanCodeJP.ttc</glob>
+    </rejectfont>
+  </selectfont>
+
 </fontconfig>
index 1be31ef4ee0d7618347dd37fea0d21b648b104f4..b7fe2f0951c1f4817907d92dc8d11096755516b8 100644 (file)
@@ -554,7 +554,7 @@ fet_endchar;
 
 %%%%%%%%
 %
-% Single Stroke for Short Appogiatura
+% Single Stroke for Short Appoggiatura
 %
 
 fet_beginchar ("grace dash (up)", "ugrace");
index a55d9d3bb03d6daa2a1b3c5d0817979d6395c5d1..d10065e32df2bebc3c2d27922e1f8b63af2c7d09 100644 (file)
@@ -6,10 +6,10 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: lilypond 2.19.41\n"
+"Project-Id-Version: lilypond 2.19.43\n"
 "Report-Msgid-Bugs-To: http://post.gmane.org/post.php?group=gmane.comp.gnu."
 "lilypond.bugs\n"
-"POT-Creation-Date: 2016-05-01 12:41+0100\n"
+"POT-Creation-Date: 2016-06-08 13:09+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -889,7 +889,7 @@ msgstr ""
 msgid "Unable to find instrument for ID=%s\n"
 msgstr ""
 
-#: abc2ly.py:1389 convert-ly.py:85 lilypond-book.py:122 midi2ly.py:1044
+#: abc2ly.py:1389 convert-ly.py:85 lilypond-book.py:122 midi2ly.py:1046
 #, python-format
 msgid "%s [OPTION]... FILE"
 msgstr ""
@@ -902,16 +902,16 @@ msgid ""
 msgstr ""
 
 #: abc2ly.py:1398 convert-ly.py:92 etf2ly.py:1208 lilypond-book.py:231
-#: midi2ly.py:1095 musicxml2ly.py:2590 main.cc:184
+#: midi2ly.py:1097 musicxml2ly.py:2590 main.cc:184
 msgid "show version number and exit"
 msgstr ""
 
 #: abc2ly.py:1401 convert-ly.py:96 etf2ly.py:1204 lilypond-book.py:140
-#: midi2ly.py:1062 musicxml2ly.py:2572 main.cc:163
+#: midi2ly.py:1064 musicxml2ly.py:2572 main.cc:163
 msgid "show this help and exit"
 msgstr ""
 
-#: abc2ly.py:1404 etf2ly.py:1209 midi2ly.py:1071
+#: abc2ly.py:1404 etf2ly.py:1209 midi2ly.py:1073
 msgid "write output to FILE"
 msgstr ""
 
@@ -932,7 +932,7 @@ msgstr ""
 #. or if there is a LilyPond users list or forum in your language
 #. "Report bugs in English via %s or in YOUR_LANG via URI"
 #: abc2ly.py:1416 convert-ly.py:157 etf2ly.py:1218 lilypond-book.py:258
-#: midi2ly.py:1107 musicxml2ly.py:2674 main.cc:318
+#: midi2ly.py:1109 musicxml2ly.py:2674 main.cc:318
 #, c-format, python-format
 msgid "Report bugs via %s"
 msgstr ""
@@ -951,16 +951,16 @@ msgstr ""
 msgid "Examples:"
 msgstr ""
 
-#: convert-ly.py:79 etf2ly.py:1191 lilypond-book.py:115 midi2ly.py:81
+#: convert-ly.py:79 etf2ly.py:1191 lilypond-book.py:115 midi2ly.py:80
 #, python-format
 msgid "Copyright (c) %s by"
 msgstr ""
 
-#: convert-ly.py:81 etf2ly.py:1193 lilypond-book.py:117 midi2ly.py:83
+#: convert-ly.py:81 etf2ly.py:1193 lilypond-book.py:117 midi2ly.py:82
 msgid "Distributed under terms of the GNU General Public License."
 msgstr ""
 
-#: convert-ly.py:82 etf2ly.py:1194 lilypond-book.py:118 midi2ly.py:84
+#: convert-ly.py:82 etf2ly.py:1194 lilypond-book.py:118 midi2ly.py:83
 msgid "It comes with NO WARRANTY."
 msgstr ""
 
@@ -1014,7 +1014,7 @@ msgstr ""
 msgid "make a numbered backup [default: filename.ext~]"
 msgstr ""
 
-#: convert-ly.py:152 etf2ly.py:1212 lilypond-book.py:234 midi2ly.py:1096
+#: convert-ly.py:152 etf2ly.py:1212 lilypond-book.py:234 midi2ly.py:1098
 #: main.cc:186
 msgid "show warranty and copyright"
 msgstr ""
@@ -1073,7 +1073,7 @@ msgid ""
 "file.\n"
 msgstr ""
 
-#: etf2ly.py:1210 midi2ly.py:1067 midi2ly.py:1072 musicxml2ly.py:2659
+#: etf2ly.py:1210 midi2ly.py:1069 midi2ly.py:1074 musicxml2ly.py:2659
 #: main.cc:169 main.cc:181
 msgid "FILE"
 msgstr ""
@@ -1180,7 +1180,7 @@ msgstr ""
 msgid "write snippet output files with the same base name as their source file"
 msgstr ""
 
-#: lilypond-book.py:223 midi2ly.py:1090 musicxml2ly.py:2596
+#: lilypond-book.py:223 midi2ly.py:1092 musicxml2ly.py:2596
 msgid "be verbose"
 msgstr ""
 
@@ -1278,97 +1278,97 @@ msgid ""
 "Setting LilyPond's output to --verbose, implied by lilypond-book's setting"
 msgstr ""
 
-#: midi2ly.py:90
+#: midi2ly.py:89
 msgid "warning: "
 msgstr ""
 
-#: midi2ly.py:93 midi2ly.py:1124
+#: midi2ly.py:92 midi2ly.py:1126
 msgid "error: "
 msgstr ""
 
-#: midi2ly.py:94
+#: midi2ly.py:93
 msgid "Exiting... "
 msgstr ""
 
-#: midi2ly.py:835
+#: midi2ly.py:834
 msgid "found more than 5 voices on a staff, expect bad output"
 msgstr ""
 
-#: midi2ly.py:1032
+#: midi2ly.py:1034
 #, python-format
 msgid "%s output to `%s'..."
 msgstr ""
 
-#: midi2ly.py:1045
+#: midi2ly.py:1047
 #, python-format
 msgid "Convert %s to LilyPond input.\n"
 msgstr ""
 
-#: midi2ly.py:1050
+#: midi2ly.py:1052
 msgid "print absolute pitches"
 msgstr ""
 
-#: midi2ly.py:1052 midi2ly.py:1080
+#: midi2ly.py:1054 midi2ly.py:1082
 msgid "DUR"
 msgstr ""
 
-#: midi2ly.py:1053
+#: midi2ly.py:1055
 msgid "quantise note durations on DUR"
 msgstr ""
 
-#: midi2ly.py:1056
+#: midi2ly.py:1058
 msgid "debug printing"
 msgstr ""
 
-#: midi2ly.py:1059
+#: midi2ly.py:1061
 msgid "print explicit durations"
 msgstr ""
 
-#: midi2ly.py:1064
+#: midi2ly.py:1066
 msgid "prepend FILE to output"
 msgstr ""
 
-#: midi2ly.py:1068
+#: midi2ly.py:1070
 msgid "set key: ALT=+sharps|-flats; MINOR=1"
 msgstr ""
 
-#: midi2ly.py:1069
+#: midi2ly.py:1071
 msgid "ALT[:MINOR]"
 msgstr ""
 
-#: midi2ly.py:1074
+#: midi2ly.py:1076
 msgid "preview of first 4 bars"
 msgstr ""
 
-#: midi2ly.py:1078
+#: midi2ly.py:1080
 msgid "suppress progress messages and warnings about excess voices"
 msgstr ""
 
-#: midi2ly.py:1079
+#: midi2ly.py:1081
 msgid "quantise note starts on DUR"
 msgstr ""
 
-#: midi2ly.py:1083
+#: midi2ly.py:1085
 msgid "use s instead of r for rests"
 msgstr ""
 
-#: midi2ly.py:1085
+#: midi2ly.py:1087
 msgid "DUR*NUM/DEN"
 msgstr ""
 
-#: midi2ly.py:1088
+#: midi2ly.py:1090
 msgid "allow tuplet durations DUR*NUM/DEN"
 msgstr ""
 
-#: midi2ly.py:1098
+#: midi2ly.py:1100
 msgid "treat every text as a lyric"
 msgstr ""
 
-#: midi2ly.py:1101
+#: midi2ly.py:1103
 msgid "Examples"
 msgstr ""
 
-#: midi2ly.py:1125
+#: midi2ly.py:1127
 msgid "no files specified on command line."
 msgstr ""
 
@@ -1721,23 +1721,23 @@ msgstr ""
 msgid "barcheck failed at: %s"
 msgstr ""
 
-#: beam-engraver.cc:148
+#: beam-engraver.cc:147
 msgid "already have a beam"
 msgstr ""
 
-#: beam-engraver.cc:235
+#: beam-engraver.cc:234
 msgid "unterminated beam"
 msgstr ""
 
-#: beam-engraver.cc:282 chord-tremolo-engraver.cc:149
+#: beam-engraver.cc:281 chord-tremolo-engraver.cc:148
 msgid "stem must have Rhythmic structure"
 msgstr ""
 
-#: beam-engraver.cc:293
+#: beam-engraver.cc:292
 msgid "stem does not fit in beam"
 msgstr ""
 
-#: beam-engraver.cc:294
+#: beam-engraver.cc:293
 msgid "beam was started here"
 msgstr ""
 
@@ -1777,11 +1777,11 @@ msgstr ""
 msgid "none of these in my family"
 msgstr ""
 
-#: chord-tremolo-engraver.cc:88
+#: chord-tremolo-engraver.cc:87
 msgid "No tremolo to end"
 msgstr ""
 
-#: chord-tremolo-engraver.cc:109
+#: chord-tremolo-engraver.cc:108
 msgid "unterminated chord tremolo"
 msgstr ""
 
@@ -1812,22 +1812,22 @@ msgstr ""
 msgid "need symbol argument for \\override and \\revert"
 msgstr ""
 
-#: context.cc:143
+#: context.cc:147
 #, c-format
 msgid "cannot find or create new `%s'"
 msgstr ""
 
-#: context.cc:222
+#: context.cc:226
 #, c-format
 msgid "cannot find or create `%s' called `%s'"
 msgstr ""
 
-#: context.cc:453
+#: context.cc:457
 #, c-format
 msgid "cannot find or create: `%s'"
 msgstr ""
 
-#: context.cc:467
+#: context.cc:471
 #, c-format
 msgid "cannot find or create new Bottom = \"%s\""
 msgstr ""
@@ -1859,14 +1859,14 @@ msgstr ""
 msgid "dot `%s' not found"
 msgstr ""
 
-#: dynamic-engraver.cc:169
+#: dynamic-engraver.cc:166
 #, c-format
 msgid ""
 "unknown crescendo style: %s\n"
 "defaulting to hairpin."
 msgstr ""
 
-#: dynamic-engraver.cc:234 slur-proto-engraver.cc:159
+#: dynamic-engraver.cc:231 slur-proto-engraver.cc:159
 #, c-format
 msgid "unterminated %s"
 msgstr ""
@@ -1878,19 +1878,19 @@ msgstr ""
 msgid "(De)crescendo with unspecified starting volume in MIDI."
 msgstr ""
 
-#: episema-engraver.cc:75
+#: episema-engraver.cc:74
 msgid "already have an episema"
 msgstr ""
 
-#: episema-engraver.cc:88
+#: episema-engraver.cc:87
 msgid "cannot find start of episema"
 msgstr ""
 
-#: episema-engraver.cc:137
+#: episema-engraver.cc:136
 msgid "unterminated episema"
 msgstr ""
 
-#: extender-engraver.cc:169 extender-engraver.cc:178
+#: extender-engraver.cc:167 extender-engraver.cc:176
 msgid "unterminated extender"
 msgstr ""
 
@@ -1955,7 +1955,7 @@ msgstr ""
 msgid "Found infinity or nan in output.  Substituting 0.0"
 msgstr ""
 
-#: glissando-engraver.cc:158
+#: glissando-engraver.cc:157
 msgid "unterminated glissando"
 msgstr ""
 
@@ -2020,19 +2020,19 @@ msgstr ""
 msgid "decrescendo too small"
 msgstr ""
 
-#: horizontal-bracket-engraver.cc:62
+#: horizontal-bracket-engraver.cc:61
 msgid "do not have that many brackets"
 msgstr ""
 
-#: horizontal-bracket-engraver.cc:71
+#: horizontal-bracket-engraver.cc:70
 msgid "conflicting note group events"
 msgstr ""
 
-#: hyphen-engraver.cc:104
+#: hyphen-engraver.cc:103
 msgid "removing unterminated hyphen"
 msgstr ""
 
-#: hyphen-engraver.cc:118
+#: hyphen-engraver.cc:117
 msgid "unterminated hyphen; removing"
 msgstr ""
 
@@ -2050,7 +2050,7 @@ msgstr ""
 msgid "position unknown"
 msgstr ""
 
-#: key-engraver.cc:197
+#: key-engraver.cc:196
 msgid "Incomplete keyAlterationOrder for key signature"
 msgstr ""
 
@@ -2063,11 +2063,11 @@ msgstr ""
 msgid "alteration not found"
 msgstr ""
 
-#: ligature-bracket-engraver.cc:72 ligature-engraver.cc:109
+#: ligature-bracket-engraver.cc:71 ligature-engraver.cc:109
 msgid "cannot find start of ligature"
 msgstr ""
 
-#: ligature-bracket-engraver.cc:85 ligature-engraver.cc:136
+#: ligature-bracket-engraver.cc:84 ligature-engraver.cc:136
 msgid "already have a ligature"
 msgstr ""
 
@@ -2394,45 +2394,45 @@ msgid "exception caught: %s"
 msgstr ""
 
 #. FIXME: constant error message.
-#: mark-engraver.cc:150
+#: mark-engraver.cc:149
 msgid "rehearsalMark must have integer value"
 msgstr ""
 
-#: mark-engraver.cc:156
+#: mark-engraver.cc:155
 msgid "mark label must be a markup object"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:100
+#: mensural-ligature-engraver.cc:93
 msgid "ligature with less than 2 heads -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:127
+#: mensural-ligature-engraver.cc:120
 msgid "cannot determine pitch of ligature primitive -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:141
+#: mensural-ligature-engraver.cc:134
 msgid "single note ligature - skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:152
+#: mensural-ligature-engraver.cc:145
 msgid "prime interval within ligature -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:163
+#: mensural-ligature-engraver.cc:156
 msgid "mensural ligature: duration none of Mx, L, B, S -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:206
+#: mensural-ligature-engraver.cc:199
 msgid "semibrevis must be followed by another one -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:216
+#: mensural-ligature-engraver.cc:209
 msgid ""
 "semibreves can only appear at the beginning of a ligature,\n"
 "and there may be only zero or two of them"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:236
+#: mensural-ligature-engraver.cc:229
 msgid ""
 "invalid ligatura ending:\n"
 "when the last note is a descending brevis,\n"
@@ -2440,11 +2440,11 @@ msgid ""
 "or the ligatura must be LB or SSB"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:396
+#: mensural-ligature-engraver.cc:389
 msgid "unexpected case fall-through"
 msgstr ""
 
-#: midi-control-function-performer.cc:107 staff-performer.cc:153
+#: midi-control-function-performer.cc:107 staff-performer.cc:159
 #, c-format
 msgid "ignoring out-of-range value change for MIDI property `%s'"
 msgstr ""
@@ -2511,7 +2511,7 @@ msgstr ""
 msgid "none of note heads `%s' or `%s' found"
 msgstr ""
 
-#: note-heads-engraver.cc:76
+#: note-heads-engraver.cc:75
 msgid "NoteEvent without pitch"
 msgstr ""
 
@@ -2707,7 +2707,7 @@ msgstr ""
 msgid "program option -dpreview not supported by backend `%s'"
 msgstr ""
 
-#: paper-column-engraver.cc:263
+#: paper-column-engraver.cc:261
 msgid ""
 "forced break was overridden by some other event, should you be using bar "
 "checks?"
@@ -2736,7 +2736,7 @@ msgstr ""
 msgid "Conversion of string `%s' to UTF-16be failed: %s"
 msgstr ""
 
-#: percent-repeat-engraver.cc:148
+#: percent-repeat-engraver.cc:147
 msgid "unterminated percent repeat"
 msgstr ""
 
@@ -2749,18 +2749,27 @@ msgstr ""
 msgid "MIDI output to `%s'..."
 msgstr ""
 
-#: piano-pedal-engraver.cc:279
+#: pfb-scheme.cc:49 ttf.cc:512 ttf.cc:562
+msgid "font index must be non-negative, using index 0"
+msgstr ""
+
+#: pfb-scheme.cc:64 ttf.cc:480 ttf.cc:528
+#, c-format
+msgid "font index %d too large for font `%s', using index 0"
+msgstr ""
+
+#: piano-pedal-engraver.cc:276
 #, c-format
 msgid "expect 3 strings for piano pedals, found: %ld"
 msgstr ""
 
-#: piano-pedal-engraver.cc:294 piano-pedal-engraver.cc:305
+#: piano-pedal-engraver.cc:291 piano-pedal-engraver.cc:302
 #: piano-pedal-performer.cc:104
 #, c-format
 msgid "cannot find start of piano pedal: `%s'"
 msgstr ""
 
-#: piano-pedal-engraver.cc:340
+#: piano-pedal-engraver.cc:337
 #, c-format
 msgid "cannot find start of piano pedal bracket: `%s'"
 msgstr ""
@@ -2866,21 +2875,21 @@ msgstr ""
 msgid "rest `%s' not found"
 msgstr ""
 
-#: score-engraver.cc:77
+#: score-engraver.cc:79
 #, c-format
 msgid "cannot find `%s'"
 msgstr ""
 
-#: score-engraver.cc:79
+#: score-engraver.cc:81
 msgid "Music font has not been installed properly."
 msgstr ""
 
-#: score-engraver.cc:81
+#: score-engraver.cc:83
 #, c-format
 msgid "Search path `%s'"
 msgstr ""
 
-#: score-engraver.cc:83
+#: score-engraver.cc:85
 msgid "Aborting"
 msgstr ""
 
@@ -2897,11 +2906,11 @@ msgid "errors found, ignoring music expression"
 msgstr ""
 
 #. FIXME:
-#: script-engraver.cc:115
+#: script-engraver.cc:114
 msgid "do not know how to interpret articulation:"
 msgstr ""
 
-#: script-engraver.cc:116
+#: script-engraver.cc:115
 msgid " scheme encoding: "
 msgstr ""
 
@@ -2941,11 +2950,11 @@ msgstr ""
 msgid "expected to read %d characters, got %d"
 msgstr ""
 
-#: staff-performer.cc:301
+#: staff-performer.cc:307
 msgid "MIDI channel wrapped around"
 msgstr ""
 
-#: staff-performer.cc:302
+#: staff-performer.cc:308
 msgid "remapping modulo 16"
 msgstr ""
 
@@ -2982,23 +2991,23 @@ msgstr ""
 msgid "Markup depth exceeds maximal value of %d; Markup: %s"
 msgstr ""
 
-#: text-spanner-engraver.cc:72
+#: text-spanner-engraver.cc:71
 msgid "cannot find start of text spanner"
 msgstr ""
 
-#: text-spanner-engraver.cc:85
+#: text-spanner-engraver.cc:84
 msgid "already have a text spanner"
 msgstr ""
 
-#: text-spanner-engraver.cc:132
+#: text-spanner-engraver.cc:131
 msgid "unterminated text spanner"
 msgstr ""
 
-#: tie-engraver.cc:121
+#: tie-engraver.cc:120
 msgid "unterminated tie"
 msgstr ""
 
-#: tie-engraver.cc:377
+#: tie-engraver.cc:376
 msgid "lonely tie"
 msgstr ""
 
@@ -3007,7 +3016,7 @@ msgstr ""
 #.
 #. OTOH, Tristan Keuris writes 8/20 in his Intermezzi.
 #.
-#: time-signature-engraver.cc:95
+#: time-signature-engraver.cc:94
 #, c-format
 msgid "strange time signature found: %d/%d"
 msgstr ""
@@ -3027,49 +3036,40 @@ msgstr ""
 msgid "cannot find: `%s'"
 msgstr ""
 
-#: translator.cc:310
+#: translator.cc:305
 #, c-format
 msgid "Two simultaneous %s events, junking this one"
 msgstr ""
 
-#: translator.cc:311
+#: translator.cc:306
 #, c-format
 msgid "Previous %s event here"
 msgstr ""
 
-#: ttf.cc:480 ttf.cc:528
-#, c-format
-msgid "font index %d too large for font `%s', using index 0"
-msgstr ""
-
-#: ttf.cc:512 ttf.cc:562
-msgid "font index must be non-negative, using index 0"
-msgstr ""
-
-#: tuplet-engraver.cc:110
+#: tuplet-engraver.cc:109
 msgid "No tuplet to end"
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:400
+#: vaticana-ligature-engraver.cc:384
 #, c-format
 msgid ""
 "ignored prefix(es) `%s' of this head according to restrictions of the "
 "selected ligature style"
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:466
+#: vaticana-ligature-engraver.cc:450
 msgid ""
 "Ambiguous use of dots in ligature: there are multiple dotted notes with the "
 "same pitch.  The ligature should be split."
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:524
+#: vaticana-ligature-engraver.cc:508
 msgid ""
 "This ligature has a dotted head followed by a non-dotted head.  The ligature "
 "should be split after the last dotted head before this head."
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:736
+#: vaticana-ligature-engraver.cc:720
 #, c-format
 msgid "Vaticana_ligature_engraver: setting `spacing-increment = %f': ptr =%ul"
 msgstr ""
@@ -3082,7 +3082,7 @@ msgstr ""
 msgid "ascending vaticana style flexa"
 msgstr ""
 
-#: vertical-align-engraver.cc:95
+#: vertical-align-engraver.cc:100
 msgid "Ignoring Vertical_align_engraver in VerticalAxisGroup"
 msgstr ""
 
@@ -3526,17 +3526,17 @@ msgstr ""
 msgid "cannot extract file matching ~a from ~a"
 msgstr ""
 
-#: framework-ps.scm:347
+#: framework-ps.scm:353
 #, scheme-format
 msgid "do not know how to embed ~S=~S"
 msgstr ""
 
-#: framework-ps.scm:372
+#: framework-ps.scm:378
 #, scheme-format
 msgid "do not know how to embed font ~s ~s ~s"
 msgstr ""
 
-#: framework-ps.scm:754
+#: framework-ps.scm:760
 msgid ""
 "\n"
 "The PostScript backend does not support the\n"
@@ -3602,58 +3602,62 @@ msgstr ""
 msgid "no \\version statement found, please add~afor future compatibility"
 msgstr ""
 
-#: lily.scm:93
+#: lily.scm:94
 msgid "call-after-session used after session start"
 msgstr ""
 
-#: lily.scm:111
+#: lily.scm:112
 msgid "define-session used after session start"
 msgstr ""
 
-#: lily.scm:420
+#: lily.scm:122
+msgid "define-session-public used after session start"
+msgstr ""
+
+#: lily.scm:434
 msgid "Using (ice-9 curried-definitions) module\n"
 msgstr ""
 
-#: lily.scm:423
+#: lily.scm:437
 msgid "Guile 1.8\n"
 msgstr ""
 
-#: lily.scm:480
+#: lily.scm:494
 #, scheme-format
 msgid "cannot find: ~A"
 msgstr ""
 
-#: lily.scm:910
+#: lily.scm:924
 msgid "Success: compilation successfully completed"
 msgstr ""
 
-#: lily.scm:911
+#: lily.scm:925
 msgid "Compilation completed with warnings or errors"
 msgstr ""
 
-#: lily.scm:972
+#: lily.scm:986
 #, scheme-format
 msgid "job ~a terminated with signal: ~a"
 msgstr ""
 
-#: lily.scm:975
+#: lily.scm:989
 #, scheme-format
 msgid ""
 "logfile ~a (exit ~a):\n"
 "~a"
 msgstr ""
 
-#: lily.scm:997 lily.scm:1086
+#: lily.scm:1011 lily.scm:1100
 #, scheme-format
 msgid "failed files: ~S"
 msgstr ""
 
-#: lily.scm:1077
+#: lily.scm:1091
 #, scheme-format
 msgid "Redirecting output to ~a..."
 msgstr ""
 
-#: lily.scm:1096
+#: lily.scm:1110
 #, scheme-format
 msgid "Invoking `~a'...\n"
 msgstr ""
@@ -3782,12 +3786,12 @@ msgstr ""
 msgid "conflicting tag group ~a"
 msgstr ""
 
-#: output-ps.scm:286 output-svg.scm:535
+#: output-ps.scm:290 output-svg.scm:539
 #, scheme-format
 msgid "unknown line-cap-style: ~S"
 msgstr ""
 
-#: output-ps.scm:291 output-svg.scm:541
+#: output-ps.scm:295 output-svg.scm:545
 #, scheme-format
 msgid "unknown line-join-style: ~S"
 msgstr ""
index f6b47c3c93582af7471c13da23b38e7eec70ae1d..e8cbcb016769301209d51af8a4f8283537959b37 100644 (file)
@@ -3,7 +3,10 @@ import inspect
 import sys
 import string
 import re
+import math
 import lilylib as ly
+import warnings
+import utilities
 
 _ = ly._
 
@@ -12,7 +15,8 @@ from rational import Rational
 # Store previously converted pitch for \relative conversion as a global state variable
 previous_pitch = None
 relative_pitches = False
-
+whatOrnament = ""
+ly_dur = None # stores lilypond durations
 
 def escape_instrument_string (input_string):
     retstring = string.replace (input_string, "\"", "\\\"")
@@ -35,13 +39,11 @@ class Output_stack_element:
         o.factor = self.factor
         return o
 
-class Output_printer:
-
-    """A class that takes care of formatting (eg.: indenting) a
+class Output_printer(object):
+    """
+    A class that takes care of formatting (eg.: indenting) a
     Music expression as a .ly file.
-
     """
-
     def __init__ (self):
         self._line = ''
         self._indent = 4
@@ -55,9 +57,8 @@ class Output_printer:
     def set_file (self, file):
         self._file = file
 
-    def dump_version (self):
-        self.newline ()
-        self.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
+    def dump_version (self, version):
+        self.print_verbatim ('\\version "' + version + '"')
         self.newline ()
 
     def get_indent (self):
@@ -69,7 +70,7 @@ class Output_printer:
 
     def add_factor (self, factor):
         self.override()
-        self._output_state_stack[-1].factor *=  factor
+        self._output_state_stack[-1].factor *= factor
 
     def revert (self):
         del self._output_state_stack[-1]
@@ -84,13 +85,13 @@ class Output_printer:
 
     def unformatted_output (self, str):
         # don't indent on \< and indent only once on <<
-        self._nesting += ( str.count ('<')
+        self._nesting += (str.count ('<')
                          - str.count ('\<') - str.count ('<<')
-                         + str.count ('{') )
-        self._nesting -= ( str.count ('>') - str.count ('\>') - str.count ('>>')
+                         + str.count ('{'))
+        self._nesting -= (str.count ('>') - str.count ('\>') - str.count ('>>')
                                            - str.count ('->') - str.count ('_>')
                                            - str.count ('^>')
-                         + str.count ('}') )
+                         + str.count ('}'))
         self.print_verbatim (str)
 
     def print_duration_string (self, str):
@@ -99,6 +100,15 @@ class Output_printer:
 
         self.unformatted_output (str)
 
+#    def print_note_color (self, object, rgb=None):
+#        if rgb:
+#            str = ("\\once\\override %s #'color = #(rgb-color %s # %s %s)" % (object, rgb[0], rgb[1], rgb[2]))
+#        else:
+#            str = "\\revert %s #'color" % object
+#            self.newline()
+#            self.add_word(str)
+#            self.newline()
+
     def add_word (self, str):
         if (len (str) + 1 + len (self._line) > self._line_len):
             self.newline()
@@ -125,11 +135,11 @@ class Output_printer:
             self._skipspace = False
             self.unformatted_output (str)
         else:
-            words = string.split (str)
+            # Avoid splitting quoted strings (e.g. "1. Wie") when indenting.
+            words = utilities.split_string_and_preserve_doublequoted_substrings(str)
             for w in words:
                 self.add_word (w)
 
-
     def close (self):
         self.newline ()
         self._file.close ()
@@ -137,19 +147,19 @@ class Output_printer:
 
 
 class Duration:
-    def __init__ (self):
+    def __init__(self):
         self.duration_log = 0
         self.dots = 0
-        self.factor = Rational (1)
+        self.factor = Rational(1)
 
-    def lisp_expression (self):
+    def lisp_expression(self):
         return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
                              self.dots,
-                             self.factor.numerator (),
-                             self.factor.denominator ())
+                             self.factor.numerator(),
+                             self.factor.denominator())
 
-
-    def ly_expression (self, factor = None, scheme_mode = False):
+    def ly_expression(self, factor=None, scheme_mode=False):
+        global ly_dur # stores lilypond durations
         if not factor:
             factor = self.factor
 
@@ -158,58 +168,131 @@ class Duration:
                 longer_dict = {-1: "breve", -2: "longa"}
             else:
                 longer_dict = {-1: "\\breve", -2: "\\longa"}
-            str = longer_dict.get (self.duration_log, "1")
+            dur_str = longer_dict.get(self.duration_log, "1")
         else:
-            str = '%d' % (1 << self.duration_log)
-        str += '.'*self.dots
+            dur_str = '%d' % (1 << self.duration_log)
+        dur_str += '.' * self.dots
 
-        if factor <> Rational (1,1):
-            if factor.denominator () <> 1:
-                str += '*%d/%d' % (factor.numerator (), factor.denominator ())
+        if factor <> Rational(1, 1):
+            if factor.denominator() <> 1:
+                dur_str += '*%d/%d' % (factor.numerator(), factor.denominator())
             else:
-                str += '*%d' % factor.numerator ()
+                dur_str += '*%d' % factor.numerator()
 
-        return str
+        if dur_str.isdigit():
+            ly_dur = int(dur_str)
+        # TODO: We need to deal with dotted notes and scaled durations
+        # otherwise ly_dur won't work in combination with tremolos.
+        return dur_str
 
-    def print_ly (self, outputter):
-        str = self.ly_expression (self.factor / outputter.duration_factor ())
-        outputter.print_duration_string (str)
+    def print_ly(self, outputter):
+        dur_str = self.ly_expression(self.factor / outputter.duration_factor())
+        outputter.print_duration_string(dur_str)
 
     def __repr__(self):
         return self.ly_expression()
 
-    def copy (self):
-        d = Duration ()
+    def copy(self):
+        d = Duration()
         d.dots = self.dots
         d.duration_log = self.duration_log
         d.factor = self.factor
         return d
 
-    def get_length (self):
-        dot_fact = Rational( (1 << (1 + self.dots))-1,
+    def get_length(self):
+        dot_fact = Rational((1 << (1 + self.dots)) - 1,
                              1 << self.dots)
 
-        log = abs (self.duration_log)
+        log = abs(self.duration_log)
         dur = 1 << log
         if self.duration_log < 0:
-            base = Rational (dur)
+            base = Rational(dur)
         else:
-            base = Rational (1, dur)
+            base = Rational(1, dur)
 
         return base * dot_fact * self.factor
 
-# implement the midi command line option '-m' and '--midi'
-# if TRUE add midi-block to .ly file (see below)
-def set_create_midi (option):
+def set_create_midi(option):
+    """
+    Implement the midi command line option '-m' and '--midi'.
+    If True, add midi-block to .ly file (see L{musicexp.Score.print_ly}).
+
+    @param option: Indicates whether the midi-block has to be added or not.
+    @type option: boolean
+    """
     global midi_option
     midi_option = option
 
 def get_create_midi ():
+    """
+    Return, if exists the state of the midi-option.
+
+    @return: The state of the midi-option.
+    @rtype: boolean
+    """
     try:
         return midi_option
     except:
         return False
 
+# implement the command line option '--transpose'
+def set_transpose(option):
+    global transpose_option
+    transpose_option = option
+
+def get_transpose(optType):
+    try:
+        if(optType == "string"):
+            return '\\transpose c %s' % transpose_option
+        elif(optType == "integer"):
+            p = generic_tone_to_pitch(transpose_option)
+            return p.semitones()
+    except:
+        if(optType == "string"):
+            return ""
+        elif(optType == "integer"):
+            return 0
+
+# implement the command line option '--tab-clef'
+def set_tab_clef(option):
+    global tab_clef_option
+    tab_clef_option = option
+
+def get_tab_clef():
+    try:
+        return ("tab", tab_clef_option)[tab_clef_option == "tab" or tab_clef_option == "moderntab"]
+    except:
+        return "tab"
+
+# definitions of the command line option '--string-numbers'
+def set_string_numbers(option):
+    global string_numbers_option
+    string_numbers_option = option
+
+def get_string_numbers():
+    try:
+        return ("t", string_numbers_option)[string_numbers_option == "t" or string_numbers_option == "f"]
+    except:
+        return "t"
+
+def generic_tone_to_pitch (tone):
+    accidentals_dict = {
+        "" : 0,
+        "es" : -1,
+        "s" : -1,
+        "eses" : -2,
+        "ses" : -2,
+        "is" : 1,
+        "isis" : 2
+    }
+    p = Pitch ()
+    tone_ = tone.strip().lower()
+    p.octave = tone_.count("'") - tone_.count(",")
+    tone_ = tone_.replace(",","").replace("'","")
+    p.step = ((ord (tone_[0]) - ord ('a') + 5) % 7)
+    p.alteration = accidentals_dict.get(tone_[1:], 0)
+    return p
+
 # Implement the different note names for the various languages
 def pitch_generic (pitch, notenames, accidentals):
     str = notenames[pitch.step]
@@ -224,7 +307,7 @@ def pitch_generic (pitch, notenames, accidentals):
             ly.warning (_ ("Language does not support microtones contained in the piece"))
         else:
             try:
-                str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration-halftones]
+                str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration - halftones]
             except KeyError:
                 ly.warning (_ ("Language does not support microtones contained in the piece"))
     return str
@@ -289,7 +372,6 @@ def set_pitch_language (language):
 # global variable to hold the formatting function.
 pitch_generating_function = pitch_general
 
-
 class Pitch:
     def __init__ (self):
         self.alteration = 0
@@ -302,12 +384,12 @@ class Pitch:
 
     def transposed (self, interval):
         c = self.copy ()
-        c.alteration  += interval.alteration
+        c.alteration += interval.alteration
         c.step += interval.step
         c.octave += interval.octave
         c.normalize ()
 
-        target_st = self.semitones()  + interval.semitones()
+        target_st = self.semitones() + interval.semitones()
         c.alteration += target_st - c.semitones()
         return c
 
@@ -316,7 +398,7 @@ class Pitch:
             c.step += 7
             c.octave -= 1
         c.octave += c.step / 7
-        c.step = c.step  % 7
+        c.step = c.step % 7
 
     def lisp_expression (self):
         return '(ly:make-pitch %d %d %d)' % (self.octave,
@@ -328,13 +410,36 @@ class Pitch:
         p.alteration = self.alteration
         p.step = self.step
         p.octave = self.octave
+        p._force_absolute_pitch = self._force_absolute_pitch
         return p
 
     def steps (self):
-        return self.step + self.octave *7
+        return self.step + self.octave * 7
 
     def semitones (self):
-        return self.octave * 12 + [0,2,4,5,7,9,11][self.step] + self.alteration
+        return self.octave * 12 + [0, 2, 4, 5, 7, 9, 11][self.step] + self.alteration
+
+    def normalize_alteration (c):
+        if(c.alteration < 0 and [True, False, False, True, False, False, False][c.step]):
+            c.alteration += 1
+            c.step -= 1
+        elif(c.alteration > 0 and [False, False, True, False, False, False, True][c.step]):
+            c.alteration -= 1
+            c.step += 1
+        c.normalize ()
+
+    def add_semitones (self, number):
+        semi = number + self.alteration
+        self.alteration = 0
+        if(semi == 0):
+            return
+        sign = (1,-1)[semi < 0]
+        prev = self.semitones()
+        while abs((prev + semi) - self.semitones ()) > 1:
+            self.step += sign
+            self.normalize()
+        self.alteration += (prev + semi) - self.semitones ()
+        self.normalize_alteration ()
 
     def ly_step_expression (self):
         return pitch_generating_function (self)
@@ -369,7 +474,6 @@ class Pitch:
             str += self.relative_pitch ()
         else:
             str += self.absolute_pitch ()
-
         return str
 
     def print_ly (self, outputter):
@@ -404,7 +508,7 @@ class Music:
 
         props = self.get_properties ()
 
-        return "(make-music '%s %s)" % (name,  props)
+        return "(make-music '%s %s)" % (name, props)
 
     def set_start (self, start):
         self.start = start
@@ -414,7 +518,7 @@ class Music:
             return self
         return None
 
-    def print_comment (self, printer, text = None):
+    def print_comment (self, printer, text=None):
         if not text:
             text = self.comment
 
@@ -595,12 +699,12 @@ class NestedMusic(Music):
     def get_subset_properties (self, predicate):
         return ("'elements (list %s)"
             % string.join (map (lambda x: x.lisp_expression(),
-                      filter ( predicate,  self.elements))))
+                      filter (predicate, self.elements))))
     def get_neighbor (self, music, dir):
         assert music.parent == self
         idx = self.elements.index (music)
         idx += dir
-        idx = min (idx, len (self.elements) -1)
+        idx = min (idx, len (self.elements) - 1)
         idx = max (idx, 0)
 
         return self.elements[idx]
@@ -630,7 +734,7 @@ class NestedMusic(Music):
 class SequentialMusic (NestedMusic):
     def get_last_event_chord (self):
         value = None
-        at = len( self.elements ) - 1
+        at = len(self.elements) - 1
         while (at >= 0 and
                not isinstance (self.elements[at], ChordEvent) and
                not isinstance (self.elements[at], BarLine)):
@@ -640,7 +744,7 @@ class SequentialMusic (NestedMusic):
             value = self.elements[at]
         return value
 
-    def print_ly (self, printer, newline = True):
+    def print_ly (self, printer, newline=True):
         printer ('{')
         if self.comment:
             self.print_comment (printer)
@@ -660,7 +764,7 @@ class SequentialMusic (NestedMusic):
 
         props = self.get_subset_properties (pred)
 
-        return "(make-music '%s %s)" % (name,  props)
+        return "(make-music '%s %s)" % (name, props)
 
     def set_start (self, start):
         for e in self.elements:
@@ -703,39 +807,60 @@ class Lyrics:
         self.lyrics_syllables = []
 
     def print_ly (self, printer):
-        printer.dump ("\lyricmode {")
-        for l in self.lyrics_syllables:
-            printer.dump ( "%s " % l )
-        printer.dump ("}")
+        printer.dump (self.ly_expression ())
+        printer.newline()
+        printer.dump ('}')
+        printer.newline()
 
     def ly_expression (self):
-        lstr = "\lyricmode {\n  "
+        lstr = "\lyricmode {\set ignoreMelismata = ##t"
         for l in self.lyrics_syllables:
-            lstr += l + " "
-        lstr += "\n}"
+            lstr += l
+        #lstr += "\n}"
         return lstr
 
-
 class Header:
+
     def __init__ (self):
         self.header_fields = {}
+
     def set_field (self, field, value):
         self.header_fields[field] = value
 
-    def print_ly (self, printer):
-        printer.dump ("\header {")
-        printer.newline ()
-        for (k,v) in self.header_fields.items ():
+    def format_header_strings(self, key, value, printer):
+        printer.dump(key + ' = ')
+
+        # If a header item contains a line break, it is segmented. The
+        # substrings are formatted with the help of \markup, using
+        # \column and \line. An exception, however, are texidoc items,
+        # which should not contain LilyPond formatting commands.
+        if (key != 'texidoc') and ('\n' in value):
+            value = value.replace('"', '')
+            printer.dump(r'\markup \column {')
+            substrings = value.split('\n')
+            for s in substrings:
+                printer.newline()
+                printer.dump(r'\line { "' + s + '"}')
+            printer.dump('}')
+            printer.newline()
+        else:
+            printer.dump(value)
+        printer.newline()
+
+    def print_ly(self, printer):
+        printer.dump("\header {")
+        printer.newline()
+        for (k, v) in self.header_fields.items():
             if v:
-                printer.dump ('%s = %s' % (k,v))
-                printer.newline ()
-        printer.dump ("}")
-        printer.newline ()
-        printer.newline ()
+               self.format_header_strings(k, v, printer)
+        #printer.newline()
+        printer.dump("}")
+        printer.newline()
+        printer.newline()
 
 
 class Paper:
-    def __init__ (self):
+    def __init__(self):
         self.global_staff_size = -1
         # page size
         self.page_width = -1
@@ -749,17 +874,31 @@ class Paper:
         self.system_right_margin = -1
         self.system_distance = -1
         self.top_system_distance = -1
+        self.indent = 0
+        self.short_indent = 0
+        self.instrument_names = []
 
     def print_length_field (self, printer, field, value):
         if value >= 0:
             printer.dump ("%s = %s\\cm" % (field, value))
             printer.newline ()
+
+    def get_longest_instrument_name(self):
+        result = ''
+        for name in self.instrument_names:
+            lines = name.split('\n')
+            for line in lines:
+                if len(line) > len(result):
+                    result = line
+        return result
+
     def print_ly (self, printer):
         if self.global_staff_size > 0:
             printer.dump ('#(set-global-staff-size %s)' % self.global_staff_size)
             printer.newline ()
         printer.dump ('\\paper {')
         printer.newline ()
+        printer.newline ()
         self.print_length_field (printer, "paper-width", self.page_width)
         self.print_length_field (printer, "paper-height", self.page_height)
         self.print_length_field (printer, "top-margin", self.top_margin)
@@ -771,6 +910,14 @@ class Paper:
         #        system_right_margin in LilyPond?
         self.print_length_field (printer, "between-system-space", self.system_distance)
         self.print_length_field (printer, "page-top-space", self.top_system_distance)
+        # TODO: Compute the indentation with the instrument name lengths
+
+        # TODO: font width ?
+        char_per_cm = (len(self.get_longest_instrument_name()) * 13) / self.page_width
+        if (self.indent != 0):
+            self.print_length_field (printer, "indent", self.indent/char_per_cm)
+        if (self.short_indent != 0):
+            self.print_length_field (printer, "short-indent", self.short_indent/char_per_cm)
 
         printer.dump ('}')
         printer.newline ()
@@ -869,6 +1016,7 @@ class ChordEvent (NestedMusic):
 
         # Print all overrides and other settings needed by the
         # articulations/ornaments before the note
+
         for e in other_events:
             e.print_before_note (printer)
 
@@ -880,10 +1028,17 @@ class ChordEvent (NestedMusic):
             global previous_pitch
             pitches = []
             basepitch = None
+            stem = None
             for x in note_events:
+                if(x.associated_events):
+                    for aev in x.associated_events:
+                        if (isinstance(aev, StemEvent) and aev.value):
+                            stem = aev
                 pitches.append (x.chord_element_ly ())
                 if not basepitch:
                     basepitch = previous_pitch
+            if stem:
+                printer (stem.ly_expression ())
             printer ('<%s>' % string.join (pitches))
             previous_pitch = basepitch
             duration = self.get_duration ()
@@ -959,7 +1114,7 @@ class SpanEvent (Event):
         self.span_direction = 0 # start/stop
         self.line_type = 'solid'
         self.span_type = 0 # e.g. cres/decrescendo, ottava up/down
-        self.size = 0 # size of e.g. ocrave shift
+        self.size = 0 # size of e.g. octave shift
     def wait_for_note (self):
         return True
     def get_properties(self):
@@ -993,14 +1148,39 @@ class PedalEvent (SpanEvent):
             1:'\\sustainOff'}.get (self.span_direction, '')
 
 class TextSpannerEvent (SpanEvent):
+    def print_before_note (self, printer):
+        if hasattr(self, 'style') and self.style=="wave":
+            printer.dump("\once \override TextSpanner #'style = #'trill")
+        try:
+            x = {-1:'\\textSpannerDown', 0:'\\textSpannerNeutral', 1: '\\textSpannerUp'}.get(self.force_direction, '')
+            printer.dump (x)
+        except:
+            pass
+
+    def print_after_note (self, printer):
+        pass
+
     def ly_expression (self):
-        return {-1: '\\startTextSpan',
-            1:'\\stopTextSpan'}.get (self.span_direction, '')
+        global whatOrnament
+        if hasattr(self, 'style') and self.style=="ignore":
+            return ""
+        # if self.style=="wave":
+        if whatOrnament == "wave":
+            return {-1: '\\startTextSpan',
+                    1:'\\stopTextSpan'}.get (self.span_direction, '')
+        else:
+            if hasattr(self, 'style') and self.style=="stop" and whatOrnament != "trill": return ""
+            return {-1: '\\startTrillSpan',
+                    1:'\\stopTrillSpan'}.get (self.span_direction, '')
 
 class BracketSpannerEvent (SpanEvent):
     # Ligature brackets use prefix-notation!!!
     def print_before_note (self, printer):
         if self.span_direction == -1:
+            if self.force_direction == 1:
+                printer.dump("\once \override LigatureBracket #' direction = #UP")
+            elif self.force_direction == -1:
+                printer.dump("\once \override LigatureBracket #' direction = #DOWN")
             printer.dump ('\[')
     # the bracket after the last note
     def print_after_note (self, printer):
@@ -1015,7 +1195,7 @@ class OctaveShiftEvent (SpanEvent):
     def wait_for_note (self):
         return False
     def set_span_type (self, type):
-        self.span_type = {'up': 1, 'down': -1}.get (type, 0)
+        self.span_type = {'up': 1, 'down':-1}.get (type, 0)
     def ly_octave_shift_indicator (self):
         # convert 8/15 to lilypond indicators (+-1/+-2)
         try:
@@ -1024,7 +1204,7 @@ class OctaveShiftEvent (SpanEvent):
             ly.warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self.size)
             value = 0
         # negative values go up!
-        value *= -1*self.span_type
+        value *= -1 * self.span_type
         return value
     def ly_expression (self):
         dir = self.ly_octave_shift_indicator ()
@@ -1032,7 +1212,7 @@ class OctaveShiftEvent (SpanEvent):
         if dir:
             value = '\ottava #%s' % dir
         return {
-            -1: value,
+            - 1: value,
             1: '\ottava #0'}.get (self.span_direction, '')
 
 class TrillSpanEvent (SpanEvent):
@@ -1044,7 +1224,7 @@ class TrillSpanEvent (SpanEvent):
 class GlissandoEvent (SpanEvent):
     def print_before_note (self, printer):
         if self.span_direction == -1:
-            style= {
+            style = {
                 "dashed" : "dashed-line",
                 "dotted" : "dotted-line",
                 "wavy"   : "zigzag"
@@ -1083,20 +1263,24 @@ class TieEvent(Event):
 
 class HairpinEvent (SpanEvent):
     def set_span_type (self, type):
-        self.span_type = {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
+        self.span_type = {'crescendo' : 1, 'decrescendo' :-1, 'diminuendo' :-1 }.get (type, 0)
     def hairpin_to_ly (self):
         if self.span_direction == 1:
             return '\!'
         else:
             return {1: '\<', -1: '\>'}.get (self.span_type, '')
 
+    def direction_mod (self):
+        return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
+
     def ly_expression (self):
         return self.hairpin_to_ly ()
 
     def print_ly (self, printer):
         val = self.hairpin_to_ly ()
         if val:
-            printer.dump (val)
+            # printer.dump (val)
+            printer.dump ('%s%s' % (self.direction_mod (), val))
 
 
 
@@ -1104,6 +1288,7 @@ class DynamicsEvent (Event):
     def __init__ (self):
         Event.__init__ (self)
         self.type = None
+        self.force_direction = 0
     def wait_for_note (self):
         return True
     def ly_expression (self):
@@ -1112,9 +1297,12 @@ class DynamicsEvent (Event):
         else:
             return
 
+    def direction_mod (self):
+        return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
+
     def print_ly (self, printer):
         if self.type:
-            printer.dump ("\\%s" % self.type)
+            printer.dump ('%s\\%s' % (self.direction_mod (), self.type))
 
 class MarkEvent (Event):
     def __init__ (self, text="\\default"):
@@ -1145,13 +1333,39 @@ class TextEvent (Event):
         self.force_direction = None
         self.markup = ''
     def wait_for_note (self):
+        """ This is problematic: the lilypond-markup ^"text"
+        requires wait_for_note to be true. Otherwise the
+        compilation will fail.  So we are forced to set return to True.
+        But in some cases this might lead to a wrong placement of the text.
+        In case of words like Allegro the text should be put in a '\tempo'-command.
+        In this case we don't want to wait for the next note.
+        In some other cases the text is supposed to be used in a '\mark\markup' construct.
+        We would not want to wait for the next note either.
+        There might be other problematic situations.
+        In the long run we should differentiate between various contexts in MusicXML, e.g.
+        the following markup should be interpreted as '\tempo "Allegretto"':
+                <direction placement="above">
+                    <direction-type>
+                        <words>Allegretto</words>
+                    </direction-type>
+                    <sound tempo="120"/>
+                </direction>
+        In the mean time arising problems have to be corrected manually after the conversion.
+        """
         return True
 
     def direction_mod (self):
+        """ 1: placement="above"; -1: placement="below"; 0: no placement attribute.
+        see musicxml_direction_to_indicator in musicxml2ly_conversion.py """
         return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
 
     def ly_expression (self):
-        base_string = '%s\"%s\"'
+        # self.text will be enclosed by quotes, and the direction
+        # modifier must be separated from the opening quote by a space.
+        # This is so that subsequent line breaking for the output file
+        # using utilities.split_string_and_preserve_doublequoted_strings()
+        # properly detects the opening quote.
+        base_string = '%s \"%s\"'
         if self.markup:
             base_string = '%s\markup{ ' + self.markup + ' {%s} }'
         return base_string % (self.direction_mod (), self.text)
@@ -1181,9 +1395,21 @@ class ShortArticulationEvent (ArticulationEvent):
             return ''
 
 class NoDirectionArticulationEvent (ArticulationEvent):
+
+    def is_breathing_sign(self):
+        return self.type == 'breathe'
+
+    def print_after_note(self, printer):
+        # The breathing sign should, according to current LilyPond
+        # praxis, be treated as an independent musical
+        # event. Consequently, it should be printed _after_ the note
+        # to which it is attached.
+        if self.is_breathing_sign():
+            printer.dump(r'\breathe')
+
     def ly_expression (self):
-        if self.type:
-            return '\\%s' % self.type
+        if self.type and not self.is_breathing_sign():
+             return '\\%s' % self.type
         else:
             return ''
 
@@ -1212,11 +1438,11 @@ class FretEvent (MarkupEvent):
         if self.frets <> 4:
             val += "h:%s;" % self.frets
         if self.barre and len (self.barre) >= 3:
-            val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2])
+            val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2]+get_transpose("integer"))
         have_fingering = False
         for i in self.elements:
             if len (i) > 1:
-                val += "%s-%s" % (i[0], i[1])
+                val += "%s-%s" % (i[0], i[1]+(get_transpose("integer"),'')[isinstance(i[1],str)])
             if len (i) > 2:
                 have_fingering = True
                 val += "-%s" % i[2]
@@ -1228,9 +1454,35 @@ class FretEvent (MarkupEvent):
         else:
             return ''
 
+class FretBoardNote (Music):
+    def __init__ (self):
+        Music.__init__ (self)
+        self.pitch = None
+        self.string = None
+        self.fingering = None
+    def ly_expression (self):
+        str = self.pitch.ly_expression()
+        if self.fingering:
+            str += "-%s" % self.fingering
+        if self.string:
+            str += "\%s" % self.string
+        return str
+
+class FretBoardEvent (NestedMusic):
+    def __init__ (self):
+        NestedMusic.__init__ (self)
+        self.duration = None
+    def print_ly (self, printer):
+        fretboard_notes = [n for n in self.elements if isinstance (n, FretBoardNote)]
+        if fretboard_notes:
+          notes = []
+          for n in fretboard_notes:
+              notes.append (n.ly_expression ())
+          contents = string.join (notes)
+          printer ('<%s>%s' % (contents,self.duration))
 
 class FunctionWrapperEvent (Event):
-    def __init__ (self, function_name = None):
+    def __init__ (self, function_name=None):
         Event.__init__ (self)
         self.function_name = function_name
     def pre_note_ly (self, is_chord_element):
@@ -1250,16 +1502,36 @@ class ParenthesizeEvent (FunctionWrapperEvent):
     def __init__ (self):
         FunctionWrapperEvent.__init__ (self, "parenthesize")
 
-class NotestyleEvent (Event):
+class StemEvent (Event):
+    """"
+    A class to take care of stem values (up, down, double, none)
+    """
+    def __init__ (self):
+        Event.__init__ (self)
+        self.value = None
+    def pre_chord_ly (self):
+        if self.value:
+            return "\\%s" % self.value
+        else:
+            return ''
+    def pre_note_ly (self, is_chord_element):
+        return ''
+    def ly_expression (self):
+        return self.pre_chord_ly ()
+
+class NotestyleEvent (Event): #class changed by DaLa: additional attribute color
     def __init__ (self):
         Event.__init__ (self)
         self.style = None
         self.filled = None
+        self.color = None
     def pre_chord_ly (self):
+        return_string = ''
         if self.style:
-            return "\\once \\override NoteHead.style = #%s" % self.style
-        else:
-            return ''
+            return_string += " \\once \\override NoteHead #'style = #%s" % self.style
+        if self.color:
+            return_string += " \\once \\override NoteHead #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
+        return return_string
     def pre_note_ly (self, is_chord_element):
         if self.style and is_chord_element:
             return "\\tweak style #%s" % self.style
@@ -1268,6 +1540,20 @@ class NotestyleEvent (Event):
     def ly_expression (self):
         return self.pre_chord_ly ()
 
+class StemstyleEvent (Event): #class added by DaLa
+    def __init__ (self):
+        Event.__init__ (self)
+        self.color = None
+    def pre_chord_ly (self):
+        if self.color:
+            return "\\once \\override Stem #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
+        else:
+            return ''
+    def pre_note_ly (self, is_chord_element):
+        return ''
+    def ly_expression (self):
+        return self.pre_chord_ly ()
+
 
 class ChordPitch:
     def __init__ (self):
@@ -1303,14 +1589,14 @@ class ChordNameEvent (Event):
     def add_modification (self, mod):
         self.modifications.append (mod)
     def ly_expression (self):
+
         if not self.root:
             return ''
         value = self.root.ly_expression ()
         if self.duration:
             value += self.duration.ly_expression ()
         if self.kind:
-            value += ":"
-            value += self.kind
+            value = self.kind.format(value)
         # First print all additions/changes, and only afterwards all subtractions
         for m in self.modifications:
             if m.type == 1:
@@ -1323,16 +1609,37 @@ class ChordNameEvent (Event):
         return value
 
 
-class TremoloEvent (ArticulationEvent):
-    def __init__ (self):
-        Event.__init__ (self)
-        self.bars = 0
-
-    def ly_expression (self):
-        str=''
-        if self.bars and self.bars > 0:
-            str += ':%s' % (2 ** (2 + string.atoi (self.bars)))
-        return str
+class TremoloEvent(ArticulationEvent):
+    def __init__(self):
+        Event.__init__(self)
+        self.strokes = 0
+
+    def ly_expression(self):
+        ly_str = ''
+        if self.strokes and int(self.strokes) > 0:
+            # ly_dur is a global variable defined in class Duration
+            # ly_dur stores the value of the reciprocal values of notes
+            # ly_dur is used here to check the current note duration
+            # if the duration is smaller than 8, e.g.
+            # quarter, half and whole notes,
+            # `:(2 ** (2 + number of tremolo strokes))'
+            # should be appended to the pitch and duration, e.g.
+            # 1 stroke: `c4:8' or `c2:8' or `c1:8'
+            # 2 strokes: `c4:16' or `c2:16' or `c1:16'
+            # ...
+            # else (if ly_dur is equal to or greater than 8):
+            # we need to make sure that the tremolo value that is to
+            # be appended to the pitch and duration is twice the
+            # duration (if there is only one tremolo stroke.
+            # Each additional stroke doubles the tremolo value, e.g.:
+            # 1 stroke: `c8:16', `c16:32', `c32:64', ...
+            # 2 strokes: `c8:32', `c16:64', `c32:128', ...
+            # ...
+            if ly_dur < 8:
+                ly_str += ':%s' % (2 ** (2 + int(self.strokes)))
+            else:
+                ly_str += ':%s' % (2 ** int((math.log(ly_dur, 2)) + int(self.strokes)))
+        return ly_str
 
 class BendEvent (ArticulationEvent):
     def __init__ (self):
@@ -1388,6 +1695,10 @@ class RestEvent (RhythmicEvent):
     def print_ly (self, printer):
         for ev in self.associated_events:
             ev.print_ly (printer)
+#        if hasattr(self, 'color'):
+#            printer.print_note_color("NoteHead", self.color)
+#            printer.print_note_color("Stem", self.color)
+#            printer.print_note_color("Beam", self.color)
         if self.pitch:
             self.pitch.print_ly (printer)
             self.duration.print_ly (printer)
@@ -1403,7 +1714,7 @@ class SkipEvent (RhythmicEvent):
 class NoteEvent(RhythmicEvent):
     def  __init__ (self):
         RhythmicEvent.__init__ (self)
-        self.pitch = None
+        #self.pitch = None
         self.drum_type = None
         self.cautionary = False
         self.forced_accidental = False
@@ -1451,6 +1762,11 @@ class NoteEvent(RhythmicEvent):
     def print_ly (self, printer):
         for ev in self.associated_events:
             ev.print_ly (printer)
+        if hasattr(self, 'color'):
+            printer.print_note_color("NoteHead", self.color)
+            printer.print_note_color("Stem", self.color)
+            printer.print_note_color("Beam", self.color)
+
         if self.pitch:
             self.pitch.print_ly (printer)
             printer (self.pitch_mods ())
@@ -1459,6 +1775,11 @@ class NoteEvent(RhythmicEvent):
 
         self.duration.print_ly (printer)
 
+#        if hasattr(self, 'color'):
+#            printer.print_note_color("NoteHead")
+#            printer.print_note_color("Stem")
+#            printer.print_note_color("Beam")
+
 class KeySignatureChange (Music):
     def __init__ (self):
         Music.__init__ (self)
@@ -1468,9 +1789,9 @@ class KeySignatureChange (Music):
 
     def format_non_standard_alteration (self, a):
         alter_dict = { -2:   ",DOUBLE-FLAT",
-                       -1.5: ",THREE-Q-FLAT",
-                       -1:   ",FLAT",
-                       -0.5: ",SEMI-FLAT",
+                       - 1.5: ",THREE-Q-FLAT",
+                       - 1:   ",FLAT",
+                       - 0.5: ",SEMI-FLAT",
                         0:   ",NATURAL",
                         0.5: ",SEMI-SHARP",
                         1:   ",SHARP",
@@ -1499,11 +1820,42 @@ class KeySignatureChange (Music):
         else:
             return ''
 
+class ShiftDurations (MusicWrapper):
+    def __init__ (self):
+        MusicWrapper.__init__ (self)
+        self.params = [0,0]
+
+    def set_shift_durations_parameters(self, timeSigChange):
+        self.params = timeSigChange.get_shift_durations_parameters()
+
+    def print_ly (self, func):
+        func (' \\shiftDurations #%d #%d ' % tuple(self.params))
+        MusicWrapper.print_ly (self, func)
+
 class TimeSignatureChange (Music):
     def __init__ (self):
         Music.__init__ (self)
-        self.fractions = [4,4]
+        self.fractions = [4, 4]
         self.style = None
+        # Used for the --time-signature option of musicxml2ly
+        self.originalFractions = [4, 4]
+
+    def get_fractions_ratio (self):
+        """
+        Calculate the ratio between the original time fraction and the new one.
+        Used for the "--time-signature" option.
+
+        @return: The ratio between the two time fractions.
+        @rtype: float
+        """
+        return (float(self.originalFractions[0])/self.originalFractions[1])*(float(self.fractions[1])/self.fractions[0])
+
+    def get_shift_durations_parameters (self):
+        dur = math.ceil(math.log(self.get_fractions_ratio(),2))
+        dots = (1/self.get_fractions_ratio())/(math.pow(2,-dur))
+        dots = int(math.log(2-dots,0.5))
+        return [dur, dots]
+
     def format_fraction (self, frac):
         if isinstance (frac, list):
             l = [self.format_fraction (f) for f in frac]
@@ -1516,7 +1868,7 @@ class TimeSignatureChange (Music):
         # Print out the style if we have ome, but the '() should only be
         # forced for 2/2 or 4/4, since in all other cases we'll get numeric
         # signatures anyway despite the default 'C signature style!
-        is_common_signature = self.fractions in ([2,2], [4,4], [4,2])
+        is_common_signature = self.fractions in ([2, 2], [4, 4], [4, 2])
         if self.style:
             if self.style == "common":
                 st = "\\defaultTimeSignature"
@@ -1542,6 +1894,7 @@ class ClefChange (Music):
 
     def octave_modifier (self):
         return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
+
     def clef_name (self):
         return {('G', 2): "treble",
                 ('G', 1): "french",
@@ -1554,9 +1907,10 @@ class ClefChange (Music):
                 ('F', 4): "bass",
                 ('F', 5): "subbass",
                 ("percussion", 2): "percussion",
-                # Workaround: MuseScore uses PERC instead of percussion
+            # Workaround: MuseScore uses PERC instead of percussion
                 ("PERC", 2): "percussion",
-                ("TAB", 5): "tab"}.get ((self.type, self.position), None)
+                ("TAB", 5): get_tab_clef ()}.get ((self.type, self.position), None)
+
     def ly_expression (self):
         return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
 
@@ -1753,10 +2107,11 @@ class Break (Music):
             printer.dump ("\\%s" % self.type)
 
 class StaffGroup:
-    def __init__ (self, command = "StaffGroup"):
+    def __init__ (self, command="StaffGroup"):
         self.stafftype = command
         self.id = None
         self.instrument_name = None
+        self.sound = None
         self.short_instrument_name = None
         self.symbol = None
         self.spanbar = None
@@ -1786,6 +2141,10 @@ class StaffGroup:
         for c in self.children:
             if c:
                 c.print_ly (printer)
+        #Intention: I want to put the content of new StaffGroup in angled brackets (<< >>)
+        #printer.dump ("test")# test is printed twice at the end of a staffgroup with two staves.
+        #printer ("test") # test is printed twice at the end of a staffgroup with two staves.
+
     def needs_with (self):
         needs_with = False
         needs_with |= self.spanbar == "no"
@@ -1793,6 +2152,7 @@ class StaffGroup:
         needs_with |= self.short_instrument_name != None
         needs_with |= (self.symbol != None) and (self.symbol != "bracket")
         return needs_with
+
     def print_ly_context_mods (self, printer):
         if self.instrument_name or self.short_instrument_name:
             printer.dump ("\\consists \"Instrument_name_engraver\"")
@@ -1812,24 +2172,45 @@ class StaffGroup:
             for m in self.context_modifications:
                 printer.dump (m)
             printer.dump ("}")
-
-    def print_ly_chords (self,printer):
+            printer.newline ()
+        #print a single << after StaffGroup only when the with-block is not needed.
+        #This doesn't work. << is printed before and after StaffGroup!
+        #else:
+        #    printer.dump (" <<")
+        #prints loads off << before and after StaffGroup and before \set Staff.instrumentName
+        #elif not needs_with:
+        #    printer.dump (" <<")
+
+    def print_chords(self, printer):
         try:
             for [staff_id, voices] in self.part_information:
-                for [v, lyrics, figuredbass, chordnames] in voices:
+                for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
                     if chordnames:
-                        printer ('\context ChordNames = "%s" \\%s' % (chordnames, chordnames))
-                        printer.newline ()
+                        printer ('\context ChordNames = "%s" {%s \\%s}' % (chordnames, get_transpose ("string"), chordnames))
+                        printer.newline()
+        except TypeError:
+            return
+
+    def print_fretboards(self, printer):
+        try:
+            for [staff_id, voices] in self.part_information:
+                for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
+                    if fretboards:
+                        printer ('\context FretBoards = "%s" {%s \\%s}' % (fretboards, get_transpose ("string"), fretboards))
+                        printer.newline()
         except TypeError:
             return
 
     def print_ly (self, printer):
-        self.print_ly_chords (printer)
+        self.print_chords(printer)
+        self.print_fretboards(printer)
         if self.stafftype:
             printer.dump ("\\new %s" % self.stafftype)
         self.print_ly_overrides (printer)
-        printer.dump ("<<")
         printer.newline ()
+        if self.stafftype:
+            printer.dump ("<<")
+            printer.newline ()
         if self.stafftype and self.instrument_name:
             printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
                     escape_instrument_string (self.instrument_name)))
@@ -1838,23 +2219,32 @@ class StaffGroup:
             printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
                     escape_instrument_string (self.short_instrument_name)))
             printer.newline ()
+        if self.sound:
+            printer.dump(
+                r'\set {stafftype}.midiInstrument = #"{sound}"'.format(
+                    stafftype=self.stafftype, sound=self.sound))
+            printer.newline ()
         self.print_ly_contents (printer)
         printer.newline ()
-        printer.dump (">>")
-        printer.newline ()
+        if self.stafftype:
+            printer.dump (">>")
+            printer.newline ()
 
 
 class Staff (StaffGroup):
-    def __init__ (self, command = "Staff"):
+    def __init__ (self, command="Staff"):
         StaffGroup.__init__ (self, command)
         self.is_group = False
         self.part = None
         self.voice_command = "Voice"
         self.substafftype = None
+        self.sound = None
 
     def needs_with (self):
         return False
+
     def print_ly_context_mods (self, printer):
+        #printer.dump ("test") #does nothing.
         pass
 
     def print_ly_contents (self, printer):
@@ -1863,39 +2253,52 @@ class Staff (StaffGroup):
         sub_staff_type = self.substafftype
         if not sub_staff_type:
             sub_staff_type = self.stafftype
+        #printer.dump ("test") #prints test in each staff after the definitions of the instrument name and before the definition of the contexts.
+        printer.newline()
 
         for [staff_id, voices] in self.part_information:
+            # now comes the real staff definition:
             if staff_id:
                 printer ('\\context %s = "%s" << ' % (sub_staff_type, staff_id))
             else:
                 printer ('\\context %s << ' % sub_staff_type)
             printer.newline ()
+            printer.dump("\mergeDifferentlyDottedOn\mergeDifferentlyHeadedOn")
+            printer.newline()
             n = 0
             nr_voices = len (voices)
-            for [v, lyrics, figuredbass, chordnames] in voices:
+            for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
                 n += 1
                 voice_count_text = ''
                 if nr_voices > 1:
-                    voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo',
-                                        3: ' \\voiceThree'}.get (n, ' \\voiceFour')
-                printer ('\\context %s = "%s" {%s \\%s }' % (self.voice_command, v, voice_count_text, v))
+                    """
+The next line contains a bug: The voices might not appear in numerical order! Some voices might be missing e.g. if the xml file contains only voice one, three and four, this would result in: \voiceOne, \voiceTwo and \voiceThree. This causes wrong stem directions and collisions.
+                    """
+                    voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo', 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
+                printer ('\\context %s = "%s" {%s %s \\%s }' % (self.voice_command, v, get_transpose ("string"), voice_count_text, v))
                 printer.newline ()
-
+                lyrics_id = 1
                 for l in lyrics:
-                    printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v,l))
+                    printer ('\\new Lyrics \\lyricsto "%s" { \\set stanza = "%s." \\%s }' % (v, lyrics_id, l))
+                    lyrics_id += 1
                     printer.newline()
                 if figuredbass:
                     printer ('\context FiguredBass = "%s" \\%s' % (figuredbass, figuredbass))
             printer ('>>')
+            #printer.dump ("test") #prints test after each definition of a context.
+            #printer.newline ()
+        #printer.dump ("test") #prints test after each definition of a context.
 
     def print_ly (self, printer):
         if self.part_information and len (self.part_information) > 1:
             self.stafftype = "PianoStaff"
             self.substafftype = "Staff"
+            #printer.dump ('test')
         StaffGroup.print_ly (self, printer)
 
+
 class TabStaff (Staff):
-    def __init__ (self, command = "TabStaff"):
+    def __init__ (self, command="TabStaff"):
         Staff.__init__ (self, command)
         self.string_tunings = []
         self.tablature_format = None
@@ -1914,7 +2317,7 @@ class TabStaff (Staff):
 
 
 class DrumStaff (Staff):
-    def __init__ (self, command = "DrumStaff"):
+    def __init__ (self, command="DrumStaff"):
         Staff.__init__ (self, command)
         self.drum_style_table = None
         self.voice_command = "DrumVoice"
@@ -1925,11 +2328,18 @@ class DrumStaff (Staff):
             printer.dump ("}")
 
 class RhythmicStaff (Staff):
-    def __init__ (self, command = "RhythmicStaff"):
+    def __init__ (self, command="RhythmicStaff"):
         Staff.__init__ (self, command)
 
+#Test
+#def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
+#       printer.dump ("test")
+
 class Score:
     def __init__ (self):
+        """
+        Constructs a new Score object.
+        """
         self.contents = None
         self.create_midi = False
 
@@ -1940,28 +2350,67 @@ class Score:
         if self.contents:
           self.contents.set_part_information (part_id, staves_info)
 
+    def set_tempo (self, tempo):
+        """
+        Set the tempo attribute of the Score.
+        This attribute can be used in L{print_ly} for the midi output (see L{musicxml.Sound}).
+
+        @param tempo: The value of the tempo, in beats per minute.
+        @type tempo: String
+        """
+        self.tempo = tempo
+    #Test
+#    def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
+#       printer.dump ("test")
+
     def print_ly (self, printer):
-        self.create_midi = get_create_midi ()
-        printer.dump ("\\score {");
+        """
+        Print the content of the score to the printer, in lilypond format.
+
+        @param printer: A printer given to display correctly the output.
+        @type printer: L{Output_printer<musicexp.Output_printer>}
+        """
+        self.create_midi = get_create_midi()
+        printer.dump("\\score {")
+        printer.newline ()
+        #prints opening <<:
+        printer.dump ('<<')
         printer.newline ()
         if self.contents:
-            self.contents.print_ly (printer);
-        printer.dump ("\\layout {}");
+            self.contents.print_ly(printer)
+            #printer.dump ("test") prints test once before the >> of the score block, independent of the existence of a staffgroup.
+        #if StaffGroup == False: # True or False: nothing happens.
+        #    printer.dump ('>>')
+        printer.dump ('>>')
         printer.newline ()
-        if not self.create_midi:
-            printer.dump ("% To create MIDI output, uncomment the following line:");
-            printer.newline ();
-            printer.dump ("% ");
-        printer.dump ("\\midi {}");
+        #StaffGroup.print_staffgroup_closing_brackets(self, printer) #TypeError: unbound method print_staffgroup_closing_brackets() must be called with StaffGroup instance as first argument (got Score instance instead)
+        #print_staffgroup_closing_brackets(self, printer) #NameError: global name 'print_staffgroup_closing_brackets' is not defined. prints test once before the >> of the score block, independent of the existence of a staffgroup.
+        printer.dump ("\\layout {}")
         printer.newline ()
-        printer.dump ("}");
+        # If the --midi option was not passed to musicxml2ly, that comments the "midi" line
+        if self.create_midi:
+            printer.dump ("}")
+            printer.newline()
+            printer.dump("\\score {")
+            printer.newline ()
+            printer.dump("\\unfoldRepeats \\articulate {")
+            printer.newline ()
+            self.contents.print_ly(printer)
+            printer.dump("}")
+            printer.newline ()
+        else:
+            printer.dump ("% To create MIDI output, uncomment the following line:")
+            printer.newline ()
+            printer.dump ("% ")
+        printer.dump ("\\midi {\\tempo 4 = "+self.tempo+" }")
+        printer.newline ()
+        printer.dump ("}")
         printer.newline ()
-
 
 def test_pitch ():
     bflat = Pitch()
     bflat.alteration = -1
-    bflat.step =  6
+    bflat.step = 6
     bflat.octave = -1
     fifth = Pitch()
     fifth.step = 4
@@ -1971,7 +2420,7 @@ def test_pitch ():
 
 
     print bflat.semitones()
-    print bflat.transposed (fifth),  bflat.transposed (fifth).transposed (fifth)
+    print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
     print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
 
     print bflat.semitones(), 'down'
@@ -2043,8 +2492,8 @@ def test_expr ():
     tonic.step = 2
     tonic.alteration = -2
     n = KeySignatureChange()
-    n.tonic=tonic.copy()
-    n.scale = [0, 0, -2, 0, 0,-2,-2]
+    n.tonic = tonic.copy()
+    n.scale = [0, 0, -2, 0, 0, -2, -2]
 
     evc.insert_around (None, n, 0)
     m.insert_around (None, evc, 0)
@@ -2060,11 +2509,10 @@ if __name__ == '__main__':
     expr = test_expr()
     expr.set_start (Rational (0))
     print expr.ly_expression()
-    start = Rational (0,4)
-    stop = Rational (4,2)
+    start = Rational (0, 4)
+    stop = Rational (4, 2)
     def sub(x, start=start, stop=stop):
-        ok = x.start >= start and x.start +x.get_length() <= stop
+        ok = x.start >= start and x.start + x.get_length() <= stop
         return ok
 
     print expr.lisp_sub_expression(sub)
-
index a061b6ea6eee0ba2deec281554413a061e978242..f0b82f1333c7613bcd80f5c418c8f99afb96f35e 100644 (file)
@@ -6,45 +6,18 @@ import re
 import sys
 import copy
 import lilylib as ly
+import warnings
 
 _ = ly._
 
-
-def escape_ly_output_string (input_string):
-    return_string = input_string
-    needs_quotes = not re.match (u"^[a-zA-ZäöüÜÄÖßñ]*$", return_string);
-    if needs_quotes:
-        return_string = "\"" + string.replace (return_string, "\"", "\\\"") + "\""
-    return return_string
-
-
-def musicxml_duration_to_log (dur):
-    return  {'256th': 8,
-             '128th': 7,
-             '64th': 6,
-             '32nd': 5,
-             '16th': 4,
-             'eighth': 3,
-             'quarter': 2,
-             'half': 1,
-             'whole': 0,
-             'breve': -1,
-             'longa': -2,
-             'long': -2}.get (dur, 0)
-
-
-
-def interpret_alter_element (alter_elm):
-    alter = 0
-    if alter_elm:
-        val = eval(alter_elm.get_text ())
-        if type (val) in (int, float):
-            alter = val
-    return alter
+import musicexp
+import musicxml2ly_conversion
+import utilities
 
 
 class Xml_node:
-    def __init__ (self):
+
+    def __init__(self):
         self._children = []
         self._data = None
         self._original = None
@@ -52,235 +25,422 @@ class Xml_node:
         self._parent = None
         self._attribute_dict = {}
 
-    def get_parent (self):
+    def get_parent(self):
         return self._parent
 
-    def is_first (self):
-        return self._parent.get_typed_children (self.__class__)[0] == self
+    def is_first(self):
+        return self._parent.get_typed_children(self.__class__)[0] == self
 
-    def original (self):
+    def original(self):
         return self._original
-    def get_name (self):
+    def get_name(self):
         return self._name
 
-    def get_text (self):
+    def get_text(self):
         if self._data:
             return self._data
 
         if not self._children:
             return ''
 
-        return ''.join ([c.get_text () for c in self._children])
+        return ''.join([c.get_text() for c in self._children])
 
-    def message (self, msg):
-        ly.warning (msg)
+    def message(self, msg):
+        ly.warning(msg)
 
         p = self
         while p:
-            ly.progress ('  In: <%s %s>\n' % (p._name, ' '.join (['%s=%s' % item for item in p._attribute_dict.items ()])))
-            p = p.get_parent ()
+            ly.progress('  In: <%s %s>\n' %(p._name, ' '.join(['%s=%s' % item for item in p._attribute_dict.items()])))
+            p = p.get_parent()
 
-    def dump (self, indent = ''):
-        ly.debug_output ('%s<%s%s>' % (indent, self._name, ''.join ([' %s=%s' % item for item in self._attribute_dict.items ()])))
-        non_text_children = [c for c in self._children if not isinstance (c, Hash_text)]
+    def dump(self, indent=''):
+        ly.debug_output('%s<%s%s>' %(indent, self._name, ''.join([' %s=%s' % item for item in self._attribute_dict.items()])))
+        non_text_children = [c for c in self._children if not isinstance(c, Hash_text)]
         if non_text_children:
-            ly.debug_output ('\n')
+            ly.debug_output('\n')
         for c in self._children:
-            c.dump (indent + "    ")
+            c.dump(indent + "    ")
         if non_text_children:
-            ly.debug_output (indent)
-        ly.debug_output ('</%s>\n' % self._name)
+            ly.debug_output(indent)
+        ly.debug_output('</%s>\n' % self._name)
 
 
-    def get_typed_children (self, klass):
+    def get_typed_children(self, klass):
         if not klass:
             return []
         else:
             return [c for c in self._children if isinstance(c, klass)]
 
-    def get_named_children (self, nm):
-        return self.get_typed_children (get_class (nm))
+    def get_named_children(self, nm):
+        return self.get_typed_children(get_class(nm))
 
-    def get_named_child (self, nm):
-        return self.get_maybe_exist_named_child (nm)
+    def get_named_child(self, nm):
+        return self.get_maybe_exist_named_child(nm)
 
-    def get_children (self, predicate):
+    def get_children(self, predicate):
         return [c for c in self._children if predicate(c)]
 
-    def get_all_children (self):
+    def get_all_children(self):
         return self._children
 
-    def get_maybe_exist_named_child (self, name):
-        return self.get_maybe_exist_typed_child (get_class (name))
+    def get_maybe_exist_named_child(self, name):
+        return self.get_maybe_exist_typed_child(get_class(name))
 
-    def get_maybe_exist_typed_child (self, klass):
-        cn = self.get_typed_children (klass)
-        if len (cn)==0:
+    def get_maybe_exist_typed_child(self, klass):
+        cn = self.get_typed_children(klass)
+        if len(cn) == 0:
             return None
-        elif len (cn) == 1:
-            return cn[0]
         else:
-            raise "More than 1 child", klass
-
-    def get_unique_typed_child (self, klass):
+            try:
+                assert len(cn) == 1
+                return cn[0]
+            except:
+                msg = ' '.join(
+                    ['more than one child of class ',
+                     klass.__name__,
+                     '...all but the first will be ignored!'])
+                warnings.warn(msg)
+                return cn[0]
+
+    def get_unique_typed_child(self, klass):
         cn = self.get_typed_children(klass)
-        if len (cn) <> 1:
-            ly.error (self.__dict__)
-            raise 'Child is not unique for', (klass, 'found', cn)
+        if len(cn) <> 1:
+            ly.error(self.__dict__)
+            raise 'Child is not unique for',(klass, 'found', cn)
 
         return cn[0]
 
-    def get_named_child_value_number (self, name, default):
-        n = self.get_maybe_exist_named_child (name)
+    def get_named_child_value_number(self, name, default):
+        n = self.get_maybe_exist_named_child(name)
         if n:
-            return string.atoi (n.get_text())
+            return int(n.get_text())
         else:
             return default
 
 
-class Music_xml_node (Xml_node):
-    def __init__ (self):
-        Xml_node.__init__ (self)
-        self.duration = Rational (0)
-        self.start = Rational (0)
+class Music_xml_node(Xml_node):
+    def __init__(self):
+        Xml_node.__init__(self)
+        self.duration = Rational(0)
+        self.start = Rational(0)
+        self.converted = False
         self.voice_id = None;
 
-class Work (Xml_node):
-    def get_work_information (self, tag):
-        wt = self.get_maybe_exist_named_child (tag)
+
+class Music_xml_spanner(Music_xml_node):
+
+    def get_type(self):
+        if hasattr(self, 'type'):
+            return self.type
+        else:
+            return 0
+
+    def get_size(self):
+        if hasattr(self, 'size'):
+            return int(self.size)
+        else:
+            return 0
+
+
+class Measure_element(Music_xml_node):
+
+    def get_voice_id(self):
+        voice_id = self.get_maybe_exist_named_child('voice')
+        if voice_id:
+            return voice_id.get_text()
+        else:
+            return None
+
+    def is_first(self):
+        # Look at all measure elements(previously we had self.__class__, which
+        # only looked at objects of the same type!
+        cn = self._parent.get_typed_children(Measure_element)
+        # But only look at the correct voice; But include Attributes, too, which
+        # are not tied to any particular voice
+        cn = [c for c in cn if(c.get_voice_id() == self.get_voice_id()) or isinstance(c, Attributes)]
+        return cn[0] == self
+
+
+class Work(Xml_node):
+
+    def get_work_information(self, tag):
+        wt = self.get_maybe_exist_named_child(tag)
         if wt:
-            return wt.get_text ()
+            return wt.get_text()
         else:
             return ''
 
-    def get_work_title (self):
-        return self.get_work_information ('work-title')
-    def get_work_number (self):
-        return self.get_work_information ('work-number')
-    def get_opus (self):
-        return self.get_work_information ('opus')
+    def get_work_title(self):
+        return self.get_work_information('work-title')
 
-class Identification (Xml_node):
-    def get_rights (self):
-        rights = self.get_named_children ('rights')
+    def get_work_number(self):
+        return self.get_work_information('work-number')
+
+    # def get_opus(self):
+    #     return self.get_work_information('opus')
+
+
+class Identification(Xml_node):
+
+    def get_rights(self):
+        rights = self.get_named_children('rights')
         ret = []
         for r in rights:
-          ret.append (r.get_text ())
-        return string.join (ret, "\n")
+            text = r.get_text()
+            # if this Xml_node has an attribute, such as 'type="words"',
+            # include it in the header. Otherwise, it is assumed that
+            # the text contents of this node looks something like this:
+            # 'Copyright: X.Y.' and thus already contains the relevant
+            # information.
+            if hasattr(r, 'type'):
+                rights_type = r.type.title() # capitalize first letter
+                result = ''.join([rights_type, ': ', text])
+                ret.append(result)
+            else:
+                ret.append(text)
+        return string.join(ret, "\n")
 
-    # get contents of the source-element (usually used for publishing information). (These contents are saved in a custom variable named "source" in the header of the .ly file.)
-    def get_source (self):
-        source = self.get_named_children ('source')
+    # get contents of the source-element(usually used for publishing information).(These contents are saved in a custom variable named "source" in the header of the .ly file.)
+    def get_source(self):
+        source = self.get_named_children('source')
         ret = []
         for r in source:
-          ret.append (r.get_text ())
-        return string.join (ret, "\n")
+          ret.append(r.get_text())
+        return string.join(ret, "\n")
 
-    def get_creator (self, type):
-        creators = self.get_named_children ('creator')
+    def get_creator(self, type):
+        creators = self.get_named_children('creator')
         # return the first creator tag that has the particular type
         for i in creators:
-            if hasattr (i, 'type') and i.type == type:
-                return i.get_text ()
+            if hasattr(i, 'type') and i.type == type:
+                return i.get_text()
         return None
 
-    def get_composer (self):
-        c = self.get_creator ('composer')
+    def get_composer(self):
+        c = self.get_creator('composer')
         if c:
             return c
-        creators = self.get_named_children ('creator')
+        creators = self.get_named_children('creator')
         # return the first creator tag that has no type at all
         for i in creators:
-            if not hasattr (i, 'type'):
-                return i.get_text ()
+            if not hasattr(i, 'type'):
+                return i.get_text()
         return None
-    def get_arranger (self):
-        return self.get_creator ('arranger')
-    def get_editor (self):
-        return self.get_creator ('editor')
-    def get_poet (self):
-        v = self.get_creator ('lyricist')
+
+    def get_arranger(self):
+        return self.get_creator('arranger')
+
+    def get_editor(self):
+        return self.get_creator('editor')
+
+    def get_poet(self):
+        v = self.get_creator('lyricist')
         if v:
             return v
-        v = self.get_creator ('poet')
+        v = self.get_creator('poet')
         return v
 
-    def get_encoding_information (self, type):
-        enc = self.get_named_children ('encoding')
+    def get_encoding_information(self, type):
+        enc = self.get_named_children('encoding')
         if enc:
-            children = enc[0].get_named_children (type)
+            children = enc[0].get_named_children(type)
             if children:
-                return children[0].get_text ()
+                return children[0].get_text()
         else:
             return None
 
-    def get_encoding_software (self):
-        return self.get_encoding_information ('software')
-    def get_encoding_date (self):
-        return self.get_encoding_information ('encoding-date')
-    def get_encoding_person (self):
-        return self.get_encoding_information ('encoder')
-    def get_encoding_description (self):
-        return self.get_encoding_information ('encoding-description')
-
-    def get_encoding_software_list (self):
-        enc = self.get_named_children ('encoding')
+    def get_encoding_software(self):
+        return self.get_encoding_information('software')
+
+    def get_encoding_date(self):
+        return self.get_encoding_information('encoding-date')
+
+    def get_encoding_person(self):
+        return self.get_encoding_information('encoder')
+
+    def get_encoding_description(self):
+        return self.get_encoding_information('encoding-description')
+
+    def get_encoding_software_list(self):
+        enc = self.get_named_children('encoding')
         software = []
         for e in enc:
-            softwares = e.get_named_children ('software')
+            softwares = e.get_named_children('software')
             for s in softwares:
-                software.append (s.get_text ())
+                software.append(s.get_text())
         return software
 
-    def get_file_description (self):
-        misc = self.get_named_children ('miscellaneous')
+    def get_file_description(self):
+        misc = self.get_named_children('miscellaneous')
         for m in misc:
-            misc_fields = m.get_named_children ('miscellaneous-field')
+            misc_fields = m.get_named_children('miscellaneous-field')
             for mf in misc_fields:
-                if hasattr (mf, 'name') and mf.name == 'description':
-                    return mf.get_text ()
+                if hasattr(mf, 'name') and mf.name == 'description':
+                    return mf.get_text()
         return None
 
-class Duration (Music_xml_node):
-    def get_length (self):
-        dur = int (self.get_text ()) * Rational (1,4)
+
+class Credit(Xml_node):
+
+    def get_type(self):
+        type = self.get_maybe_exist_named_child('credit-type')
+        if(type != None):
+            return type.get_text()
+        else:
+            return None
+
+    def find_type(self, credits):
+        sizes = self.get_font_sizes(credits)
+        sizes.sort(reverse=True)
+        ys = self.get_default_ys(credits)
+        ys.sort(reverse=True)
+        xs = self.get_default_xs(credits)
+        xs.sort(reverse=True)
+
+        # Words child of the self credit-element
+        words = self.get_maybe_exist_named_child('credit-words')
+        size = None
+        x = None
+        y = None
+        halign = None
+        valign = None
+        justify = None
+        if(words != None):
+            if hasattr(words, 'font-size'):
+                size = utilities.string_to_integer(getattr(words, 'font-size'))
+            if hasattr(words, 'default-x'):
+                x = round(float(getattr(words, 'default-x')))
+            if hasattr(words, 'default-y'):
+                y = round(float(getattr(words, 'default-y')))
+            if hasattr(words, 'halign'):
+                halign = getattr(words, 'halign')
+            if hasattr(words, 'valign'):
+                valign = getattr(words, 'valign')
+            if hasattr(words, 'justify'):
+                justify = getattr(words, 'justify')
+        if(size and size == max(sizes) and y and y == max(ys) and(justify or halign) and(justify == 'center' or halign == 'center')):
+            return 'title'
+        elif((y and y > min(ys) and y < max(ys)) and((justify or halign) and(justify == 'center' or halign == 'center'))):
+            return 'subtitle'
+        elif((justify or halign) and(justify == 'left' or halign == 'left') and(not(x) or x == min(xs))):
+            return 'lyricist'
+        elif((justify or halign) and(justify == 'right' or halign == 'right') and(not(x) or x == max(xs))):
+            return 'composer'
+        elif(size and size == min(sizes) and y == min(ys)):
+            return 'rights'
+        # Special cases for Finale NotePad
+        elif((valign and(valign == 'top')) and(y and y == ys[1])):
+            return 'subtitle'
+        elif((valign and(valign == 'top')) and(x and x == min(xs))):
+            return 'lyricist'
+        elif((valign and(valign == 'top')) and(y and y == min(ys))):
+            return 'rights'
+        # Other special cases
+        elif((valign and(valign == 'bottom'))):
+            return 'rights'
+        elif(len([item for item in range(len(ys)) if ys[item] == y]) == 2):
+            # The first one is the composer, the second one is the lyricist
+            return 'composer'
+
+        return None # no type recognized
+
+    def get_font_sizes(self, credits):
+        sizes = []
+        for cred in credits:
+            words = cred.get_maybe_exist_named_child('credit-words')
+            if((words != None) and hasattr(words, 'font-size')):
+                sizes.append(getattr(words, 'font-size'))
+        return map(utilities.string_to_integer, sizes)
+
+    def get_default_xs(self, credits):
+        default_xs = []
+        for cred in credits:
+            words = cred.get_maybe_exist_named_child('credit-words')
+            if((words != None) and hasattr(words, 'default-x')):
+                default_xs.append(getattr(words, 'default-x'))
+        return map(round, map(float, default_xs))
+
+    def get_default_ys(self, credits):
+        default_ys = []
+        for cred in credits:
+            words = cred.get_maybe_exist_named_child('credit-words')
+            if((words != None) and hasattr(words, 'default-y')):
+                default_ys.append(getattr(words, 'default-y'))
+        return map(round, map(float, default_ys))
+
+    def get_text(self):
+        words = self.get_maybe_exist_named_child('credit-words')
+        if(words != None):
+            return words.get_text()
+        else:
+            return ''
+
+
+class Duration(Music_xml_node):
+
+    def get_length(self):
+        dur = int(self.get_text()) * Rational(1, 4)
         return dur
 
-class Hash_comment (Music_xml_node):
-    pass
-class Hash_text (Music_xml_node):
-    def dump (self, indent = ''):
-        ly.debug_output ('%s' % string.strip (self._data))
-
-class Pitch (Music_xml_node):
-    def get_step (self):
-        ch = self.get_unique_typed_child (get_class (u'step'))
-        step = ch.get_text ().strip ()
+
+class Hash_text(Music_xml_node):
+
+    def dump(self, indent=''):
+        ly.debug_output('%s' % string.strip(self._data))
+
+
+class Pitch(Music_xml_node):
+
+    def get_step(self):
+        ch = self.get_unique_typed_child(get_class(u'step'))
+        step = ch.get_text().strip()
         return step
-    def get_octave (self):
-        ch = self.get_unique_typed_child (get_class (u'octave'))
-        octave = ch.get_text ().strip ()
-        return int (octave)
-
-    def get_alteration (self):
-        ch = self.get_maybe_exist_typed_child (get_class (u'alter'))
-        return interpret_alter_element (ch)
-
-class Unpitched (Music_xml_node):
-    def get_step (self):
-        ch = self.get_unique_typed_child (get_class (u'display-step'))
-        step = ch.get_text ().strip ()
+
+    def get_octave(self):
+        ch = self.get_unique_typed_child(get_class(u'octave'))
+        octave = ch.get_text().strip()
+        return int(octave)
+
+    def get_alteration(self):
+        ch = self.get_maybe_exist_typed_child(get_class(u'alter'))
+        return utilities.interpret_alter_element(ch)
+
+    def to_lily_object(self):
+        p = musicexp.Pitch()
+        p.alteration = self.get_alteration()
+        p.step = musicxml2ly_conversion.musicxml_step_to_lily(self.get_step())
+        p.octave = self.get_octave() - 4
+        return p
+
+
+class Unpitched(Music_xml_node):
+
+    def get_step(self):
+        ch = self.get_unique_typed_child(get_class(u'display-step'))
+        step = ch.get_text().strip()
         return step
 
-    def get_octave (self):
-        ch = self.get_unique_typed_child (get_class (u'display-octave'))
+    def get_octave(self):
+        ch = self.get_unique_typed_child(get_class(u'display-octave'))
 
         if ch:
-            octave = ch.get_text ().strip ()
-            return int (octave)
+            octave = ch.get_text().strip()
+            return int(octave)
         else:
             return None
 
+    def to_lily_object(self):
+        p = None
+        step = self.get_step()
+        if step:
+            p = musicexp.Pitch()
+            p.step = musicxml2ly_conversion.musicxml_step_to_lily(step)
+        octave = self.get_octave()
+        if octave and p:
+            p.octave = octave - 4
+        return p
+
+
 class Measure_element (Music_xml_node):
     def get_voice_id (self):
         voice = self.get_maybe_exist_named_child ('voice')
@@ -289,345 +449,847 @@ class Measure_element (Music_xml_node):
         else:
             return self.voice_id;
 
-    def is_first (self):
-        # Look at all measure elements (previously we had self.__class__, which
-        # only looked at objects of the same type!
-        cn = self._parent.get_typed_children (Measure_element)
-        # But only look at the correct voice; But include Attributes, too, which
-        # are not tied to any particular voice
-        cn = [c for c in cn if (c.get_voice_id () == self.get_voice_id ()) or isinstance (c, Attributes)]
-        return cn[0] == self
 
-class Attributes (Measure_element):
-    def __init__ (self):
-        Measure_element.__init__ (self)
+class Attributes(Measure_element):
+
+    def __init__(self):
+        Measure_element.__init__(self)
         self._dict = {}
         self._original_tag = None
         self._time_signature_cache = None
 
-    def is_first (self):
-        cn = self._parent.get_typed_children (self.__class__)
+    def is_first(self):
+        cn = self._parent.get_typed_children(self.__class__)
         if self._original_tag:
             return cn[0] == self._original_tag
         else:
             return cn[0] == self
 
-    def set_attributes_from_previous (self, dict):
-        self._dict.update (dict)
+    def set_attributes_from_previous(self, dict):
+        self._dict.update(dict)
 
-    def read_self (self):
-        for c in self.get_all_children ():
+    def read_self(self):
+        for c in self.get_all_children():
             self._dict[c.get_name()] = c
 
-    def get_named_attribute (self, name):
-        return self._dict.get (name)
+    def get_named_attribute(self, name):
+        return self._dict.get(name)
 
-    def single_time_sig_to_fraction (self, sig):
-        if len (sig) < 2:
+    def single_time_sig_to_fraction(self, sig):
+        if len(sig) < 2:
             return 0
         n = 0
         for i in sig[0:-1]:
           n += i
-        return Rational (n, sig[-1])
+        return Rational(n, sig[-1])
 
-    def get_measure_length (self):
-        sig = self.get_time_signature ()
-        if not sig or len (sig) == 0:
+    def get_measure_length(self):
+        sig = self.get_time_signature()
+        if not sig or len(sig) == 0:
             return 1
-        if isinstance (sig[0], list):
+        if isinstance(sig[0], list):
             # Complex compound time signature
             l = 0
             for i in sig:
-                l += self.single_time_sig_to_fraction (i)
+                l += self.single_time_sig_to_fraction(i)
             return l
         else:
-           # Simple (maybe compound) time signature of the form (beat, ..., type)
-            return self.single_time_sig_to_fraction (sig)
+           # Simple(maybe compound) time signature of the form(beat, ..., type)
+            return self.single_time_sig_to_fraction(sig)
         return 0
 
-    def get_time_signature (self):
-        "Return time sig as a (beat, beat-type) tuple. For compound signatures,"
-        "return either (beat, beat,..., beat-type) or ((beat,..., type), "
+    def get_time_signature(self):
+        "Return time sig as a(beat, beat-type) tuple. For compound signatures,"
+        "return either(beat, beat,..., beat-type) or((beat,..., type), "
         "(beat,..., type), ...)."
         if self._time_signature_cache:
             return self._time_signature_cache
 
         try:
-            mxl = self.get_named_attribute ('time')
+            mxl = self.get_named_attribute('time')
             if not mxl:
                 return None
 
-            if mxl.get_maybe_exist_named_child ('senza-misura'):
+            if mxl.get_maybe_exist_named_child('senza-misura'):
                 # TODO: Handle pieces without a time signature!
-                ly.warning (_ ("Senza-misura time signatures are not yet supported!"))
-                return (4, 4)
+                ly.warning(_("Senza-misura time signatures are not yet supported!"))
+                return(4, 4)
             else:
                 signature = []
                 current_sig = []
-                for i in mxl.get_all_children ():
-                    if isinstance (i, Beats):
-                        beats = string.split (i.get_text ().strip (), "+")
-                        current_sig = [int (j) for j in beats]
-                    elif isinstance (i, BeatType):
-                        current_sig.append (int (i.get_text ()))
-                        signature.append (current_sig)
+                for i in mxl.get_all_children():
+                    if isinstance(i, Beats):
+                        beats = string.split(i.get_text().strip(), "+")
+                        current_sig = [int(j) for j in beats]
+                    elif isinstance(i, BeatType):
+                        current_sig.append(int(i.get_text()))
+                        signature.append(current_sig)
                         current_sig = []
-                if isinstance (signature[0], list) and len (signature) == 1:
+                if isinstance(signature[0], list) and len(signature) == 1:
                     signature = signature[0]
                 self._time_signature_cache = signature
                 return signature
-        except (KeyError, ValueError):
-            self.message (_ ("Unable to interpret time signature! Falling back to 4/4."))
-            return (4, 4)
+        except(KeyError, ValueError):
+            self.message(_("Unable to interpret time signature! Falling back to 4/4."))
+            return(4, 4)
 
-    # returns clef information in the form ("cleftype", position, octave-shift)
-    def get_clef_information (self):
+    # returns clef information in the form("cleftype", position, octave-shift)
+    def get_clef_information(self):
         clefinfo = ['G', 2, 0]
-        mxl = self.get_named_attribute ('clef')
+        mxl = self.get_named_attribute('clef')
         if not mxl:
             return clefinfo
-        sign = mxl.get_maybe_exist_named_child ('sign')
+        sign = mxl.get_maybe_exist_named_child('sign')
         if sign:
             clefinfo[0] = sign.get_text()
-        line = mxl.get_maybe_exist_named_child ('line')
+        line = mxl.get_maybe_exist_named_child('line')
         if line:
-            clefinfo[1] = string.atoi (line.get_text ())
-        octave = mxl.get_maybe_exist_named_child ('clef-octave-change')
+            clefinfo[1] = int(line.get_text())
+        octave = mxl.get_maybe_exist_named_child('clef-octave-change')
         if octave:
-            clefinfo[2] = string.atoi (octave.get_text ())
+            clefinfo[2] = int(octave.get_text())
         return clefinfo
 
-    def get_key_signature (self):
-        "return (fifths, mode) tuple if the key signatures is given as "
+    def get_key_signature(self):
+        "return(fifths, mode) tuple if the key signatures is given as "
         "major/minor in the Circle of fifths. Otherwise return an alterations"
         "list of the form [[step,alter<,octave>], [step,alter<,octave>], ...], "
         "where the octave values are optional."
 
-        key = self.get_named_attribute ('key')
+        key = self.get_named_attribute('key')
         if not key:
             return None
-        fifths_elm = key.get_maybe_exist_named_child ('fifths')
+        fifths_elm = key.get_maybe_exist_named_child('fifths')
         if fifths_elm:
-            mode_node = key.get_maybe_exist_named_child ('mode')
+            mode_node = key.get_maybe_exist_named_child('mode')
             mode = None
             if mode_node:
-                mode = mode_node.get_text ()
+                mode = mode_node.get_text()
             if not mode or mode == '':
                 mode = 'major'
-            fifths = int (fifths_elm.get_text ())
+            fifths = int(fifths_elm.get_text())
             # TODO: Shall we try to convert the key-octave and the cancel, too?
-            return (fifths, mode)
+            return(fifths, mode)
         else:
             alterations = []
             current_step = 0
-            for i in key.get_all_children ():
-                if isinstance (i, KeyStep):
-                    current_step = i.get_text ().strip ()
-                elif isinstance (i, KeyAlter):
-                    alterations.append ([current_step, interpret_alter_element (i)])
-                elif isinstance (i, KeyOctave):
+            for i in key.get_all_children():
+                if isinstance(i, KeyStep):
+                    current_step = i.get_text().strip()
+                elif isinstance(i, KeyAlter):
+                    alterations.append([current_step, utilities.interpret_alter_element(i)])
+                elif isinstance(i, KeyOctave):
                     nr = -1
-                    if hasattr (i, 'number'):
-                        nr = int (i.number)
-                    if (nr > 0) and (nr <= len (alterations)):
+                    if hasattr(i, 'number'):
+                        nr = int(i.number)
+                    if(nr > 0) and(nr <= len(alterations)):
                         # MusicXML Octave 4 is middle C -> shift to 0
-                        alterations[nr-1].append (int (i.get_text ())-4)
+                        alterations[nr - 1].append(int(i.get_text()) - 4)
                     else:
-                        i.message (_ ("Key alteration octave given for a "
-                            "non-existing alteration nr. %s, available numbers: %s!") % (nr, len(alterations)))
+                        i.message(_("Key alteration octave given for a "
+                            "non-existing alteration nr. %s, available numbers: %s!") %(nr, len(alterations)))
             return alterations
 
-    def get_transposition (self):
-        return self.get_named_attribute ('transpose')
+    def get_transposition(self):
+        return self.get_named_attribute('transpose')
+
+
+class Barline(Measure_element):
+
+    def to_lily_object(self):
+        # retval contains all possible markers in the order:
+        # 0..bw_ending, 1..bw_repeat, 2..barline, 3..fw_repeat, 4..fw_ending
+        retval = {}
+        bartype_element = self.get_maybe_exist_named_child("bar-style")
+        repeat_element = self.get_maybe_exist_named_child("repeat")
+        ending_element = self.get_maybe_exist_named_child("ending")
+
+        bartype = None
+        if bartype_element:
+            bartype = bartype_element.get_text()
+
+        if repeat_element and hasattr(repeat_element, 'direction'):
+            repeat = musicxml2ly_conversion.RepeatMarker()
+            repeat.direction = {"forward":-1, "backward": 1}.get(
+                repeat_element.direction, 0)
+
+            if((repeat_element.direction == "forward" and bartype == "heavy-light") or
+                (repeat_element.direction == "backward" and bartype == "light-heavy")):
+                bartype = None
+            if hasattr(repeat_element, 'times'):
+                try:
+                    repeat.times = int(repeat_element.times)
+                except ValueError:
+                    repeat.times = 2
+            repeat.event = self
+            if repeat.direction == -1:
+                retval[3] = repeat
+            else:
+                retval[1] = repeat
+
+        if ending_element and hasattr(ending_element, 'type'):
+            ending = musicxml2ly_conversion.EndingMarker()
+            ending.direction = {"start":-1, "stop": 1, "discontinue": 1}.get(
+                ending_element.type, 0)
+            ending.event = self
+            if ending.direction == -1:
+                retval[4] = ending
+            else:
+                retval[0] = ending
+          # TODO. ending number=""
 
-class KeyAlter (Music_xml_node):
-    pass
-class KeyStep (Music_xml_node):
-    pass
-class KeyOctave (Music_xml_node):
-    pass
+        if bartype:
+            b = musicexp.BarLine()
+            b.type = bartype
+            retval[2] = b
 
+        return retval.values()
 
-class Barline (Measure_element):
-    pass
-class BarStyle (Music_xml_node):
-    pass
-class Partial (Measure_element):
-    def __init__ (self, partial):
-        Measure_element.__init__ (self)
+
+class Partial(Measure_element):
+    def __init__(self, partial):
+        Measure_element.__init__(self)
         self.partial = partial
 
-class Note (Measure_element):
-    def __init__ (self):
-        Measure_element.__init__ (self)
+
+class Stem(Music_xml_node):
+
+    stem_value_dict = {
+        'down': 'stemDown',
+        'up': 'stemUp',
+        'double': None, # TODO: Implement
+        'none': 'stemNeutral'
+    }
+
+    def to_stem_event(self):
+        values = []
+        value = self.stem_value_dict.get(self.get_text(), None)
+        stem_value = musicexp.StemEvent()
+        if value:
+            stem_value.value = value
+            values.append(stem_value)
+        return values
+
+    def to_stem_style_event(self):
+        styles = []
+        style_elm = musicexp.StemstyleEvent()
+        if hasattr(self, 'color'):
+            style_elm.color = utilities.hex_to_color(getattr(self, 'color'))
+        if(style_elm.color != None):
+            styles.append(style_elm)
+        return styles
+
+
+class Notehead(Music_xml_node):
+
+    notehead_styles_dict = {
+        'slash': '\'slash',
+        'triangle': '\'triangle',
+        'diamond': '\'diamond',
+        'square': '\'la', # TODO: Proper squared note head
+        'cross': None, # TODO: + shaped note head
+        'x': '\'cross',
+        'circle-x': '\'xcircle',
+        'inverted triangle': None, # TODO: Implement
+        'arrow down': None, # TODO: Implement
+        'arrow up': None, # TODO: Implement
+        'slashed': None, # TODO: Implement
+        'back slashed': None, # TODO: Implement
+        'normal': None,
+        'cluster': None, # TODO: Implement
+        'none': '#f',
+        'do': '\'do',
+        're': '\'re',
+        'mi': '\'mi',
+        'fa': '\'fa',
+        'so': None,
+        'la': '\'la',
+        'ti': '\'ti',
+        }
+
+    def to_lily_object(self): #function changed: additionally processcolor attribute
+        styles = []
+
+        # Notehead style
+        key = self.get_text().strip()
+        style = self.notehead_styles_dict.get(key, None)
+        event = musicexp.NotestyleEvent()
+        if style:
+            event.style = style
+        if hasattr(self, 'filled'):
+            event.filled =(getattr(self, 'filled') == "yes")
+        if hasattr(self, 'color'):
+            event.color = utilities.hex_to_color(getattr(self, 'color'))
+        if event.style or(event.filled != None) or(event.color != None):
+            styles.append(event)
+        # parentheses
+        if hasattr(self, 'parentheses') and(self.parentheses == "yes"):
+            styles.append(musicexp.ParenthesizeEvent())
+
+        return styles
+
+
+class Note(Measure_element):
+
+    drumtype_dict = {
+        'Acoustic Snare Drum': 'acousticsnare',
+        'Side Stick': 'sidestick',
+        'Open Triangle': 'opentriangle',
+        'Mute Triangle': 'mutetriangle',
+        'Tambourine': 'tambourine',
+        'Bass Drum': 'bassdrum',
+    }
+
+    def __init__(self):
+        Measure_element.__init__(self)
         self.instrument_name = ''
         self._after_grace = False
-    def is_grace (self):
-        return self.get_maybe_exist_named_child (u'grace')
-    def is_after_grace (self):
+        self._duration = 1
+
+    def is_grace(self):
+        return self.get_maybe_exist_named_child(u'grace')
+
+    def is_after_grace(self):
         if not self.is_grace():
             return False;
-        gr = self.get_maybe_exist_typed_child (Grace)
-        return self._after_grace or hasattr (gr, 'steal-time-previous');
+        gr = self.get_maybe_exist_typed_child(Grace)
+        return self._after_grace or hasattr(gr, 'steal-time-previous');
 
-    def get_duration_log (self):
-        ch = self.get_maybe_exist_named_child (u'type')
+    def get_duration_log(self):
+        ch = self.get_maybe_exist_named_child(u'type')
 
         if ch:
-            log = ch.get_text ().strip()
-            return musicxml_duration_to_log (log)
-        elif self.get_maybe_exist_named_child (u'grace'):
+            log = ch.get_text().strip()
+            return utilities.musicxml_duration_to_log(log)
+        elif self.get_maybe_exist_named_child(u'grace'):
             # FIXME: is it ok to default to eight note for grace notes?
             return 3
         else:
             return None
 
-    def get_duration_info (self):
-        log = self.get_duration_log ()
+    def get_duration_info(self):
+        log = self.get_duration_log()
         if log != None:
-            dots = len (self.get_typed_children (Dot))
-            return (log, dots)
+            dots = len(self.get_typed_children(Dot))
+            return(log, dots)
         else:
             return None
 
-    def get_factor (self):
+    def get_factor(self):
         return 1
 
-    def get_pitches (self):
-        return self.get_typed_children (get_class (u'pitch'))
+    def get_pitches(self):
+        return self.get_typed_children(get_class(u'pitch'))
+
+    def set_notehead_style(self, event):
+        noteheads = self.get_named_children('notehead')
+        for nh in noteheads:
+            styles = nh.to_lily_object()
+            for style in styles:
+                event.add_associated_event(style)
+
+    def set_stem_directions(self, event):
+        stems = self.get_named_children('stem')
+        for stem in stems:
+            values = stem.to_stem_event()
+            for v in values:
+                event.add_associated_event(v)
+
+    def set_stem_style(self, event):
+        stems = self.get_named_children('stem')
+        for stem in stems:
+            styles = stem.to_stem_style_event()
+            for style in styles:
+                event.add_associated_event(style)
+
+    def initialize_duration(self):
+        from musicxml2ly_conversion import rational_to_lily_duration
+        from musicexp import Duration
+        # if the note has no Type child, then that method returns None. In that case,
+        # use the <duration> tag instead. If that doesn't exist, either -> Error
+        dur = self.get_duration_info()
+        if dur:
+            d = Duration()
+            d.duration_log = dur[0]
+            d.dots = dur[1]
+            # Grace notes by specification have duration 0, so no time modification
+            # factor is possible. It even messes up the output with *0/1
+            if not self.get_maybe_exist_typed_child(Grace):
+                d.factor = self._duration / d.get_length()
+            return d
+        else:
+            if self._duration > 0:
+                return rational_to_lily_duration(self._duration)
+            else:
+                self.message(
+                    _("Encountered note at %s without type and duration(=%s)") \
+                    %(mxl_note.start, mxl_note._duration))
+                return None
+
+    def initialize_pitched_event(self):
+        mxl_pitch = self.get_maybe_exist_typed_child(Pitch)
+        pitch = mxl_pitch.to_lily_object()
+        event = musicexp.NoteEvent()
+        event.pitch = pitch
+        acc = self.get_maybe_exist_named_child('accidental')
+        if acc:
+            # let's not force accs everywhere.
+            event.cautionary = acc.cautionary
+            # TODO: Handle editorial accidentals
+            # TODO: Handle the level-display setting for displaying brackets/parentheses
+        return event
+
+    def initialize_unpitched_event(self):
+        # Unpitched elements have display-step and can also have
+        # display-octave.
+        unpitched = self.get_maybe_exist_typed_child(Unpitched)
+        event = musicexp.NoteEvent()
+        event.pitch = unpitched.to_lily_object()
+        return event
+
+    def initialize_rest_event(self, convert_rest_positions=True):
+        # rests can have display-octave and display-step, which are
+        # treated like an ordinary note pitch
+        rest = self.get_maybe_exist_typed_child(Rest)
+        event = musicexp.RestEvent()
+        if convert_rest_positions:
+            pitch = rest.to_lily_object()
+            event.pitch = pitch
+        return event
+
+    def initialize_drum_event(self):
+        event = musicexp.NoteEvent()
+        drum_type = self.drumtype_dict.get(self.instrument_name)
+        if drum_type:
+            event.drum_type = drum_type
+        else:
+            self.message(
+                _("drum %s type unknown, please add to instrument_drumtype_dict")
+                % n.instrument_name)
+            event.drum_type = 'acousticsnare'
+        return event
+
+    def to_lily_object(self,
+                       convert_stem_directions=True,
+                       convert_rest_positions=True):
+        pitch = None
+        duration = None
+        event = None
+
+        if self.get_maybe_exist_typed_child(Pitch):
+            event = self.initialize_pitched_event()
+        elif self.get_maybe_exist_typed_child(Unpitched):
+            event = self.initialize_unpitched_event()
+        elif self.get_maybe_exist_typed_child(Rest):
+            event = self.initialize_rest_event(convert_rest_positions)
+        elif self.instrument_name:
+            event = self.initialize_drum_event()
+        else:
+            self.message(_("cannot find suitable event"))
+
+        if event:
+            event.duration = self.initialize_duration()
+
+        self.set_notehead_style(event)
+        self.set_stem_style(event)
+        if convert_stem_directions:
+            self.set_stem_directions(event)
 
-class Part_list (Music_xml_node):
-    def __init__ (self):
-        Music_xml_node.__init__ (self)
+        return event
+
+
+class Part_list(Music_xml_node):
+
+    def __init__(self):
+        Music_xml_node.__init__(self)
         self._id_instrument_name_dict = {}
 
-    def generate_id_instrument_dict (self):
+    def generate_id_instrument_dict(self):
 
         ## not empty to make sure this happens only once.
         mapping = {1: 1}
-        for score_part in self.get_named_children ('score-part'):
-            for instr in score_part.get_named_children ('score-instrument'):
+        for score_part in self.get_named_children('score-part'):
+            for instr in score_part.get_named_children('score-instrument'):
                 id = instr.id
-                name = instr.get_named_child ("instrument-name")
-                mapping[id] = name.get_text ()
+                name = instr.get_named_child("instrument-name")
+                mapping[id] = name.get_text()
 
         self._id_instrument_name_dict = mapping
 
-    def get_instrument (self, id):
+    def get_instrument(self, id):
         if not self._id_instrument_name_dict:
             self.generate_id_instrument_dict()
 
-        instrument_name = self._id_instrument_name_dict.get (id)
+        instrument_name = self._id_instrument_name_dict.get(id)
         if instrument_name:
             return instrument_name
         else:
-            ly.warning (_ ("Unable to find instrument for ID=%s\n") % id)
+            ly.warning(_("Unable to find instrument for ID=%s\n") % id)
             return "Grand Piano"
 
-class Part_group (Music_xml_node):
-    pass
-class Score_part (Music_xml_node):
-    pass
 
-class Measure (Music_xml_node):
-    def __init__ (self):
-        Music_xml_node.__init__ (self)
+class Measure(Music_xml_node):
+
+    def __init__(self):
+        Music_xml_node.__init__(self)
         self.partial = 0
-    def is_implicit (self):
-        return hasattr (self, 'implicit') and self.implicit == 'yes'
-    def get_notes (self):
-        return self.get_typed_children (get_class (u'note'))
 
-class Syllabic (Music_xml_node):
-    def continued (self):
+    def is_implicit(self):
+        return hasattr(self, 'implicit') and self.implicit == 'yes'
+
+    def get_notes(self):
+        return self.get_typed_children(get_class(u'note'))
+
+
+class Syllabic(Music_xml_node):
+
+    def continued(self):
         text = self.get_text()
-        return (text == "begin") or (text == "middle")
-class Elision (Music_xml_node):
-    pass
-class Extend (Music_xml_node):
-    pass
-class Text (Music_xml_node):
-    pass
+        return(text == "begin") or(text == "middle")
+
+    def begin(self):
+        return(text == "begin")
+
+    def middle(self):
+        return(text == "middle")
 
-class Lyric (Music_xml_node):
-    def get_number (self):
-        if hasattr (self, 'number'):
+    def end(self):
+        return(text == "end")
+
+
+class Lyric(Music_xml_node):
+
+    def number(self):
+        """
+        Return the number attribute(if it exists) of the lyric element.
+
+        @rtype: number
+        @return: The value of the number attribute
+        """
+        if hasattr(self, 'number'):
             return self.number
         else:
             return -1
 
+
+class Sound(Music_xml_node):
+
+    def get_tempo(self):
+        """
+        Return the tempo attribute(if it exists) of the sound element.
+        This attribute can be used by musicxml2ly for the midi output(see L{musicexp.Score}).
+
+        @rtype: string
+        @return: The value of the tempo attribute
+        """
+        if hasattr(self, 'tempo'):
+            return self.tempo
+        else:
+            return None
+
+
+class Notations(Music_xml_node):
+
+    def get_tie(self):
+        ts = self.get_named_children('tied')
+        starts = [t for t in ts if t.type == 'start']
+        if starts:
+            return starts[0]
+        else:
+            return None
+
+    def get_tuplets(self):
+        return self.get_typed_children(Tuplet)
+
+
+class Time_modification(Music_xml_node):
+
+    def get_fraction(self):
+        b = self.get_maybe_exist_named_child('actual-notes')
+        a = self.get_maybe_exist_named_child('normal-notes')
+        return(int(a.get_text()), int(b.get_text()))
+
+    def get_normal_type(self):
+        tuplet_type = self.get_maybe_exist_named_child('normal-type')
+        if tuplet_type:
+            dots = self.get_named_children('normal-dot')
+            log = utilities.musicxml_duration_to_log(tuplet_type.get_text().strip())
+            return(log , len(dots))
+        else:
+            return None
+
+
+class Accidental(Music_xml_node):
+
+    def __init__(self):
+        Music_xml_node.__init__(self)
+        self.editorial = False
+        self.cautionary = False
+
+
+class Tuplet(Music_xml_spanner):
+
+    def duration_info_from_tuplet_note(self, tuplet_note):
+        tuplet_type = tuplet_note.get_maybe_exist_named_child('tuplet-type')
+        if tuplet_type:
+            dots = tuplet_note.get_named_children('tuplet-dot')
+            log = utilities.musicxml_duration_to_log(tuplet_type.get_text().strip())
+            return(log, len(dots))
+        else:
+            return None
+
+    # Return tuplet note type as(log, dots)
+    def get_normal_type(self):
+        tuplet = self.get_maybe_exist_named_child('tuplet-normal')
+        if tuplet:
+            return self.duration_info_from_tuplet_note(tuplet)
+        else:
+            return None
+
+    def get_actual_type(self):
+        tuplet = self.get_maybe_exist_named_child('tuplet-actual')
+        if tuplet:
+            return self.duration_info_from_tuplet_note(tuplet)
+        else:
+            return None
+
+    def get_tuplet_note_count(self, tuplet_note):
+        if tuplet_note:
+            tuplet_nr = tuplet_note.get_maybe_exist_named_child('tuplet-number')
+            if tuplet_nr:
+                return int(tuplet_nr.get_text())
+        return None
+
+    def get_normal_nr(self):
+        return self.get_tuplet_note_count(self.get_maybe_exist_named_child('tuplet-normal'))
+
+    def get_actual_nr(self):
+        return self.get_tuplet_note_count(self.get_maybe_exist_named_child('tuplet-actual'))
+
+
+class Slur(Music_xml_spanner):
+
+    def get_type(self):
+        return self.type
+
+
+class Tied(Music_xml_spanner):
+
+    def get_type(self):
+        return self.type
+
+
+class Beam(Music_xml_spanner):
+    def get_type(self):
+        return self.get_text()
+    def is_primary(self):
+        if hasattr(self, 'number'):
+            return self.number == "1"
+        else:
+            return True
+
+class Octave_shift(Music_xml_spanner):
+    # default is 8 for the octave-shift!
+    def get_size(self):
+        if hasattr(self, 'size'):
+            return int(self.size)
+        else:
+            return 8
+
+
+# Rests in MusicXML are <note> blocks with a <rest> inside. This class is only
+# for the inner <rest> element, not the whole rest block.
+class Rest(Music_xml_node):
+
+    def __init__(self):
+        Music_xml_node.__init__(self)
+        self._is_whole_measure = False
+
+    def is_whole_measure(self):
+        return self._is_whole_measure
+
+    def get_step(self):
+        ch = self.get_maybe_exist_typed_child(get_class(u'display-step'))
+        if ch:
+            return ch.get_text().strip()
+        else:
+            return None
+
+    def get_octave(self):
+        ch = self.get_maybe_exist_typed_child(get_class(u'display-octave'))
+        if ch:
+            oct = ch.get_text().strip()
+            return int(oct)
+        else:
+            return None
+
+    def to_lily_object(self):
+        p = None
+        step = self.get_step()
+        if step:
+            p = musicexp.Pitch()
+            p.step = musicxml2ly_conversion.musicxml_step_to_lily(step)
+        octave = self.get_octave()
+        if octave and p:
+            p.octave = octave - 4
+        return p
+
+
+class Bend(Music_xml_node):
+
+    def bend_alter(self):
+        alter = self.get_maybe_exist_named_child('bend-alter')
+        return utilities.interpret_alter_element(alter)
+
+
+class ChordPitch(Music_xml_node):
+
+    def step_class_name(self):
+        return u'root-step'
+
+    def alter_class_name(self):
+        return u'root-alter'
+
+    def get_step(self):
+        ch = self.get_unique_typed_child(get_class(self.step_class_name()))
+        return ch.get_text().strip()
+
+    def get_alteration(self):
+        ch = self.get_maybe_exist_typed_child(get_class(self.alter_class_name()))
+        return utilities.interpret_alter_element(ch)
+
+
+class Bass(ChordPitch):
+
+    def step_class_name(self):
+        return u'bass-step'
+
+    def alter_class_name(self):
+        return u'bass-alter'
+
+
+class ChordModification(Music_xml_node):
+
+    def get_type(self):
+        ch = self.get_maybe_exist_typed_child(get_class(u'degree-type'))
+        return {'add': 1, 'alter': 1, 'subtract':-1}.get(ch.get_text().strip(), 0)
+
+    def get_value(self):
+        ch = self.get_maybe_exist_typed_child(get_class(u'degree-value'))
+        value = 0
+        if ch:
+            value = int(ch.get_text().strip())
+        return value
+
+    def get_alter(self):
+        ch = self.get_maybe_exist_typed_child(get_class(u'degree-alter'))
+        return utilities.interpret_alter_element(ch)
+
+
+class Frame(Music_xml_node):
+
+    def get_frets(self):
+        return self.get_named_child_value_number('frame-frets', 4)
+
+    def get_strings(self):
+        return self.get_named_child_value_number('frame-strings', 6)
+
+    def get_first_fret(self):
+        return self.get_named_child_value_number('first-fret', 1)
+
+
+class Frame_Note(Music_xml_node):
+
+    def get_string(self):
+        return self.get_named_child_value_number('string', 1)
+
+    def get_fret(self):
+        return self.get_named_child_value_number('fret', 0)
+
+    def get_fingering(self):
+        return self.get_named_child_value_number('fingering', -1)
+
+    def get_barre(self):
+        n = self.get_maybe_exist_named_child('barre')
+        if n:
+            return getattr(n, 'type', '')
+        else:
+            return ''
+
+
 class Musicxml_voice:
-    def __init__ (self):
+
+    def __init__(self):
         self._elements = []
         self._staves = {}
         self._start_staff = None
         self._lyrics = []
         self._has_lyrics = False
 
-    def add_element (self, e):
-        self._elements.append (e)
-        if (isinstance (e, Note)
-            and e.get_maybe_exist_typed_child (Staff)):
-            name = e.get_maybe_exist_typed_child (Staff).get_text ()
+    def add_element(self, e):
+        self._elements.append(e)
+        if(isinstance(e, Note)
+            and e.get_maybe_exist_typed_child(Staff)):
+            name = e.get_maybe_exist_typed_child(Staff).get_text()
 
-            if not self._start_staff and not e.get_maybe_exist_typed_child (Grace):
+            if not self._start_staff and not e.get_maybe_exist_typed_child(Grace):
                 self._start_staff = name
             self._staves[name] = True
 
-        lyrics = e.get_typed_children (Lyric)
+        lyrics = e.get_typed_children(Lyric)
         if not self._has_lyrics:
-          self.has_lyrics = len (lyrics) > 0
+          self.has_lyrics = len(lyrics) > 0
 
         for l in lyrics:
-            nr = l.get_number()
-            if (nr > 0) and not (nr in self._lyrics):
-                self._lyrics.append (nr)
+            nr = l.number
+            if(nr > 0) and not(nr in self._lyrics):
+                self._lyrics.append(nr)
 
-    def insert (self, idx, e):
-        self._elements.insert (idx, e)
+    def insert(self, idx, e):
+        self._elements.insert(idx, e)
 
-    def get_lyrics_numbers (self):
-        if (len (self._lyrics) == 0) and self._has_lyrics:
+    def get_lyrics_numbers(self):
+        if(len(self._lyrics) == 0) and self._has_lyrics:
             #only happens if none of the <lyric> tags has a number attribute
             return [1]
         else:
             return self._lyrics
 
 
-def graces_to_aftergraces (pending_graces):
-    for gr in pending_graces:
-        gr._when = gr._prev_when
-        gr._measure_position = gr._prev_measure_position
-        gr._after_grace = True
-
+class Part(Music_xml_node):
 
-class Part (Music_xml_node):
-    def __init__ (self):
-        Music_xml_node.__init__ (self)
+    def __init__(self):
+        Music_xml_node.__init__(self)
         self._voices = {}
         self._staff_attributes_dict = {}
 
-    def get_part_list (self):
+    def get_part_list(self):
         n = self
         while n and n.get_name() != 'score-partwise':
             n = n._parent
 
-        return n.get_named_child ('part-list')
+        return n.get_named_child('part-list')
 
-    def interpret (self):
+    def graces_to_aftergraces(self, pending_graces):
+        for gr in pending_graces:
+            gr._when = gr._prev_when
+            gr._measure_position = gr._prev_measure_position
+            gr._after_grace = True
+
+    def interpret(self):
         """Set durations and starting points."""
         """The starting point of the very first note is 0!"""
 
-        part_list = self.get_part_list ()
+        part_list = self.get_part_list()
 
-        now = Rational (0)
-        factor = Rational (1)
+        now = Rational(0)
+        factor = Rational(1)
         attributes_dict = {}
         attributes_object = None
-        measures = self.get_typed_children (Measure)
-        last_moment = Rational (-1)
-        last_measure_position = Rational (-1)
-        measure_position = Rational (0)
+        measures = self.get_typed_children(Measure)
+        last_moment = Rational(-1)
+        last_measure_position = Rational(-1)
+        measure_position = Rational(0)
         measure_start_moment = now
         is_first_measure = True
         previous_measure = None
@@ -638,14 +1300,14 @@ class Part (Music_xml_node):
             # implicit measures are used for artificial measures, e.g. when
             # a repeat bar line splits a bar into two halves. In this case,
             # don't reset the measure position to 0. They are also used for
-            # upbeats (initial value of 0 fits these, too).
+            # upbeats(initial value of 0 fits these, too).
             # Also, don't reset the measure position at the end of the loop,
-            # but rather when starting the next measure (since only then do we
+            # but rather when starting the next measure(since only then do we
             # know if the next measure is implicit and continues that measure)
-            if not m.is_implicit ():
+            if not m.is_implicit():
                 # Warn about possibly overfull measures and reset the position
                 if attributes_object and previous_measure and previous_measure.partial == 0:
-                    length = attributes_object.get_measure_length ()
+                    length = attributes_object.get_measure_length()
                     new_now = measure_start_moment + length
                     if now <> new_now:
                         problem = 'incomplete'
@@ -653,10 +1315,10 @@ class Part (Music_xml_node):
                             problem = 'overfull'
                         ## only for verbose operation.
                         if problem <> 'incomplete' and previous_measure:
-                            previous_measure.message ('%s measure? Expected: %s, Difference: %s' % (problem, now, new_now - now))
+                            previous_measure.message('%s measure? Expected: %s, Difference: %s' %(problem, now, new_now - now))
                     now = new_now
                 measure_start_moment = now
-                measure_position = Rational (0)
+                measure_position = Rational(0)
 
             voice_id = None;
             assign_to_next_voice = []
@@ -679,47 +1341,47 @@ class Part (Music_xml_node):
 
                 # figured bass has a duration, but applies to the next note
                 # and should not change the current measure position!
-                if isinstance (n, FiguredBass):
-                    n._divisions = factor.denominator ()
+                if isinstance(n, FiguredBass):
+                    n._divisions = factor.denominator()
                     n._when = now
                     n._measure_position = measure_position
                     continue
 
-                if isinstance (n, Hash_text):
+                if isinstance(n, Hash_text):
                     continue
-                dur = Rational (0)
+                dur = Rational(0)
 
                 if n.__class__ == Attributes:
-                    n.set_attributes_from_previous (attributes_dict)
-                    n.read_self ()
-                    attributes_dict = n._dict.copy ()
+                    n.set_attributes_from_previous(attributes_dict)
+                    n.read_self()
+                    attributes_dict = n._dict.copy()
                     attributes_object = n
 
-                    factor = Rational (1,
-                                       int (attributes_dict.get ('divisions').get_text ()))
+                    factor = Rational(1,
+                                       int(attributes_dict.get('divisions').get_text()))
 
 
-                if (n.get_maybe_exist_typed_child (Duration)):
-                    mxl_dur = n.get_maybe_exist_typed_child (Duration)
-                    dur = mxl_dur.get_length () * factor
+                if(n.get_maybe_exist_typed_child(Duration)):
+                    mxl_dur = n.get_maybe_exist_typed_child(Duration)
+                    dur = mxl_dur.get_length() * factor
 
                     if n.get_name() == 'backup':
-                        dur = - dur
+                        dur = -dur
                         # reset all graces before the backup to after-graces:
-                        graces_to_aftergraces (pending_graces)
+                        self.graces_to_aftergraces(pending_graces)
                         pending_graces = []
-                    if n.get_maybe_exist_typed_child (Grace):
-                        dur = Rational (0)
+                    if n.get_maybe_exist_typed_child(Grace):
+                        dur = Rational(0)
 
-                    rest = n.get_maybe_exist_typed_child (Rest)
-                    if (rest
+                    rest = n.get_maybe_exist_typed_child(Rest)
+                    if(rest
                         and attributes_object
-                        and attributes_object.get_measure_length () == dur):
+                        and attributes_object.get_measure_length() == dur):
 
                         rest._is_whole_measure = True
 
-                if (dur > Rational (0)
-                    and n.get_maybe_exist_typed_child (Chord)):
+                if(dur > Rational(0)
+                    and n.get_maybe_exist_typed_child(Chord)):
                     now = last_moment
                     measure_position = last_measure_position
 
@@ -728,27 +1390,27 @@ class Part (Music_xml_node):
 
                 # For all grace notes, store the previous note,  in case need
                 # to turn the grace note into an after-grace later on!
-                if isinstance(n, Note) and n.is_grace ():
+                if isinstance(n, Note) and n.is_grace():
                     n._prev_when = last_moment
                     n._prev_measure_position = last_measure_position
                 # After-graces are placed at the same position as the previous note
-                if isinstance(n, Note) and  n.is_after_grace ():
+                if isinstance(n, Note) and  n.is_after_grace():
                     # TODO: We should do the same for grace notes at the end of
                     # a measure with no following note!!!
                     n._when = last_moment
                     n._measure_position = last_measure_position
-                elif isinstance(n, Note) and n.is_grace ():
-                    pending_graces.append (n)
-                elif (dur > Rational (0)):
+                elif isinstance(n, Note) and n.is_grace():
+                    pending_graces.append(n)
+                elif(dur > Rational(0)):
                     pending_graces = [];
 
                 n._duration = dur
-                if dur > Rational (0):
+                if dur > Rational(0):
                     last_moment = now
                     last_measure_position = measure_position
                     now += dur
                     measure_position += dur
-                elif dur < Rational (0):
+                elif dur < Rational(0):
                     # backup element, reset measure position
                     now += dur
                     measure_position += dur
@@ -759,425 +1421,297 @@ class Part (Music_xml_node):
                     last_moment = now
                     last_measure_position = measure_position
                 if n._name == 'note':
-                    instrument = n.get_maybe_exist_named_child ('instrument')
+                    instrument = n.get_maybe_exist_named_child('instrument')
                     if instrument:
-                        n.instrument_name = part_list.get_instrument (instrument.id)
+                        n.instrument_name = part_list.get_instrument(instrument.id)
 
             # reset all graces at the end of the measure to after-graces:
-            graces_to_aftergraces (pending_graces)
+            self.graces_to_aftergraces(pending_graces)
             pending_graces = []
             # Incomplete first measures are not padded, but registered as partial
             if is_first_measure:
                 is_first_measure = False
                 # upbeats are marked as implicit measures
-                if attributes_object and m.is_implicit ():
-                    length = attributes_object.get_measure_length ()
+                if attributes_object and m.is_implicit():
+                    length = attributes_object.get_measure_length()
                     measure_end = measure_start_moment + length
                     if measure_end <> now:
                         m.partial = now
             previous_measure = m
 
     # modify attributes so that only those applying to the given staff remain
-    def extract_attributes_for_staff (part, attr, staff):
-        attributes = copy.copy (attr)
+    def extract_attributes_for_staff(part, attr, staff):
+        attributes = copy.copy(attr)
         attributes._children = [];
-        attributes._dict = attr._dict.copy ()
+        attributes._dict = attr._dict.copy()
         attributes._original_tag = attr
         # copy only the relevant children over for the given staff
         if staff == "None":
             staff = "1"
         for c in attr._children:
-            if (not (hasattr (c, 'number') and (c.number != staff)) and
-                not (isinstance (c, Hash_text))):
-                attributes._children.append (c)
+            if(not(hasattr(c, 'number') and(c.number != staff)) and
+                not(isinstance(c, Hash_text))):
+                attributes._children.append(c)
         if not attributes._children:
             return None
         else:
             return attributes
 
-    def extract_voices (part):
+    def extract_voices(part):
+        # The last indentified voice
+        last_voice = None
+
         voices = {}
-        measures = part.get_typed_children (Measure)
+        measures = part.get_typed_children(Measure)
         elements = []
         for m in measures:
             if m.partial > 0:
-                elements.append (Partial (m.partial))
-            elements.extend (m.get_all_children ())
+                elements.append(Partial(m.partial))
+            elements.extend(m.get_all_children())
         # make sure we know all voices already so that dynamics, clefs, etc.
         # can be assigned to the correct voices
         voice_to_staff_dict = {}
         for n in elements:
-            voice_id = n.get_maybe_exist_named_child (u'voice')
+            voice_id = n.get_maybe_exist_named_child(u'voice')
             vid = None
             if voice_id:
-                vid = voice_id.get_text ()
-            elif isinstance (n, Note):
+                vid = voice_id.get_text()
+            elif isinstance(n, Note):
                 # TODO: Check whether we shall really use "None" here, or
                 #       rather use "1" as the default?
-                vid = "None"
+                if n.get_maybe_exist_named_child(u'chord'):
+                    vid = last_voice
+                else:
+                    vid = "1"
+
+            if(vid != None):
+                last_voice = vid
 
-            staff_id = n.get_maybe_exist_named_child (u'staff')
+            staff_id = n.get_maybe_exist_named_child(u'staff')
             sid = None
             if staff_id:
-                sid = staff_id.get_text ()
+                sid = staff_id.get_text()
             else:
                 # TODO: Check whether we shall really use "None" here, or
                 #       rather use "1" as the default?
                 #       If this is changed, need to change the corresponding
                 #       check in extract_attributes_for_staff, too.
                 sid = "None"
-            if vid and not voices.has_key (vid):
+            if vid and not voices.has_key(vid):
                 voices[vid] = Musicxml_voice()
-            if vid and sid and not n.get_maybe_exist_typed_child (Grace):
-                if not voice_to_staff_dict.has_key (vid):
+            if vid and sid and not n.get_maybe_exist_typed_child(Grace):
+                if not voice_to_staff_dict.has_key(vid):
                     voice_to_staff_dict[vid] = sid
-        # invert the voice_to_staff_dict into a staff_to_voice_dict (since we
+
+        # invert the voice_to_staff_dict into a staff_to_voice_dict(since we
         # need to assign staff-assigned objects like clefs, times, etc. to
         # all the correct voices. This will never work entirely correct due
         # to staff-switches, but that's the best we can do!
         staff_to_voice_dict = {}
-        for (v,s) in voice_to_staff_dict.items ():
-            if not staff_to_voice_dict.has_key (s):
+        for(v, s) in voice_to_staff_dict.items():
+            if not staff_to_voice_dict.has_key(s):
                 staff_to_voice_dict[s] = [v]
             else:
-                staff_to_voice_dict[s].append (v)
-
+                staff_to_voice_dict[s].append(v)
 
         start_attr = None
         assign_to_next_note = []
         id = None
         for n in elements:
-            voice_id = n.get_maybe_exist_typed_child (get_class ('voice'))
+            voice_id = n.get_maybe_exist_typed_child(get_class('voice'))
             if voice_id:
-                id = voice_id.get_text ()
+                id = voice_id.get_text()
             else:
-                id = "None"
+                if n.get_maybe_exist_typed_child(get_class('chord')):
+                    id = last_voice
+                else:
+                    id = "1"
+
+            if(id != "None"):
+                last_voice = id
 
             # We don't need backup/forward any more, since we have already
             # assigned the correct onset times.
             # TODO: Let Grouping through. Also: link, print, bokmark sound
-            if not (isinstance (n, Note) or isinstance (n, Attributes) or
-                    isinstance (n, Direction) or isinstance (n, Partial) or
-                    isinstance (n, Barline) or isinstance (n, Harmony) or
-                    isinstance (n, FiguredBass) or isinstance (n, Print)):
+            if not(isinstance(n, Note) or isinstance(n, Attributes) or
+                    isinstance(n, Direction) or isinstance(n, Partial) or
+                    isinstance(n, Barline) or isinstance(n, Harmony) or
+                    isinstance(n, FiguredBass) or isinstance(n, Print)):
                 continue
 
-            if isinstance (n, Attributes) and not start_attr:
+            if isinstance(n, Attributes) and not start_attr:
                 start_attr = n
                 continue
 
-            if isinstance (n, Attributes):
+            if isinstance(n, Attributes):
                 # assign these only to the voices they really belong to!
-                for (s, vids) in staff_to_voice_dict.items ():
-                    staff_attributes = part.extract_attributes_for_staff (n, s)
+                for(s, vids) in staff_to_voice_dict.items():
+                    staff_attributes = part.extract_attributes_for_staff(n, s)
                     if staff_attributes:
                         for v in vids:
-                            voices[v].add_element (staff_attributes)
+                            voices[v].add_element(staff_attributes)
                 continue
 
-            if isinstance (n, Partial) or isinstance (n, Barline) or isinstance (n, Print):
-                for v in voices.keys ():
-                    voices[v].add_element (n)
+            if isinstance(n, Partial) or isinstance(n, Barline) or isinstance(n, Print):
+                for v in voices.keys():
+                    voices[v].add_element(n)
                 continue
 
-            if isinstance (n, Direction):
-                if (n.voice_id):
-                    voices[n.voice_id].add_element (n)
+            if isinstance(n, Direction):
+                staff_id = n.get_maybe_exist_named_child(u'staff')
+                if staff_id:
+                    staff_id = staff_id.get_text()
+                if staff_id:
+                    dir_voices = staff_to_voice_dict.get(staff_id, voices.keys())
                 else:
-                    assign_to_next_note.append (n)
+                    dir_voices = voices.keys()
+                for v in dir_voices:
+                    voices[v].add_element(n)
                 continue
 
-            if isinstance (n, Harmony) or isinstance (n, FiguredBass):
+            if isinstance(n, Harmony) or isinstance(n, FiguredBass):
                 # store the harmony or figured bass element until we encounter
                 # the next note and assign it only to that one voice.
-                assign_to_next_note.append (n)
+                assign_to_next_note.append(n)
                 continue
 
-            if hasattr (n, 'print-object') and getattr (n, 'print-object') == "no":
+            if hasattr(n, 'print-object') and getattr(n, 'print-object') == "no":
                 #Skip this note.
                 pass
             else:
                 for i in assign_to_next_note:
-                    voices[id].add_element (i)
+                    voices[id].add_element(i)
                 assign_to_next_note = []
-                voices[id].add_element (n)
+                voices[id].add_element(n)
 
         # Assign all remaining elements from assign_to_next_note to the voice
         # of the previous note:
         for i in assign_to_next_note:
-            voices[id].add_element (i)
+            voices[id].add_element(i)
         assign_to_next_note = []
 
         if start_attr:
-            for (s, vids) in staff_to_voice_dict.items ():
-                staff_attributes = part.extract_attributes_for_staff (start_attr, s)
-                staff_attributes.read_self ()
+            for(s, vids) in staff_to_voice_dict.items():
+                staff_attributes = part.extract_attributes_for_staff(start_attr, s)
+                staff_attributes.read_self()
                 part._staff_attributes_dict[s] = staff_attributes
                 for v in vids:
-                    voices[v].insert (0, staff_attributes)
+                    voices[v].insert(0, staff_attributes)
                     voices[v]._elements[0].read_self()
 
         part._voices = voices
 
-    def get_voices (self):
+    def get_voices(self):
         return self._voices
-    def get_staff_attributes (self):
-        return self._staff_attributes_dict
-
-class Notations (Music_xml_node):
-    def get_tie (self):
-        ts = self.get_named_children ('tied')
-        starts = [t for t in ts if t.type == 'start']
-        if starts:
-            return starts[0]
-        else:
-            return None
-
-    def get_tuplets (self):
-        return self.get_typed_children (Tuplet)
-
-class Time_modification(Music_xml_node):
-    def get_fraction (self):
-        b = self.get_maybe_exist_named_child ('actual-notes')
-        a = self.get_maybe_exist_named_child ('normal-notes')
-        return (int(a.get_text ()), int (b.get_text ()))
-
-    def get_normal_type (self):
-        tuplet_type = self.get_maybe_exist_named_child ('normal-type')
-        if tuplet_type:
-            dots = self.get_named_children ('normal-dot')
-            log = musicxml_duration_to_log (tuplet_type.get_text ().strip ())
-            return (log , len (dots))
-        else:
-            return None
 
+    def get_staff_attributes(self):
+        return self._staff_attributes_dict
 
-class Accidental (Music_xml_node):
-    def __init__ (self):
-        Music_xml_node.__init__ (self)
-        self.editorial = False
-        self.cautionary = False
-
-class Music_xml_spanner (Music_xml_node):
-    def get_type (self):
-        if hasattr (self, 'type'):
-            return self.type
-        else:
-            return 0
-    def get_size (self):
-        if hasattr (self, 'size'):
-            return string.atoi (self.size)
-        else:
-            return 0
 
-class Wedge (Music_xml_spanner):
+class BarStyle(Music_xml_node):
     pass
 
-class Tuplet (Music_xml_spanner):
-    def duration_info_from_tuplet_note (self, tuplet_note):
-        tuplet_type = tuplet_note.get_maybe_exist_named_child ('tuplet-type')
-        if tuplet_type:
-            dots = tuplet_note.get_named_children ('tuplet-dot')
-            log = musicxml_duration_to_log (tuplet_type.get_text ().strip ())
-            return (log, len (dots))
-        else:
-            return None
-
-    # Return tuplet note type as (log, dots)
-    def get_normal_type (self):
-        tuplet = self.get_maybe_exist_named_child ('tuplet-normal')
-        if tuplet:
-            return self.duration_info_from_tuplet_note (tuplet)
-        else:
-            return None
+class BeatType(Music_xml_node):
+    pass
 
-    def get_actual_type (self):
-        tuplet = self.get_maybe_exist_named_child ('tuplet-actual')
-        if tuplet:
-            return self.duration_info_from_tuplet_note (tuplet)
-        else:
-            return None
+class BeatUnit(Music_xml_node):
+    pass
 
-    def get_tuplet_note_count (self, tuplet_note):
-        if tuplet_note:
-            tuplet_nr = tuplet_note.get_maybe_exist_named_child ('tuplet-number')
-            if tuplet_nr:
-                return int (tuplet_nr.get_text ())
-        return None
-    def get_normal_nr (self):
-        return self.get_tuplet_note_count (self.get_maybe_exist_named_child ('tuplet-normal'))
-    def get_actual_nr (self):
-        return self.get_tuplet_note_count (self.get_maybe_exist_named_child ('tuplet-actual'))
+class BeatUnitDot(Music_xml_node):
+    pass
 
-class Bracket (Music_xml_spanner):
+class Beats(Music_xml_node):
     pass
 
-class Dashes (Music_xml_spanner):
+class Bracket(Music_xml_spanner):
     pass
 
-class Slur (Music_xml_spanner):
-    def get_type (self):
-        return self.type
+class Chord(Music_xml_node):
+    pass
 
-class Beam (Music_xml_spanner):
-    def get_type (self):
-        return self.get_text ()
-    def is_primary (self):
-        if hasattr (self, 'number'):
-            return self.number == "1"
-        else:
-            return True
+class Dashes(Music_xml_spanner):
+    pass
 
-class Wavy_line (Music_xml_spanner):
+class DirType(Music_xml_node):
     pass
 
-class Pedal (Music_xml_spanner):
+class Direction(Music_xml_node):
     pass
 
-class Glissando (Music_xml_spanner):
+class Dot(Music_xml_node):
     pass
 
-class Slide (Music_xml_spanner):
+class Elision(Music_xml_node):
     pass
 
-class Octave_shift (Music_xml_spanner):
-    # default is 8 for the octave-shift!
-    def get_size (self):
-        if hasattr (self, 'size'):
-            return string.atoi (self.size)
-        else:
-            return 8
+class Extend(Music_xml_node):
+    pass
 
-class Chord (Music_xml_node):
+class FiguredBass(Music_xml_node):
     pass
 
-class Dot (Music_xml_node):
+class Glissando(Music_xml_spanner):
     pass
 
-# Rests in MusicXML are <note> blocks with a <rest> inside. This class is only
-# for the inner <rest> element, not the whole rest block.
-class Rest (Music_xml_node):
-    def __init__ (self):
-        Music_xml_node.__init__ (self)
-        self._is_whole_measure = False
-    def is_whole_measure (self):
-        return self._is_whole_measure
-    def get_step (self):
-        ch = self.get_maybe_exist_typed_child (get_class (u'display-step'))
-        if ch:
-            return ch.get_text ().strip ()
-        else:
-            return None
-    def get_octave (self):
-        ch = self.get_maybe_exist_typed_child (get_class (u'display-octave'))
-        if ch:
-            oct = ch.get_text ().strip ()
-            return int (oct)
-        else:
-            return None
+class Grace(Music_xml_node):
+    pass
 
-class Type (Music_xml_node):
+class Harmony(Music_xml_node):
     pass
-class Grace (Music_xml_node):
+
+class Hash_comment(Music_xml_node):
     pass
-class Staff (Music_xml_node):
+
+class KeyAlter(Music_xml_node):
     pass
 
 class Direction (Measure_element):
     pass
-class DirType (Music_xml_node):
+
+class KeyOctave(Music_xml_node):
     pass
 
-class Bend (Music_xml_node):
-    def bend_alter (self):
-        alter = self.get_maybe_exist_named_child ('bend-alter')
-        return interpret_alter_element (alter)
+class KeyStep(Music_xml_node):
+    pass
 
-class Words (Music_xml_node):
+class Part_group(Music_xml_node):
     pass
 
-class Harmony (Music_xml_node):
+class Pedal(Music_xml_spanner):
     pass
 
-class ChordPitch (Music_xml_node):
-    def step_class_name (self):
-        return u'root-step'
-    def alter_class_name (self):
-        return u'root-alter'
-    def get_step (self):
-        ch = self.get_unique_typed_child (get_class (self.step_class_name ()))
-        return ch.get_text ().strip ()
-    def get_alteration (self):
-        ch = self.get_maybe_exist_typed_child (get_class (self.alter_class_name ()))
-        return interpret_alter_element (ch)
-
-class Root (ChordPitch):
+class PerMinute(Music_xml_node):
     pass
 
-class Bass (ChordPitch):
-    def step_class_name (self):
-        return u'bass-step'
-    def alter_class_name (self):
-        return u'bass-alter'
+class Print(Music_xml_node):
+    pass
 
-class ChordModification (Music_xml_node):
-    def get_type (self):
-        ch = self.get_maybe_exist_typed_child (get_class (u'degree-type'))
-        return {'add': 1, 'alter': 1, 'subtract': -1}.get (ch.get_text ().strip (), 0)
-    def get_value (self):
-        ch = self.get_maybe_exist_typed_child (get_class (u'degree-value'))
-        value = 0
-        if ch:
-            value = int (ch.get_text ().strip ())
-        return value
-    def get_alter (self):
-        ch = self.get_maybe_exist_typed_child (get_class (u'degree-alter'))
-        return interpret_alter_element (ch)
-
-
-class Frame (Music_xml_node):
-    def get_frets (self):
-        return self.get_named_child_value_number ('frame-frets', 4)
-    def get_strings (self):
-        return self.get_named_child_value_number ('frame-strings', 6)
-    def get_first_fret (self):
-        return self.get_named_child_value_number ('first-fret', 1)
-
-class Frame_Note (Music_xml_node):
-    def get_string (self):
-        return self.get_named_child_value_number ('string', 1)
-    def get_fret (self):
-        return self.get_named_child_value_number ('fret', 0)
-    def get_fingering (self):
-        return self.get_named_child_value_number ('fingering', -1)
-    def get_barre (self):
-        n = self.get_maybe_exist_named_child ('barre')
-        if n:
-            return getattr (n, 'type', '')
-        else:
-            return ''
+class Root(ChordPitch):
+    pass
 
-class FiguredBass (Music_xml_node):
+class Score_part(Music_xml_node):
     pass
 
-class Beats (Music_xml_node):
+class Slide(Music_xml_spanner):
     pass
 
-class BeatType (Music_xml_node):
+class Staff(Music_xml_node):
     pass
 
-class BeatUnit (Music_xml_node):
+class Text(Music_xml_node):
     pass
 
-class BeatUnitDot (Music_xml_node):
+class Type(Music_xml_node):
     pass
 
-class PerMinute (Music_xml_node):
+class Wavy_line(Music_xml_spanner):
     pass
 
-class Print (Music_xml_node):
+class Wedge(Music_xml_spanner):
     pass
 
+class Words(Music_xml_node):
+    pass
 
 
 ## need this, not all classes are instantiated
@@ -1199,6 +1733,7 @@ class_dict = {
         'bend' : Bend,
         'bracket' : Bracket,
         'chord': Chord,
+        'credit': Credit,
         'dashes' : Dashes,
         'degree' : ChordModification,
         'dot': Dot,
@@ -1221,9 +1756,10 @@ class_dict = {
         'measure': Measure,
         'notations': Notations,
         'note': Note,
+        'notehead': Notehead,
         'octave-shift': Octave_shift,
         'part': Part,
-    'part-group': Part_group,
+        'part-group': Part_group,
         'part-list': Part_list,
         'pedal': Pedal,
         'per-minute': PerMinute,
@@ -1234,10 +1770,13 @@ class_dict = {
         'score-part': Score_part,
         'slide': Slide,
         'slur': Slur,
+        'sound': Sound,
         'staff': Staff,
+        'stem': Stem,
         'syllabic': Syllabic,
         'text': Text,
         'time-modification': Time_modification,
+        'tied': Tied,
         'tuplet': Tuplet,
         'type': Type,
         'unpitched': Unpitched,
@@ -1247,59 +1786,59 @@ class_dict = {
         'work': Work,
 }
 
-def name2class_name (name):
-    name = name.replace ('-', '_')
-    name = name.replace ('#', 'hash_')
+def name2class_name(name):
+    name = name.replace('-', '_')
+    name = name.replace('#', 'hash_')
     name = name[0].upper() + name[1:].lower()
 
-    return str (name)
+    return str(name)
 
-def get_class (name):
-    classname = class_dict.get (name)
+def get_class(name):
+    classname = class_dict.get(name)
     if classname:
         return classname
     else:
-        class_name = name2class_name (name)
-        klass = new.classobj (class_name, (Music_xml_node,) , {})
+        class_name = name2class_name(name)
+        klass = new.classobj(class_name,(Music_xml_node,) , {})
         class_dict[name] = klass
         return klass
 
-def lxml_demarshal_node (node):
+def lxml_demarshal_node(node):
     name = node.tag
 
     # Ignore comment nodes, which are also returned by the etree parser!
     if name is None or node.__class__.__name__ == "_Comment":
         return None
-    klass = get_class (name)
+    klass = get_class(name)
     py_node = klass()
 
     py_node._original = node
     py_node._name = name
     py_node._data = node.text
-    py_node._children = [lxml_demarshal_node (cn) for cn in node.getchildren()]
-    py_node._children = filter (lambda x: x, py_node._children)
+    py_node._children = [lxml_demarshal_node(cn) for cn in node.getchildren()]
+    py_node._children = filter(lambda x: x, py_node._children)
 
     for c in py_node._children:
         c._parent = py_node
 
-    for (k, v) in node.items ():
+    for(k, v) in node.items():
         py_node.__dict__[k] = v
         py_node._attribute_dict[k] = v
 
     return py_node
 
-def minidom_demarshal_node (node):
+def minidom_demarshal_node(node):
     name = node.nodeName
 
-    klass = get_class (name)
-    py_node = klass ()
+    klass = get_class(name)
+    py_node = klass()
     py_node._name = name
-    py_node._children = [minidom_demarshal_node (cn) for cn in node.childNodes]
+    py_node._children = [minidom_demarshal_node(cn) for cn in node.childNodes]
     for c in py_node._children:
         c._parent = py_node
 
     if node.attributes:
-        for (nm, value) in node.attributes.items ():
+        for(nm, value) in node.attributes.items():
             py_node.__dict__[nm] = value
             py_node._attribute_dict[nm] = value
 
@@ -1311,11 +1850,11 @@ def minidom_demarshal_node (node):
     return py_node
 
 
-if __name__  == '__main__':
+if __name__ == '__main__':
     import lxml.etree
 
-    tree = lxml.etree.parse ('beethoven.xml')
-    mxl_tree = lxml_demarshal_node (tree.getroot ())
-    ks = class_dict.keys ()
-    ks.sort ()
-    print '\n'.join (ks)
+    tree = lxml.etree.parse('beethoven.xml')
+    mxl_tree = lxml_demarshal_node(tree.getroot())
+    ks = class_dict.keys()
+    ks.sort()
+    print '\n'.join(ks)
diff --git a/python/musicxml2ly_conversion.py b/python/musicxml2ly_conversion.py
new file mode 100644 (file)
index 0000000..67df2ad
--- /dev/null
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+from rational import *
+import lilylib as ly
+import musicexp
+_ = ly._
+
+def rational_to_lily_duration(rational_len):
+    d = musicexp.Duration()
+
+    rational_len.normalize_self()
+    d_log = {1: 0, 2: 1, 4:2, 8:3, 16:4, 32:5, 64:6, 128:7, 256:8, 512:9}.get(rational_len.denominator(), -1)
+
+    # Duration of the form 1/2^n or 3/2^n can be converted to a simple lilypond duration
+    dots = {1: 0, 3: 1, 7: 2, 15: 3, 31: 4, 63: 5, 127: 6}.get(rational_len.numerator(), -1)
+    if(d_log >= dots >= 0):
+        # account for the dots!
+        d.duration_log = d_log - dots
+        d.dots = dots
+    elif(d_log >= 0):
+        d.duration_log = d_log
+        d.factor = Rational(rational_len.numerator())
+    else:
+        ly.warning(_("Encountered rational duration with denominator %s, "
+                       "unable to convert to lilypond duration") %
+                    rational_len.denominator())
+        # TODO: Test the above error message
+        return None
+
+    return d
+
+def musicxml_step_to_lily(step):
+    if step:
+        return (ord(step) - ord('A') + 7 - 2) % 7
+    else:
+        return None
+
+class Marker(musicexp.Music):
+    def __init__(self):
+        self.direction = 0
+        self.event = None
+    def print_ly(self, printer):
+        ly.warning(_("Encountered unprocessed marker %s\n") % self)
+        pass
+    def ly_expression(self):
+        return ""
+    
+class RepeatMarker(Marker):
+    def __init__(self):
+        Marker.__init__(self)
+        self.times = 0
+
+class EndingMarker(Marker):
+    pass
diff --git a/python/utilities.py b/python/utilities.py
new file mode 100644 (file)
index 0000000..da2386b
--- /dev/null
@@ -0,0 +1,268 @@
+# -*- coding: utf-8 -*-
+import re
+import string
+
+def string_to_number(s):
+    try:
+        return int(s)
+    except ValueError:
+        return float(s)
+
+def string_to_integer(s):
+    num = string_to_number(s)
+    if isinstance(num, int):
+        return num
+    else:
+        return int(num)
+
+def escape_ly_output_string (input_string):
+    return_string = input_string
+    needs_quotes = not re.match (u"^[a-zA-ZäöüÜÄÖßñ]*$", return_string);
+    if needs_quotes:
+        return_string = "\"" + string.replace (return_string, "\"", "\\\"") + "\""
+    return return_string
+
+def interpret_alter_element (alter_elm):
+    alter = 0
+    if alter_elm:
+        val = eval(alter_elm.get_text ())
+        if type (val) in (int, float):
+            alter = val
+    return alter
+
+def musicxml_duration_to_log (dur):
+    return  {'256th': 8,
+             '128th': 7,
+             '64th': 6,
+             '32nd': 5,
+             '16th': 4,
+             'eighth': 3,
+             'quarter': 2,
+             'half': 1,
+             'whole': 0,
+             'breve':-1,
+             'longa':-2,
+             'long':-2}.get (dur, 0)
+
+def hexcolorval_to_nr (hex_val):
+    try:
+        v = int (hex_val, 16)
+        if v == 255:
+            v = 256
+        return v / 256.
+    except ValueError:
+        return 0.
+
+def hex_to_color(hex_val):
+    res = re.match (
+        r'#([0-9a-f][0-9a-f]|)([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$',
+        hex_val,
+        re.IGNORECASE)
+    if res:
+        return map(lambda x: hexcolorval_to_nr (x), res.group (2, 3, 4))
+    else:
+        return None
+
+def split_string_and_preserve_doublequoted_substrings(value):
+    import shlex
+    lex = shlex.shlex(value)
+    lex.quotes = '"'
+    lex.whitespace_split = True
+    lex.commenters = ''
+    return list(lex)
+
+def musicxml_sound_to_lilypond_midi_instrument(sound):
+    sounds = {
+        "brass.french-horn": 'french horn',
+        "brass.group": 'brass section',
+        "brass.group.synth": 'synthbrass 1',
+        "brass.trombone": 'trombone',
+        "brass.trombone.alto": 'trombone',
+        "brass.trombone.bass": 'trombone',
+        "brass.trombone.contrabass": 'trombone',
+        "brass.trombone.tenor": 'trombone',
+        "brass.trumpet": 'trumpet',
+        "brass.trumpet.baroque": 'trumpet',
+        "brass.trumpet.bass": 'trumpet',
+        "brass.trumpet.bflat": 'trumpet',
+        "brass.trumpet.c": 'trumpet',
+        "brass.trumpet.d": 'trumpet',
+        "brass.trumpet.piccolo": 'trumpet',
+        "brass.trumpet.pocket": 'trumpet',
+        "brass.trumpet.slide": 'trumpet',
+        "brass.trumpet.tenor": 'trumpet',
+        "brass.tuba": 'tuba',
+        "brass.tuba.bass": 'tuba',
+        "brass.tuba.subcontrabass": 'tuba',
+        "brass.wagner-tuba": 'french horn',
+        "drum.timpani": 'timpani',
+        "drum.tom-tom": 'melodic tom',
+        "drum.tom-tom.synth": 'synth drum',
+        "effect.applause": 'applause',
+        "effect.bass-string-slap": 'slap bass 1',
+        "effect.bird": 'bird tweet',
+        "effect.bird.tweet": 'bird tweet',
+        "effect.breath": 'breath noise',
+        "effect.guitar-fret": 'guitar fret noise',
+        "effect.gunshot": 'gunshot',
+        "effect.helicopter": 'helicopter',
+        "effect.metronome-click": 'woodblock',
+        "effect.rain": 'fx1 (rain)',
+        "effect.seashore": 'seashore',
+        "effect.telephone-ring": 'telephone ring',
+        "keyboard.accordion": 'accordion',
+        "keyboard.bandoneon": 'accordion',
+        "keyboard.celesta": 'celesta',
+        "keyboard.clavichord": 'clav',
+        "keyboard.concertina": 'concertina',
+        "keyboard.harpsichord": 'harpsichord',
+        "keyboard.ondes-martenot": 'ocarina',
+        "keyboard.organ": 'church organ',
+        "keyboard.organ.drawbar": 'drawbar organ',
+        "keyboard.organ.percussive": 'percussive organ',
+        "keyboard.organ.pipe": 'church organ',
+        "keyboard.organ.reed": 'reed organ',
+        "keyboard.piano": 'acoustic grand',
+        "keyboard.piano.electric": 'electric piano 1',
+        "keyboard.piano.grand": 'acoustic grand',
+        "keyboard.piano.honky-tonk": 'honky-tonk',
+        "metal.bells.agogo": 'agogo',
+        "metal.bells.tinklebell": 'tinkle bell',
+        "metal.cymbal.reverse": 'reverse cymbal',
+        "pitched-percussion.glockenspiel": 'glockenspiel',
+        "pitched-percussion.glockenspiel.alto": 'glockenspiel',
+        "pitched-percussion.glockenspiel.soprano": 'glockenspiel',
+        "pitched-percussion.hammer-dulcimer": 'dulcimer',
+        "pitched-percussion.kalimba": 'kalimba',
+        "pitched-percussion.marimba": 'marimba',
+        "pitched-percussion.marimba.bass": 'marimba',
+        "pitched-percussion.music-box": 'music box',
+        "pitched-percussion.tubular-bells": 'tubular bells',
+        "pitched-percussion.vibraphone": 'vibraphone',
+        "pitched-percussion.xylophone": 'xylophone',
+        "pitched-percussion.xylophone.alto": 'xylophone',
+        "pitched-percussion.xylophone.bass": 'xylophone',
+        "pitched-percussion.xylophone.soprano": 'xylophone',
+        "pitched-percussion.xylorimba": 'xylophone',
+        "pluck.banjo": 'banjo',
+        "pluck.banjo.tenor": 'banjo',
+        "pluck.bass": 'acoustic bass',
+        "pluck.bass.acoustic": 'acoustic bass',
+        "pluck.bass.electric": 'electric bass',
+        "pluck.bass.fretless": 'fretless bass',
+        "pluck.bass.synth": 'synth bass 1',
+        "pluck.dulcimer": 'dulcimer',
+        "pluck.guitar": 'acoustic guitar (nylon)',
+        "pluck.guitar.acoustic": 'acoustic guitar (nylon)',
+        "pluck.guitar.electric": 'electric guitar (jazz)',
+        "pluck.guitar.nylon-string": 'acoustic guitar (nylon)',
+        "pluck.guitar.steel-string": 'acoustic guitar (steel)',
+        "pluck.harp": 'orchestral harp',
+        "pluck.lute": 'acoustic guitar (nylon)',
+        "pluck.shamisen": 'shamisen',
+        "pluck.sitar": 'sitar',
+        "strings.cello": 'cello',
+        "strings.cello.piccolo": 'cello',
+        "strings.contrabass": 'contrabass',
+        "strings.fiddle": 'fiddle',
+        "strings.group.synth": 'synth strings 1',
+        "strings.viola": 'viola',
+        "strings.violin": 'violin',
+        "synth.effects.atmosphere": 'fx 4 (atmosphere)',
+        "synth.effects.brightness": 'fx 5 (brightness)',
+        "synth.effects.crystal": 'fx 3 (crystal)',
+        "synth.effects.echoes": 'fx 7 echoes',
+        "synth.effects.goblins": 'fx 6 goblins',
+        "synth.effects.rain": 'fx 1 rain',
+        "synth.effects.sci-fi": 'fx 8 sci-fi',
+        "synth.effects.soundtrack": 'fx 2 (soundtrack)',
+        "synth.pad.bowed": 'pad 5 bowed',
+        "synth.pad.choir": 'pad 4 choir',
+        "synth.pad.halo": 'pad 7 halo',
+        "synth.pad.metallic": 'pad 6 metallic',
+        "synth.pad.polysynth": 'pad 3 polysynth',
+        "synth.pad.sweep": 'pad 8 sweep',
+        "synth.pad.warm": 'pad 2 warm',
+        "synth.tone.sawtooth": 'lead 1 (square)',
+        "synth.tone.square": 'lead 2 (sawtooth)',
+        "voice.aa": 'choir aahs',
+        "voice.alto": 'choir aahs',
+        "voice.aw": 'choir aahs',
+        "voice.baritone": 'choir aahs',
+        "voice.bass": 'choir aahs',
+        "voice.child": 'choir aahs',
+        "voice.countertenor": 'choir aahs',
+        "voice.doo": 'choir aahs',
+        "voice.ee": 'choir aahs',
+        "voice.female": 'choir aahs',
+        "voice.kazoo": 'choir aahs',
+        "voice.male": 'choir aahs',
+        "voice.mezzo-soprano": 'choir aahs',
+        "voice.mm": 'choir aahs',
+        "voice.oo": 'voice oohs',
+        "voice.soprano": 'choir aahs',
+        "voice.synth": 'synth voice',
+        "wind.flutes.blown-bottle": 'blown bottle',
+        "wind.flutes.calliope": 'lead 3 (calliope)',
+        "wind.flutes.flute": 'flute',
+        "wind.flutes.flute.alto": 'flute',
+        "wind.flutes.flute.bass": 'flute',
+        "wind.flutes.flute.contra-alto": 'flute',
+        "wind.flutes.flute.contrabass": 'flute',
+        "wind.flutes.flute.double-contrabass": 'flute',
+        "wind.flutes.flute.piccolo": 'flute',
+        "wind.flutes.flute.subcontrabass": 'flute',
+        "wind.flutes.ocarina": 'ocarina',
+        "wind.flutes.recorder": 'recorder',
+        "wind.flutes.recorder.alto": 'recorder',
+        "wind.flutes.recorder.bass": 'recorder',
+        "wind.flutes.recorder.contrabass": 'recorder',
+        "wind.flutes.recorder.descant": 'recorder',
+        "wind.flutes.recorder.garklein": 'recorder',
+        "wind.flutes.recorder.great-bass": 'recorder',
+        "wind.flutes.recorder.sopranino": 'recorder',
+        "wind.flutes.recorder.soprano": 'recorder',
+        "wind.flutes.recorder.tenor": 'recorder',
+        "wind.flutes.shakuhachi": 'shakuhachi',
+        "wind.flutes.whistle": 'whistle',
+        "wind.flutes.whistle.alto": 'whistle',
+        "wind.pipes.bagpipes": 'bagpipe',
+        "wind.reed.basset-horn": 'clarinet',
+        "wind.reed.bassoon": 'bassoon',
+        "wind.reed.clarinet": 'clarinet',
+        "wind.reed.clarinet.a": 'clarinet',
+        "wind.reed.clarinet.alto": 'clarinet',
+        "wind.reed.clarinet.bass": 'clarinet',
+        "wind.reed.clarinet.basset": 'clarinet',
+        "wind.reed.clarinet.bflat": 'clarinet',
+        "wind.reed.clarinet.contra-alto": 'clarinet',
+        "wind.reed.clarinet.contrabass": 'clarinet',
+        "wind.reed.clarinet.eflat": 'clarinet',
+        "wind.reed.clarinet.piccolo.aflat": 'clarinet',
+        "wind.reed.contrabass": 'contrabass',
+        "wind.reed.contrabassoon": 'bassoon',
+        "wind.reed.english-horn": 'oboe',
+        "wind.reed.harmonica": 'harmonica',
+        "wind.reed.harmonica.bass": 'harmonica',
+        "wind.reed.oboe": 'oboe',
+        "wind.reed.oboe.bass": 'oboe',
+        "wind.reed.oboe.piccolo": 'oboe',
+        "wind.reed.oboe-da-caccia": 'oboe',
+        "wind.reed.oboe-damore": 'oboe',
+        "wind.reed.saxophone": 'alto sax',
+        "wind.reed.saxophone.alto": 'alto sax',
+        "wind.reed.saxophone.baritone": 'baritone sax',
+        "wind.reed.saxophone.bass": 'baritone sax',
+        "wind.reed.saxophone.contrabass": 'baritone sax',
+        "wind.reed.saxophone.melody": 'soprano sax',
+        "wind.reed.saxophone.mezzo-soprano": 'soprano sax',
+        "wind.reed.saxophone.sopranino": 'soprano sax',
+        "wind.reed.saxophone.sopranissimo": 'soprano sax',
+        "wind.reed.saxophone.soprano": 'soprano, sax',
+        "wind.reed.saxophone.subcontrabass": 'baritone sax',
+        "wind.reed.saxophone.tenor": 'tenor sax',
+        "wind.reed.shenai": 'shanai',
+        "wood.temple-block": 'wood block',
+        "wood.wood-block": 'wood block',
+        }
+    return sounds.get(sound, 'acoustic grand')
index 1d41c973e80330876afc9de25d5e090e4bc223ef..23601a8deaba4e54a3014c0b2fcdc8dd9c324dd1 100644 (file)
@@ -18,6 +18,8 @@
 ;; for define-safe-public when byte-compiling using Guile V2
 (use-modules (scm safe-utility-defs) (ice-9 receive))
 
+(define-session-public chordmodifiers '())
+
 (define-public (construct-chord-elements root duration modifications)
   "Build a chord on root using modifiers in @var{modifications}.
 @code{NoteEvents} have duration @var{duration}.
index 3ee68e5e6a5ebceba368c151b01e13effddc64aa..75f1807e61818507374bfc420aa654c381a37257 100644 (file)
@@ -28,7 +28,7 @@
 
 
   (if (not (equal? #f (object-property symbol 'translation-doc)))
-      (ly:error (_ "symbol ~S redefined" symbol)))
+      (ly:error (_ "symbol ~S redefined") symbol))
 
   (set-object-property! symbol 'translation-type? type?)
   (set-object-property! symbol 'translation-doc description)
index 4eebdfac0ee7627aec9cdc616fbafe7e58bcb2b1..8695bc5b78874801405a36288a8c5757e0679bfd 100644 (file)
@@ -107,7 +107,7 @@ previously defined event class."
      ((ly:make-event-class class)
       (ly:error (_ "Cannot redefine event class `~S'") class))
      ((not parentclass)
-      (ly:error (_ "Undefined parent event class `~S'" parentclass)))
+      (ly:error (_ "Undefined parent event class `~S'") parentclass))
      (else
       (hashq-set! ancestor-lookup
                   class
index 10aecbd1db6794f29b3ee54f9cb99bdef23e47b4..42637cd16c0c5548b44395186893e0d96cdedd05 100644 (file)
@@ -89,8 +89,7 @@ expression."
   (define (pitch= pitch1 pitch2)
     (and (= (ly:pitch-notename pitch1) (ly:pitch-notename pitch2))
          (= (ly:pitch-alteration pitch1) (ly:pitch-alteration pitch2))))
-  (let* ((pitches (ly:parser-lookup 'pitchnames))
-         (result (rassoc ly-pitch pitches pitch=)))
+  (let* ((result (rassoc ly-pitch pitchnames pitch=)))
     (and result (car result))))
 
 (define-public (octave->lily-string pitch)
@@ -860,7 +859,11 @@ Otherwise, return #f."
                 num den
                 (new-line->lily-string))
         (format #f
-                "\\time #'~a ~a/~a~a"
+                ;; This is silly but the latter will also work for #f
+                ;; and other
+                (if (key-list? structure)
+                    "\\time ~{~a~^,~} ~a/~a~a"
+                    "\\time #'~a ~a/~a~a")
                 structure num den
                 (new-line->lily-string)))))
 
index 5825967428d9a3e14036480acd83b32d3d7ba627..e7d208a5119c6230372d0981ea780af70c4cb562 100644 (file)
 
 
 ;;; Variable declaration
-(define-public pitchnames '())
-(define-public default-language "")
-(define-public previous-pitchnames #f)
+(define-session-public pitchnames '())
+(define-session-public default-language "")
+(define-session-public previous-pitchnames #f)
 
-(define-public language-pitch-names
+;;; A bit out of place, but we don't have a good place elsewhere in
+;;; scm since it is only filled in ly/drumpitch-init.ly and we need it
+;;; in (scm lily) in order to access it in ly/parser.yy.
+(define-session-public drumPitchNames '())
+
+(define-session-public language-pitch-names
   `(
     ;; Language: Nederlands --------------------------------------------;
     ;;  Dutch note names -- LilyPond's default language.
index ca3372ca92557b2d32129ea705f692f2e8977be0..a781055f5077d152520e7d7c4643341a9fc5ea0f 100644 (file)
        ((and file-name (string-endswith downcase-file-name ".ttf"))
         (ly:ttf->pfa file-name))
        ((and file-name (string-endswith downcase-file-name ".ttc"))
-        (ly:ttf->pfa file-name font-index))
+        ;; TODO: distinguish files which have extension `*.ttc'
+        ;; whether TrueType Collection (TTC) fonts
+        ;; or OpenType/CFF Collection (OTC) fonts.
+        (ly:ttf->pfa file-name font-index)) ;; TTC fonts
        ((and file-name (string-endswith downcase-file-name ".otf"))
         (ps-embed-cff (ly:otf->cff file-name) name 0))
+       ((and file-name (string-endswith downcase-file-name ".otc"))
+        ;; The files which have the extension `*.otc' are OTC fonts.
+        (ps-embed-cff (ly:otf->cff file-name font-index) name 0)) ;; OTC fonts
        (else
         (ly:warning (_ "do not know how to embed ~S=~S") name file-name)
         ""))))
index 5ead4e6c9cf9da25e8f12bcf08cdfa145692f613..d1248cdd92d6c0e1a23e0ecfebfc9e877d25dc5a 100644 (file)
@@ -86,6 +86,7 @@
 ;;
 
 (define lilypond-declarations '())
+(define lilypond-exports '())
 (define after-session-hook (make-hook))
 
 (define-public (call-after-session thunk)
       (ly:error (_ "call-after-session used after session start")))
   (add-hook! after-session-hook thunk #t))
 
-(defmacro-public define-session (name value)
+(define (make-session-variable name value)
+  (if (ly:undead? lilypond-declarations)
+      (ly:error (_ "define-session used after session start")))
+  (let ((var (module-make-local-var! (current-module) name)))
+    (if (variable-bound? var)
+        (ly:error (_ "symbol ~S redefined") name))
+    (variable-set! var value)
+    var))
+
+(defmacro define-session (name value)
   "This defines a variable @var{name} with the starting value
 @var{value} that is reinitialized at the start of each session.
 A@tie{}session basically corresponds to one LilyPond file on the
@@ -107,17 +117,22 @@ to their front or replacing them altogether, not by modifying parts of
 them.  It is an error to call @code{define-session} after the first
 session has started."
   (define (add-session-variable name value)
-    (if (ly:undead? lilypond-declarations)
-        (ly:error (_ "define-session used after session start")))
-    (let ((var (make-variable value)))
-      (module-add! (current-module) name var)
-      (set! lilypond-declarations (cons var lilypond-declarations))))
+    (set! lilypond-declarations
+          (cons (make-session-variable name value) lilypond-declarations)))
   `(,add-session-variable ',name ,value))
 
-(defmacro-public define-session-public (name value)
-  "Like @code{define-session}, but also exports @var{name}."
+(defmacro define-session-public (name value)
+  "Like @code{define-session}, but also exports @var{name} into parser modules."
+  (define (add-session-variable name value)
+    (set! lilypond-exports
+          (acons name (make-session-variable name value) lilypond-exports)))
   `(begin
-     (define-session ,name ,value)
+     ;; this is a bit icky: we place the variable right into every
+     ;; parser module so that both set! and define will affect the
+     ;; original variable in the (lily) module.  However, we _also_
+     ;; export it normally from (lily) for the sake of other modules
+     ;; not sharing the name space of the parser.
+     (,add-session-variable ',name ,value)
      (export ,name)))
 
 (define (session-terminate)
@@ -158,7 +173,16 @@ variables to their value after the initial call of @var{thunk}."
                  (module-add! (current-module) (car p) var))))
          (ly:get-undead lilypond-declarations)))
       (begin
+        ;; import all public session variables natively into parser
+        ;; module.  That makes them behave identically under define/set!
+        (for-each (lambda (v)
+                    (module-add! (current-module) (car v) (cdr v)))
+                  lilypond-exports)
+        ;; Initialize first session
         (thunk)
+        ;; lilypond-exports is no longer needed since we will grab its
+        ;; values from (current-module).
+        (set! lilypond-exports #f)
         (set! lilypond-interfaces
               (filter (lambda (m) (eq? 'interface (module-kind m)))
                       (module-uses (current-module))))
index 69f277203934985a01979476b56df1803c5a1bae..70b13848e4aa6ad898bac04f79d33c80dfdaf838 100644 (file)
                                 (ly:in-event-class? cause t))
                               point-and-click))))
             (let* ((location (ly:input-file-line-char-column music-origin))
+                   (raw-file (car location))
+                   (file (if (is-absolute? raw-file)
+                             raw-file
+                             (string-append (ly-getcwd) "/" raw-file)))
                    (x-ext (ly:grob-extent grob grob X))
                    (y-ext (ly:grob-extent grob grob Y)))
 
                              ;; Backslashes are not valid
                              ;; file URI path separators.
                              (ly:string-percent-encode
-                              (ly:string-substitute "\\" "/" (car location)))
+                              (ly:string-substitute "\\" "/" file))
 
                              (cadr location)
                              (caddr location)
index ca086318d7810d1f4769d59e6d2e88d4fc28668d..78bda3c35b8c88f376fadc6f9d471597ca1ba482 100644 (file)
                     (else (any (lambda (t)
                                  (ly:in-event-class? cause t))
                                point-and-click)))
-              (let* ((location (ly:input-file-line-char-column music-origin)))
-
+              (let* ((location (ly:input-file-line-char-column music-origin))
+                     (raw-file (car location))
+                     (file (if (is-absolute? raw-file)
+                               raw-file
+                               (string-append (ly-getcwd) "/" raw-file))))
+                
                 (ly:format "<a style=\"color:inherit;\" xlink:href=\"textedit://~a:~a:~a:~a\">\n"
                            ;; Backslashes are not valid
                            ;; file URI path separators.
                            (ly:string-percent-encode
-                            (ly:string-substitute "\\" "/" (car location)))
-
+                            (ly:string-substitute "\\" "/" file))
+                           
                            (cadr location)
                            (caddr location)
                            (1+ (cadddr location))))))))
index e529ca7327cdd5a6a4ff2a36a861bd7a413a3b7b..e631c27fd8b43a5e7c75792be202237fadfb9d3d 100644 (file)
@@ -554,7 +554,7 @@ def make_regtest_links(name, version, lang):
         getTrans("PDF of lilypond-book regtests for ", lang)+version)
 
 def make_doctarball_links(name, version, lang):
-    url = depth + "download/binaries/documentation/lilypond-"
+    url = depth + "downloads/binaries/documentation/lilypond-"
     # ugly FIXME, but proper build number support isn't Critical.
     url += version + "-1"
     url += ".documentation.tar.bz2"
index f4a47fb79ab963c889a9d372b9952e89ac3cdbd9..5358fc46984ad6e8a49e363c2aaf622f816c18b9 100644 (file)
@@ -32,7 +32,6 @@ import sys
 @relocate-preamble@
 """
 
-import midi
 import lilylib as ly
 global _;_=ly._
 
@@ -923,6 +922,9 @@ class Staff:
         return dump_track (self.voices, i)
 
 def convert_midi (in_file, out_file):
+    global midi
+    import midi
+
     global clocks_per_1, clocks_per_4, key
     global start_quant_clocks
     global duration_quant_clocks
index b1cc496f6eb2697541a62afca5aad4eed1308783..766214bd762b5dc8e991849d70a91473f4bbb782 100644 (file)
@@ -9,6 +9,7 @@ import codecs
 import zipfile
 import tempfile
 import StringIO
+import warnings
 
 """
 @relocate-preamble@
@@ -17,31 +18,38 @@ import StringIO
 import lilylib as ly
 _ = ly._
 
+import utilities
+import musicxml2ly_conversion
 import musicxml
 import musicexp
 
 from rational import Rational
 
+lilypond_version = "@TOPLEVEL_VERSION@"
+
 # Store command-line options in a global variable, so we can access them everywhere
 options = None
 
 class Conversion_Settings:
     def __init__(self):
        self.ignore_beaming = False
+       self.convert_stem_directions = False
+       self.convert_rest_positions = True
 
-conversion_settings = Conversion_Settings ()
+conversion_settings = Conversion_Settings()
 # Use a global variable to store the setting needed inside a \layout block.
 # whenever we need to change a setting or add/remove an engraver, we can access
 # this layout and add the corresponding settings
-layout_information = musicexp.Layout ()
+layout_information = musicexp.Layout()
+# Use a global variable to store the setting needed inside a \paper block.
+paper = musicexp.Paper()
 
 needed_additional_definitions = []
 additional_definitions = {
-
   "tuplet-note-wrapper": """      % a formatter function, which is simply a wrapper around an existing
       % tuplet formatter function. It takes the value returned by the given
       % function and appends a note of given length.
-  #(define ((tuplet-number::append-note-wrapper function note) grob)
+  #(define-public ((tuplet-number::append-note-wrapper function note) grob)
     (let* ((txt (if function (function grob) #f)))
       (if txt
         (markup txt #:fontsize -5 #:note note UP)
@@ -64,91 +72,105 @@ additional_definitions = {
 """,
 }
 
-def round_to_two_digits (val):
-    return round (val * 100) / 100
+def round_to_two_digits(val):
+    return round(val * 100) / 100
 
-def extract_paper_information (tree):
-    paper = musicexp.Paper ()
-    defaults = tree.get_maybe_exist_named_child ('defaults')
+def extract_paper_information(score_partwise):
+    defaults = score_partwise.get_maybe_exist_named_child('defaults')
     if not defaults:
         return None
     tenths = -1
-    scaling = defaults.get_maybe_exist_named_child ('scaling')
+    scaling = defaults.get_maybe_exist_named_child('scaling')
+    default_tenths_to_millimeters_ratio = 0.175
+    default_staff_size = 20
     if scaling:
-        mm = scaling.get_named_child ('millimeters')
-        mm = string.atof (mm.get_text ())
-        tn = scaling.get_maybe_exist_named_child ('tenths')
-        tn = string.atof (tn.get_text ())
+        mm = scaling.get_named_child('millimeters')
+        mm = float(mm.get_text())
+        tn = scaling.get_maybe_exist_named_child('tenths')
+        tn = float(tn.get_text())
+        # The variable 'tenths' is actually a ratio, NOT the value of <tenths>.
+        # TODO: rename and replace.
         tenths = mm / tn
-        paper.global_staff_size = mm * 72.27 / 25.4
-    # We need the scaling (i.e. the size of staff tenths for everything!
+        ratio = tenths / default_tenths_to_millimeters_ratio
+        staff_size = default_staff_size * ratio
+
+        if 1 < staff_size < 100:
+            paper.global_staff_size = staff_size
+        else:
+            msg = "paper.global_staff_size {} is too large, using defaults=20".format(
+                staff_size)
+            warnings.warn(msg)
+            paper.global_staff_size = 20
+
+    # We need the scaling(i.e. the size of staff tenths for everything!
     if tenths < 0:
         return None
 
-    def from_tenths (txt):
-        return round_to_two_digits (string.atof (txt) * tenths / 10)
-    def set_paper_variable (varname, parent, element_name):
-        el = parent.get_maybe_exist_named_child (element_name)
+    def from_tenths(txt):
+        return round_to_two_digits(float(txt) * tenths / 10)
+    def set_paper_variable(varname, parent, element_name):
+        el = parent.get_maybe_exist_named_child(element_name)
         if el: # Convert to cm from tenths
-            setattr (paper, varname, from_tenths (el.get_text ()))
+            setattr(paper, varname, from_tenths(el.get_text()))
 
-    pagelayout = defaults.get_maybe_exist_named_child ('page-layout')
+    pagelayout = defaults.get_maybe_exist_named_child('page-layout')
     if pagelayout:
         # TODO: How can one have different margins for even and odd pages???
-        set_paper_variable ("page_height", pagelayout, 'page-height')
-        set_paper_variable ("page_width", pagelayout, 'page-width')
-
-        pmargins = pagelayout.get_named_children ('page-margins')
-        for pm in pmargins:
-            set_paper_variable ("left_margin", pm, 'left-margin')
-            set_paper_variable ("right_margin", pm, 'right-margin')
-            set_paper_variable ("bottom_margin", pm, 'bottom-margin')
-            set_paper_variable ("top_margin", pm, 'top-margin')
-
-    systemlayout = defaults.get_maybe_exist_named_child ('system-layout')
+        set_paper_variable("page_height", pagelayout, 'page-height')
+        set_paper_variable("page_width", pagelayout, 'page-width')
+
+        if conversion_settings.convert_page_margins:
+            pmargins = pagelayout.get_named_children('page-margins')
+            for pm in pmargins:
+                set_paper_variable("left_margin", pm, 'left-margin')
+                set_paper_variable("right_margin", pm, 'right-margin')
+                set_paper_variable("bottom_margin", pm, 'bottom-margin')
+                set_paper_variable("top_margin", pm, 'top-margin')
+
+    systemlayout = defaults.get_maybe_exist_named_child('system-layout')
     if systemlayout:
-        sl = systemlayout.get_maybe_exist_named_child ('system-margins')
+        sl = systemlayout.get_maybe_exist_named_child('system-margins')
         if sl:
-            set_paper_variable ("system_left_margin", sl, 'left-margin')
-            set_paper_variable ("system_right_margin", sl, 'right-margin')
-        set_paper_variable ("system_distance", systemlayout, 'system-distance')
-        set_paper_variable ("top_system_distance", systemlayout, 'top-system-distance')
+            set_paper_variable("system_left_margin", sl, 'left-margin')
+            set_paper_variable("system_right_margin", sl, 'right-margin')
+        set_paper_variable("system_distance", systemlayout, 'system-distance')
+        set_paper_variable("top_system_distance", systemlayout, 'top-system-distance')
 
-    stafflayout = defaults.get_named_children ('staff-layout')
+    stafflayout = defaults.get_named_children('staff-layout')
     for sl in stafflayout:
-        nr = getattr (sl, 'number', 1)
-        dist = sl.get_named_child ('staff-distance')
+        nr = getattr(sl, 'number', 1)
+        dist = sl.get_named_child('staff-distance')
         #TODO: the staff distance needs to be set in the Staff context!!!
 
     # TODO: Finish appearance?, music-font?, word-font?, lyric-font*, lyric-language*
-    appearance = defaults.get_named_child ('appearance')
+    appearance = defaults.get_named_child('appearance')
     if appearance:
-        lws = appearance.get_named_children ('line-width')
+        lws = appearance.get_named_children('line-width')
         for lw in lws:
             # Possible types are: beam, bracket, dashes,
             #    enclosure, ending, extend, heavy barline, leger,
             #    light barline, octave shift, pedal, slur middle, slur tip,
             #    staff, stem, tie middle, tie tip, tuplet bracket, and wedge
             tp = lw.type
-            w = from_tenths (lw.get_text  ())
+            w = from_tenths(lw.get_text())
             # TODO: Do something with these values!
-        nss = appearance.get_named_children ('note-size')
+        nss = appearance.get_named_children('note-size')
         for ns in nss:
             # Possible types are: cue, grace and large
             tp = ns.type
-            sz = from_tenths (ns.get_text ())
+            sz = from_tenths(ns.get_text())
             # TODO: Do something with these values!
         # <other-appearance> elements have no specified meaning
 
-    rawmusicfont = defaults.get_named_child ('music-font')
+    rawmusicfont = defaults.get_named_child('music-font')
     if rawmusicfont:
         # TODO: Convert the font
         pass
-    rawwordfont = defaults.get_named_child ('word-font')
+    rawwordfont = defaults.get_named_child('word-font')
     if rawwordfont:
         # TODO: Convert the font
         pass
-    rawlyricsfonts = defaults.get_named_children ('lyric-font')
+    rawlyricsfonts = defaults.get_named_children('lyric-font')
     for lyricsfont in rawlyricsfonts:
         # TODO: Convert the font
         pass
@@ -156,58 +178,68 @@ def extract_paper_information (tree):
     return paper
 
 
-
+credit_dict = {
+    None:None,
+    '':None,
+    'page number':None, #TODO: what is it used for ?
+    'title':'title',
+    'subtitle':'subtitle',
+    'composer':'composer',
+    'arranger':'arranger',
+    'lyricist':'poet',
+    'rights':'copyright'
+}
 # score information is contained in the <work>, <identification> or <movement-title> tags
 # extract those into a hash, indexed by proper lilypond header attributes
-def extract_score_information (tree):
-    header = musicexp.Header ()
-    def set_if_exists (field, value):
+def extract_score_information(tree):
+    header = musicexp.Header()
+    def set_if_exists(field, value):
         if value:
-            header.set_field (field, musicxml.escape_ly_output_string (value))
+            header.set_field(field, utilities.escape_ly_output_string(value))
 
-    work = tree.get_maybe_exist_named_child ('work')
-    if work:
-        set_if_exists ('worknumber', work.get_work_number ())
-        set_if_exists ('opus', work.get_opus ())
-
-    movement_title = tree.get_maybe_exist_named_child ('movement-title')
+    movement_title = tree.get_maybe_exist_named_child('movement-title')
+    movement_number = tree.get_maybe_exist_named_child('movement-number')
+    if movement_title:
+        set_if_exists('title', movement_title.get_text())
+    if movement_number:
+          set_if_exists('movementnumber', movement_number.get_text())
+          # set_if_exists('piece', movement_number.get_text()) # the movement number should be visible in the score.
 
-    # use either work-title or movement-title as title.
-    # if both exist use movement-title as subtitle.
-    # if there is only a movement-title (or work-title is empty or missing) the movement-title should be typeset as a title
+    work = tree.get_maybe_exist_named_child('work')
     if work:
-        work_title = work.get_work_title ()
-        set_if_exists ('title', work_title)
-        if work_title == '' and movement_title :
-            set_if_exists ('title', movement_title.get_text ())
-        elif movement_title:
-            set_if_exists ('subtitle', movement_title.get_text ())
-    elif movement_title:
-        set_if_exists ('title', movement_title.get_text ())
-
-    identifications = tree.get_named_children ('identification')
+        work_number = work.get_work_number()
+        work_title = work.get_work_title()
+        # Overwrite the title from movement-title with work->title
+        set_if_exists('title', work.get_work_title())
+        set_if_exists('opus', work.get_work_number())
+        # Use movement-title as subtitle
+        if movement_title:
+              set_if_exists('subtitle', movement_title.get_text())
+
+# TODO: Translation of opus element. Not to be confused with opus in LilyPond. MusicXML opus is a document element for opus DTD
+    identifications = tree.get_named_children('identification')
     for ids in identifications:
-        set_if_exists ('copyright', ids.get_rights ())
-        set_if_exists ('composer', ids.get_composer ())
-        set_if_exists ('arranger', ids.get_arranger ())
-        set_if_exists ('editor', ids.get_editor ())
-        set_if_exists ('poet', ids.get_poet ())
-
-        set_if_exists ('encodingsoftware', ids.get_encoding_software ())
-        set_if_exists ('encodingdate', ids.get_encoding_date ())
-        set_if_exists ('encoder', ids.get_encoding_person ())
-        set_if_exists ('encodingdescription', ids.get_encoding_description ())
-
-        set_if_exists ('source', ids.get_source ())
-
-        # miscellaneous --> texidoc
-        set_if_exists ('texidoc', ids.get_file_description ());
+        set_if_exists('copyright', ids.get_rights())
+        set_if_exists('composer', ids.get_composer())
+        set_if_exists('arranger', ids.get_arranger())
+        set_if_exists('editor', ids.get_editor())
+        set_if_exists('poet', ids.get_poet())
+
+        set_if_exists('encodingsoftware', ids.get_encoding_software())
+        set_if_exists('encodingdate', ids.get_encoding_date())
+        set_if_exists('encoder', ids.get_encoding_person())
+        set_if_exists('encodingdescription', ids.get_encoding_description())
+        set_if_exists('source', ids.get_source())
+
+        # <miscellaneous><miscellaneous-field name="description"> ... becomes
+        # \header { texidoc = ...
+        set_if_exists('texidoc', ids.get_file_description());
 
         # Finally, apply the required compatibility modes
         # Some applications created wrong MusicXML files, so we need to
         # apply some compatibility mode, e.g. ignoring some features/tags
         # in those files
-        software = ids.get_encoding_software_list ()
+        software = ids.get_encoding_software_list()
 
         # Case 1: "Sibelius 5.1" with the "Dolet 3.4 for Sibelius" plugin
         #         is missing all beam ends => ignore all beaming information
@@ -222,179 +254,204 @@ def extract_score_information (tree):
             "Noteworthy Composer": "Noteworthy Composer's nwc2xm[",
         }
         for s in software:
-            app_description = ignore_beaming_software.get (s, False);
+            app_description = ignore_beaming_software.get(s, False);
             if app_description:
                 conversion_settings.ignore_beaming = True
-                ly.warning (_ ("Encountered file created by %s, containing "
+                ly.warning(_("Encountered file created by %s, containing "
                                "wrong beaming information. All beaming "
                                "information in the MusicXML file will be "
                                "ignored") % app_description)
 
+    credits = tree.get_named_children('credit')
+    has_composer = False
+    for cred in credits:
+        type = credit_dict.get(cred.get_type())
+        if(type == None):
+            type = credit_dict.get(cred.find_type(credits))
+        if(type == 'composer'):
+            if(has_composer):
+                type = 'poet'
+            else:
+                has_composer = True
+            set_if_exists(type, cred.get_text())
+        elif(type == 'title'):
+            if(not(work) and not(movement_title)):
+                set_if_exists('title', cred.get_text())
+            #elif(not(movement_title)): #bullshit!
+            #    set_if_exists('subtitle', cred.get_text()) #bullshit! otherwise both title and subtitle show the work-title.
+        elif(type == None):
+            pass
+        else:
+            set_if_exists(type, cred.get_text())
+
+
     # TODO: Check for other unsupported features
     return header
 
 class PartGroupInfo:
-    def __init__ (self):
+    def __init__(self):
         self.start = {}
         self.end = {}
-    def is_empty (self):
-        return len (self.start) + len (self.end) == 0
-    def add_start (self, g):
-        self.start[getattr (g, 'number', "1")] = g
-    def add_end (self, g):
-        self.end[getattr (g, 'number', "1")] = g
-    def print_ly (self, printer):
-        ly.warning (_ ("Unprocessed PartGroupInfo %s encountered") % self)
-    def ly_expression (self):
-        ly.warning (_ ("Unprocessed PartGroupInfo %s encountered") % self)
+    def is_empty(self):
+        return len(self.start) + len(self.end) == 0
+    def add_start(self, g):
+        self.start[getattr(g, 'number', "1")] = g
+    def add_end(self, g):
+        self.end[getattr(g, 'number', "1")] = g
+    def print_ly(self, printer):
+        ly.warning(_("Unprocessed PartGroupInfo %s encountered") % self)
+    def ly_expression(self):
+        ly.warning(_("Unprocessed PartGroupInfo %s encountered") % self)
         return ''
 
-def musicxml_step_to_lily (step):
-    if step:
-        return (ord (step) - ord ('A') + 7 - 2) % 7
-    else:
-        return None
-
-
-def staff_attributes_to_string_tunings (mxl_attr):
-    details = mxl_attr.get_maybe_exist_named_child ('staff-details')
+def staff_attributes_to_string_tunings(mxl_attr):
+    details = mxl_attr.get_maybe_exist_named_child('staff-details')
     if not details:
         return []
     lines = 6
-    staff_lines = details.get_maybe_exist_named_child ('staff-lines')
+    staff_lines = details.get_maybe_exist_named_child('staff-lines')
     if staff_lines:
-        lines = string.atoi (staff_lines.get_text ())
-
+        lines = string.atoi(staff_lines.get_text())
     tunings = [musicexp.Pitch()] * lines
-    staff_tunings = details.get_named_children ('staff-tuning')
+    staff_tunings = details.get_named_children('staff-tuning')
     for i in staff_tunings:
         p = musicexp.Pitch()
         line = 0
         try:
-            line = string.atoi (i.line) - 1
+            line = string.atoi(i.line) - 1
         except ValueError:
             pass
         tunings[line] = p
 
-        step = i.get_named_child (u'tuning-step')
-        step = step.get_text ().strip ()
-        p.step = musicxml_step_to_lily (step)
+        step = i.get_named_child(u'tuning-step')
+        step = step.get_text().strip()
+        p.step = musicxml2ly_conversion.musicxml_step_to_lily(step)
 
-        octave = i.get_named_child (u'tuning-octave')
-        octave = octave.get_text ().strip ()
-        p.octave = int (octave) - 4
+        octave = i.get_named_child(u'tuning-octave')
+        octave = octave.get_text().strip()
+        p.octave = int(octave) - 4
 
-        alter = i.get_named_child (u'tuning-alter')
+        alter = i.get_named_child(u'tuning-alter')
         if alter:
-            p.alteration = int (alter.get_text ().strip ())
+            p.alteration = int(alter.get_text().strip())
     # lilypond seems to use the opposite ordering than MusicXML...
-    tunings.reverse ()
-
+    tunings.reverse()
     return tunings
 
-
-def staff_attributes_to_lily_staff (mxl_attr):
+def staff_attributes_to_lily_staff(mxl_attr):
     if not mxl_attr:
-        return musicexp.Staff ()
+        return musicexp.Staff()
 
-    (staff_id, attributes) = mxl_attr.items ()[0]
+    (staff_id, attributes) = mxl_attr.items()[0]
 
     # distinguish by clef:
-    # percussion (percussion and rhythmic), tab, and everything else
+    # percussion(percussion and rhythmic), tab, and everything else
     clef_sign = None
-    clef = attributes.get_maybe_exist_named_child ('clef')
+    clef = attributes.get_maybe_exist_named_child('clef')
     if clef:
-        sign = clef.get_maybe_exist_named_child ('sign')
+        sign = clef.get_maybe_exist_named_child('sign')
         if sign:
-            clef_sign = {"percussion": "percussion", "TAB": "tab"}.get (sign.get_text (), None)
+            clef_sign = {"percussion": "percussion", "TAB": "tab"}.get(sign.get_text(), None)
 
     lines = 5
-    details = attributes.get_named_children ('staff-details')
+    details = attributes.get_named_children('staff-details')
     for d in details:
-        staff_lines = d.get_maybe_exist_named_child ('staff-lines')
+        staff_lines = d.get_maybe_exist_named_child('staff-lines')
         if staff_lines:
-            lines = string.atoi (staff_lines.get_text ())
+            lines = string.atoi(staff_lines.get_text())
 
     # TODO: Handle other staff attributes like staff-space, etc.
 
     staff = None
     if clef_sign == "percussion" and lines == 1:
-        staff = musicexp.RhythmicStaff ()
+        staff = musicexp.RhythmicStaff()
     elif clef_sign == "percussion":
-        staff = musicexp.DrumStaff ()
+        staff = musicexp.DrumStaff()
         # staff.drum_style_table = ???
     elif clef_sign == "tab":
-        staff = musicexp.TabStaff ()
-        staff.string_tunings = staff_attributes_to_string_tunings (attributes)
+        staff = musicexp.TabStaff()
+        staff.string_tunings = staff_attributes_to_string_tunings(attributes)
         # staff.tablature_format = ???
     else:
-        staff = musicexp.Staff ()
+        staff = musicexp.Staff()
         # TODO: Handle case with lines <> 5!
-        if (lines != 5):
-            staff.add_context_modification ("\\override StaffSymbol.line-count = #%s" % lines)
-
+        if(lines != 5):
+            staff.add_context_modification("\\override StaffSymbol #'line-count = #%s" % lines)
 
     return staff
 
+def extract_instrument_sound(score_part):
+    score_instrument = score_part.get_maybe_exist_named_child('score-instrument')
+    if not score_instrument:
+        return None
+    sound = score_instrument.get_maybe_exist_named_child('instrument-sound')
+    if sound:
+        return utilities.musicxml_sound_to_lilypond_midi_instrument(sound.get_text())
 
-def extract_score_structure (part_list, staffinfo):
-    score = musicexp.Score ()
-    structure = musicexp.StaffGroup (None)
-    score.set_contents (structure)
+def extract_score_structure(part_list, staffinfo):
+    score = musicexp.Score()
+    structure = musicexp.StaffGroup(None)
+    score.set_contents(structure)
 
     if not part_list:
         return structure
 
-    def read_score_part (el):
-        if not isinstance (el, musicxml.Score_part):
+    def read_score_part(el):
+        if not isinstance(el, musicxml.Score_part):
             return
         # Depending on the attributes of the first measure, we create different
-        # types of staves (Staff, RhythmicStaff, DrumStaff, TabStaff, etc.)
-        staff = staff_attributes_to_lily_staff (staffinfo.get (el.id, None))
+        # types of staves(Staff, RhythmicStaff, DrumStaff, TabStaff, etc.)
+        staff = staff_attributes_to_lily_staff(staffinfo.get(el.id, None))
         if not staff:
             return None
         staff.id = el.id
-        partname = el.get_maybe_exist_named_child ('part-name')
+        partname = el.get_maybe_exist_named_child('part-name')
         # Finale gives unnamed parts the name "MusicXML Part" automatically!
         if partname and partname.get_text() != "MusicXML Part":
-            staff.instrument_name = partname.get_text ()
+            staff.instrument_name = partname.get_text()
         # part-name-display overrides part-name!
-        partname = el.get_maybe_exist_named_child ("part-name-display")
+        partname = el.get_maybe_exist_named_child("part-name-display")
         if partname:
-            staff.instrument_name = extract_display_text (partname)
-
-        partdisplay = el.get_maybe_exist_named_child ('part-abbreviation')
+            staff.instrument_name = extract_display_text(partname)
+        if hasattr(options, 'midi') and options.midi:
+            staff.sound = extract_instrument_sound(el)
+        if staff.instrument_name:
+            paper.indent = max(paper.indent, len(staff.instrument_name))
+            paper.instrument_names.append(staff.instrument_name)
+        partdisplay = el.get_maybe_exist_named_child('part-abbreviation')
         if partdisplay:
-            staff.short_instrument_name = partdisplay.get_text ()
+            staff.short_instrument_name = partdisplay.get_text()
         # part-abbreviation-display overrides part-abbreviation!
-        partdisplay = el.get_maybe_exist_named_child ("part-abbreviation-display")
+        partdisplay = el.get_maybe_exist_named_child("part-abbreviation-display")
         if partdisplay:
-            staff.short_instrument_name = extract_display_text (partdisplay)
+            staff.short_instrument_name = extract_display_text(partdisplay)
         # TODO: Read in the MIDI device / instrument
+        if staff.short_instrument_name:
+            paper.short_indent = max(paper.short_indent, len(staff.short_instrument_name))
 
         return staff
 
-    def read_score_group (el):
-        if not isinstance (el, musicxml.Part_group):
+    def read_score_group(el):
+        if not isinstance(el, musicxml.Part_group):
             return
-        group = musicexp.StaffGroup ()
-        if hasattr (el, 'number'):
+        group = musicexp.StaffGroup()
+        if hasattr(el, 'number'):
             id = el.number
             group.id = id
             #currentgroups_dict[id] = group
-            #currentgroups.append (id)
-        if el.get_maybe_exist_named_child ('group-name'):
-            group.instrument_name = el.get_maybe_exist_named_child ('group-name').get_text ()
-        if el.get_maybe_exist_named_child ('group-abbreviation'):
-            group.short_instrument_name = el.get_maybe_exist_named_child ('group-abbreviation').get_text ()
-        if el.get_maybe_exist_named_child ('group-symbol'):
-            group.symbol = el.get_maybe_exist_named_child ('group-symbol').get_text ()
-        if el.get_maybe_exist_named_child ('group-barline'):
-            group.spanbar = el.get_maybe_exist_named_child ('group-barline').get_text ()
+            #currentgroups.append(id)
+        if el.get_maybe_exist_named_child('group-name'):
+            group.instrument_name = el.get_maybe_exist_named_child('group-name').get_text()
+        if el.get_maybe_exist_named_child('group-abbreviation'):
+            group.short_instrument_name = el.get_maybe_exist_named_child('group-abbreviation').get_text()
+        if el.get_maybe_exist_named_child('group-symbol'):
+            group.symbol = el.get_maybe_exist_named_child('group-symbol').get_text()
+        if el.get_maybe_exist_named_child('group-barline'):
+            group.spanbar = el.get_maybe_exist_named_child('group-barline').get_text()
         return group
 
 
-    parts_groups = part_list.get_all_children ()
+    parts_groups = part_list.get_all_children()
 
     # the start/end group tags are not necessarily ordered correctly and groups
     # might even overlap, so we can't go through the children sequentially!
@@ -402,146 +459,102 @@ def extract_score_structure (part_list, staffinfo):
     # 1) Replace all Score_part objects by their corresponding Staff objects,
     #    also collect all group start/stop points into one PartGroupInfo object
     staves = []
-    group_info = PartGroupInfo ()
+    group_info = PartGroupInfo()
     for el in parts_groups:
-        if isinstance (el, musicxml.Score_part):
-            if not group_info.is_empty ():
-                staves.append (group_info)
-                group_info = PartGroupInfo ()
-            staff = read_score_part (el)
+        if isinstance(el, musicxml.Score_part):
+            if not group_info.is_empty():
+                staves.append(group_info)
+                group_info = PartGroupInfo()
+            staff = read_score_part(el)
             if staff:
-                staves.append (staff)
-        elif isinstance (el, musicxml.Part_group):
+                staves.append(staff)
+        elif isinstance(el, musicxml.Part_group):
             if el.type == "start":
-                group_info.add_start (el)
+                group_info.add_start(el)
             elif el.type == "stop":
-                group_info.add_end (el)
-    if not group_info.is_empty ():
-        staves.append (group_info)
+                group_info.add_end(el)
+    if not group_info.is_empty():
+        staves.append(group_info)
 
     # 2) Now, detect the groups:
     group_starts = []
     pos = 0
-    while pos < len (staves):
+    while pos < len(staves):
         el = staves[pos]
-        if isinstance (el, PartGroupInfo):
+        if isinstance(el, PartGroupInfo):
             prev_start = 0
-            if len (group_starts) > 0:
+            if len(group_starts) > 0:
                 prev_start = group_starts[-1]
-            elif len (el.end) > 0: # no group to end here
+            elif len(el.end) > 0: # no group to end here
                 el.end = {}
-            if len (el.end) > 0: # closes an existing group
-                ends = el.end.keys ()
-                prev_started = staves[prev_start].start.keys ()
+            if len(el.end) > 0: # closes an existing group
+                ends = el.end.keys()
+                prev_started = staves[prev_start].start.keys()
                 grpid = None
                 intersection = filter(lambda x:x in ends, prev_started)
-                if len (intersection) > 0:
+                if len(intersection) > 0:
                     grpid = intersection[0]
                 else:
                     # Close the last started group
-                    grpid = staves[prev_start].start.keys () [0]
+                    grpid = staves[prev_start].start.keys() [0]
                     # Find the corresponding closing tag and remove it!
                     j = pos + 1
                     foundclosing = False
-                    while j < len (staves) and not foundclosing:
-                        if isinstance (staves[j], PartGroupInfo) and staves[j].end.has_key (grpid):
+                    while j < len(staves) and not foundclosing:
+                        if isinstance(staves[j], PartGroupInfo) and staves[j].end.has_key(grpid):
                             foundclosing = True
                             del staves[j].end[grpid]
-                            if staves[j].is_empty ():
+                            if staves[j].is_empty():
                                 del staves[j]
                         j += 1
                 grpobj = staves[prev_start].start[grpid]
-                group = read_score_group (grpobj)
+                group = read_score_group(grpobj)
                 # remove the id from both the start and end
-                if el.end.has_key (grpid):
+                if el.end.has_key(grpid):
                     del el.end[grpid]
                 del staves[prev_start].start[grpid]
-                if el.is_empty ():
+                if el.is_empty():
                     del staves[pos]
                 # replace the staves with the whole group
                 for j in staves[(prev_start + 1):pos]:
-                    group.append_staff (j)
+                    group.append_staff(j)
                 del staves[(prev_start + 1):pos]
-                staves.insert (prev_start + 1, group)
+                staves.insert(prev_start + 1, group)
                 # reset pos so that we continue at the correct position
                 pos = prev_start
                 # remove an empty start group
-                if staves[prev_start].is_empty ():
+                if staves[prev_start].is_empty():
                     del staves[prev_start]
-                    group_starts.remove (prev_start)
+                    group_starts.remove(prev_start)
                     pos -= 1
-            elif len (el.start) > 0: # starts new part groups
-                group_starts.append (pos)
+            elif len(el.start) > 0: # starts new part groups
+                group_starts.append(pos)
         pos += 1
 
     for i in staves:
-        structure.append_staff (i)
+        structure.append_staff(i)
     return score
 
 
-def musicxml_duration_to_lily (mxl_note):
-    # if the note has no Type child, then that method returns None. In that case,
-    # use the <duration> tag instead. If that doesn't exist, either -> Error
-    dur = mxl_note.get_duration_info ()
-    if dur:
-        d = musicexp.Duration ()
-        d.duration_log = dur[0]
-        d.dots = dur[1]
-        # Grace notes by specification have duration 0, so no time modification
-        # factor is possible. It even messes up the output with *0/1
-        if not mxl_note.get_maybe_exist_typed_child (musicxml.Grace):
-            d.factor = mxl_note._duration / d.get_length ()
-        return d
-
-    else:
-        if mxl_note._duration > 0:
-            return rational_to_lily_duration (mxl_note._duration)
-        else:
-            mxl_note.message (_ ("Encountered note at %s without type and duration (=%s)") % (mxl_note.start, mxl_note._duration) )
-            return None
-
-
-def rational_to_lily_duration (rational_len):
-    d = musicexp.Duration ()
 
-    rational_len.normalize_self ()
-    d_log = {1: 0, 2: 1, 4:2, 8:3, 16:4, 32:5, 64:6, 128:7, 256:8, 512:9}.get (rational_len.denominator (), -1)
-
-    # Duration of the form 1/2^n or 3/2^n can be converted to a simple lilypond duration
-    dots = {1: 0, 3: 1, 7: 2, 15: 3, 31: 4, 63: 5, 127: 6}.get (rational_len.numerator(), -1)
-    if ( d_log >= dots >= 0 ):
-        # account for the dots!
-        d.duration_log = d_log - dots
-        d.dots = dots
-    elif (d_log >= 0):
-        d.duration_log = d_log
-        d.factor = Rational (rational_len.numerator ())
-    else:
-        ly.warning (_ ("Encountered rational duration with denominator %s, "
-                       "unable to convert to lilypond duration") %
-                    rational_len.denominator ())
-        # TODO: Test the above error message
-        return None
 
-    return d
-
-def musicxml_partial_to_lily (partial_len):
+def musicxml_partial_to_lily(partial_len):
     if partial_len > 0:
-        p = musicexp.Partial ()
-        p.partial = rational_to_lily_duration (partial_len)
+        p = musicexp.Partial()
+        p.partial = musicxml2ly_conversion.rational_to_lily_duration(partial_len)
         return p
     else:
         return None
 
-# Detect repeats and alternative endings in the chord event list (music_list)
+# Detect repeats and alternative endings in the chord event list(music_list)
 # and convert them to the corresponding musicexp objects, containing nested
 # music
-def group_repeats (music_list):
+def group_repeats(music_list):
     repeat_replaced = True
     music_start = 0
     i = 0
     # Walk through the list of expressions, looking for repeat structure
-    # (repeat start/end, corresponding endings). If we find one, try to find the
+    #(repeat start/end, corresponding endings). If we find one, try to find the
     # last event of the repeat, replace the whole structure and start over again.
     # For nested repeats, as soon as we encounter another starting repeat bar,
     # treat that one first, and start over for the outer repeat.
@@ -553,13 +566,13 @@ def group_repeats (music_list):
         ending_start = -1 # position of current ending start
         endings = [] # list of already finished endings
         pos = 0
-        last = len (music_list) - 1
+        last = len(music_list) - 1
         repeat_replaced = False
         final_marker = 0
-        while pos < len (music_list) and not repeat_replaced:
+        while pos < len(music_list) and not repeat_replaced:
             e = music_list[pos]
             repeat_finished = False
-            if isinstance (e, RepeatMarker):
+            if isinstance(e, musicxml2ly_conversion.RepeatMarker):
                 if not repeat_times and e.times:
                     repeat_times = e.times
                 if e.direction == -1:
@@ -576,7 +589,7 @@ def group_repeats (music_list):
                     if repeat_end < 0:
                         repeat_end = pos
                     final_marker = pos
-            elif isinstance (e, EndingMarker):
+            elif isinstance(e, musicxml2ly_conversion.EndingMarker):
                 if e.direction == -1:
                     if repeat_start < 0:
                         repeat_start = 0
@@ -586,17 +599,17 @@ def group_repeats (music_list):
                 elif e.direction == 1:
                     if ending_start < 0:
                         ending_start = 0
-                    endings.append ([ending_start, pos])
+                    endings.append([ending_start, pos])
                     ending_start = -1
                     final_marker = pos
-            elif not isinstance (e, musicexp.BarLine):
+            elif not isinstance(e, musicexp.BarLine):
                 # As soon as we encounter an element when repeat start and end
                 # is set and we are not inside an alternative ending,
                 # this whole repeat structure is finished => replace it
                 if repeat_start >= 0 and repeat_end > 0 and ending_start < 0:
                     repeat_finished = True
 
-            # Finish off all repeats without explicit ending bar (e.g. when
+            # Finish off all repeats without explicit ending bar(e.g. when
             # we convert only one page of a multi-page score with repeats)
             if pos == last and repeat_start >= 0:
                 repeat_finished = True
@@ -604,27 +617,27 @@ def group_repeats (music_list):
                 if repeat_end < 0:
                     repeat_end = pos
                 if ending_start >= 0:
-                    endings.append ([ending_start, pos])
+                    endings.append([ending_start, pos])
                     ending_start = -1
 
             if repeat_finished:
                 # We found the whole structure replace it!
-                r = musicexp.RepeatedMusic ()
+                r = musicexp.RepeatedMusic()
                 if repeat_times <= 0:
                     repeat_times = 2
                 r.repeat_count = repeat_times
-                # don't erase the first element for "implicit" repeats (i.e. no
+                # don't erase the first element for "implicit" repeats(i.e. no
                 # starting repeat bars at the very beginning)
                 start = repeat_start + 1
                 if repeat_start == music_start:
                     start = music_start
-                r.set_music (music_list[start:repeat_end])
-                for (start, end) in endings:
-                    s = musicexp.SequentialMusic ()
+                r.set_music(music_list[start:repeat_end])
+                for(start, end) in endings:
+                    s = musicexp.SequentialMusic()
                     s.elements = music_list[start + 1:end]
-                    r.add_ending (s)
+                    r.add_ending(s)
                 del music_list[repeat_start:final_marker + 1]
-                music_list.insert (repeat_start, r)
+                music_list.insert(repeat_start, r)
                 repeat_replaced = True
             pos += 1
         # TODO: Implement repeats until the end without explicit ending bar
@@ -633,148 +646,160 @@ def group_repeats (music_list):
 
 # Extract the settings for tuplets from the <notations><tuplet> and the
 # <time-modification> elements of the note:
-def musicxml_tuplet_to_lily (tuplet_elt, time_modification):
-    tsm = musicexp.TimeScaledMusic ()
-    fraction = (1, 1)
+def musicxml_tuplet_to_lily(tuplet_elt, time_modification):
+    tsm = musicexp.TimeScaledMusic()
+    fraction =(1, 1)
     if time_modification:
-        fraction = time_modification.get_fraction ()
+        fraction = time_modification.get_fraction()
     tsm.numerator = fraction[0]
     tsm.denominator = fraction[1]
 
 
-    normal_type = tuplet_elt.get_normal_type ()
+    normal_type = tuplet_elt.get_normal_type()
     if not normal_type and time_modification:
-        normal_type = time_modification.get_normal_type ()
+        normal_type = time_modification.get_normal_type()
     if not normal_type and time_modification:
-        note = time_modification.get_parent ()
+        note = time_modification.get_parent()
         if note:
-            normal_type = note.get_duration_info ()
+            normal_type = note.get_duration_info()
     if normal_type:
-        normal_note = musicexp.Duration ()
+        normal_note = musicexp.Duration()
         (normal_note.duration_log, normal_note.dots) = normal_type
         tsm.normal_type = normal_note
 
-    actual_type = tuplet_elt.get_actual_type ()
+    actual_type = tuplet_elt.get_actual_type()
     if actual_type:
-        actual_note = musicexp.Duration ()
+        actual_note = musicexp.Duration()
         (actual_note.duration_log, actual_note.dots) = actual_type
         tsm.actual_type = actual_note
 
     # Obtain non-default nrs of notes from the tuplet object!
-    tsm.display_numerator = tuplet_elt.get_normal_nr ()
-    tsm.display_denominator = tuplet_elt.get_actual_nr ()
+    tsm.display_numerator = tuplet_elt.get_normal_nr()
+    tsm.display_denominator = tuplet_elt.get_actual_nr()
 
 
-    if hasattr (tuplet_elt, 'bracket') and tuplet_elt.bracket == "no":
+    if hasattr(tuplet_elt, 'bracket') and tuplet_elt.bracket == "no":
         tsm.display_bracket = None
-    elif hasattr (tuplet_elt, 'line-shape') and getattr (tuplet_elt, 'line-shape') == "curved":
+    elif hasattr(tuplet_elt, 'line-shape') and getattr(tuplet_elt, 'line-shape') == "curved":
         tsm.display_bracket = "curved"
     else:
         tsm.display_bracket = "bracket"
 
     display_values = {"none": None, "actual": "actual", "both": "both"}
-    if hasattr (tuplet_elt, "show-number"):
-        tsm.display_number = display_values.get (getattr (tuplet_elt, "show-number"), "actual")
+    if hasattr(tuplet_elt, "show-number"):
+        tsm.display_number = display_values.get(getattr(tuplet_elt, "show-number"), "actual")
 
-    if hasattr (tuplet_elt, "show-type"):
-        tsm.display_type = display_values.get (getattr (tuplet_elt, "show-type"), None)
+    if hasattr(tuplet_elt, "show-type"):
+        tsm.display_type = display_values.get(getattr(tuplet_elt, "show-type"), None)
 
     return tsm
 
 
-def group_tuplets (music_list, events):
+def group_tuplets(music_list, events):
 
 
     """Collect Musics from
     MUSIC_LIST demarcated by EVENTS_LIST in TimeScaledMusic objects.
     """
 
-
     indices = []
     brackets = {}
 
     j = 0
-    for (ev_chord, tuplet_elt, time_modification) in events:
-        while (j < len (music_list)):
+    for(ev_chord, tuplet_elt, time_modification) in events:
+        while(j < len(music_list)):
             if music_list[j] == ev_chord:
                 break
             j += 1
         nr = 0
-        if hasattr (tuplet_elt, 'number'):
-            nr = getattr (tuplet_elt, 'number')
+        if hasattr(tuplet_elt, 'number'):
+            nr = getattr(tuplet_elt, 'number')
         if tuplet_elt.type == 'start':
-            tuplet_object = musicxml_tuplet_to_lily (tuplet_elt, time_modification)
+            tuplet_object = musicxml_tuplet_to_lily(tuplet_elt, time_modification)
             tuplet_info = [j, None, tuplet_object]
-            indices.append (tuplet_info)
+            indices.append(tuplet_info)
             brackets[nr] = tuplet_info
         elif tuplet_elt.type == 'stop':
-            bracket_info = brackets.get (nr, None)
+            bracket_info = brackets.get(nr, None)
             if bracket_info:
                 bracket_info[1] = j # Set the ending position to j
                 del brackets[nr]
 
     new_list = []
     last = 0
-    for (i1, i2, tsm) in indices:
+    for(i1, i2, tsm) in indices:
         if i1 > i2:
             continue
 
-        new_list.extend (music_list[last:i1])
-        seq = musicexp.SequentialMusic ()
+        new_list.extend(music_list[last:i1])
+        seq = musicexp.SequentialMusic()
         last = i2 + 1
+
+        # At this point music_list[i1:last] encompasses all the notes of the
+        # tuplet. There might be dynamics following this range, however, which
+        # apply to the last note of the tuplet. Advance last to include them
+        # in the range.
+        while last < len(music_list) and isinstance(music_list[last], musicexp.DynamicsEvent):
+            last += 1
+
         seq.elements = music_list[i1:last]
 
         tsm.element = seq
 
-        new_list.append (tsm)
+        new_list.append(tsm)
         #TODO: Handle nested tuplets!!!!
 
-    new_list.extend (music_list[last:])
+    new_list.extend(music_list[last:])
     return new_list
 
 
-def musicxml_clef_to_lily (attributes):
-    change = musicexp.ClefChange ()
-    (change.type, change.position, change.octave) = attributes.get_clef_information ()
+def musicxml_clef_to_lily(attributes):
+    change = musicexp.ClefChange()
+    (change.type, change.position, change.octave) = attributes.get_clef_information()
     return change
 
-def musicxml_time_to_lily (attributes):
-    sig = attributes.get_time_signature ()
+def musicxml_time_to_lily(attributes):
+    change = musicexp.TimeSignatureChange()
+    # time signature function
+    if hasattr(options, 'shift_meter') and options.shift_meter:
+        tmp_meter = options.shift_meter.split("/",1)
+        sig = [int(tmp_meter[0]), int(tmp_meter[1])]
+        change.originalFractions = attributes.get_time_signature()
+    else:
+        sig = attributes.get_time_signature()
     if not sig:
         return None
-    change = musicexp.TimeSignatureChange()
     change.fractions = sig
 
-    time_elm = attributes.get_maybe_exist_named_child ('time')
-    if time_elm and hasattr (time_elm, 'symbol'):
+    time_elm = attributes.get_maybe_exist_named_child('time')
+    if time_elm and hasattr(time_elm, 'symbol'):
         change.style = { 'single-number': "'single-digit",
                          'cut': None,
                          'common': None,
-                         'normal': "'()"}.get (time_elm.symbol, "'()")
+                         'normal': "'()"}.get(time_elm.symbol, "'()")
     else:
         change.style = "'()"
 
     # TODO: Handle senza-misura measures
-    # TODO: Handle hidden time signatures (print-object="no")
+    # TODO: Handle hidden time signatures(print-object="no")
     # TODO: What shall we do if the symbol clashes with the sig? e.g. "cut"
-    #       with 3/8 or "single-number" with (2+3)/8 or 3/8+2/4?
-
+    #       with 3/8 or "single-number" with(2+3)/8 or 3/8+2/4?
     return change
 
-def musicxml_key_to_lily (attributes):
-    key_sig = attributes.get_key_signature ()
-    if not key_sig or not (isinstance (key_sig, list) or isinstance (key_sig, tuple)):
-        ly.warning (_ ("Unable to extract key signature!"))
+def musicxml_key_to_lily(attributes):
+    key_sig = attributes.get_key_signature()
+    if not key_sig or not(isinstance(key_sig, list) or isinstance(key_sig, tuple)):
+        ly.warning(_("Unable to extract key signature!"))
         return None
 
     change = musicexp.KeySignatureChange()
 
-    if len (key_sig) == 2 and not isinstance (key_sig[0], list):
-        # standard key signature, (fifths, mode)
+    if len(key_sig) == 2 and not isinstance(key_sig[0], list):
+        # standard key signature,(fifths, mode)
         (fifths, mode) = key_sig
         change.mode = mode
 
-        start_pitch = musicexp.Pitch ()
+        start_pitch = musicexp.Pitch()
         start_pitch.octave = 0
         try:
             (n, a) = {
@@ -791,7 +816,7 @@ def musicxml_key_to_lily (attributes):
             start_pitch.step = n
             start_pitch.alteration = a
         except  KeyError:
-            ly.warning (_ ("unknown mode %s, expecting 'major' or 'minor' "
+            ly.warning(_("unknown mode %s, expecting 'major' or 'minor' "
                 "or a church mode!") % mode)
 
         fifth = musicexp.Pitch()
@@ -799,9 +824,9 @@ def musicxml_key_to_lily (attributes):
         if fifths < 0:
             fifths *= -1
             fifth.step *= -1
-            fifth.normalize ()
-        for x in range (fifths):
-            start_pitch = start_pitch.transposed (fifth)
+            fifth.normalize()
+        for x in range(fifths):
+            start_pitch = start_pitch.transposed(fifth)
         change.tonic = start_pitch
 
     else:
@@ -809,21 +834,21 @@ def musicxml_key_to_lily (attributes):
         # MusicXML contains C,D,E,F,G,A,B as steps, lily uses 0-7, so convert
         alterations = []
         for k in key_sig:
-            k[0] = musicxml_step_to_lily (k[0])
-            alterations.append (k)
+            k[0] = musicxml2ly_conversion.musicxml_step_to_lily(k[0])
+            alterations.append(k)
         change.non_standard_alterations = alterations
     return change
 
-def musicxml_transpose_to_lily (attributes):
-    transpose = attributes.get_transposition ()
+def musicxml_transpose_to_lily(attributes):
+    transpose = attributes.get_transposition()
     if not transpose:
         return None
 
-    shift = musicexp.Pitch ()
-    octave_change = transpose.get_maybe_exist_named_child ('octave-change')
+    shift = musicexp.Pitch()
+    octave_change = transpose.get_maybe_exist_named_child('octave-change')
     if octave_change:
-        shift.octave = string.atoi (octave_change.get_text ())
-    chromatic_shift = string.atoi (transpose.get_named_child ('chromatic').get_text ())
+        shift.octave = string.atoi(octave_change.get_text())
+    chromatic_shift = string.atoi(transpose.get_named_child('chromatic').get_text())
     chromatic_shift_normalized = chromatic_shift % 12;
     (shift.step, shift.alteration) = [
         (0, 0), (0, 1), (1, 0), (2, -1), (2, 0),
@@ -832,38 +857,38 @@ def musicxml_transpose_to_lily (attributes):
 
     shift.octave += (chromatic_shift - chromatic_shift_normalized) / 12
 
-    diatonic = transpose.get_maybe_exist_named_child ('diatonic')
+    diatonic = transpose.get_maybe_exist_named_child('diatonic')
     if diatonic:
-        diatonic_step = string.atoi (diatonic.get_text ()) % 7
+        diatonic_step = string.atoi(diatonic.get_text()) % 7
         if diatonic_step != shift.step:
             # We got the alter incorrect!
-            old_semitones = shift.semitones ()
+            old_semitones = shift.semitones()
             shift.step = diatonic_step
-            new_semitones = shift.semitones ()
+            new_semitones = shift.semitones()
             shift.alteration += old_semitones - new_semitones
 
-    transposition = musicexp.Transposition ()
-    transposition.pitch = musicexp.Pitch ().transposed (shift)
+    transposition = musicexp.Transposition()
+    transposition.pitch = musicexp.Pitch().transposed(shift)
     return transposition
 
-def musicxml_staff_details_to_lily (attributes):
-    details = attributes.get_maybe_exist_named_child ('staff-details')
+def musicxml_staff_details_to_lily(attributes):
+    details = attributes.get_maybe_exist_named_child('staff-details')
     if not details:
         return None
 
     ## TODO: Handle staff-type, staff-lines, staff-tuning, capo, staff-size
     ret = []
 
-    stafflines = details.get_maybe_exist_named_child ('staff-lines')
+    stafflines = details.get_maybe_exist_named_child('staff-lines')
     if stafflines:
-        lines = string.atoi (stafflines.get_text ());
-        lines_event = musicexp.StaffLinesEvent (lines);
-        ret.append (lines_event);
+        lines = string.atoi(stafflines.get_text());
+        lines_event = musicexp.StaffLinesEvent(lines);
+        ret.append(lines_event);
 
     return ret;
 
 
-def musicxml_attributes_to_lily (attrs):
+def musicxml_attributes_to_lily(attrs):
     elts = []
     attr_dispatch = {
         'clef': musicxml_clef_to_lily,
@@ -872,27 +897,27 @@ def musicxml_attributes_to_lily (attrs):
         'transpose': musicxml_transpose_to_lily,
         'staff-details': musicxml_staff_details_to_lily,
     }
-    for (k, func) in attr_dispatch.items ():
-        children = attrs.get_named_children (k)
+    for (k, func) in attr_dispatch.items():
+        children = attrs.get_named_children(k)
         if children:
-            ev = func (attrs)
-            if isinstance (ev, list):
+            ev = func(attrs)
+            if isinstance(ev, list):
               for e in ev:
-                elts.append (e)
+                elts.append(e)
             elif ev:
-                elts.append (ev)
+                elts.append(ev)
 
     return elts
 
-def extract_display_text (el):
-    child = el.get_maybe_exist_named_child ("display-text")
+def extract_display_text(el):
+    child = el.get_maybe_exist_named_child("display-text")
     if child:
-        return child.get_text ()
+        return child.get_text()
     else:
         return False
 
 
-def musicxml_print_to_lily (el):
+def musicxml_print_to_lily(el):
     # TODO: Implement other print attributes
     #  <!ELEMENT print (page-layout?, system-layout?, staff-layout*,
     #          measure-layout?, measure-numbering?, part-name-display?,
@@ -905,89 +930,26 @@ def musicxml_print_to_lily (el):
     #      page-number CDATA #IMPLIED
     #  >
     elts = []
-    if (hasattr (el, "new-system") and conversion_settings.convert_page_layout):
-        val = getattr (el, "new-system")
+    if (hasattr(el, "new-system") and conversion_settings.convert_system_breaks):
+        val = getattr(el, "new-system")
         if (val == "yes"):
-            elts.append (musicexp.Break ("break"))
-    if (hasattr (el, "new-page") and conversion_settings.convert_page_layout):
-        val = getattr (el, "new-page")
+            elts.append(musicexp.Break("break"))
+    if (hasattr(el, "new-page") and conversion_settings.convert_page_breaks):
+        val = getattr(el, "new-page")
         if (val == "yes"):
-            elts.append (musicexp.Break ("pageBreak"))
-    child = el.get_maybe_exist_named_child ("part-name-display")
+            elts.append(musicexp.Break("pageBreak"))
+    child = el.get_maybe_exist_named_child("part-name-display")
     if child:
-        elts.append (musicexp.SetEvent ("Staff.instrumentName",
-                                        "\"%s\"" % extract_display_text (child)))
-    child = el.get_maybe_exist_named_child ("part-abbreviation-display")
+        elts.append(musicexp.SetEvent("Staff.instrumentName",
+                                        "\"%s\"" % extract_display_text(child)))
+    child = el.get_maybe_exist_named_child("part-abbreviation-display")
     if child:
-        elts.append (musicexp.SetEvent ("Staff.shortInstrumentName",
-                                        "\"%s\"" % extract_display_text (child)))
+        elts.append(musicexp.SetEvent("Staff.shortInstrumentName",
+                                        "\"%s\"" % extract_display_text(child)))
     return elts
 
 
-class Marker (musicexp.Music):
-    def __init__ (self):
-        self.direction = 0
-        self.event = None
-    def print_ly (self, printer):
-        ly.warning (_ ("Encountered unprocessed marker %s\n") % self)
-        pass
-    def ly_expression (self):
-        return ""
-class RepeatMarker (Marker):
-    def __init__ (self):
-        Marker.__init__ (self)
-        self.times = 0
-class EndingMarker (Marker):
-    pass
-
-# Convert the <barline> element to musicxml.BarLine (for non-standard barlines)
-# and to RepeatMarker and EndingMarker objects for repeat and
-# alternatives start/stops
-def musicxml_barline_to_lily (barline):
-    # retval contains all possible markers in the order:
-    # 0..bw_ending, 1..bw_repeat, 2..barline, 3..fw_repeat, 4..fw_ending
-    retval = {}
-    bartype_element = barline.get_maybe_exist_named_child ("bar-style")
-    repeat_element = barline.get_maybe_exist_named_child ("repeat")
-    ending_element = barline.get_maybe_exist_named_child ("ending")
-
-    bartype = None
-    if bartype_element:
-        bartype = bartype_element.get_text ()
-
-    if repeat_element and hasattr (repeat_element, 'direction'):
-        repeat = RepeatMarker ()
-        repeat.direction = {"forward": -1, "backward": 1}.get (repeat_element.direction, 0)
-
-        if ( (repeat_element.direction == "forward" and bartype == "heavy-light") or
-             (repeat_element.direction == "backward" and bartype == "light-heavy") ):
-            bartype = None
-        if hasattr (repeat_element, 'times'):
-            try:
-                repeat.times = int (repeat_element.times)
-            except ValueError:
-                repeat.times = 2
-        repeat.event = barline
-        if repeat.direction == -1:
-            retval[3] = repeat
-        else:
-            retval[1] = repeat
-
-    if ending_element and hasattr (ending_element, 'type'):
-        ending = EndingMarker ()
-        ending.direction = {"start": -1, "stop": 1, "discontinue": 1}.get (ending_element.type, 0)
-        ending.event = barline
-        if ending.direction == -1:
-            retval[4] = ending
-        else:
-            retval[0] = ending
-
-    if bartype:
-        b = musicexp.BarLine ()
-        b.type = bartype
-        retval[2] = b
 
-    return retval.values ()
 
 spanner_event_dict = {
     'beam' : musicexp.BeamEvent,
@@ -998,119 +960,140 @@ spanner_event_dict = {
     'pedal' : musicexp.PedalEvent,
     'slide' : musicexp.GlissandoEvent,
     'slur' : musicexp.SlurEvent,
-    'wavy-line' : musicexp.TrillSpanEvent,
+    'wavy-line' : musicexp.TextSpannerEvent,
     'wedge' : musicexp.HairpinEvent
 }
 spanner_type_dict = {
-    'start': -1,
-    'begin': -1,
-    'crescendo': -1,
-    'decreschendo': -1,
-    'diminuendo': -1,
+    'start':-1,
+    'begin':-1,
+    'crescendo':-1,
+    'decreschendo':-1,
+    'diminuendo':-1,
     'continue': 0,
     'change': 0,
-    'up': -1,
-    'down': -1,
+    'up':-1,
+    'down':-1,
     'stop': 1,
     'end' : 1
 }
 
-def musicxml_spanner_to_lily_event (mxl_event):
+def musicxml_spanner_to_lily_event(mxl_event):
     ev = None
 
     name = mxl_event.get_name()
-    func = spanner_event_dict.get (name)
+    func = spanner_event_dict.get(name)
     if func:
         ev = func()
     else:
-        ly.warning (_ ('unknown span event %s') % mxl_event)
+        ly.warning(_('unknown span event %s') % mxl_event)
 
+    if name == "wavy-line":
+        ev.style=OrnamenthasWhat(mxl_event)
 
-    type = mxl_event.get_type ()
-    span_direction = spanner_type_dict.get (type)
+    type = mxl_event.get_type()
+    span_direction = spanner_type_dict.get(type)
     # really check for None, because some types will be translated to 0, which
     # would otherwise also lead to the unknown span warning
     if span_direction != None:
         ev.span_direction = span_direction
     else:
-        ly.warning (_ ('unknown span type %s for %s') % (type, name))
+        ly.warning(_('unknown span type %s for %s') %(type, name))
 
-    ev.set_span_type (type)
-    ev.line_type = getattr (mxl_event, 'line-type', 'solid')
+    ev.set_span_type(type)
+    ev.line_type = getattr(mxl_event, 'line-type', 'solid')
 
     # assign the size, which is used for octave-shift, etc.
-    ev.size = mxl_event.get_size ()
+    ev.size = mxl_event.get_size()
 
     return ev
 
-def musicxml_direction_to_indicator (direction):
-    return { "above": 1, "upright": 1, "up": 1, "below": -1, "downright": -1, "down": -1, "inverted": -1 }.get (direction, 0)
+def musicxml_direction_to_indicator(direction):
+    return { "above": 1, "upright": 1, "up": 1, "below":-1, "downright":-1, "down":-1, "inverted":-1 }.get(direction, 0)
+
+def musicxml_fermata_to_lily_event(mxl_event):
+
+    ev = musicexp.ArticulationEvent()
+    txt = mxl_event.get_text()
 
-def musicxml_fermata_to_lily_event (mxl_event):
-    ev = musicexp.ArticulationEvent ()
-    txt = mxl_event.get_text ()
     # The contents of the element defined the shape, possible are normal, angled and square
-    ev.type = { "angled": "shortfermata", "square": "longfermata" }.get (txt, "fermata")
-    if hasattr (mxl_event, 'type'):
-      dir = musicxml_direction_to_indicator (mxl_event.type)
-      if dir and options.convert_directions:
-        ev.force_direction = dir
+    ev.type = { "angled": "shortfermata", "square": "longfermata" }.get(txt, "fermata")
+    fermata_types= { "angled": "shortfermata",
+                     "square": "longfermata" }
+
+    # MusicXML fermata types can be specified in two different ways:
+    # 1. <fermata>angled</fermata> and
+    # 2. <fermata type="angled"/> -- both need to be handled.
+    if hasattr(mxl_event, 'type'):
+        fermata_type = fermata_types.get(mxl_event.type, 'fermata')
+    else:
+        fermata_type = fermata_types.get(mxl_event.get_text(), 'fermata')
+
+    ev.type = fermata_type
+
+    if hasattr(mxl_event, 'type'):
+        dir = musicxml_direction_to_indicator(mxl_event.type)
+        if dir and options.convert_directions:
+            ev.force_direction = dir
     return ev
 
-def musicxml_arpeggiate_to_lily_event (mxl_event):
-    ev = musicexp.ArpeggioEvent ()
-    ev.direction = musicxml_direction_to_indicator (getattr (mxl_event, 'direction', None))
+def musicxml_arpeggiate_to_lily_event(mxl_event):
+    ev = musicexp.ArpeggioEvent()
+    ev.direction = musicxml_direction_to_indicator(getattr(mxl_event, 'direction', None))
     return ev
 
-def musicxml_nonarpeggiate_to_lily_event (mxl_event):
-    ev = musicexp.ArpeggioEvent ()
+def musicxml_nonarpeggiate_to_lily_event(mxl_event):
+    ev = musicexp.ArpeggioEvent()
     ev.non_arpeggiate = True
-    ev.direction = musicxml_direction_to_indicator (getattr (mxl_event, 'direction', None))
+    ev.direction = musicxml_direction_to_indicator(getattr(mxl_event, 'direction', None))
     return ev
 
-def musicxml_tremolo_to_lily_event (mxl_event):
-    ev = musicexp.TremoloEvent ()
-    txt = mxl_event.get_text ()
+def musicxml_tremolo_to_lily_event(mxl_event):
+    ev = musicexp.TremoloEvent()
+    txt = mxl_event.get_text()
     if txt:
-      ev.bars = txt
+      ev.strokes = txt
     else:
-      ev.bars = "3"
+      # This is supposed to be a default for empty tremolo elements
+      # TODO: Add empty tremolo element to test cases in tremolo.xml
+      # TODO: Test empty tremolo element
+      # TODO: Consideration: Is 3 really a reasonable default?
+      ev.strokes = "3"
     return ev
 
-def musicxml_falloff_to_lily_event (mxl_event):
-    ev = musicexp.BendEvent ()
+def musicxml_falloff_to_lily_event(mxl_event):
+    ev = musicexp.BendEvent()
     ev.alter = -4
     return ev
 
-def musicxml_doit_to_lily_event (mxl_event):
-    ev = musicexp.BendEvent ()
+def musicxml_doit_to_lily_event(mxl_event):
+    ev = musicexp.BendEvent()
     ev.alter = 4
     return ev
 
-def musicxml_bend_to_lily_event (mxl_event):
-    ev = musicexp.BendEvent ()
-    ev.alter = mxl_event.bend_alter ()
+def musicxml_bend_to_lily_event(mxl_event):
+    ev = musicexp.BendEvent()
+    ev.alter = mxl_event.bend_alter()
     return ev
 
-def musicxml_caesura_to_lily_event (mxl_event):
-    ev = musicexp.MarkupEvent ()
+def musicxml_caesura_to_lily_event(mxl_event):
+    ev = musicexp.MarkupEvent()
     # FIXME: default to straight or curved caesura?
     ev.contents = "\\musicglyph #\"scripts.caesura.straight\""
     ev.force_direction = 1
     return ev
 
-def musicxml_fingering_event (mxl_event):
-    ev = musicexp.ShortArticulationEvent ()
-    ev.type = mxl_event.get_text ()
+def musicxml_fingering_event(mxl_event):
+    ev = musicexp.ShortArticulationEvent()
+    ev.type = mxl_event.get_text()
     return ev
 
-def musicxml_string_event (mxl_event):
-    ev = musicexp.NoDirectionArticulationEvent ()
-    ev.type = mxl_event.get_text ()
+def musicxml_string_event(mxl_event):
+    ev = musicexp.NoDirectionArticulationEvent()
+    ev.type = mxl_event.get_text()
     return ev
 
-def musicxml_accidental_mark (mxl_event):
-    ev = musicexp.MarkupEvent ()
+def musicxml_accidental_mark(mxl_event):
+    ev = musicexp.MarkupEvent()
     contents = { "sharp": "\\sharp",
       "natural": "\\natural",
       "flat": "\\flat",
@@ -1124,7 +1107,7 @@ def musicxml_accidental_mark (mxl_event):
       "quarter-sharp": "\\semisharp",
       "three-quarters-flat": "\\sesquiflat",
       "three-quarters-sharp": "\\sesquisharp",
-    }.get (mxl_event.get_text ())
+    }.get(mxl_event.get_text())
     if contents:
         ev.contents = contents
         return ev
@@ -1187,85 +1170,148 @@ articulations_dict = {
 }
 articulation_spanners = [ "wavy-line" ]
 
-def musicxml_articulation_to_lily_event (mxl_event):
+def OrnamenthasWhat(mxl_event):
+    wavy = trilly = ignore = start = stop = False
+    for i in mxl_event._parent._children:
+            if i._name == "wavy-line": wavy = True
+            elif i._name == "trill-mark": trilly = True
+            try:
+                if i.type == "continue": ignore = True
+                elif i.type == "start": start = True
+                elif i.type == "stop": stop = True
+            except:
+                pass
+    if start == True:
+        if wavy == True and trilly == False: musicexp.whatOrnament = "wave"
+        else: musicexp.whatOrnament = "trill"
+    if ignore == True: return "ignore"
+    elif stop == True: return "stop"
+    elif wavy == True and trilly == True: return "trill and wave"
+    elif wavy == True: return "wave"
+    elif trilly == True: return "trill"
+
+def OrnamenthasWavyline(mxl_event):
+    for i in mxl_event._parent._children:
+            if i._name == "wavy-line": return True
+    return False
+
+
+def musicxml_articulation_to_lily_event(mxl_event):
     # wavy-line elements are treated as trill spanners, not as articulation ornaments
-    if mxl_event.get_name () in articulation_spanners:
-        return musicxml_spanner_to_lily_event (mxl_event)
+    if mxl_event.get_name() in articulation_spanners:
+        return musicxml_spanner_to_lily_event(mxl_event)
 
-    tmp_tp = articulations_dict.get (mxl_event.get_name ())
+    tmp_tp = articulations_dict.get(mxl_event.get_name())
+    if OrnamenthasWavyline(mxl_event):
+        return
     if not tmp_tp:
         return
 
-    if isinstance (tmp_tp, str):
-        ev = musicexp.ArticulationEvent ()
+    if isinstance(tmp_tp, str):
+        ev = musicexp.ArticulationEvent()
         ev.type = tmp_tp
-    elif isinstance (tmp_tp, tuple):
-        ev = tmp_tp[0] ()
+    elif isinstance(tmp_tp, tuple):
+        ev = tmp_tp[0]()
         ev.type = tmp_tp[1]
     else:
-        ev = tmp_tp (mxl_event)
+        ev = tmp_tp(mxl_event)
 
     # Some articulations use the type attribute, other the placement...
     dir = None
-    if hasattr (mxl_event, 'type') and options.convert_directions:
-        dir = musicxml_direction_to_indicator (mxl_event.type)
-    if hasattr (mxl_event, 'placement') and options.convert_directions:
-        dir = musicxml_direction_to_indicator (mxl_event.placement)
+    if hasattr(mxl_event, 'type') and hasattr(options, 'convert_directions') and options.convert_directions:
+        dir = musicxml_direction_to_indicator(mxl_event.type)
+    if hasattr(mxl_event, 'placement') and hasattr(options, 'convert_directions') and options.convert_directions:
+        dir = musicxml_direction_to_indicator(mxl_event.placement)
     if dir:
         ev.force_direction = dir
     return ev
 
 
 
-def musicxml_dynamics_to_lily_event (dynentry):
+def musicxml_dynamics_to_lily_event(dynentry):
     dynamics_available = (
         "ppppp", "pppp", "ppp", "pp", "p", "mp", "mf",
-        "f", "ff", "fff", "ffff", "fp", "sf", "sff", "sp", "spp", "sfz", "rfz" )
-    dynamicsname = dynentry.get_name ()
+        "f", "ff", "fff", "ffff", "fp", "sf", "sff", "sp", "spp", "sfz", "rfz")
+    dynamicsname = dynentry.get_name()
     if dynamicsname == "other-dynamics":
-        dynamicsname = dynentry.get_text ()
+        dynamicsname = dynentry.get_text()
     if not dynamicsname or dynamicsname == "#text":
-        return
+        return None
 
     if not dynamicsname in dynamics_available:
         # Get rid of - in tag names (illegal in ly tags!)
         dynamicstext = dynamicsname
-        dynamicsname = string.replace (dynamicsname, "-", "")
+        dynamicsname = string.replace(dynamicsname, "-", "")
         additional_definitions[dynamicsname] = dynamicsname + \
               " = #(make-dynamic-script \"" + dynamicstext + "\")"
-        needed_additional_definitions.append (dynamicsname)
-    event = musicexp.DynamicsEvent ()
+        needed_additional_definitions.append(dynamicsname)
+    event = musicexp.DynamicsEvent()
     event.type = dynamicsname
     return event
 
 # Convert single-color two-byte strings to numbers 0.0 - 1.0
-def hexcolorval_to_nr (hex_val):
+def hexcolorval_to_nr(hex_val):
     try:
-        v = int (hex_val, 16)
+        v = int(hex_val, 16)
         if v == 255:
             v = 256
         return v / 256.
     except ValueError:
         return 0.
 
-def hex_to_color (hex_val):
-    res = re.match (r'#([0-9a-f][0-9a-f]|)([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$', hex_val, re.IGNORECASE)
+def hex_to_color(hex_val):
+    res = re.match(r'#([0-9a-f][0-9a-f]|)([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$', hex_val, re.IGNORECASE)
     if res:
-        return map (lambda x: hexcolorval_to_nr (x), res.group (2, 3, 4))
+        return map(lambda x: hexcolorval_to_nr(x), res.group(2, 3, 4))
     else:
         return None
 
-def musicxml_words_to_lily_event (words):
-    event = musicexp.TextEvent ()
-    text = words.get_text ()
-    text = re.sub ('^ *\n? *', '', text)
-    text = re.sub (' *\n? *$', '', text)
+def font_size_number_to_lily_command(size):
+    d = {
+        (0, 8): r'\teeny',
+        (8, 10): r'\tiny',
+        (10, 12): r'\small',
+        (12, 16): r'',
+        (16, 24): r'\large',
+        (24, float('inf')): r'\huge',
+    }
+    result = None
+    for r in d.keys():
+        if r[0] <= size < r[1]:
+            result = d[r]
+            break
+    return result
+
+def font_size_word_to_lily_command(size):
+    font_size_dict = {
+        "xx-small": '\\teeny',
+        "x-small": '\\tiny',
+        "small": '\\small',
+        "medium": '',
+        "large": '\\large',
+        "x-large": '\\huge',
+        "xx-large": '\\larger\\huge'
+        }
+    return font_size_dict.get(size, '')
+
+def get_font_size(size):
+    try:
+        size = float(size)
+        return font_size_number_to_lily_command(size)
+    except ValueError:
+        return font_size_word_to_lily_command(size)
+
+def musicxml_words_to_lily_event(words):
+    event = musicexp.TextEvent()
+    text = words.get_text()
+    text = re.sub('^ *\n? *', '', text) #remove white spaces and line breaks before text
+    text = re.sub(' *\n? *$', '', text) #remove white spaces and line breaks before text
     event.text = text
 
-    if hasattr (words, 'default-y') and options.convert_directions:
-        offset = getattr (words, 'default-y')
+    if hasattr(words, 'default-y') and hasattr(options, 'convert_directions') and options.convert_directions:
+        offset = getattr(words, 'default-y')
         try:
-            off = string.atoi (offset)
+            off = string.atoi(offset)
             if off > 0:
                 event.force_direction = 1
             else:
@@ -1273,33 +1319,26 @@ def musicxml_words_to_lily_event (words):
         except ValueError:
             event.force_direction = 0
 
-    if hasattr (words, 'font-weight'):
-        font_weight = { "normal": '', "bold": '\\bold' }.get (getattr (words, 'font-weight'), '')
+    if hasattr(words, 'font-weight'):
+        font_weight = { "normal": '', "bold": '\\bold' }.get(getattr(words, 'font-weight'), '')
         if font_weight:
             event.markup += font_weight
 
-    if hasattr (words, 'font-size'):
-        size = getattr (words, 'font-size')
-        font_size = {
-            "xx-small": '\\teeny',
-            "x-small": '\\tiny',
-            "small": '\\small',
-            "medium": '',
-            "large": '\\large',
-            "x-large": '\\huge',
-            "xx-large": '\\larger\\huge'
-        }.get (size, '')
+    if hasattr(words, 'font-size'):
+        size = getattr(words, 'font-size')
+        # font_size = font_size_dict.get(size, '')
+        font_size = get_font_size(size)
         if font_size:
             event.markup += font_size
 
-    if hasattr (words, 'color'):
-        color = getattr (words, 'color')
-        rgb = hex_to_color (color)
+    if hasattr(words, 'color'):
+        color = getattr(words, 'color')
+        rgb = hex_to_color(color)
         if rgb:
             event.markup += "\\with-color #(rgb-color %s %s %s)" % (rgb[0], rgb[1], rgb[2])
 
-    if hasattr (words, 'font-style'):
-        font_style = { "italic": '\\italic' }.get (getattr (words, 'font-style'), '')
+    if hasattr(words, 'font-style'):
+        font_style = { "italic": '\\italic' }.get(getattr(words, 'font-style'), '')
         if font_style:
             event.markup += font_style
 
@@ -1315,24 +1354,24 @@ def musicxml_words_to_lily_event (words):
 # convert accordion-registration to lilypond.
 # Since lilypond does not have any built-in commands, we need to create
 # the markup commands manually and define our own variables.
-# Idea was taken from: http://lsr.di.unimi.it/LSR/Item?id=194
-def musicxml_accordion_to_markup (mxl_event):
+# Idea was taken from: http://lsr.dsi.unimi.it/LSR/Item?id=194
+def musicxml_accordion_to_markup(mxl_event):
     commandname = "accReg"
     command = ""
 
-    high = mxl_event.get_maybe_exist_named_child ('accordion-high')
+    high = mxl_event.get_maybe_exist_named_child('accordion-high')
     if high:
         commandname += "H"
         command += """\\combine
           \\raise #2.5 \\musicglyph #\"accordion.dot\"
           """
-    middle = mxl_event.get_maybe_exist_named_child ('accordion-middle')
+    middle = mxl_event.get_maybe_exist_named_child('accordion-middle')
     if middle:
         # By default, use one dot (when no or invalid content is given). The
         # MusicXML spec is quiet about this case...
         txt = 1
         try:
-          txt = string.atoi (middle.get_text ())
+          txt = string.atoi(middle.get_text())
         except ValueError:
             pass
         if txt == 3:
@@ -1356,7 +1395,7 @@ def musicxml_accordion_to_markup (mxl_event):
             command += """\\combine
           \\raise #1.5 \\musicglyph #\"accordion.dot\"
           """
-    low = mxl_event.get_maybe_exist_named_child ('accordion-low')
+    low = mxl_event.get_maybe_exist_named_child('accordion-low')
     if low:
         commandname += "L"
         command += """\\combine
@@ -1367,98 +1406,100 @@ def musicxml_accordion_to_markup (mxl_event):
     command = "\\markup { \\normalsize %s }" % command
     # Define the newly built command \accReg[H][MMM][L]
     additional_definitions[commandname] = "%s = %s" % (commandname, command)
-    needed_additional_definitions.append (commandname)
+    needed_additional_definitions.append(commandname)
     return "\\%s" % commandname
 
-def musicxml_accordion_to_ly (mxl_event):
-    txt = musicxml_accordion_to_markup (mxl_event)
+def musicxml_accordion_to_ly(mxl_event):
+    txt = musicxml_accordion_to_markup(mxl_event)
     if txt:
-        ev = musicexp.MarkEvent (txt)
+        ev = musicexp.MarkEvent(txt)
         return ev
     return
 
 
-def musicxml_rehearsal_to_ly_mark (mxl_event):
-    text = mxl_event.get_text ()
+def musicxml_rehearsal_to_ly_mark(mxl_event):
+    text = mxl_event.get_text()
     if not text:
         return
     # default is boxed rehearsal marks!
     encl = "box"
-    if hasattr (mxl_event, 'enclosure'):
-        encl = {"none": None, "square": "box", "circle": "circle" }.get (mxl_event.enclosure, None)
+    if hasattr(mxl_event, 'enclosure'):
+        encl = {"none": None, "square": "box", "circle": "circle" }.get(mxl_event.enclosure, None)
     if encl:
         text = "\\%s { %s }" % (encl, text)
-    ev = musicexp.MarkEvent ("\\markup { %s }" % text)
+    ev = musicexp.MarkEvent("\\markup { %s }" % text)
     return ev
 
-def musicxml_harp_pedals_to_ly (mxl_event):
+def musicxml_harp_pedals_to_ly(mxl_event):
     count = 0
     result = "\\harp-pedal #\""
-    for t in mxl_event.get_named_children ('pedal-tuning'):
-      alter = t.get_named_child ('pedal-alter')
+    for t in mxl_event.get_named_children('pedal-tuning'):
+      alter = t.get_named_child('pedal-alter')
       if alter:
-        val = int (alter.get_text ().strip ())
-        result += {1: "v", 0: "-", -1: "^"}.get (val, "")
+        val = int(alter.get_text().strip())
+        result += {1: "v", 0: "-", -1: "^"}.get(val, "")
       count += 1
       if count == 3:
         result += "|"
-    ev = musicexp.MarkupEvent ()
+    ev = musicexp.MarkupEvent()
     ev.contents = result + "\""
     return ev
 
-def musicxml_eyeglasses_to_ly (mxl_event):
-    needed_additional_definitions.append ("eyeglasses")
-    return musicexp.MarkEvent ("\\markup { \\eyeglasses }")
+def musicxml_eyeglasses_to_ly(mxl_event):
+    needed_additional_definitions.append("eyeglasses")
+    return musicexp.MarkEvent("\\markup { \\eyeglasses }")
 
-def next_non_hash_index (lst, pos):
+def next_non_hash_index(lst, pos):
     pos += 1
-    while pos < len (lst) and isinstance (lst[pos], musicxml.Hash_text):
+    while pos < len(lst) and isinstance(lst[pos], musicxml.Hash_text):
         pos += 1
     return pos
 
-def musicxml_metronome_to_ly (mxl_event):
-    children = mxl_event.get_all_children ()
+def musicxml_metronome_to_ly(mxl_event):
+    children = mxl_event.get_all_children()
     if not children:
         return
 
     index = -1
-    index = next_non_hash_index (children, index)
-    if isinstance (children[index], musicxml.BeatUnit):
+    index = next_non_hash_index(children, index)
+    if isinstance(children[index], musicxml.BeatUnit):
         # first form of metronome-mark, using unit and beats/min or other unit
-        ev = musicexp.TempoMark ()
-        if hasattr (mxl_event, 'parentheses'):
-            ev.set_parentheses (mxl_event.parentheses == "yes")
-
-        d = musicexp.Duration ()
-        d.duration_log = musicxml.musicxml_duration_to_log (children[index].get_text ())
-        index = next_non_hash_index (children, index)
-        if isinstance (children[index], musicxml.BeatUnitDot):
+        ev = musicexp.TempoMark()
+        if hasattr(mxl_event, 'parentheses'):
+            ev.set_parentheses(mxl_event.parentheses == "yes")
+
+        d = musicexp.Duration()
+        d.duration_log = utilities.musicxml_duration_to_log(
+            children[index].get_text())
+        index = next_non_hash_index(children, index)
+        if isinstance(children[index], musicxml.BeatUnitDot):
             d.dots = 1
-            index = next_non_hash_index (children, index)
-        ev.set_base_duration (d)
-        if isinstance (children[index], musicxml.BeatUnit):
+            index = next_non_hash_index(children, index)
+        ev.set_base_duration(d)
+        if isinstance(children[index], musicxml.BeatUnit):
             # Form "note = newnote"
-            newd = musicexp.Duration ()
-            newd.duration_log = musicxml.musicxml_duration_to_log (children[index].get_text ())
-            index = next_non_hash_index (children, index)
-            if isinstance (children[index], musicxml.BeatUnitDot):
+            newd = musicexp.Duration()
+            newd.duration_log = utilities.musicxml_duration_to_log(
+                children[index].get_text())
+            index = next_non_hash_index(children, index)
+            if isinstance(children[index], musicxml.BeatUnitDot):
                 newd.dots = 1
-                index = next_non_hash_index (children, index)
-            ev.set_new_duration (newd)
-        elif isinstance (children[index], musicxml.PerMinute):
+                index = next_non_hash_index(children, index)
+            ev.set_new_duration(newd)
+        elif isinstance(children[index], musicxml.PerMinute):
             # Form "note = bpm"
             try:
-                beats = int (children[index].get_text ())
-                ev.set_beats_per_minute (beats)
+                beats = int(children[index].get_text())
+                ev.set_beats_per_minute(beats)
             except ValueError:
                 pass
         else:
-            ly.warning (_ ("Unknown metronome mark, ignoring"))
+            ly.warning(_("Unknown metronome mark, ignoring"))
             return
         return ev
     else:
         #TODO: Implement the other (more complex) way for tempo marks!
-        ly.warning (_ ("Metronome marks with complex relations (<metronome-note> in MusicXML) are not yet implemented."))
+        ly.warning(_("Metronome marks with complex relations (<metronome-note> in MusicXML) are not yet implemented."))
         return
 
 # translate directions into Events, possible values:
@@ -1481,85 +1522,53 @@ directions_dict = {
 }
 directions_spanners = [ 'octave-shift', 'pedal', 'wedge', 'dashes', 'bracket' ]
 
-def musicxml_direction_to_lily (n):
+def musicxml_direction_to_lily(n):
     # TODO: Handle the <staff> element!
     res = []
     # placement applies to all children!
     dir = None
-    if hasattr (n, 'placement') and options.convert_directions:
-        dir = musicxml_direction_to_indicator (n.placement)
+    if hasattr(n, 'placement') and hasattr(options, 'convert_directions') and options.convert_directions:
+        dir = musicxml_direction_to_indicator(n.placement)
     dirtype_children = []
     # TODO: The direction-type is used for grouping (e.g. dynamics with text),
     #       so we can't simply flatten them out!
-    for dt in n.get_typed_children (musicxml.DirType):
-        dirtype_children += dt.get_all_children ()
+    for dt in n.get_typed_children(musicxml.DirType):
+        dirtype_children += dt.get_all_children()
 
     for entry in dirtype_children:
-        # backets, dashes, octave shifts. pedal marks, hairpins etc. are spanners:
+        # brackets, dashes, octave shifts. pedal marks, hairpins etc. are spanners:
         if entry.get_name() in directions_spanners:
-            event = musicxml_spanner_to_lily_event (entry)
+            event = musicxml_spanner_to_lily_event(entry)
             if event:
-                res.append (event)
+                event.force_direction=dir
+                res.append(event)
             continue
 
         # now treat all the "simple" ones, that can be translated using the dict
         ev = None
-        tmp_tp = directions_dict.get (entry.get_name (), None)
-        if isinstance (tmp_tp, str): # string means MarkEvent
-            ev = musicexp.MarkEvent (tmp_tp)
-        elif isinstance (tmp_tp, tuple): # tuple means (EventClass, "text")
-            ev = tmp_tp[0] (tmp_tp[1])
+        tmp_tp = directions_dict.get(entry.get_name(), None)
+        if isinstance(tmp_tp, str): # string means MarkEvent
+            ev = musicexp.MarkEvent(tmp_tp)
+        elif isinstance(tmp_tp, tuple): # tuple means (EventClass, "text")
+            ev = tmp_tp[0](tmp_tp[1])
         elif tmp_tp:
-            ev = tmp_tp (entry)
+            ev = tmp_tp(entry)
         if ev:
             # TODO: set the correct direction! Unfortunately, \mark in ly does
             #       not seem to support directions!
             ev.force_direction = dir
-            res.append (ev)
+            res.append(ev)
             continue
 
-        if entry.get_name () == "dynamics":
-            for dynentry in entry.get_all_children ():
-                ev = musicxml_dynamics_to_lily_event (dynentry)
+        if entry.get_name() == "dynamics":
+            for dynentry in entry.get_all_children():
+                ev = musicxml_dynamics_to_lily_event(dynentry)
                 if ev:
-                    res.append (ev)
-
-    return res
-
-def musicxml_frame_to_lily_event (frame):
-    ev = musicexp.FretEvent ()
-    ev.strings = frame.get_strings ()
-    ev.frets = frame.get_frets ()
-    #offset = frame.get_first_fret () - 1
-    barre = []
-    for fn in frame.get_named_children ('frame-note'):
-        fret = fn.get_fret ()
-        if fret <= 0:
-            fret = "o"
-        el = [ fn.get_string (), fret ]
-        fingering = fn.get_fingering ()
-        if fingering >= 0:
-            el.append (fingering)
-        ev.elements.append (el)
-        b = fn.get_barre ()
-        if b == 'start':
-            barre[0] = el[0] # start string
-            barre[2] = el[1] # fret
-        elif b == 'stop':
-            barre[1] = el[0] # end string
-    if barre:
-        ev.barre = barre
-    return ev
+                    ev.force_direction = dir
+                    res.append(ev)
 
-def musicxml_harmony_to_lily (n):
-    res = []
-    for f in n.get_named_children ('frame'):
-        ev = musicxml_frame_to_lily_event (f)
-        if ev:
-            res.append (ev)
     return res
 
-
 notehead_styles_dict = {
     'slash': '\'slash',
     'triangle': '\'triangle',
@@ -1585,63 +1594,44 @@ notehead_styles_dict = {
     'ti': '\'ti',
     }
 
-def musicxml_notehead_to_lily (nh):
-    styles = []
-
-    # Notehead style
-    style = notehead_styles_dict.get (nh.get_text ().strip (), None)
-    style_elm = musicexp.NotestyleEvent ()
-    if style:
-        style_elm.style = style
-    if hasattr (nh, 'filled'):
-        style_elm.filled = (getattr (nh, 'filled') == "yes")
-    if style_elm.style or (style_elm.filled != None):
-        styles.append (style_elm)
-
-    # parentheses
-    if hasattr (nh, 'parentheses') and (nh.parentheses == "yes"):
-        styles.append (musicexp.ParenthesizeEvent ())
-
-    return styles
-
-def musicxml_chordpitch_to_lily (mxl_cpitch):
-    r = musicexp.ChordPitch ()
-    r.alteration = mxl_cpitch.get_alteration ()
-    r.step = musicxml_step_to_lily (mxl_cpitch.get_step ())
+def musicxml_chordpitch_to_lily(mxl_cpitch):
+    r = musicexp.ChordPitch()
+    r.alteration = mxl_cpitch.get_alteration()
+    r.step = musicxml2ly_conversion.musicxml_step_to_lily(mxl_cpitch.get_step())
     return r
 
 chordkind_dict = {
-    'major': '5',
-    'minor': 'm5',
-    'augmented': 'aug5',
-    'diminished': 'dim5',
+    'major': r'{}:5',
+    'minor': r'{}:m5',
+    'augmented': r'{}:aug5',
+    'diminished': r'{}:dim5',
         # Sevenths:
-    'dominant': '7',
-    'dominant-seventh': '7',
-    'major-seventh': 'maj7',
-    'minor-seventh': 'm7',
-    'diminished-seventh': 'dim7',
-    'augmented-seventh': 'aug7',
-    'half-diminished': 'dim5m7',
-    'major-minor': 'maj7m5',
+    'dominant': r'{}:7',
+    'dominant-seventh': r'{}:7',
+    'major-seventh': r'{}:maj7',
+    'minor-seventh': r'{}:m7',
+    'diminished-seventh': r'{}:dim7',
+    'augmented-seventh': r'{}:aug7',
+    'half-diminished': r'{}:dim5m7',
+    'major-minor': r'{}:maj7m5',
         # Sixths:
-    'major-sixth': '6',
-    'minor-sixth': 'm6',
+    'major-sixth': r'{}:6',
+    'minor-sixth': r'{}:m6',
         # Ninths:
-    'dominant-ninth': '9',
-    'major-ninth': 'maj9',
-    'minor-ninth': 'm9',
+    'dominant-ninth': r'{}:9',
+    'major-ninth': r'{}:maj9',
+    'minor-ninth': r'{}:m9',
         # 11ths (usually as the basis for alteration):
-    'dominant-11th': '11',
-    'major-11th': 'maj11',
-    'minor-11th': 'm11',
+    'dominant-11th': r'{}:11',
+    'major-11th': r'{}:maj11',
+    'minor-11th': r'{}:m11',
         # 13ths (usually as the basis for alteration):
-    'dominant-13th': '13.11',
-    'major-13th': 'maj13.11',
-    'minor-13th': 'm13',
+    'dominant-13th': r'{}:13.11',
+    'major-13th': r'{}:maj13.11',
+    'minor-13th': r'{}:m13',
         # Suspended:
-    'suspended-second': 'sus2',
-    'suspended-fourth': 'sus4',
+    'suspended-second': r'{}:sus2',
+    'suspended-fourth': r'{}:sus4',
         # Functional sixths:
     # TODO
     #'Neapolitan': '???',
@@ -1650,34 +1640,118 @@ chordkind_dict = {
     #'German': '???',
         # Other:
     #'pedal': '???',(pedal-point bass)
-    'power': '5^3',
+    'power': r'\powerChords {}:1.5',
     #'Tristan': '???',
-    'other': '1',
+    'other': r'{}:1',
     'none': None,
 }
 
-def musicxml_chordkind_to_lily (kind):
-    res = chordkind_dict.get (kind, None)
+def musicxml_chordkind_to_lily(kind):
+    res = chordkind_dict.get(kind, None)
     # Check for None, since a major chord is converted to ''
     if res == None:
-        ly.warning (_ ("Unable to convert chord type %s to lilypond.") % kind)
+        ly.warning(_("Unable to convert chord type %s to lilypond.") % kind)
+    return res
+
+
+# Global variable for guitar string tunings
+string_tunings = None
+
+def musicxml_get_string_tunings(lines):
+    global string_tunings
+    if (string_tunings == None):
+        if not lines:
+            lines = 6
+        string_tunings = [musicexp.Pitch()] * lines
+        for i in range(0, lines):
+            p = musicexp.Pitch()
+            p.step = musicxml2ly_conversion.musicxml_step_to_lily(((("E","A","D","G","B")*(lines/5+1))[0:lines])[i])
+            p.octave = (([-2+int(x%5>1)+2*(x/5) for x in range(0,lines)][0:lines])[i])
+            p.alteration = 0
+            p._force_absolute_pitch = True
+            string_tunings[i] = p
+        string_tunings = string_tunings[::-1]
+    return string_tunings[0:lines]
+
+def musicxml_frame_to_lily_event(frame):
+    ev = musicexp.FretEvent()
+    ev.strings = frame.get_strings()
+    ev.frets = frame.get_frets()
+    #offset = frame.get_first_fret() - 1
+    #offset = frame.get_first_fret()
+    barre = []
+    open_strings = range(1,ev.strings+1)
+    for fn in frame.get_named_children('frame-note'):
+        fret = fn.get_fret()
+        if fret <= 0:
+            fret = "o"
+        el = [ fn.get_string(), fret ]
+        fingering = fn.get_fingering()
+        if fingering >= 0:
+            el.append(fingering)
+        ev.elements.append(el)
+        open_strings.remove(fn.get_string())
+        b = fn.get_barre()
+        if b == 'start':
+            barre.append(el[0]) # start string
+            barre.append(el[1]) # fret
+        elif b == 'stop':
+            barre.insert(1, el[0]) # end string
+    for string in open_strings:
+        ev.elements.append([string, 'x'])
+    ev.elements.sort()
+    ev.elements.reverse()
+    if barre:
+        ev.barre = barre
+    return ev
+
+def musicxml_harmony_to_lily(n):
+    res = []
+    for f in n.get_named_children('frame'):
+        ev = musicxml_frame_to_lily_event(f)
+        if ev:
+            res.append(ev)
+    return res
+
+def musicxml_harmony_to_lily_fretboards(n):
+    res = []
+    frame = n.get_maybe_exist_named_child('frame')
+    if frame:
+        strings = frame.get_strings()
+        if not strings:
+            strings = 6
+        tunings = musicxml_get_string_tunings(strings)
+        ev = musicexp.FretBoardEvent()
+        #barre = []
+        for fn in frame.get_named_children('frame-note'):
+            fbn = musicexp.FretBoardNote()
+            string = fn.get_string()
+            fbn.string = string
+            fingering = fn.get_fingering()
+            if fingering >= 0:
+                fbn.fingering = fingering
+            p = tunings[string-1].copy()
+            p.add_semitones(fn.get_fret())
+            fbn.pitch = p
+            ev.append(fbn)
+        res.append(ev)
     return res
 
-def musicxml_harmony_to_lily_chordname (n):
+def musicxml_harmony_to_lily_chordname(n):
     res = []
-    root = n.get_maybe_exist_named_child ('root')
+    root = n.get_maybe_exist_named_child('root')
     if root:
-        ev = musicexp.ChordNameEvent ()
-        ev.root = musicxml_chordpitch_to_lily (root)
-        kind = n.get_maybe_exist_named_child ('kind')
+        ev = musicexp.ChordNameEvent()
+        ev.root = musicxml_chordpitch_to_lily(root)
+        kind = n.get_maybe_exist_named_child('kind')
         if kind:
-            ev.kind = musicxml_chordkind_to_lily (kind.get_text ())
+            ev.kind = musicxml_chordkind_to_lily(kind.get_text())
             if not ev.kind:
                 return res
-        bass = n.get_maybe_exist_named_child ('bass')
+        bass = n.get_maybe_exist_named_child('bass')
         if bass:
-            ev.bass = musicxml_chordpitch_to_lily (bass)
-        inversion = n.get_maybe_exist_named_child ('inversion')
+            ev.bass = musicxml_chordpitch_to_lily(bass)
+        inversion = n.get_maybe_exist_named_child('inversion')
         if inversion:
             # TODO: LilyPond does not support inversions, does it?
 
@@ -1689,17 +1763,17 @@ def musicxml_harmony_to_lily_chordname (n):
             # require you to know the chord and calculate either the fifth
             # pitch (for the first inversion) or the third pitch (for the
             # second inversion) so they may not be helpful for musicxml2ly.
-            inversion_count = string.atoi (inversion.get_text ())
+            inversion_count = string.atoi(inversion.get_text())
             if inversion_count == 1:
               # TODO: Calculate the bass note for the inversion...
               pass
             pass
-        for deg in n.get_named_children ('degree'):
-            d = musicexp.ChordModification ()
-            d.type = deg.get_type ()
-            d.step = deg.get_value ()
-            d.alteration = deg.get_alter ()
-            ev.add_modification (d)
+        for deg in n.get_named_children('degree'):
+            d = musicexp.ChordModification()
+            d.type = deg.get_type()
+            d.step = deg.get_value()
+            d.alteration = deg.get_alter()
+            ev.add_modification(d)
         #TODO: convert the user-symbols attribute:
             #major: a triangle, like Unicode 25B3
             #minor: -, like Unicode 002D
@@ -1707,12 +1781,11 @@ def musicxml_harmony_to_lily_chordname (n):
             #diminished: (degree), like Unicode 00B0
             #half-diminished: (o with slash), like Unicode 00F8
         if ev and ev.root:
-            res.append (ev)
-
+            res.append(ev)
     return res
 
-def musicxml_figured_bass_note_to_lily (n):
-    res = musicexp.FiguredBassNote ()
+def musicxml_figured_bass_note_to_lily(n):
+    res = musicexp.FiguredBassNote()
     suffix_dict = { 'sharp' : "+",
                     'flat' : "-",
                     'natural' : "!",
@@ -1720,16 +1793,16 @@ def musicxml_figured_bass_note_to_lily (n):
                     'flat-flat' : "--",
                     'sharp-sharp' : "++",
                     'slash' : "/" }
-    prefix = n.get_maybe_exist_named_child ('prefix')
+    prefix = n.get_maybe_exist_named_child('prefix')
     if prefix:
-        res.set_prefix (suffix_dict.get (prefix.get_text (), ""))
-    fnumber = n.get_maybe_exist_named_child ('figure-number')
+        res.set_prefix(suffix_dict.get(prefix.get_text(), ""))
+    fnumber = n.get_maybe_exist_named_child('figure-number')
     if fnumber:
-        res.set_number (fnumber.get_text ())
-    suffix = n.get_maybe_exist_named_child ('suffix')
+        res.set_number(fnumber.get_text())
+    suffix = n.get_maybe_exist_named_child('suffix')
     if suffix:
-        res.set_suffix (suffix_dict.get (suffix.get_text (), ""))
-    if n.get_maybe_exist_named_child ('extend'):
+        res.set_suffix(suffix_dict.get(suffix.get_text(), ""))
+    if n.get_maybe_exist_named_child('extend'):
         # TODO: Implement extender lines (unfortunately, in lilypond you have
         #       to use \set useBassFigureExtenders = ##t, which turns them on
         #       globally, while MusicXML has a property for each note...
@@ -1740,24 +1813,24 @@ def musicxml_figured_bass_note_to_lily (n):
 
 
 
-def musicxml_figured_bass_to_lily (n):
-    if not isinstance (n, musicxml.FiguredBass):
+def musicxml_figured_bass_to_lily(n):
+    if not isinstance(n, musicxml.FiguredBass):
         return
-    res = musicexp.FiguredBassEvent ()
-    for i in n.get_named_children ('figure'):
-        note = musicxml_figured_bass_note_to_lily (i)
+    res = musicexp.FiguredBassEvent()
+    for i in n.get_named_children('figure'):
+        note = musicxml_figured_bass_note_to_lily(i)
         if note:
-            res.append (note)
-    dur = n.get_maybe_exist_named_child ('duration')
+            res.append(note)
+    dur = n.get_maybe_exist_named_child('duration')
     if dur:
         # apply the duration to res
         length = Rational(int(dur.get_text()), n._divisions) * Rational(1, 4)
-        res.set_real_duration (length)
-        duration = rational_to_lily_duration (length)
+        res.set_real_duration(length)
+        duration = musicxml2ly_conversion.rational_to_lily_duration(length)
         if duration:
-            res.set_duration (duration)
-    if hasattr (n, 'parentheses') and n.parentheses == "yes":
-        res.set_parentheses (True)
+            res.set_duration(duration)
+    if hasattr(n, 'parentheses') and n.parentheses == "yes":
+        res.set_parentheses(True)
     return res
 
 instrument_drumtype_dict = {
@@ -1769,85 +1842,26 @@ instrument_drumtype_dict = {
     'Bass Drum': 'bassdrum',
 }
 
-def musicxml_note_to_lily_main_event (n):
-    pitch = None
-    duration = None
-    event = None
-
-    mxl_pitch = n.get_maybe_exist_typed_child (musicxml.Pitch)
-    if mxl_pitch:
-        pitch = musicxml_pitch_to_lily (mxl_pitch)
-        event = musicexp.NoteEvent ()
-        event.pitch = pitch
-
-        acc = n.get_maybe_exist_named_child ('accidental')
-        if acc:
-            # AccidentalCautionary in lily has parentheses
-            # so treat accidental explicitly in parentheses as cautionary
-            if hasattr(acc, 'parentheses') and acc.parentheses == "yes":
-                event.cautionary = True
-            else:
-                event.cautionary = acc.cautionary
-            # TODO: Handle editorial accidentals
-            # TODO: Handle the level-display setting for displaying brackets/parentheses
-
-    elif n.get_maybe_exist_typed_child (musicxml.Unpitched):
-        # Unpitched elements have display-step and can also have
-        # display-octave.
-        unpitched = n.get_maybe_exist_typed_child (musicxml.Unpitched)
-        event = musicexp.NoteEvent ()
-        event.pitch = musicxml_unpitched_to_lily (unpitched)
-
-    elif n.get_maybe_exist_typed_child (musicxml.Rest):
-        # rests can have display-octave and display-step, which are
-        # treated like an ordinary note pitch
-        rest = n.get_maybe_exist_typed_child (musicxml.Rest)
-        event = musicexp.RestEvent ()
-        if options.convert_rest_positions:
-            pitch = musicxml_restdisplay_to_lily (rest)
-            event.pitch = pitch
-
-    elif n.instrument_name:
-        event = musicexp.NoteEvent ()
-        drum_type = instrument_drumtype_dict.get (n.instrument_name)
-        if drum_type:
-            event.drum_type = drum_type
-        else:
-            n.message (_ ("drum %s type unknown, please add to instrument_drumtype_dict") % n.instrument_name)
-            event.drum_type = 'acousticsnare'
-
-    else:
-        n.message (_ ("cannot find suitable event"))
 
-    if event:
-        event.duration = musicxml_duration_to_lily (n)
 
-    noteheads = n.get_named_children ('notehead')
-    for nh in noteheads:
-        styles = musicxml_notehead_to_lily (nh)
-        for s in styles:
-            event.add_associated_event (s)
-
-    return event
-
-def musicxml_lyrics_to_text (lyrics):
+def musicxml_lyrics_to_text(lyrics, ignoremelismata):
     # TODO: Implement text styles for lyrics syllables
     continued = False
     extended = False
     text = ''
-    for e in lyrics.get_all_children ():
-        if isinstance (e, musicxml.Syllabic):
-            continued = e.continued ()
-        elif isinstance (e, musicxml.Text):
+    for e in lyrics.get_all_children():
+        if isinstance(e, musicxml.Syllabic):
+            continued = e.continued()
+        elif isinstance(e, musicxml.Text):
             # We need to convert soft hyphens to -, otherwise the ascii codec as well
             # as lilypond will barf on that character
-            text += string.replace( e.get_text(), u'\xad', '-' )
-        elif isinstance (e, musicxml.Elision):
+            text += string.replace(e.get_text(), u'\xad', '-')
+        elif isinstance(e, musicxml.Elision):
             if text:
                 text += " "
             continued = False
             extended = False
-        elif isinstance (e, musicxml.Extend):
+        elif isinstance(e, musicxml.Extend):
             if text:
                 text += " "
             extended = True
@@ -1857,195 +1871,298 @@ def musicxml_lyrics_to_text (lyrics):
     elif text == "_" and extended:
         return "__"
     elif continued and text:
-        return musicxml.escape_ly_output_string (text) + " --"
+        if hasattr(options, 'convert_beaming') and options.convert_beaming:
+            if (ignoremelismata == "on"):
+                return " \set ignoreMelismata = ##t " + utilities.escape_ly_output_string (text)
+            elif (ignoremelismata == "off"):
+                return " " + utilities.escape_ly_output_string(text) + " -- \unset ignoreMelismata"
+            else:
+                return " " + utilities.escape_ly_output_string(text) + " --"
+        else:
+            return " " + utilities.escape_ly_output_string(text) + " -- "
     elif continued:
         return "--"
     elif extended and text:
-        return musicxml.escape_ly_output_string (text) + " __"
+        return " " + utilities.escape_ly_output_string(text) + " __"
     elif extended:
         return "__"
     elif text:
-        return musicxml.escape_ly_output_string (text)
+        return " " + utilities.escape_ly_output_string(text)
     else:
         return ""
 
 ## TODO
 class NegativeSkip:
-    def __init__ (self, here, dest):
+    def __init__(self, here, dest):
         self.here = here
         self.dest = dest
 
 class LilyPondVoiceBuilder:
-    def __init__ (self):
+    def __init__(self):
         self.elements = []
         self.pending_dynamics = []
-        self.end_moment = Rational (0)
-        self.begin_moment = Rational (0)
-        self.pending_multibar = Rational (0)
+        self.end_moment = Rational(0)
+        self.begin_moment = Rational(0)
+        self.pending_multibar = Rational(0)
         self.ignore_skips = False
         self.has_relevant_elements = False
-        self.measure_length = Rational (4, 4)
+        self.measure_length = Rational(4, 4)
+        self.stay_here = False
 
-    def _insert_multibar (self):
-        layout_information.set_context_item ('Score', 'skipBars = ##t')
-        r = musicexp.MultiMeasureRest ()
+    def _insert_multibar(self):
+        layout_information.set_context_item('Score', 'skipBars = ##t')
+        r = musicexp.MultiMeasureRest()
         lenfrac = self.measure_length
-        r.duration = rational_to_lily_duration (lenfrac)
+        r.duration = musicxml2ly_conversion.rational_to_lily_duration(lenfrac)
         r.duration.factor *= self.pending_multibar / lenfrac
-        self.elements.append (r)
+        self.elements.append(r)
         self.begin_moment = self.end_moment
         self.end_moment = self.begin_moment + self.pending_multibar
-        self.pending_multibar = Rational (0)
+        self.pending_multibar = Rational(0)
 
-    def set_measure_length (self, mlen):
+    def set_measure_length(self, mlen):
         if (mlen != self.measure_length) and self.pending_multibar:
-            self._insert_multibar ()
+            self._insert_multibar()
         self.measure_length = mlen
 
-    def add_multibar_rest (self, duration):
+    def add_multibar_rest(self, duration):
         self.pending_multibar += duration
 
-    def set_duration (self, duration):
+    def set_duration(self, duration):
         self.end_moment = self.begin_moment + duration
-    def current_duration (self):
+    def current_duration(self):
         return self.end_moment - self.begin_moment
 
-    def add_music (self, music, duration, relevant=True):
-        assert isinstance (music, musicexp.Music)
-        if self.pending_multibar > Rational (0):
-            self._insert_multibar ()
+    def add_pending_dynamics(self):
+        for d in self.pending_dynamics:
+            self.elements.append(d)
+        self.pending_dynamics = []
+
+    def add_music(self, music, duration, relevant=True):
+        assert isinstance(music, musicexp.Music)
+        if self.pending_multibar > Rational(0):
+            self._insert_multibar()
 
         self.has_relevant_elements = self.has_relevant_elements or relevant
-        self.elements.append (music)
+
+        if isinstance(music, musicexp.BarLine):
+            if self.pending_dynamics:
+                for d in self.pending_dynamics:
+                    if not isinstance(d, (musicexp.SpanEvent, musicexp.DynamicsEvent)):
+                        index = self.pending_dynamics.index(d)
+                        dyn = self.pending_dynamics.pop(index)
+                        self.elements.append(dyn)
+
+        self.elements.append(music)
         self.begin_moment = self.end_moment
-        self.set_duration (duration)
+        self.set_duration(duration)
 
         # Insert all pending dynamics right after the note/rest:
-        if isinstance (music, musicexp.ChordEvent) and self.pending_dynamics:
-            for d in self.pending_dynamics:
-                music.append (d)
-            self.pending_dynamics = []
+        if isinstance(music, musicexp.ChordEvent) and self.pending_dynamics:
+            self.add_pending_dynamics()
 
     # Insert some music command that does not affect the position in the measure
-    def add_command (self, command, relevant=True):
-        assert isinstance (command, musicexp.Music)
-        if self.pending_multibar > Rational (0):
-            self._insert_multibar ()
+    def add_command(self, command, relevant=True):
+        assert isinstance(command, musicexp.Music)
+        if self.pending_multibar > Rational(0):
+            self._insert_multibar()
         self.has_relevant_elements = self.has_relevant_elements or relevant
-        self.elements.append (command)
-    def add_barline (self, barline, relevant=False):
+        self.elements.append(command)
+    def add_barline(self, barline, relevant=False):
         # Insert only if we don't have a barline already
         # TODO: Implement proper merging of default barline and custom bar line
         has_relevant = self.has_relevant_elements
         if (not (self.elements) or
             not (isinstance (self.elements[-1], musicexp.BarLine)) or
-            (self.pending_multibar > Rational (0))):
-            self.add_music (barline, Rational (0))
+            (self.pending_multibar > Rational(0))):
+
+            self.add_music(barline, Rational(0))
+
         self.has_relevant_elements = has_relevant or relevant
-    def add_partial (self, command):
+
+    def add_partial(self, command):
         self.ignore_skips = True
         # insert the partial, but restore relevant_elements (partial is not relevant)
         relevant = self.has_relevant_elements
-        self.add_command (command)
+        self.add_command(command)
         self.has_relevant_elements = relevant
 
-    def add_dynamics (self, dynamic):
+    def add_dynamics(self, dynamic):
         # store the dynamic item(s) until we encounter the next note/rest:
-        self.pending_dynamics.append (dynamic)
+        self.pending_dynamics.append(dynamic)
 
-    def add_bar_check (self, number):
+    def add_bar_check(self, number):
         # re/store has_relevant_elements, so that a barline alone does not
         # trigger output for figured bass, chord names
-        b = musicexp.BarLine ()
+        b = musicexp.BarLine()
         b.bar_number = number
-        self.add_barline (b)
-
-    def jumpto (self, moment):
-        current_end = self.end_moment + self.pending_multibar
-        diff = moment - current_end
-
-        if diff < Rational (0):
-            ly.warning (_ ('Negative skip %s (from position %s to %s)')
-                % (diff, current_end, moment))
-            diff = Rational (0)
-
-        if diff > Rational (0) and not (self.ignore_skips and moment == 0):
-            skip = musicexp.SkipEvent()
-            duration_factor = 1
-            duration_log = {1: 0, 2: 1, 4:2, 8:3, 16:4, 32:5, 64:6, 128:7, 256:8, 512:9}.get (diff.denominator (), -1)
-            duration_dots = 0
-            # TODO: Use the time signature for skips, too. Problem: The skip
-            #       might not start at a measure boundary!
-            if duration_log > 0: # denominator is a power of 2...
-                if diff.numerator () == 3:
-                    duration_log -= 1
-                    duration_dots = 1
+        self.add_barline(b)
+
+    def jumpto(self, moment):
+        if (not self.stay_here):
+            current_end = self.end_moment + self.pending_multibar
+            diff = moment - current_end
+
+            if diff < Rational(0):
+                ly.warning(_('Negative skip %s (from position %s to %s)') %
+                            (diff, current_end, moment))
+                diff = Rational(0)
+
+            if diff > Rational(0) and not(self.ignore_skips and moment == 0):
+                skip = musicexp.SkipEvent()
+                duration_factor = 1
+                duration_log = {1: 0, 2: 1, 4:2, 8:3, 16:4, 32:5, 64:6, 128:7, 256:8, 512:9}.get(diff.denominator(), -1)
+                duration_dots = 0
+                # TODO: Use the time signature for skips, too. Problem: The skip
+                #       might not start at a measure boundary!
+                if duration_log > 0: # denominator is a power of 2...
+                    if diff.numerator() == 3:
+                        duration_log -= 1
+                        duration_dots = 1
+                    else:
+                        duration_factor = Rational(diff.numerator())
                 else:
-                    duration_factor = Rational (diff.numerator ())
-            else:
-                # for skips of a whole or more, simply use s1*factor
-                duration_log = 0
-                duration_factor = diff
-            skip.duration.duration_log = duration_log
-            skip.duration.factor = duration_factor
-            skip.duration.dots = duration_dots
-
-            evc = musicexp.ChordEvent ()
-            evc.elements.append (skip)
-            self.add_music (evc, diff, False)
+                    # for skips of a whole or more, simply use s1*factor
+                    duration_log = 0
+                    duration_factor = diff
+                skip.duration.duration_log = duration_log
+                skip.duration.factor = duration_factor
+                skip.duration.dots = duration_dots
 
-        if diff > Rational (0) and moment == 0:
-            self.ignore_skips = False
+                evc = musicexp.ChordEvent()
+                evc.elements.append(skip)
+                self.add_music(evc, diff, False)
 
-    def last_event_chord (self, starting_at):
+            if diff > Rational(0) and moment == 0:
+                self.ignore_skips = False
 
+    def last_event_chord(self, starting_at):
         value = None
 
         # if the position matches, find the last ChordEvent, do not cross a bar line!
         at = len(self.elements) - 1
         while (at >= 0 and
-               not isinstance (self.elements[at], musicexp.ChordEvent) and
-               not isinstance (self.elements[at], musicexp.BarLine)):
+               not isinstance(self.elements[at], musicexp.ChordEvent) and
+               not isinstance(self.elements[at], musicexp.BarLine)):
             at -= 1
 
         if (self.elements
             and at >= 0
-            and isinstance (self.elements[at], musicexp.ChordEvent)
+            and isinstance(self.elements[at], musicexp.ChordEvent)
             and self.begin_moment == starting_at):
             value = self.elements[at]
         else:
-            self.jumpto (starting_at)
+            self.jumpto(starting_at)
             value = None
         return value
 
-    def correct_negative_skip (self, goto):
+    def correct_negative_skip(self, goto):
         self.end_moment = goto
         self.begin_moment = goto
-        evc = musicexp.ChordEvent ()
-        self.elements.append (evc)
-
+        evc = musicexp.ChordEvent()
+        self.elements.append(evc)
 
 class VoiceData:
-    def __init__ (self):
+    def __init__(self):
         self.voicename = None
         self.voicedata = None
         self.ly_voice = None
         self.figured_bass = None
         self.chordnames = None
+        self.fretboards = None
         self.lyrics_dict = {}
         self.lyrics_order = []
 
-def measure_length_from_attributes (attr, current_measure_length):
-    len = attr.get_measure_length ()
+def measure_length_from_attributes(attr, current_measure_length):
+    len = attr.get_measure_length()
     if not len:
         len = current_measure_length
     return len
 
-def musicxml_voice_to_lily_voice (voice):
+def music_xml_voice_name_to_lily_name(part_id, name):
+    str = "Part%sVoice%s" % (part_id, name)
+    return musicxml_id_to_lily(str)
+
+def music_xml_lyrics_name_to_lily_name(part_id, name, lyricsnr):
+    str = music_xml_voice_name_to_lily_name(part_id, name)+("Lyrics%s" % lyricsnr)
+    return musicxml_id_to_lily(str)
+
+def music_xml_figuredbass_name_to_lily_name(part_id, voicename):
+    str = music_xml_voice_name_to_lily_name(part_id, voicename)+"FiguredBass"
+    return musicxml_id_to_lily(str)
+
+def music_xml_chordnames_name_to_lily_name(part_id, voicename):
+    str = music_xml_voice_name_to_lily_name(part_id, voicename)+"Chords"
+    return musicxml_id_to_lily(str)
+
+def music_xml_fretboards_name_to_lily_name(part_id, voicename):
+    str = music_xml_voice_name_to_lily_name(part_id, voicename)+"FretBoards"
+    return musicxml_id_to_lily(str)
+
+def get_all_lyric_parts_in_voice(voice):
+    '''
+    Collect the indexes of all lyric parts in this voice.
+    In case not all of the current lyric parts are active (a typical case would be
+    a refrain/chorus), the current implementation inserts \skip-commands in the
+    inactive parts to keep them in sync.
+    '''
+    all_lyric_parts = []
+    for elem in voice._elements:
+        lyrics = elem.get_typed_children(musicxml.Lyric)
+        if lyrics:
+            for lyric in lyrics:
+                index = lyric.number
+                if not index in all_lyric_parts:
+                    all_lyric_parts.append(index)
+    return all_lyric_parts
+
+
+def extract_lyrics(voice, lyric_key, lyrics_dict):
+    curr_number = None
+    result = []
+
+    def is_note(elem):
+        return isinstance(elem, musicxml.Note)
+
+    def is_rest(elem):
+        return elem.get_typed_children(musicxml.Rest)
+
+    def is_note_and_not_rest(elem):
+        return is_note(elem) and not is_rest(elem)
+
+    def get_lyric_elements(note):
+        return note.get_typed_children(musicxml.Lyric)
+
+    def has_lyric_belonging_to_lyric_part(note, lyric_part_id):
+        lyric_elements = get_lyric_elements(note)
+        lyric_numbers = [lyric.number for lyric in lyric_elements]
+        return any([lyric_number == lyric_part_id for lyric_number in lyric_numbers])
+
+    for idx, elem in enumerate(voice._elements):
+        lyrics = get_lyric_elements(elem)
+        lyric_keys = [lyric.number for lyric in lyrics]
+        note_has_lyric_belonging_to_lyric_part = lyric_key in lyric_keys
+        # Current note has lyric with 'number' matching 'lyric_key'.
+        if note_has_lyric_belonging_to_lyric_part:
+            for lyric in lyrics:
+                if lyric.number == lyric_key:
+                    text = musicxml_lyrics_to_text(lyric, None)
+                    result.append(text)
+        # Note has any lyric.
+        elif get_lyric_elements(elem) and \
+             not note_has_lyric_belonging_to_lyric_part:
+            result.append('\skip1 ')
+        # Note does not have any lyric attached to it.
+        elif is_note_and_not_rest(elem):
+            result.append('\skip1 ')
+
+    lyrics_dict[lyric_key].extend(result)
+
+def musicxml_voice_to_lily_voice(voice):
     tuplet_events = []
     modes_found = {}
     lyrics = {}
-    return_value = VoiceData ()
+    return_value = VoiceData()
     return_value.voicedata = voice
 
     # First pitch needed for relative mode (if selected in command-line options)
@@ -2062,153 +2179,190 @@ def musicxml_voice_to_lily_voice (voice):
 
     pending_figured_bass = []
     pending_chordnames = []
+    pending_fretboards = []
 
     # Make sure that the keys in the dict don't get reordered, since
     # we need the correct ordering of the lyrics stanzas! By default,
     # a dict will reorder its keys
-    return_value.lyrics_order = voice.get_lyrics_numbers ()
+    return_value.lyrics_order = voice.get_lyrics_numbers()
     for k in return_value.lyrics_order:
         lyrics[k] = []
 
-    voice_builder = LilyPondVoiceBuilder ()
-    figured_bass_builder = LilyPondVoiceBuilder ()
-    chordnames_builder = LilyPondVoiceBuilder ()
-    current_measure_length = Rational (4, 4)
-    voice_builder.set_measure_length (current_measure_length)
+    voice_builder = LilyPondVoiceBuilder()
+    figured_bass_builder = LilyPondVoiceBuilder()
+    chordnames_builder = LilyPondVoiceBuilder()
+    fretboards_builder = LilyPondVoiceBuilder()
+    current_measure_length = Rational(4, 4)
+    voice_builder.set_measure_length(current_measure_length)
+    in_slur = False
 
-    for n in voice._elements:
+    all_lyric_parts = set(get_all_lyric_parts_in_voice(voice))
+    if lyrics.keys():
+        for number in lyrics.keys():
+            extracted_lyrics = extract_lyrics(voice, number, lyrics)
+
+    for idx, n in enumerate(voice._elements):
         tie_started = False
-        if n.get_name () == 'forward':
+        if n.get_name() == 'forward':
             continue
-        staff = n.get_maybe_exist_named_child ('staff')
+        staff = n.get_maybe_exist_named_child('staff')
         if staff:
-            staff = staff.get_text ()
-            if current_staff and staff <> current_staff and not n.get_maybe_exist_named_child ('chord'):
-                voice_builder.add_command (musicexp.StaffChange (staff))
+            staff = staff.get_text()
+            if current_staff and staff <> current_staff and not n.get_maybe_exist_named_child('chord'):
+                voice_builder.add_command(musicexp.StaffChange(staff))
             current_staff = staff
 
-        if isinstance (n, musicxml.Partial) and n.partial > 0:
-            a = musicxml_partial_to_lily (n.partial)
+        if isinstance(n, musicxml.Partial) and n.partial > 0:
+            a = musicxml_partial_to_lily(n.partial)
             if a:
-                voice_builder.add_partial (a)
-                figured_bass_builder.add_partial (a)
-                chordnames_builder.add_partial (a)
+                voice_builder.add_partial(a)
+                figured_bass_builder.add_partial(a)
+                chordnames_builder.add_partial(a)
+                fretboards_builder.add_partial(a)
             continue
 
-        is_chord = n.get_maybe_exist_named_child ('chord')
-        is_after_grace = (isinstance (n, musicxml.Note) and n.is_after_grace ());
+        is_chord = n.get_maybe_exist_named_child('chord')
+        is_after_grace =(isinstance(n, musicxml.Note) and n.is_after_grace());
         if not is_chord and not is_after_grace:
             try:
-                voice_builder.jumpto (n._when)
-                figured_bass_builder.jumpto (n._when)
-                chordnames_builder.jumpto (n._when)
+                voice_builder.jumpto(n._when)
+                figured_bass_builder.jumpto(n._when)
+                chordnames_builder.jumpto(n._when)
+                fretboards_builder.jumpto(n._when)
             except NegativeSkip, neg:
-                voice_builder.correct_negative_skip (n._when)
-                figured_bass_builder.correct_negative_skip (n._when)
-                chordnames_builder.correct_negative_skip (n._when)
-                n.message (_ ("Negative skip found: from %s to %s, difference is %s") % (neg.here, neg.dest, neg.dest - neg.here))
-
-        if isinstance (n, musicxml.Barline):
-            barlines = musicxml_barline_to_lily (n)
+                voice_builder.correct_negative_skip(n._when)
+                figured_bass_builder.correct_negative_skip(n._when)
+                chordnames_builder.correct_negative_skip(n._when)
+                fretboards_builder.correct_negative_skip(n._when)
+                n.message(_("Negative skip found: from %s to %s, difference is %s") % (neg.here, neg.dest, neg.dest - neg.here))
+
+        if isinstance(n, musicxml.Barline):
+            barlines = n.to_lily_object()
             for a in barlines:
-                if isinstance (a, musicexp.BarLine):
-                    voice_builder.add_barline (a)
-                    figured_bass_builder.add_barline (a, False)
-                    chordnames_builder.add_barline (a, False)
-                elif isinstance (a, RepeatMarker) or isinstance (a, EndingMarker):
-                    voice_builder.add_command (a)
-                    figured_bass_builder.add_barline (a, False)
-                    chordnames_builder.add_barline (a, False)
+                if isinstance(a, musicexp.BarLine):
+                    voice_builder.add_barline(a)
+                    figured_bass_builder.add_barline(a, False)
+                    chordnames_builder.add_barline(a, False)
+                    fretboards_builder.add_barline(a, False)
+                elif isinstance(a, musicxml2ly_conversion.RepeatMarker) or isinstance(a, musicxml2ly_conversion.EndingMarker):
+                    voice_builder.add_command(a)
+                    figured_bass_builder.add_barline(a, False)
+                    chordnames_builder.add_barline(a, False)
+                    fretboards_builder.add_barline(a, False)
             continue
 
-
-        if isinstance (n, musicxml.Print):
-            for a in musicxml_print_to_lily (n):
-                voice_builder.add_command (a, False)
+        if isinstance(n, musicxml.Print):
+            for a in musicxml_print_to_lily(n):
+                voice_builder.add_command(a, False)
             continue
 
         # Continue any multimeasure-rests before trying to add bar checks!
         # Don't handle new MM rests yet, because for them we want bar checks!
-        rest = n.get_maybe_exist_typed_child (musicxml.Rest)
-        if (rest and rest.is_whole_measure ()
-                 and voice_builder.pending_multibar > Rational (0)):
-            voice_builder.add_multibar_rest (n._duration)
+        rest = n.get_maybe_exist_typed_child(musicxml.Rest)
+        if (rest and rest.is_whole_measure()
+                 and voice_builder.pending_multibar > Rational(0)):
+            voice_builder.add_multibar_rest(n._duration)
             continue
 
-
         # print a bar check at the beginning of each measure!
-        if n.is_first () and n._measure_position == Rational (0) and n != voice._elements[0]:
+        if n.is_first() and n._measure_position == Rational(0) and n != voice._elements[0]:
             try:
-                num = int (n.get_parent ().number)
+                num = int(n.get_parent().number)
             except ValueError:
                 num = 0
             if num > 0:
-                voice_builder.add_bar_check (num)
-                figured_bass_builder.add_bar_check (num)
-                chordnames_builder.add_bar_check (num)
+                voice_builder.add_bar_check(num)
+                figured_bass_builder.add_bar_check(num)
+                chordnames_builder.add_bar_check(num)
+                fretboards_builder.add_bar_check(num)
+
+        if isinstance(n, musicxml.Direction):
+            # check if Direction already has been converted in another voice.
+            if n.converted:
+                continue
+            else:
+                n.converted = True
+                for direction in musicxml_direction_to_lily(n):
+                    if direction.wait_for_note():
+                        voice_builder.add_dynamics(direction)
+                    else:
+                        voice_builder.add_command(direction)
+                continue
 
         # Start any new multimeasure rests
-        if (rest and rest.is_whole_measure ()):
-            voice_builder.add_multibar_rest (n._duration)
-            continue
-
-
-        if isinstance (n, musicxml.Direction):
-            for a in musicxml_direction_to_lily (n):
-                if a.wait_for_note ():
-                    voice_builder.add_dynamics (a)
-                else:
-                    voice_builder.add_command (a)
+        if (rest and rest.is_whole_measure()):
+            if pending_chordnames:
+                chordnames_builder.jumpto(n._when)
+                chordnames_builder.stay_here = True
+            if pending_figured_bass:
+                figured_bass_builder.jumpto(n._when)
+                figured_bass_builder.stay_here = True
+            if pending_fretboards:
+                fretboards_builder.jumpto(n._when)
+                fretboards_builder.stay_here = True
+            voice_builder.add_multibar_rest(n._duration)
             continue
 
-        if isinstance (n, musicxml.Harmony):
-            for a in musicxml_harmony_to_lily (n):
-                if a.wait_for_note ():
-                    voice_builder.add_dynamics (a)
-                else:
-                    voice_builder.add_command (a)
-            for a in musicxml_harmony_to_lily_chordname (n):
-                pending_chordnames.append (a)
+        if isinstance(n, musicxml.Harmony):
+            if (options.fretboards):
+                # Makes fretboard diagrams in a separate FretBoards voice
+                for a in musicxml_harmony_to_lily_fretboards(n):
+                    pending_fretboards.append(a)
+            else:
+                # Makes markup fretboard-diagrams inside the voice
+                for a in musicxml_harmony_to_lily(n):
+                    if a.wait_for_note():
+                        voice_builder.add_dynamics(a)
+                    else:
+                        voice_builder.add_command(a)
+            for a in musicxml_harmony_to_lily_chordname(n):
+                pending_chordnames.append(a)
             continue
 
-        if isinstance (n, musicxml.FiguredBass):
-            a = musicxml_figured_bass_to_lily (n)
+        if isinstance(n, musicxml.FiguredBass):
+            a = musicxml_figured_bass_to_lily(n)
             if a:
-                pending_figured_bass.append (a)
+                pending_figured_bass.append(a)
             continue
 
-        if isinstance (n, musicxml.Attributes):
-            for a in musicxml_attributes_to_lily (n):
-                voice_builder.add_command (a)
-            measure_length = measure_length_from_attributes (n, current_measure_length)
+        if isinstance(n, musicxml.Attributes):
+            for a in musicxml_attributes_to_lily(n):
+                voice_builder.add_command(a)
+            measure_length = measure_length_from_attributes(n, current_measure_length)
             if current_measure_length != measure_length:
                 current_measure_length = measure_length
-                voice_builder.set_measure_length (current_measure_length)
+                voice_builder.set_measure_length(current_measure_length)
             continue
 
         if not n.__class__.__name__ == 'Note':
-            n.message (_ ('unexpected %s; expected %s or %s or %s') % (n, 'Note', 'Attributes', 'Barline'))
+            n.message(_('unexpected %s; expected %s or %s or %s') % (n, 'Note', 'Attributes', 'Barline'))
             continue
 
-        main_event = musicxml_note_to_lily_main_event (n)
+#        if not hasattr(conversion_settings, 'convert_rest_positions'):
+#            conversion_settings.convert_rest_positions = True
+
+        main_event = n.to_lily_object(
+            convert_stem_directions=conversion_settings.convert_stem_directions,
+            convert_rest_positions=conversion_settings.convert_rest_positions)
+
         if main_event and not first_pitch:
             first_pitch = main_event.pitch
         # ignore lyrics for notes inside a slur, tie, chord or beam
-        ignore_lyrics = inside_slur or is_tied or is_chord or is_beamed
+        ignore_lyrics = is_tied or is_chord #or is_beamed or inside_slur
 
-        if main_event and hasattr (main_event, 'drum_type') and main_event.drum_type:
+        if main_event and hasattr(main_event, 'drum_type') and main_event.drum_type:
             modes_found['drummode'] = True
 
-        ev_chord = voice_builder.last_event_chord (n._when)
+        ev_chord = voice_builder.last_event_chord(n._when)
         if not ev_chord:
             ev_chord = musicexp.ChordEvent()
-            voice_builder.add_music (ev_chord, n._duration)
+            voice_builder.add_music(ev_chord, n._duration)
 
         # For grace notes:
-        grace = n.get_maybe_exist_typed_child (musicxml.Grace)
-        if n.is_grace ():
-            is_after_grace = ev_chord.has_elements () or n.is_after_grace ();
-            is_chord = n.get_maybe_exist_typed_child (musicxml.Chord)
+        grace = n.get_maybe_exist_typed_child(musicxml.Grace)
+        if n.is_grace():
+            is_after_grace = ev_chord.has_elements() or n.is_after_grace();
+            is_chord = n.get_maybe_exist_typed_child(musicxml.Chord)
 
             grace_chord = None
 
@@ -2216,64 +2370,81 @@ def musicxml_voice_to_lily_voice (voice):
             # whether we have a chord or not, obtain either a new ChordEvent or
             # the previous one to create a chord
             if is_after_grace:
-                if ev_chord.after_grace_elements and n.get_maybe_exist_typed_child (musicxml.Chord):
-                    grace_chord = ev_chord.after_grace_elements.get_last_event_chord ()
+                if ev_chord.after_grace_elements and n.get_maybe_exist_typed_child(musicxml.Chord):
+                    grace_chord = ev_chord.after_grace_elements.get_last_event_chord()
                 if not grace_chord:
-                    grace_chord = musicexp.ChordEvent ()
-                    ev_chord.append_after_grace (grace_chord)
-            elif n.is_grace ():
-                if ev_chord.grace_elements and n.get_maybe_exist_typed_child (musicxml.Chord):
-                    grace_chord = ev_chord.grace_elements.get_last_event_chord ()
+                    grace_chord = musicexp.ChordEvent()
+                    ev_chord.append_after_grace(grace_chord)
+            elif n.is_grace():
+                if ev_chord.grace_elements and n.get_maybe_exist_typed_child(musicxml.Chord):
+                    grace_chord = ev_chord.grace_elements.get_last_event_chord()
                 if not grace_chord:
-                    grace_chord = musicexp.ChordEvent ()
-                    ev_chord.append_grace (grace_chord)
+                    grace_chord = musicexp.ChordEvent()
+                    ev_chord.append_grace(grace_chord)
 
-            if hasattr (grace, 'slash') and not is_after_grace:
+            if hasattr(grace, 'slash') and not is_after_grace:
                 # TODO: use grace_type = "appoggiatura" for slurred grace notes
                 if grace.slash == "yes":
                     ev_chord.grace_type = "acciaccatura"
             # now that we have inserted the chord into the grace music, insert
             # everything into that chord instead of the ev_chord
             ev_chord = grace_chord
-            ev_chord.append (main_event)
+            ev_chord.append(main_event)
             ignore_lyrics = True
         else:
-            ev_chord.append (main_event)
+            ev_chord.append(main_event)
             # When a note/chord has grace notes (duration==0), the duration of the
             # event chord is not yet known, but the event chord was already added
             # with duration 0. The following correct this when we hit the real note!
-            if voice_builder.current_duration () == 0 and n._duration > 0:
-                voice_builder.set_duration (n._duration)
+            if voice_builder.current_duration() == 0 and n._duration > 0:
+                voice_builder.set_duration(n._duration)
 
         # if we have a figured bass, set its voice builder to the correct position
         # and insert the pending figures
         if pending_figured_bass:
             try:
-                figured_bass_builder.jumpto (n._when)
+                figured_bass_builder.jumpto(n._when)
+                if (figured_bass_builder.stay_here):
+                    figured_bass_builder.stay_here = False
             except NegativeSkip, neg:
                 pass
             for fb in pending_figured_bass:
                 # if a duration is given, use that, otherwise the one of the note
                 dur = fb.real_duration
                 if not dur:
-                    dur = ev_chord.get_length ()
+                    dur = ev_chord.get_length()
                 if not fb.duration:
-                    fb.duration = ev_chord.get_duration ()
-                figured_bass_builder.add_music (fb, dur)
+                    fb.duration = ev_chord.get_duration()
+                figured_bass_builder.add_music(fb, dur)
             pending_figured_bass = []
 
         if pending_chordnames:
             try:
-                chordnames_builder.jumpto (n._when)
+                chordnames_builder.jumpto(n._when)
+                if (chordnames_builder.stay_here):
+                    chordnames_builder.stay_here = False
             except NegativeSkip, neg:
                 pass
             for cn in pending_chordnames:
                 # Assign the duration of the EventChord
-                cn.duration = ev_chord.get_duration ()
-                chordnames_builder.add_music (cn, ev_chord.get_length ())
+                cn.duration = ev_chord.get_duration()
+                chordnames_builder.add_music(cn, ev_chord.get_length())
             pending_chordnames = []
 
-        notations_children = n.get_typed_children (musicxml.Notations)
+        if pending_fretboards:
+            try:
+                fretboards_builder.jumpto(n._when)
+                if (fretboards_builder.stay_here):
+                    fretboards_builder.stay_here = False
+            except NegativeSkip, neg:
+                pass
+            for fb in pending_fretboards:
+                # Assign the duration of the EventChord
+                fb.duration = ev_chord.get_duration()
+                fretboards_builder.add_music(fb, ev_chord.get_length())
+            pending_fretboards = []
+
+        notations_children = n.get_typed_children(musicxml.Notations)
         tuplet_event = None
         span_events = []
 
@@ -2284,76 +2455,76 @@ def musicxml_voice_to_lily_voice (voice):
         #    accidental-mark | other-notation
         for notations in notations_children:
             for tuplet_event in notations.get_tuplets():
-                time_mod = n.get_maybe_exist_typed_child (musicxml.Time_modification)
-                tuplet_events.append ((ev_chord, tuplet_event, time_mod))
+                time_mod = n.get_maybe_exist_typed_child(musicxml.Time_modification)
+                tuplet_events.append((ev_chord, tuplet_event, time_mod))
 
             # First, close all open slurs, only then start any new slur
             # TODO: Record the number of the open slur to dtermine the correct
             #       closing slur!
-            endslurs = [s for s in notations.get_named_children ('slur')
-                if s.get_type () in ('stop')]
+            endslurs = [s for s in notations.get_named_children('slur')
+                if s.get_type() in ('stop')]
             if endslurs and not inside_slur:
-                endslurs[0].message (_ ('Encountered closing slur, but no slur is open'))
+                endslurs[0].message(_('Encountered closing slur, but no slur is open'))
             elif endslurs:
-                if len (endslurs) > 1:
-                    endslurs[0].message (_ ('Cannot have two simultaneous (closing) slurs'))
+                if len(endslurs) > 1:
+                    endslurs[0].message(_('Cannot have two simultaneous (closing) slurs'))
                 # record the slur status for the next note in the loop
                 inside_slur = False
-                lily_ev = musicxml_spanner_to_lily_event (endslurs[0])
-                ev_chord.append (lily_ev)
+                lily_ev = musicxml_spanner_to_lily_event(endslurs[0])
+                ev_chord.append(lily_ev)
 
-            startslurs = [s for s in notations.get_named_children ('slur')
-                if s.get_type () in ('start')]
+            startslurs = [s for s in notations.get_named_children('slur')
+                if s.get_type() in('start')]
             if startslurs and inside_slur:
-                startslurs[0].message (_ ('Cannot have a slur inside another slur'))
+                startslurs[0].message(_('Cannot have a slur inside another slur'))
             elif startslurs:
-                if len (startslurs) > 1:
-                    startslurs[0].message (_ ('Cannot have two simultaneous slurs'))
+                if len(startslurs) > 1:
+                    startslurs[0].message(_('Cannot have two simultaneous slurs'))
                 # record the slur status for the next note in the loop
                 inside_slur = True
-                lily_ev = musicxml_spanner_to_lily_event (startslurs[0])
-                ev_chord.append (lily_ev)
+                lily_ev = musicxml_spanner_to_lily_event(startslurs[0])
+                ev_chord.append(lily_ev)
 
 
             if not grace:
-                mxl_tie = notations.get_tie ()
+                mxl_tie = notations.get_tie()
                 if mxl_tie and mxl_tie.type == 'start':
-                    ev_chord.append (musicexp.TieEvent ())
+                    ev_chord.append(musicexp.TieEvent())
                     is_tied = True
                     tie_started = True
                 else:
                     is_tied = False
 
-            fermatas = notations.get_named_children ('fermata')
+            fermatas = notations.get_named_children('fermata')
             for a in fermatas:
-                ev = musicxml_fermata_to_lily_event (a)
+                ev = musicxml_fermata_to_lily_event(a)
                 if ev:
-                    ev_chord.append (ev)
+                    ev_chord.append(ev)
 
-            arpeggiate = notations.get_named_children ('arpeggiate')
+            arpeggiate = notations.get_named_children('arpeggiate')
             for a in arpeggiate:
-                ev = musicxml_arpeggiate_to_lily_event (a)
+                ev = musicxml_arpeggiate_to_lily_event(a)
                 if ev:
-                    ev_chord.append (ev)
+                    ev_chord.append(ev)
 
-            arpeggiate = notations.get_named_children ('non-arpeggiate')
+            arpeggiate = notations.get_named_children('non-arpeggiate')
             for a in arpeggiate:
-                ev = musicxml_nonarpeggiate_to_lily_event (a)
+                ev = musicxml_nonarpeggiate_to_lily_event(a)
                 if ev:
-                    ev_chord.append (ev)
+                    ev_chord.append(ev)
 
-            glissandos = notations.get_named_children ('glissando')
-            glissandos += notations.get_named_children ('slide')
+            glissandos = notations.get_named_children('glissando')
+            glissandos += notations.get_named_children('slide')
             for a in glissandos:
-                ev = musicxml_spanner_to_lily_event (a)
+                ev = musicxml_spanner_to_lily_event(a)
                 if ev:
-                    ev_chord.append (ev)
+                    ev_chord.append(ev)
 
             # accidental-marks are direct children of <notation>!
-            for a in notations.get_named_children ('accidental-mark'):
-                ev = musicxml_articulation_to_lily_event (a)
+            for a in notations.get_named_children('accidental-mark'):
+                ev = musicxml_articulation_to_lily_event(a)
                 if ev:
-                    ev_chord.append (ev)
+                    ev_chord.append(ev)
 
             # Articulations can contain the following child elements:
             #         accent | strong-accent | staccato | tenuto |
@@ -2370,88 +2541,85 @@ def musicxml_voice_to_lily_voice (voice):
             #         trill-mark | turn | delayed-turn | inverted-turn |
             #         shake | wavy-line | mordent | inverted-mordent |
             #         schleifer | tremolo | other-ornament, accidental-mark
-            ornaments = notations.get_named_children ('ornaments')
-            ornaments += notations.get_named_children ('articulations')
-            ornaments += notations.get_named_children ('technical')
+            ornaments = notations.get_named_children('ornaments')
+            ornaments += notations.get_named_children('articulations')
+            ornaments += notations.get_named_children('technical')
 
             for a in ornaments:
-                for ch in a.get_all_children ():
-                    ev = musicxml_articulation_to_lily_event (ch)
+                for ch in a.get_all_children():
+                    ev = musicxml_articulation_to_lily_event(ch)
                     if ev:
-                        ev_chord.append (ev)
+                        ev_chord.append(ev)
 
-            dynamics = notations.get_named_children ('dynamics')
+            dynamics = notations.get_named_children('dynamics')
             for a in dynamics:
-                for ch in a.get_all_children ():
-                    ev = musicxml_dynamics_to_lily_event (ch)
+                for ch in a.get_all_children():
+                    ev = musicxml_dynamics_to_lily_event(ch)
                     if ev:
-                        ev_chord.append (ev)
+                        ev_chord.append(ev)
 
 
-        mxl_beams = [b for b in n.get_named_children ('beam')
-                     if (b.get_type () in ('begin', 'end')
-                         and b.is_primary ())]
+        mxl_beams = [b for b in n.get_named_children('beam')
+                     if (b.get_type() in('begin', 'end')
+                         and b.is_primary())]
         if mxl_beams and not conversion_settings.ignore_beaming:
-            beam_ev = musicxml_spanner_to_lily_event (mxl_beams[0])
+            beam_ev = musicxml_spanner_to_lily_event(mxl_beams[0])
             if beam_ev:
-                ev_chord.append (beam_ev)
+                ev_chord.append(beam_ev)
                 if beam_ev.span_direction == -1: # beam and thus melisma starts here
                     is_beamed = True
                 elif beam_ev.span_direction == 1: # beam and thus melisma ends here
                     is_beamed = False
 
-        # Extract the lyrics
-        if not rest and not ignore_lyrics:
-            note_lyrics_processed = []
-            note_lyrics_elements = n.get_typed_children (musicxml.Lyric)
-            for l in note_lyrics_elements:
-                if l.get_number () < 0:
-                    for k in lyrics.keys ():
-                        lyrics[k].append (musicxml_lyrics_to_text (l))
-                        note_lyrics_processed.append (k)
-                else:
-                    lyrics[l.number].append(musicxml_lyrics_to_text (l))
-                    note_lyrics_processed.append (l.number)
-            for lnr in lyrics.keys ():
-                if not lnr in note_lyrics_processed:
-                    lyrics[lnr].append ("\skip4")
-
         # Assume that a <tie> element only lasts for one note.
         # This might not be correct MusicXML interpretation, but works for
         # most cases and fixes broken files, which have the end tag missing
         if is_tied and not tie_started:
             is_tied = False
 
-    ## force trailing mm rests to be written out.
-    voice_builder.add_music (musicexp.ChordEvent (), Rational (0))
+    # force trailing mm rests to be written out.
+    # voice_builder.add_music (musicexp.ChordEvent(), Rational(0))
+    if hasattr(options, 'shift_meter') and options.shift_meter:
+        for event in voice_builder.elements:
+            if isinstance(event, musicexp.TimeSignatureChange):
+                sd = []
+                for i in range(0,5):
+                    sd.append(musicexp.ShiftDurations())
+                    sd[i].set_shift_durations_parameters(event)
+                break;
 
-    ly_voice = group_tuplets (voice_builder.elements, tuplet_events)
-    ly_voice = group_repeats (ly_voice)
+    ly_voice = group_tuplets(voice_builder.elements, tuplet_events)
+    ly_voice = group_repeats(ly_voice)
 
-    seq_music = musicexp.SequentialMusic ()
+    seq_music = musicexp.SequentialMusic()
 
-    if 'drummode' in modes_found.keys ():
+    if 'drummode' in modes_found.keys():
         ## \key <pitch> barfs in drummode.
         ly_voice = [e for e in ly_voice
                     if not isinstance(e, musicexp.KeySignatureChange)]
 
     seq_music.elements = ly_voice
-    for k in lyrics.keys ():
-        return_value.lyrics_dict[k] = musicexp.Lyrics ()
+    for k in lyrics.keys():
+        return_value.lyrics_dict[k] = musicexp.Lyrics()
         return_value.lyrics_dict[k].lyrics_syllables = lyrics[k]
 
 
-    if len (modes_found) > 1:
-       ly.warning (_ ('cannot simultaneously have more than one mode: %s') % modes_found.keys ())
+    if len(modes_found) > 1:
+       ly.warning(_('cannot simultaneously have more than one mode: %s') % modes_found.keys())
+
+    if hasattr(options, 'shift_meter') and options.shift_meter:
+        sd[-1].element = seq_music
+        seq_music = sd[-1]
+        sd.pop()
 
-    if options.relative:
-        v = musicexp.RelativeMusic ()
+    if hasattr(options, 'relative') and options.relative:
+        v = musicexp.RelativeMusic()
         v.element = seq_music
         v.basepitch = first_pitch
         seq_music = v
 
     return_value.ly_voice = seq_music
-    for mode in modes_found.keys ():
+    for mode in modes_found.keys():
         v = musicexp.ModeChangingMusicWrapper()
         v.element = seq_music
         v.mode = mode
@@ -2459,81 +2627,87 @@ def musicxml_voice_to_lily_voice (voice):
 
     # create \figuremode { figured bass elements }
     if figured_bass_builder.has_relevant_elements:
-        fbass_music = musicexp.SequentialMusic ()
-        fbass_music.elements = group_repeats (figured_bass_builder.elements)
+        fbass_music = musicexp.SequentialMusic()
+        fbass_music.elements = group_repeats(figured_bass_builder.elements)
         v = musicexp.ModeChangingMusicWrapper()
         v.mode = 'figuremode'
         v.element = fbass_music
+        if hasattr(options, 'shift_meter') and options.shift_meter:
+            sd[-1].element = v
+            v = sd[-1]
+            sd.pop()
         return_value.figured_bass = v
 
     # create \chordmode { chords }
     if chordnames_builder.has_relevant_elements:
-        cname_music = musicexp.SequentialMusic ()
-        cname_music.elements = group_repeats (chordnames_builder.elements)
+        cname_music = musicexp.SequentialMusic()
+        cname_music.elements = group_repeats(chordnames_builder.elements)
         v = musicexp.ModeChangingMusicWrapper()
         v.mode = 'chordmode'
         v.element = cname_music
+        if hasattr(options, 'shift_meter') and options.shift_meter:
+            sd[-1].element = v
+            v = sd[-1]
+            sd.pop()
         return_value.chordnames = v
 
+    # create diagrams for FretBoards engraver
+    if fretboards_builder.has_relevant_elements:
+        fboard_music = musicexp.SequentialMusic()
+        fboard_music.elements = group_repeats(fretboards_builder.elements)
+        v = musicexp.MusicWrapper()
+        v.element = fboard_music
+        if hasattr(options, 'shift_meter') and options.shift_meter:
+            sd[-1].element = v
+            v = sd[-1]
+            sd.pop()
+        return_value.fretboards = v
+
+    # coll = []
+    # pending = []
+
+    # for elt in return_value.ly_voice.element.elements:
+    #     if isinstance(elt, musicexp.TimeScaledMusic):
+    #         print elt.element.elements
+    #         pending.append(elt)
+    #     else:
+    #         coll.append(elt)
+
+    # if pending:
+    #     coll.extend(pending)
+
+    # return_value.ly_voice.element.elements = coll
+
     return return_value
 
-def musicxml_id_to_lily (id):
+def musicxml_id_to_lily(id):
     digits = ['Zero', 'One', 'Two', 'Three', 'Four', 'Five',
               'Six', 'Seven', 'Eight', 'Nine', 'Ten']
 
     for digit in digits:
-        d = digits.index (digit)
-        id = re.sub ('%d' % d, digit, id)
+        d = digits.index(digit)
+        id = re.sub('%d' % d, digit, id)
 
-    id = re.sub  ('[^a-zA-Z]', 'X', id)
+    id = re.sub('[^a-zA-Z]', 'X', id)
     return id
 
-def musicxml_pitch_to_lily (mxl_pitch):
-    p = musicexp.Pitch ()
-    p.alteration = mxl_pitch.get_alteration ()
-    p.step = musicxml_step_to_lily (mxl_pitch.get_step ())
-    p.octave = mxl_pitch.get_octave () - 4
-    return p
-
-def musicxml_unpitched_to_lily (mxl_unpitched):
-    p = None
-    step = mxl_unpitched.get_step ()
-    if step:
-        p = musicexp.Pitch ()
-        p.step = musicxml_step_to_lily (step)
-    octave = mxl_unpitched.get_octave ()
-    if octave and p:
-        p.octave = octave - 4
-    return p
-
-def musicxml_restdisplay_to_lily (mxl_rest):
-    p = None
-    step = mxl_rest.get_step ()
-    if step:
-        p = musicexp.Pitch ()
-        p.step = musicxml_step_to_lily (step)
-    octave = mxl_rest.get_octave ()
-    if octave and p:
-        p.octave = octave - 4
-    return p
-
-def voices_in_part (part):
+def voices_in_part(part):
     """Return a Name -> Voice dictionary for PART"""
-    part.interpret ()
-    part.extract_voices ()
-    voices = part.get_voices ()
-    part_info = part.get_staff_attributes ()
+    part.interpret()
+    part.extract_voices()
+    voices = part.get_voices()
+    part_info = part.get_staff_attributes()
 
     return (voices, part_info)
 
-def voices_in_part_in_parts (parts):
+def voices_in_part_in_parts(parts):
     """return a Part -> Name -> Voice dictionary"""
-    # don't crash if p doesn't have an id (that's invalid MusicXML,
-    # but such files are out in the wild!
+    # don't crash if Part doesn't have an id (that's invalid MusicXML,
+    # but such files are out in the wild!)
     dictionary = {}
     for p in parts:
-        voices = voices_in_part (p)
-        if (hasattr (p, "id")):
+        voices = voices_in_part(p)
+        if (hasattr(p, "id")):
              dictionary[p.id] = voices
         else:
              # TODO: extract correct part id from other sources
@@ -2541,18 +2715,19 @@ def voices_in_part_in_parts (parts):
     return dictionary;
 
 
-def get_all_voices (parts):
-    all_voices = voices_in_part_in_parts (parts)
+def get_all_voices(parts):
+    all_voices = voices_in_part_in_parts(parts)
 
     all_ly_voices = {}
     all_ly_staffinfo = {}
-    for p, (name_voice, staff_info) in all_voices.items ():
+    for p, (name_voice, staff_info) in all_voices.items():
 
         part_ly_voices = {}
-        for n, v in name_voice.items ():
-            ly.progress (_ ("Converting to LilyPond expressions..."), True)
+        for n, v in name_voice.items():
+            ly.progress(_("Converting to LilyPond expressions..."), True)
             # musicxml_voice_to_lily_voice returns (lily_voice, {nr->lyrics, nr->lyrics})
-            part_ly_voices[n] = musicxml_voice_to_lily_voice (v)
+            voice = musicxml_voice_to_lily_voice(v)
+            part_ly_voices[n] = voice
 
         all_ly_voices[p] = part_ly_voices
         all_ly_staffinfo[p] = staff_info
@@ -2560,23 +2735,24 @@ def get_all_voices (parts):
     return (all_ly_voices, all_ly_staffinfo)
 
 
-def option_parser ():
-    p = ly.get_option_parser (usage = _ ("musicxml2ly [OPTION]... FILE.xml"),
-                             description =
-_ ("""Convert MusicXML from FILE.xml to LilyPond input.
+def option_parser():
+    p = ly.get_option_parser(usage=_("musicxml2ly [OPTION]... FILE.xml"),
+                             description=
+_("""Convert MusicXML from FILE.xml to LilyPond input.
 If the given filename is -, musicxml2ly reads from the command line.
 """), add_help_option=False)
 
     p.add_option("-h", "--help",
                  action="help",
-                 help=_ ("show this help and exit"))
+                 help=_("show this help and exit"))
 
-    p.version = ('''%prog (LilyPond) @TOPLEVEL_VERSION@\n\n'''
+    p.version = ('%prog (LilyPond) ' + lilypond_version + '\n\n'
 +
-_ ("""Copyright (c) 2005--2015 by
+_ ("""Copyright (c) 2005--2016 by
     Han-Wen Nienhuys <hanwen@xs4all.nl>,
     Jan Nieuwenhuizen <janneke@gnu.org> and
     Reinhold Kainhofer <reinhold@kainhofer.com>
+    Patrick L. Schmidt <pls@philomelos.net>
 """
 +
 """
@@ -2589,41 +2765,41 @@ information.""") % 'lilypond')
                  action="version",
                  help=_ ("show version number and exit"))
 
-    p.add_option ('-v', '--verbose',
+    p.add_option('-v', '--verbose',
                   action="callback",
                   callback=ly.handle_loglevel_option,
                   callback_args=("DEBUG",),
-                  help = _ ("be verbose"))
-
-    p.add_option ('', '--lxml',
-                  action = "store_true",
-                  default = False,
-                  dest = "use_lxml",
-                  help = _ ("use lxml.etree; uses less memory and cpu time"))
-
-    p.add_option ('-z', '--compressed',
-                  action = "store_true",
-                  dest = 'compressed',
-                  default = False,
-                  help = _ ("input file is a zip-compressed MusicXML file"))
-
-    p.add_option ('-r', '--relative',
-                  action = "store_true",
-                  default = True,
-                  dest = "relative",
-                  help = _ ("convert pitches in relative mode (default)"))
-
-    p.add_option ('-a', '--absolute',
-                  action = "store_false",
-                  dest = "relative",
-                  help = _ ("convert pitches in absolute mode"))
-
-    p.add_option ('-l', '--language',
-                  metavar = _ ("LANG"),
-                  action = "store",
-                  help = _ ("use LANG for pitch names, e.g. 'deutsch' for note names in German"))
-
-    p.add_option ("--loglevel",
+                  help=_ ("be verbose"))
+
+    p.add_option('', '--lxml',
+                  action="store_true",
+                  default=False,
+                  dest="use_lxml",
+                  help=_ ("use lxml.etree; uses less memory and cpu time"))
+
+    p.add_option('-z', '--compressed',
+                  action="store_true",
+                  dest='compressed',
+                  default=False,
+                  help=_ ("input file is a zip-compressed MusicXML file"))
+
+    p.add_option('-r', '--relative',
+                  action="store_true",
+                  default=True,
+                  dest="relative",
+                  help=_ ("convert pitches in relative mode (default)"))
+
+    p.add_option('-a', '--absolute',
+                  action="store_false",
+                  dest="relative",
+                  help=_ ("convert pitches in absolute mode"))
+
+    p.add_option('-l', '--language',
+                  metavar=_ ("LANG"),
+                  action="store",
+                  help=_ ("use LANG for pitch names, e.g. 'deutsch' for note names in German"))
+
+    p.add_option("--loglevel",
                   help=_ ("Print log messages according to LOGLEVEL "
                           "(NONE, ERROR, WARNING, PROGRESS (default), DEBUG)"),
                   metavar=_ ("LOGLEVEL"),
@@ -2631,67 +2807,110 @@ information.""") % 'lilypond')
                   callback=ly.handle_loglevel_option,
                   type='string')
 
-    p.add_option ('--nd', '--no-articulation-directions',
-                  action = "store_false",
-                  default = True,
-                  dest = "convert_directions",
-                  help = _ ("do not convert directions (^, _ or -) for articulations, dynamics, etc."))
-
-    p.add_option ('--nrp', '--no-rest-positions',
-                  action = "store_false",
-                  default = True,
-                  dest = "convert_rest_positions",
-                  help = _ ("do not convert exact vertical positions of rests"))
-
-    p.add_option ('--npl', '--no-page-layout',
-                  action = "store_false",
-                  default = True,
-                  dest = "convert_page_layout",
-                  help = _ ("do not convert the exact page layout and breaks"))
-
-    p.add_option ('--no-beaming',
-                  action = "store_false",
-                  default = True,
-                  dest = "convert_beaming",
-                  help = _ ("do not convert beaming information, use lilypond's automatic beaming instead"))
-
-    p.add_option ('-o', '--output',
-                  metavar = _ ("FILE"),
-                  action = "store",
-                  default = None,
-                  type = 'string',
-                  dest = 'output_name',
-                  help = _ ("set output filename to FILE, stdout if -"))
-
-    p.add_option ('-m', '--midi',
-                  action = "store_true",
-                  default = False,
-                  dest = "midi",
-                  help = _("activate midi-block"))
-
-    p.add_option_group ('',
-                        description = (
+    p.add_option('--nd', '--no-articulation-directions',
+                  action="store_false",
+                  default=True,
+                  dest="convert_directions",
+                  help=_ ("do not convert directions (^, _ or -) for articulations, dynamics, etc."))
+
+    p.add_option('--nrp', '--no-rest-positions',
+                  action="store_false",
+                  default=True,
+                  dest="convert_rest_positions",
+                  help=_ ("do not convert exact vertical positions of rests"))
+
+    p.add_option('--nsb', '--no-system-breaks',
+                  action="store_false",
+                  default=True,
+                  dest="convert_system_breaks",
+                  help=_ ("ignore system breaks"))
+
+    p.add_option('--npb', '--no-page-breaks',
+                  action="store_false",
+                  default=True,
+                  dest="convert_page_breaks",
+                  help=_ ("ignore page breaks"))
+
+    p.add_option('--npm', '--no-page-margins',
+                  action="store_false",
+                  default=True,
+                  dest="convert_page_margins",
+                  help=_ ("ignore page margins"))
+
+    p.add_option('--npl', '--no-page-layout',
+                  action="store_false",
+                  default=True,
+                  dest="convert_page_layout",
+                  help=_ ("do not convert the exact page layout and breaks (shortcut for \"--nsb --npb --npm\" options)"))
+
+    p.add_option('--nsd', '--no-stem-directions',
+                  action="store_false",
+                  default=True,
+                  dest="convert_stem_directions",
+                  help=_ ("ignore stem directions from MusicXML, use lilypond's automatic stemming instead"))
+
+    p.add_option('--nb', '--no-beaming',
+                  action="store_false",
+                  default=True,
+                  dest="convert_beaming",
+                  help=_ ("do not convert beaming information, use lilypond's automatic beaming instead"))
+
+    p.add_option('-o', '--output',
+                  metavar=_ ("FILE"),
+                  action="store",
+                  default=None,
+                  type='string',
+                  dest='output_name',
+                  help=_ ("set output filename to FILE, stdout if -"))
+
+    p.add_option('-m', '--midi',
+                  action="store_true",
+                  default=False,
+                  dest="midi",
+                  help=_("activate midi-block in .ly file"))
+
+    # transpose function
+    p.add_option('--transpose',
+                  metavar=_ ("TOPITCH"),
+                  action="store",
+                  dest="transpose",
+                  help=_ ("set pitch to transpose by the interval between pitch 'c' and TOPITCH"))
+
+    # time signature changing function
+    p.add_option('--sm', '--shift-meter',
+                  metavar=_ ("BEATS/BEATTYPE"),
+                  action="store",
+                  dest="shift_meter",
+                  help=_ ("change the length|duration of notes as a function of a given time signature to make the score look faster or slower, (eg. '4/4' or '2/2')"))
+
+    # switch tabstaff clef
+    p.add_option('--tc', '--tab-clef',
+                  metavar=_ ("TABCLEFNAME"),
+                  action="store",
+                  dest="tab_clef",
+                  help=_ ("switch between two versions of tab clefs (\"tab\" and \"moderntab\")"))
+
+    # StringNumber stencil on/off
+    p.add_option('--sn', '--string-numbers',
+                  metavar=_ ("t[rue]/f[alse]"),
+                  action="store",
+                  dest="string_numbers",
+                  help=_ ("deactivate string number stencil with --string-numbers f[alse]. Default is t[rue]"))
+
+    # StringNumber stencil on/off
+    p.add_option('--fb', '--fretboards',
+                  action="store_true",
+                  default=False,
+                  dest="fretboards",
+                  help=_("converts '<frame>' events to a separate FretBoards voice instead of markups"))
+
+    p.add_option_group('',
+                        description=(
             _ ("Report bugs via %s")
             % 'http://post.gmane.org/post.php'
             '?group=gmane.comp.gnu.lilypond.bugs') + '\n')
     return p
 
-def music_xml_voice_name_to_lily_name (part_id, name):
-    str = "Part%sVoice%s" % (part_id, name)
-    return musicxml_id_to_lily (str)
-
-def music_xml_lyrics_name_to_lily_name (part_id, name, lyricsnr):
-    str = "Part%sVoice%sLyrics%s" % (part_id, name, lyricsnr)
-    return musicxml_id_to_lily (str)
-
-def music_xml_figuredbass_name_to_lily_name (part_id, voicename):
-    str = "Part%sVoice%sFiguredBass" % (part_id, voicename)
-    return musicxml_id_to_lily (str)
-
-def music_xml_chordnames_name_to_lily_name (part_id, voicename):
-    str = "Part%sVoice%sChords" % (part_id, voicename)
-    return musicxml_id_to_lily (str)
-
 def print_voice_definitions (printer, part_list, voices):
     for part in part_list:
         part_id = part.id
@@ -2703,23 +2922,27 @@ def print_voice_definitions (printer, part_list, voices):
             printer.newline()
             if voice.chordnames:
                 cnname = music_xml_chordnames_name_to_lily_name (part_id, name)
-                printer.dump ('%s = ' % cnname )
+                printer.dump ('%s = ' % cnname)
                 voice.chordnames.print_ly (printer)
                 printer.newline()
             for l in voice.lyrics_order:
                 lname = music_xml_lyrics_name_to_lily_name (part_id, name, l)
-                printer.dump ('%s = ' % lname )
+                printer.dump ('%s = ' % lname)
                 voice.lyrics_dict[l].print_ly (printer)
                 printer.newline()
             if voice.figured_bass:
                 fbname = music_xml_figuredbass_name_to_lily_name (part_id, name)
-                printer.dump ('%s = ' % fbname )
+                printer.dump ('%s = ' % fbname)
                 voice.figured_bass.print_ly (printer)
                 printer.newline()
+            if voice.fretboards:
+                fbdname = music_xml_fretboards_name_to_lily_name (part_id, name)
+                printer.dump ('%s = ' % fbdname)
+                voice.fretboards.print_ly (printer)
+                printer.newline()
 
-
-def uniq_list (l):
-    return dict ([(elt, 1) for elt in l]).keys ()
+def uniq_list(l):
+    return dict([(elt, 1) for elt in l]).keys()
 
 # format the information about the staff in the form
 #     [staffid,
@@ -2730,159 +2953,189 @@ def uniq_list (l):
 #         ]
 #     ]
 # raw_voices is of the form [(voicename, lyricsids, havefiguredbass)*]
-def format_staff_info (part_id, staff_id, raw_voices):
+def format_staff_info(part_id, staff_id, raw_voices):
     voices = []
-    for (v, lyricsids, figured_bass, chordnames) in raw_voices:
-        voice_name = music_xml_voice_name_to_lily_name (part_id, v)
-        voice_lyrics = [music_xml_lyrics_name_to_lily_name (part_id, v, l)
+    for (v, lyricsids, figured_bass, chordnames, fretboards) in raw_voices:
+        voice_name = music_xml_voice_name_to_lily_name(part_id, v)
+        voice_lyrics = [music_xml_lyrics_name_to_lily_name(part_id, v, l)
                    for l in lyricsids]
         figured_bass_name = ''
         if figured_bass:
-            figured_bass_name = music_xml_figuredbass_name_to_lily_name (part_id, v)
+            figured_bass_name = music_xml_figuredbass_name_to_lily_name(part_id, v)
         chordnames_name = ''
         if chordnames:
-            chordnames_name = music_xml_chordnames_name_to_lily_name (part_id, v)
-        voices.append ([voice_name, voice_lyrics, figured_bass_name, chordnames_name])
+            chordnames_name = music_xml_chordnames_name_to_lily_name(part_id, v)
+        fretboards_name = ''
+        if fretboards:
+            fretboards_name = music_xml_fretboards_name_to_lily_name(part_id, v)
+        voices.append([voice_name, voice_lyrics, figured_bass_name, chordnames_name, fretboards_name])
     return [staff_id, voices]
 
-def update_score_setup (score_structure, part_list, voices):
-
+def update_score_setup(score_structure, part_list, voices, parts):
     for part_definition in part_list:
         part_id = part_definition.id
-        nv_dict = voices.get (part_id)
+        nv_dict = voices.get(part_id)
         if not nv_dict:
-            ly.warning (_ ('unknown part in part-list: %s') % part_id)
+            ly.warning(_('unknown part in part-list: %s') % part_id)
             continue
 
-        staves = reduce (lambda x,y: x+ y,
-                [voice.voicedata._staves.keys ()
-                 for voice in nv_dict.values ()],
+        staves = reduce(lambda x, y: x + y,
+                [voice.voicedata._staves.keys()
+                 for voice in nv_dict.values()],
                 [])
         staves_info = []
-        if len (staves) > 1:
+        if len(staves) > 1:
             staves_info = []
-            staves = uniq_list (staves)
-            staves.sort ()
+            staves = uniq_list(staves)
+            staves.sort()
             for s in staves:
-                thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass, voice.chordnames)
-                    for (voice_name, voice) in nv_dict.items ()
+                thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass, voice.chordnames, voice.fretboards)
+                    for (voice_name, voice) in nv_dict.items()
                     if voice.voicedata._start_staff == s]
-                staves_info.append (format_staff_info (part_id, s, thisstaff_raw_voices))
+                staves_info.append(format_staff_info(part_id, s, thisstaff_raw_voices))
         else:
-            thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass, voice.chordnames)
-                for (voice_name, voice) in nv_dict.items ()]
-            staves_info.append (format_staff_info (part_id, None, thisstaff_raw_voices))
-        score_structure.set_part_information (part_id, staves_info)
+            thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass, voice.chordnames, voice.fretboards)
+                for (voice_name, voice) in nv_dict.items()]
+            staves_info.append(format_staff_info(part_id, None, thisstaff_raw_voices))
+        score_structure.set_part_information(part_id, staves_info)
+
+    sounds = []
+    for part in parts:
+        for measure in part.get_typed_children(musicxml.Measure):
+            for sound in measure.get_typed_children(musicxml.Sound):
+                sounds.append(sound)
+            for direction in measure.get_typed_children(musicxml.Direction):
+                for sound in direction.get_typed_children(musicxml.Sound):
+                    sounds.append(sound)
+
+    score_structure.set_tempo('100')
+    if len(sounds) != 0:
+        for sound in sounds:
+            if (sound.get_tempo() != None and sound.get_tempo() != ""):
+                score_structure.set_tempo(sound.get_tempo())
+                break
+
 
 # Set global values in the \layout block, like auto-beaming etc.
-def update_layout_information ():
+def update_layout_information():
     if not conversion_settings.ignore_beaming and layout_information:
-        layout_information.set_context_item ('Score', 'autoBeaming = ##f')
-
-def print_ly_preamble (printer, filename):
-    printer.dump_version ()
-    printer.print_verbatim ('%% automatically converted by musicxml2ly from %s\n' % filename)
+        layout_information.set_context_item('Score', 'autoBeaming = ##f')
+    if musicexp.get_string_numbers() == "f":
+        layout_information.set_context_item('Score', '\\override StringNumber #\'stencil = ##f')
+
+#  \n\t\t\t\t\\override StringNumber #\'stencil = ##f
+
+def print_ly_preamble(printer, filename):
+    printer.dump_version(lilypond_version)
+    printer.print_verbatim('% automatically converted by musicxml2ly from ' + filename)
+    printer.newline()
+    printer.dump(r'\pointAndClickOff')
+    printer.newline()
+    if options.midi:
+        printer.newline()
+        printer.dump(r'\include "articulate.ly"')
+        printer.newline()
 
-def print_ly_additional_definitions (printer, filename):
+def print_ly_additional_definitions(printer, filename=None):
     if needed_additional_definitions:
-        printer.newline ()
-        printer.print_verbatim ('%% additional definitions required by the score:')
-        printer.newline ()
+        printer.newline()
+        printer.print_verbatim('%% additional definitions required by the score:')
+        printer.newline()
     for a in set(needed_additional_definitions):
-        printer.print_verbatim (additional_definitions.get (a, ''))
-        printer.newline ()
-    printer.newline ()
+        printer.print_verbatim(additional_definitions.get(a, ''))
+        printer.newline()
+    printer.newline()
 
 # Read in the tree from the given I/O object (either file or string) and
 # demarshall it using the classes from the musicxml.py file
-def read_xml (io_object, use_lxml):
+def read_xml(io_object, use_lxml):
     if use_lxml:
         import lxml.etree
-        tree = lxml.etree.parse (io_object)
-        mxl_tree = musicxml.lxml_demarshal_node (tree.getroot ())
+        tree = lxml.etree.parse(io_object)
+        mxl_tree = musicxml.lxml_demarshal_node(tree.getroot())
         return mxl_tree
     else:
         from xml.dom import minidom, Node
         doc = minidom.parse(io_object)
         node = doc.documentElement
-        return musicxml.minidom_demarshal_node (node)
+        return musicxml.minidom_demarshal_node(node)
     return None
 
 
-def read_musicxml (filename, compressed, use_lxml):
+def read_musicxml(filename, compressed, use_lxml):
     raw_string = None
     if compressed:
         if filename == "-":
-             ly.progress (_ ("Input is compressed, extracting raw MusicXML data from stdin"), True)
+             ly.progress(_("Input is compressed, extracting raw MusicXML data from stdin"), True)
              # unfortunately, zipfile.ZipFile can't read directly from
              # stdin, so copy everything from stdin to a temp file and read
              # that. TemporaryFile() will remove the file when it is closed.
              tmp = tempfile.TemporaryFile()
              sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0) # Make sys.stdin binary
-             bytes_read = sys.stdin.read (8192)
+             bytes_read = sys.stdin.read(8192)
              while bytes_read:
                  for b in bytes_read:
                      tmp.write(b)
-                 bytes_read = sys.stdin.read (8192)
-             z = zipfile.ZipFile (tmp, "r")
+                 bytes_read = sys.stdin.read(8192)
+             z = zipfile.ZipFile(tmp, "r")
         else:
-            ly.progress (_ ("Input file %s is compressed, extracting raw MusicXML data") % filename, True)
-            z = zipfile.ZipFile (filename, "r")
-        container_xml = z.read ("META-INF/container.xml")
+            ly.progress(_("Input file %s is compressed, extracting raw MusicXML data") % filename, True)
+            z = zipfile.ZipFile(filename, "r")
+        container_xml = z.read("META-INF/container.xml")
         if not container_xml:
             return None
-        container = read_xml (StringIO.StringIO (container_xml), use_lxml)
+        container = read_xml(StringIO.StringIO(container_xml), use_lxml)
         if not container:
             return None
-        rootfiles = container.get_maybe_exist_named_child ('rootfiles')
+        rootfiles = container.get_maybe_exist_named_child('rootfiles')
         if not rootfiles:
             return None
-        rootfile_list = rootfiles.get_named_children ('rootfile')
+        rootfile_list = rootfiles.get_named_children('rootfile')
         mxml_file = None
-        if len (rootfile_list) > 0:
-            mxml_file = getattr (rootfile_list[0], 'full-path', None)
+        if len(rootfile_list) > 0:
+            mxml_file = getattr(rootfile_list[0], 'full-path', None)
         if mxml_file:
-            raw_string = z.read (mxml_file)
+            raw_string = z.read(mxml_file)
 
     if raw_string:
-        io_object = StringIO.StringIO (raw_string)
+        io_object = StringIO.StringIO(raw_string)
     elif filename == "-":
         io_object = sys.stdin
     else:
         io_object = filename
 
-    return read_xml (io_object, use_lxml)
+    return read_xml(io_object, use_lxml)
 
 
-def convert (filename, options):
+def convert(filename, options):
     if filename == "-":
-        ly.progress (_ ("Reading MusicXML from Standard input ..."), True)
+        ly.progress(_("Reading MusicXML from Standard input ..."), True)
     else:
-        ly.progress (_ ("Reading MusicXML from %s ...") % filename, True)
+        ly.progress(_("Reading MusicXML from %s ...") % filename, True)
 
-    tree = read_musicxml (filename, options.compressed, options.use_lxml)
-    score_information = extract_score_information (tree)
-    paper_information = extract_paper_information (tree)
+    tree = read_musicxml(filename, options.compressed, options.use_lxml)
+    score_information = extract_score_information(tree)
+    paper_information = extract_paper_information(tree)
 
-    parts = tree.get_typed_children (musicxml.Part)
-    (voices, staff_info) = get_all_voices (parts)
+    parts = tree.get_typed_children(musicxml.Part)
+    (voices, staff_info) = get_all_voices(parts)
 
     score = None
-    mxl_pl = tree.get_maybe_exist_typed_child (musicxml.Part_list)
+    mxl_pl = tree.get_maybe_exist_typed_child(musicxml.Part_list)
     if mxl_pl:
-        score = extract_score_structure (mxl_pl, staff_info)
-        part_list = mxl_pl.get_named_children ("score-part")
+        score = extract_score_structure(mxl_pl, staff_info)
+        part_list = mxl_pl.get_named_children("score-part")
 
     # score information is contained in the <work>, <identification> or <movement-title> tags
-    update_score_setup (score, part_list, voices)
+    update_score_setup(score, part_list, voices, parts)
     # After the conversion, update the list of settings for the \layout block
-    update_layout_information ()
+    update_layout_information()
 
     if not options.output_name:
-        options.output_name = os.path.basename (filename)
-        options.output_name = os.path.splitext (options.output_name)[0]
-    elif re.match (".*\.ly", options.output_name):
-        options.output_name = os.path.splitext (options.output_name)[0]
+        options.output_name = os.path.basename(filename)
+        options.output_name = os.path.splitext(options.output_name)[0]
+    elif re.match(".*\.ly", options.output_name):
+        options.output_name = os.path.splitext(options.output_name)[0]
 
 
     #defs_ly_name = options.output_name + '-defs.ly'
@@ -2890,78 +3143,108 @@ def convert (filename, options):
       output_ly_name = 'Standard output'
     else:
       output_ly_name = options.output_name + '.ly'
-
-    ly.progress (_ ("Output to `%s'") % output_ly_name, True)
+    ly.progress(_("Output to `%s'") % output_ly_name, True)
     printer = musicexp.Output_printer()
-    #ly.progress (_ ("Output to `%s'") % defs_ly_name, True)
+    #ly.progress(_("Output to `%s'") % defs_ly_name, True)
     if (options.output_name == "-"):
-      printer.set_file (codecs.getwriter ("utf-8")(sys.stdout))
+      printer.set_file(codecs.getwriter("utf-8")(sys.stdout))
     else:
-      printer.set_file (codecs.open (output_ly_name, 'wb', encoding='utf-8'))
-    print_ly_preamble (printer, filename)
-    print_ly_additional_definitions (printer, filename)
+      printer.set_file(codecs.open(output_ly_name, 'wb', encoding='utf-8'))
+    print_ly_preamble(printer, filename)
+    print_ly_additional_definitions(printer, filename)
     if score_information:
-        score_information.print_ly (printer)
+        score_information.print_ly(printer)
     if paper_information and conversion_settings.convert_page_layout:
-        paper_information.print_ly (printer)
+        paper_information.print_ly(printer)
     if layout_information:
-        layout_information.print_ly (printer)
-    print_voice_definitions (printer, part_list, voices)
+        layout_information.print_ly(printer)
+    print_voice_definitions(printer, part_list, voices)
+
+    printer.newline()
+    printer.dump("% The score definition")
+    printer.newline()
+    score.print_ly(printer)
+    printer.newline()
 
-    printer.newline ()
-    printer.dump ("% The score definition")
-    printer.newline ()
-    score.print_ly (printer)
-    printer.newline ()
+    # Syntax update to current version
+    if (options.output_name != "-"):
+        version = os.popen("lilypond --version | head -1 | cut -d' ' -f3").read().strip()
+        ly.progress(_("Converting to current version (%s) notations ..." % version), True)
+        os.system("convert-ly -e %s 2> /dev/null" % utilities.escape_ly_output_string(output_ly_name))
 
     return voices
 
-def get_existing_filename_with_extension (filename, ext):
-    if os.path.exists (filename):
+def get_existing_filename_with_extension(filename, ext):
+    if os.path.exists(filename):
         return filename
     newfilename = filename + "." + ext
-    if os.path.exists (newfilename):
+    if os.path.exists(newfilename):
         return newfilename;
     newfilename = filename + ext
-    if os.path.exists (newfilename):
+    if os.path.exists(newfilename):
         return newfilename;
     return ''
 
-def main ():
+
+def main():
     opt_parser = option_parser()
 
     global options
-    (options, args) = opt_parser.parse_args ()
+    (options, args) = opt_parser.parse_args()
     if not args:
         opt_parser.print_usage()
-        sys.exit (2)
+        sys.exit(2)
 
+    # midi-block option
     if options.midi:
-        musicexp.set_create_midi (options.midi)
+        musicexp.set_create_midi(options.midi)
+
+    # transpose function
+    if options.transpose:
+        musicexp.set_transpose(options.transpose)
+
+    # tab clef option
+    if options.tab_clef:
+        musicexp.set_tab_clef(options.tab_clef)
+
+    # string numbers option
+    if options.string_numbers:
+        musicexp.set_string_numbers(options.string_numbers)
 
     if options.language:
-        musicexp.set_pitch_language (options.language)
-        needed_additional_definitions.append (options.language)
+        musicexp.set_pitch_language(options.language)
+        needed_additional_definitions.append(options.language)
         additional_definitions[options.language] = "\\language \"%s\"\n" % options.language
+
     conversion_settings.ignore_beaming = not options.convert_beaming
     conversion_settings.convert_page_layout = options.convert_page_layout
+    if conversion_settings.convert_page_layout:
+        conversion_settings.convert_system_breaks = options.convert_system_breaks
+        conversion_settings.convert_page_breaks = options.convert_page_breaks
+        conversion_settings.convert_page_margins = options.convert_page_margins
+    else:
+        conversion_settings.convert_system_breaks = False
+        conversion_settings.convert_page_breaks = False
+        conversion_settings.convert_page_margins = False
+    conversion_settings.convert_stem_directions = options.convert_stem_directions
 
     # Allow the user to leave out the .xml or xml on the filename
     basefilename = args[0].decode('utf-8')
     if basefilename == "-": # Read from stdin
         filename = "-"
     else:
-        filename = get_existing_filename_with_extension (basefilename, "xml")
+        filename = get_existing_filename_with_extension(basefilename, "xml")
         if not filename:
-            filename = get_existing_filename_with_extension (basefilename, "mxl")
+            filename = get_existing_filename_with_extension(basefilename, "mxl")
             options.compressed = True
-    if filename and filename.endswith ("mxl"):
+    if filename and filename.endswith("mxl"):
         options.compressed = True
 
-    if filename and (filename == "-" or os.path.exists (filename)):
-        voices = convert (filename, options)
+    if filename and (filename == "-" or os.path.exists(filename)):
+        voices = convert(filename, options)
     else:
-        ly.error (_ ("Unable to find input file %s") % basefilename)
+        ly.error(_("Unable to find input file %s") % basefilename)
+        sys.exit(1)
 
 if __name__ == '__main__':
     main()
index 785be9ef6f4ee1e1ba84e1db581facab63aef0d8..daf2d8659d1b90c966349c6b167fa4b6103f3697 100644 (file)
@@ -10,4 +10,4 @@ $(O_FILES): $(outdir)/config.hh
 
 $(EXECUTABLE): $(O_FILES) $(outdir)/version.hh $(MODULE_LIBS:%=%/$(outdir)/library.a)
        $(foreach a, $(MODULE_LIBS), $(MAKE) -C $(a) && ) true
-       $(LD) -o $@ $(O_FILES) $(LOADLIBES) $(ALL_LDFLAGS)
+       $(CXX) -o $@ $(O_FILES) $(LOADLIBES) $(ALL_LDFLAGS)
index e10e83c7d8fbdee9b4bc110de4d961d7bdd9caf6..7fbb413c78e12b5e1633a8d2d155a52f5742cc70 100644 (file)
@@ -8,4 +8,4 @@ $(foreach a, $(MODULE_LIBS), $(eval $(call MODULE_LIB_template,$(a))))
 
 $(TEST_EXECUTABLE): $(TEST_O_FILES) $(TEST_MODULE_LIBS:%=%/$(outdir)/library.a)
        $(foreach a, $(TEST_MODULE_LIBS), $(MAKE) -C $(a) && ) true
-       $(LD) -o $@ $(TEST_O_FILES) $(TEST_LOADLIBES) $(ALL_LDFLAGS)
+       $(CXX) -o $@ $(TEST_O_FILES) $(TEST_LOADLIBES) $(ALL_LDFLAGS)
index d164d451b89075c9d7670202182e788aa5659f40..d7e6b1f6b802a1b82e7eaaad11697ebee30b7eb8 100644 (file)
@@ -3,7 +3,7 @@
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{2016-03-29.15}
+\def\texinfoversion{2016-05-26.20}
 %
 % Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
 % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
 \everyjob{\message{[Texinfo version \texinfoversion]}%
   \catcode`+=\active \catcode`\_=\active}
 
+% LaTeX's \typeout.  This ensures that the messages it is used for
+% are identical in format to the corresponding ones from latex/pdflatex.
+\def\typeout{\immediate\write17}%
+
 \chardef\other=12
 
 % We never want plain's \outer definition of \+ in Texinfo.
@@ -1534,7 +1538,6 @@ output) for that.)}
   %
   % PDF outline support
   %
-  \pdfmakepagedesttrue \relax
   % Emulate the primitive of pdfTeX
   \def\pdfdest name#1 xyz{%
     \special{pdf:dest (name#1) [@thispage /XYZ @xpos @ypos]}%
@@ -3270,8 +3273,8 @@ end
 % @{ @} @lbracechar{} @rbracechar{} all generate brace characters.
 % Unless we're in typewriter, use \ecfont because the CM text fonts do
 % not have braces, and we don't want to switch into math.
-\def\mylbrace{{\ifmonospace\else\ecfont\fi \char123}}
-\def\myrbrace{{\ifmonospace\else\ecfont\fi \char125}}
+\def\mylbrace{{\ifmonospace\char123\else\ensuremath\lbrace\fi}}
+\def\myrbrace{{\ifmonospace\char125\else\ensuremath\rbrace\fi}}
 \let\{=\mylbrace \let\lbracechar=\{
 \let\}=\myrbrace \let\rbracechar=\}
 \begingroup
@@ -4603,6 +4606,19 @@ end
   \fi
 }
 
+% Like \expandablevalue, but completely expandable (the \message in the
+% definition above operates at the execution level of TeX).  Used when
+% writing to auxiliary files, due to the expansion that \write does.
+%
+% NB flag names containing - or _ may not work here.
+\def\dummyvalue#1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    [No value for ``#1'']%
+  \else
+    \csname SET#1\endcsname
+  \fi
+}
+
 % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
 % with @set.
 % 
@@ -4753,7 +4769,7 @@ end
 \def\docodeindex#1{\edef\indexname{#1}\parsearg\docodeindexxxx}
 \def\docodeindexxxx #1{\doind{\indexname}{\code{#1}}}
 
-% Used when writing an index entry out to an index file, to prevent
+% Used when writing an index entry out to an index file to prevent
 % expansion of Texinfo commands that can appear in an index entry.
 %
 \def\indexdummies{%
@@ -4889,12 +4905,9 @@ end
   %
   % We want to disable all macros so that they are not expanded by \write.
   \macrolist
+  \let\value\dummyvalue
   %
   \normalturnoffactive
-  %
-  % Handle some cases of @value -- where it does not contain any
-  % (non-fully-expandable) commands.
-  \makevalueexpandable
 }
 
 % \commondummiesnofonts: common to \commondummies and \indexnofonts.
@@ -5159,9 +5172,10 @@ end
   \ifx\suffix\indexisfl\def\suffix{f1}\fi
   % Open the file
   \immediate\openout\csname#1indfile\endcsname \jobname.\suffix
-  % Using \immediate here prevents an object entering into the current box,
-  % which could confound checks such as those in \safewhatsit for preceding
-  % skips.
+  % Using \immediate above here prevents an object entering into the current 
+  % box, which could confound checks such as those in \safewhatsit for
+  % preceding skips.
+  \typeout{Writing index file \jobname.\suffix}%
 \fi}
 \def\indexisfl{fl}
 
@@ -5369,9 +5383,9 @@ end
     % index.  The easiest way to prevent this problem is to make sure
     % there is some text.
     \putwordIndexNonexistent
+    \typeout{No file \jobname.\indexname s.}%
   \else
     \catcode`\\ = 0
-    \escapechar = `\\
     %
     % If the index file exists but is empty, then \openin leaves \ifeof
     % false.  We have to make TeX try to read something from the file, so
@@ -6683,7 +6697,14 @@ end
   % 1 and 2 (the page numbers aren't printed), and so are the first
   % two pages of the document.  Thus, we'd have two destinations named
   % `1', and two named `2'.
-  \ifpdf \global\pdfmakepagedesttrue \fi
+  \ifpdf
+    \global\pdfmakepagedesttrue
+  \else
+    \ifx\XeTeXrevision\thisisundefined
+    \else
+      \global\pdfmakepagedesttrue
+    \fi
+  \fi
 }
 
 
@@ -6943,7 +6964,6 @@ end
   \catcode `\>=\other
   \catcode `\`=\other
   \catcode `\'=\other
-  \escapechar=`\\
   %
   % ' is active in math mode (mathcode"8000).  So reset it, and all our
   % other math active characters (just in case), to plain's definitions.
@@ -7921,14 +7941,28 @@ end
 % alias because \c means cedilla in @tex or @math
 \let\texinfoc=\c
 
+\newcount\savedcatcodeone
+\newcount\savedcatcodetwo
+
 % Used at the time of macro expansion.
 % Argument is macro body with arguments substituted
 \def\scanmacro#1{%
   \newlinechar`\^^M
   \def\xeatspaces{\eatspaces}%
   %
+  % Temporarily undo catcode changes of \printindex.  Set catcode of @ to
+  % 0 so that @-commands in macro expansions aren't printed literally when 
+  % formatting an index file, where \ is used as the escape character.
+  \savedcatcodeone=\catcode`\@
+  \savedcatcodetwo=\catcode`\\
+  \catcode`\@=0
+  \catcode`\\=\active
+  %
   % Process the macro body under the current catcode regime.
-  \scantokens{#1\texinfoc}\aftermacro%
+  \scantokens{#1@texinfoc}\aftermacro%
+  %
+  \catcode`\@=\savedcatcodeone
+  \catcode`\\=\savedcatcodetwo
   %
   % The \texinfoc is to remove the \newlinechar added by \scantokens, and
   % can be noticed by \parsearg.
@@ -8686,6 +8720,8 @@ end
     {%
       \requireauxfile
       \atdummies  % preserve commands, but don't expand them
+      % match definition in \xrdef, \refx, \xrefX.
+      \def\value##1{##1}%
       \edef\writexrdef##1##2{%
        \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
          ##1}{##2}}% these are parameters of \writexrdef
@@ -8850,6 +8886,7 @@ end
     % include an _ in the xref name, etc.
     \indexnofonts
     \turnoffactive
+    \def\value##1{##1}%
     \expandafter\global\expandafter\let\expandafter\Xthisreftitle
       \csname XR#1-title\endcsname
   }%
@@ -8990,14 +9027,14 @@ end
   \fi\fi\fi
 }
 
-% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
-% If its value is nonempty, SUFFIX is output afterward.
-%
+% \refx{NAME}{SUFFIX} - reference a cross-reference string named NAME.  SUFFIX 
+% is output afterwards if non-empty.
 \def\refx#1#2{%
   \requireauxfile
   {%
     \indexnofonts
     \otherbackslash
+    \def\value##1{##1}%
     \expandafter\global\expandafter\let\expandafter\thisrefX
       \csname XR#1\endcsname
   }%
@@ -9022,16 +9059,18 @@ end
   #2% Output the suffix in any case.
 }
 
-% This is the macro invoked by entries in the aux file.  Usually it's
-% just a \def (we prepend XR to the control sequence name to avoid
-% collisions).  But if this is a float type, we have more work to do.
+% This is the macro invoked by entries in the aux file.  Define a control 
+% sequence for a cross-reference target (we prepend XR to the control sequence 
+% name to avoid collisions).  The value is the page number.  If this is a float 
+% type, we have more work to do.
 %
 \def\xrdef#1#2{%
-  {% The node name might contain 8-bit characters, which in our current
-   % implementation are changed to commands like @'e.  Don't let these
-   % mess up the control sequence name.
+  {% Expand the node or anchor name to remove control sequences.
+   % \turnoffactive stops 8-bit characters being changed to commands
+   % like @'e.  \refx does the same to retrieve the value in the definition.
     \indexnofonts
     \turnoffactive
+    \def\value##1{##1}%
     \xdef\safexrefname{#1}%
   }%
   %
index c822c43f016863c1292acbe3e08b09c3b022a5bf..0c3a8dc7e2582547a5a56261d4c9d1f5b633e1b3 100644 (file)
@@ -18,10 +18,10 @@ setlocal shiftwidth=2
 " some handy key mappings
 "
 " <F4>  save & make and play midi with timidity
-map <buffer> <F4> :w<Return>:se makeprg=lilypond\ \"%<\"<Return>:make<Return>:!timidity "%<.midi"<Return>
+map <buffer> <F4> :w<Return>:setl makeprg=lilypond\ \"%<\"<Return>:make<Return>:!timidity "%<.midi"<Return>
 "
 " <F5>  save & make
-map <buffer> <F5> :w<Return>:se makeprg=lilypond\ \"%<\"<Return>:make<Return>
+map <buffer> <F5> :w<Return>:setl makeprg=lilypond\ \"%<\"<Return>:make<Return>
 "
 " <F6>  view pdf with ghostview
 map <buffer> <F6> :!gv --watch "%<.pdf" &<Return>
@@ -33,7 +33,7 @@ map <buffer> <F7> :cp<Return>
 map <buffer> <F8> :cn<Return>
 "
 " <F9>  make
-map <buffer> <F9> :w<Return>:se makeprg=make\ -k<Return>:make<Return>
+map <buffer> <F9> :w<Return>:setl makeprg=make\ -k<Return>:make<Return>
 "
 " <F10> menu
 source $VIMRUNTIME/menu.vim