From: Jean-Charles Malahieude Date: Sat, 11 Jun 2016 12:26:38 +0000 (+0200) Subject: Merge branch 'master' of /home/jcharles/GIT/Lily/. into translation X-Git-Tag: release/2.19.44-1~24 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=ef9512388b15e1e5e2b3592299ffe489ac43abb4;hp=d1490200bca6cc3ff201d1d9a1599465dd300d33;p=lilypond.git Merge branch 'master' of /home/jcharles/GIT/Lily/. into translation --- diff --git a/Documentation/ca/web/community.itexi b/Documentation/ca/web/community.itexi index ca5d0e4120..8264c97144 100644 --- a/Documentation/ca/web/community.itexi +++ b/Documentation/ca/web/community.itexi @@ -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 diff --git a/Documentation/contributor/release-work.itexi b/Documentation/contributor/release-work.itexi index 3869505630..a2e3cb15d5 100644 --- a/Documentation/contributor/release-work.itexi +++ b/Documentation/contributor/release-work.itexi @@ -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 diff --git a/Documentation/contributor/source-code.itexi b/Documentation/contributor/source-code.itexi index 9541fe963a..8e07f9fb06 100644 --- a/Documentation/contributor/source-code.itexi +++ b/Documentation/contributor/source-code.itexi @@ -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. diff --git a/Documentation/cs/learning/common-notation.itely b/Documentation/cs/learning/common-notation.itely index 188dae02d4..f9f4f68ae7 100644 --- a/Documentation/cs/learning/common-notation.itely +++ b/Documentation/cs/learning/common-notation.itely @@ -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 { diff --git a/Documentation/cs/web/community.itexi b/Documentation/cs/web/community.itexi index 14705906f8..062f780c48 100644 --- a/Documentation/cs/web/community.itexi +++ b/Documentation/cs/web/community.itexi @@ -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 diff --git a/Documentation/de/notation/rhythms.itely b/Documentation/de/notation/rhythms.itely index a87acd3a5d..8e5c266ae0 100644 --- a/Documentation/de/notation/rhythms.itely +++ b/Documentation/de/notation/rhythms.itely @@ -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 diff --git a/Documentation/de/web/community.itexi b/Documentation/de/web/community.itexi index eabe6754c4..de6578eec8 100644 --- a/Documentation/de/web/community.itexi +++ b/Documentation/de/web/community.itexi @@ -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 diff --git a/Documentation/es/web/community.itexi b/Documentation/es/web/community.itexi index 2e2d994ed3..cdbf9c870d 100644 --- a/Documentation/es/web/community.itexi +++ b/Documentation/es/web/community.itexi @@ -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. diff --git a/Documentation/es/web/news.itexi b/Documentation/es/web/news.itexi index 9f2bc23ea2..60497e625b 100644 --- a/Documentation/es/web/news.itexi +++ b/Documentation/es/web/news.itexi @@ -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 diff --git a/Documentation/fr/learning/common-notation.itely b/Documentation/fr/learning/common-notation.itely index 43b221956b..909ec9b7ab 100644 --- a/Documentation/fr/learning/common-notation.itely +++ b/Documentation/fr/learning/common-notation.itely @@ -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 diff --git a/Documentation/fr/notation/cheatsheet.itely b/Documentation/fr/notation/cheatsheet.itely index 37bd09c765..b147dcd852 100644 --- a/Documentation/fr/notation/cheatsheet.itely +++ b/Documentation/fr/notation/cheatsheet.itely @@ -240,7 +240,7 @@ f8 c2 d e @item @code{\grace} -@tab appogiatures +@tab appoggiatures @tab @lilypond[relative=2] \set Staff.initialTimeSignatureVisibility = #all-invisible diff --git a/Documentation/fr/notation/input.itely b/Documentation/fr/notation/input.itely index f0665906f4..040e7eb79b 100644 --- a/Documentation/fr/notation/input.itely +++ b/Documentation/fr/notation/input.itely @@ -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 diff --git a/Documentation/fr/notation/rhythms.itely b/Documentation/fr/notation/rhythms.itely index c23e2bfc86..197f40b1fd 100644 --- a/Documentation/fr/notation/rhythms.itely +++ b/Documentation/fr/notation/rhythms.itely @@ -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}, diff --git a/Documentation/fr/web/community.itexi b/Documentation/fr/web/community.itexi index 7a44948fc3..98cf3dc3b0 100644 --- a/Documentation/fr/web/community.itexi +++ b/Documentation/fr/web/community.itexi @@ -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. diff --git a/Documentation/hu/web/community.itexi b/Documentation/hu/web/community.itexi index 864020d948..73efbec681 100644 --- a/Documentation/hu/web/community.itexi +++ b/Documentation/hu/web/community.itexi @@ -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 diff --git a/Documentation/it/web/community.itexi b/Documentation/it/web/community.itexi index 53e1dba955..3ff3be32bb 100644 --- a/Documentation/it/web/community.itexi +++ b/Documentation/it/web/community.itexi @@ -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 diff --git a/Documentation/ja/web/community.itexi b/Documentation/ja/web/community.itexi index 212c7d401e..8be2657353 100644 --- a/Documentation/ja/web/community.itexi +++ b/Documentation/ja/web/community.itexi @@ -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 diff --git a/Documentation/misc/announce-v2.0.html b/Documentation/misc/announce-v2.0.html index 8b72cf4a26..6551a677bb 100644 --- a/Documentation/misc/announce-v2.0.html +++ b/Documentation/misc/announce-v2.0.html @@ -153,7 +153,7 @@ and \appoggiatura, \acciaccatura g8 f4 -

Both reflect the traditional meanings of acciaccatura and appogiatura, +

Both reflect the traditional meanings of acciaccatura and appoggiatura, and both insert insert a slur from the first grace note to the main note. diff --git a/Documentation/music-glossary.tely b/Documentation/music-glossary.tely index 300c9c18a8..0b03549d88 100644 --- a/Documentation/music-glossary.tely +++ b/Documentation/music-glossary.tely @@ -3030,7 +3030,7 @@ D: doppelter Vorschlag, NL: dubbele voorslag, DK: dobbelt forslag, S: dubbelslag, -FI: kaksoisappogiatura, kaksoisetuhele. +FI: kaksoisappoggiatura, kaksoisetuhele. @seealso @ref{appoggiatura}. diff --git a/Documentation/snippets/contemporary-notation.snippet-list b/Documentation/snippets/contemporary-notation.snippet-list index 098532b961..b12e5980dd 100644 --- a/Documentation/snippets/contemporary-notation.snippet-list +++ b/Documentation/snippets/contemporary-notation.snippet-list @@ -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 index 0000000000..0d2a8cee6a --- /dev/null +++ b/Documentation/snippets/customize-drumpitchnames,-drumstyletable-and-drumpitchtable-in-layout-and-midi.ly @@ -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 index 0000000000..db63fb42fb --- /dev/null +++ b/Documentation/snippets/flat-ties.ly @@ -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 + ~ 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 +} diff --git a/Documentation/snippets/midi.snippet-list b/Documentation/snippets/midi.snippet-list index ecc73acb4e..243a5a03a0 100644 --- a/Documentation/snippets/midi.snippet-list +++ b/Documentation/snippets/midi.snippet-list @@ -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 diff --git a/Documentation/snippets/obtaining-2.12-lyrics-spacing-in-newer-versions.ly b/Documentation/snippets/obtaining-2.12-lyrics-spacing-in-newer-versions.ly index 1b294569e3..de3e108a48 100644 --- a/Documentation/snippets/obtaining-2.12-lyrics-spacing-in-newer-versions.ly +++ b/Documentation/snippets/obtaining-2.12-lyrics-spacing-in-newer-versions.ly @@ -49,7 +49,7 @@ bassMusic = \relative c { } words = \lyricmode { - Great is Thy faith- ful- ness, + Great is Thy faith -- ful -- ness, } \score { diff --git a/Documentation/snippets/percussion.snippet-list b/Documentation/snippets/percussion.snippet-list index 5a29fb2c15..edef3b78e2 100644 --- a/Documentation/snippets/percussion.snippet-list +++ b/Documentation/snippets/percussion.snippet-list @@ -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 diff --git a/Documentation/snippets/piano-template-with-centered-lyrics.ly b/Documentation/snippets/piano-template-with-centered-lyrics.ly index d1f05af6dc..008535e304 100644 --- a/Documentation/snippets/piano-template-with-centered-lyrics.ly +++ b/Documentation/snippets/piano-template-with-centered-lyrics.ly @@ -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 { } } diff --git a/Documentation/snippets/pitches.snippet-list b/Documentation/snippets/pitches.snippet-list index 7410307eb5..ce27407d67 100644 --- a/Documentation/snippets/pitches.snippet-list +++ b/Documentation/snippets/pitches.snippet-list @@ -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 diff --git a/Documentation/snippets/scheme-language.snippet-list b/Documentation/snippets/scheme-language.snippet-list index 2513ba4682..a963aea6be 100644 --- a/Documentation/snippets/scheme-language.snippet-list +++ b/Documentation/snippets/scheme-language.snippet-list @@ -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 diff --git a/Documentation/snippets/simultaneous-notes.snippet-list b/Documentation/snippets/simultaneous-notes.snippet-list index c2be0bb2e3..cd3e01f1de 100644 --- a/Documentation/snippets/simultaneous-notes.snippet-list +++ b/Documentation/snippets/simultaneous-notes.snippet-list @@ -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 diff --git a/Documentation/snippets/specific-notation.snippet-list b/Documentation/snippets/specific-notation.snippet-list index b372f9879f..bc43d7d3ba 100644 --- a/Documentation/snippets/specific-notation.snippet-list +++ b/Documentation/snippets/specific-notation.snippet-list @@ -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 diff --git a/Documentation/snippets/staff-notation.snippet-list b/Documentation/snippets/staff-notation.snippet-list index 0322a423b0..bfb3706161 100644 --- a/Documentation/snippets/staff-notation.snippet-list +++ b/Documentation/snippets/staff-notation.snippet-list @@ -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 diff --git a/Documentation/snippets/tweaks-and-overrides.snippet-list b/Documentation/snippets/tweaks-and-overrides.snippet-list index ed848f2c0a..b0bf51340d 100644 --- a/Documentation/snippets/tweaks-and-overrides.snippet-list +++ b/Documentation/snippets/tweaks-and-overrides.snippet-list @@ -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 index 0000000000..da3d7b3d44 --- /dev/null +++ b/Documentation/snippets/two--partcombine-pairs-on-one-staff.ly @@ -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 +>> diff --git a/Documentation/topdocs/README.texi b/Documentation/topdocs/README.texi index e282c32fba..4dce2a313f 100644 --- a/Documentation/topdocs/README.texi +++ b/Documentation/topdocs/README.texi @@ -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 diff --git a/Documentation/web/community.itexi b/Documentation/web/community.itexi index 5013b4d954..31b400fa89 100644 --- a/Documentation/web/community.itexi +++ b/Documentation/web/community.itexi @@ -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 diff --git a/Documentation/web/manuals.itexi b/Documentation/web/manuals.itexi index e741a960ea..07ccb42aa9 100644 --- a/Documentation/web/manuals.itexi +++ b/Documentation/web/manuals.itexi @@ -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. diff --git a/Documentation/web/news-front.itexi b/Documentation/web/news-front.itexi index e7c6d228db..675244a213 100644 --- a/Documentation/web/news-front.itexi +++ b/Documentation/web/news-front.itexi @@ -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 diff --git a/Documentation/web/news.itexi b/Documentation/web/news.itexi index 9095620830..fbabbd846e 100644 --- a/Documentation/web/news.itexi +++ b/Documentation/web/news.itexi @@ -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 diff --git a/Documentation/zh/web/community.itexi b/Documentation/zh/web/community.itexi index 58d63f0e6f..5e3efa38ca 100644 --- a/Documentation/zh/web/community.itexi +++ b/Documentation/zh/web/community.itexi @@ -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 a71d765f26..f18fd1a1d6 100644 --- 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 diff --git a/aclocal.m4 b/aclocal.m4 index 0037c58ca8..ed47b8350e 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -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) ]) diff --git a/lily/accidental-engraver.cc b/lily/accidental-engraver.cc index f9d2e15cd4..1be735b0ed 100644 --- a/lily/accidental-engraver.cc +++ b/lily/accidental-engraver.cc @@ -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 */ diff --git a/lily/all-font-metrics.cc b/lily/all-font-metrics.cc index a560a25940..ab4f2a4ce4 100644 --- a/lily/all-font-metrics.cc +++ b/lily/all-font-metrics.cc @@ -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, diff --git a/lily/ambitus-engraver.cc b/lily/ambitus-engraver.cc index 9ceea9387c..665c83a4cc 100644 --- a/lily/ambitus-engraver.cc +++ b/lily/ambitus-engraver.cc @@ -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.", diff --git a/lily/arpeggio-engraver.cc b/lily/arpeggio-engraver.cc index e191470161..d308a43068 100644 --- a/lily/arpeggio-engraver.cc +++ b/lily/arpeggio-engraver.cc @@ -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 */ diff --git a/lily/auto-beam-engraver.cc b/lily/auto-beam-engraver.cc index 3787257738..a7a92d9d6d 100644 --- a/lily/auto-beam-engraver.cc +++ b/lily/auto-beam-engraver.cc @@ -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. " diff --git a/lily/axis-group-engraver.cc b/lily/axis-group-engraver.cc index 3a9b0d6775..2bc4858479 100644 --- a/lily/axis-group-engraver.cc +++ b/lily/axis-group-engraver.cc @@ -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 */ diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc index 52520280f2..38a193caf6 100644 --- a/lily/axis-group-interface.cc +++ b/lily/axis-group-interface.cc @@ -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 diff --git a/lily/balloon-engraver.cc b/lily/balloon-engraver.cc index 980aa92231..4f0f136db0 100644 --- a/lily/balloon-engraver.cc +++ b/lily/balloon-engraver.cc @@ -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 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 */ diff --git a/lily/bar-engraver.cc b/lily/bar-engraver.cc index 397743b4b0..8feb63dd13 100644 --- a/lily/bar-engraver.cc +++ b/lily/bar-engraver.cc @@ -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 (g)); } -ADD_END_ACKNOWLEDGER (Bar_engraver, spanner); + +void +Bar_engraver::boot () +{ + ADD_END_ACKNOWLEDGER (Bar_engraver, spanner); +} ADD_TRANSLATOR (Bar_engraver, /* doc */ diff --git a/lily/bar-number-engraver.cc b/lily/bar-number-engraver.cc index 144076439c..1af5f19da1 100644 --- a/lily/bar-number-engraver.cc +++ b/lily/bar-number-engraver.cc @@ -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 */ diff --git a/lily/beam-collision-engraver.cc b/lily/beam-collision-engraver.cc index 151ffacf16..31f96b72b1 100644 --- a/lily/beam-collision-engraver.cc +++ b/lily/beam-collision-engraver.cc @@ -30,15 +30,15 @@ protected: vector beams_; vector 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 */ diff --git a/lily/beam-engraver.cc b/lily/beam-engraver.cc index e6ca4caf16..277d1b0a0e 100644 --- a/lily/beam-engraver.cc +++ b/lily/beam-engraver.cc @@ -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 */ diff --git a/lily/beam-performer.cc b/lily/beam-performer.cc index a6e78d67c7..0970e8b5e7 100644 --- a/lily/beam-performer.cc +++ b/lily/beam-performer.cc @@ -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 */ "", diff --git a/lily/bend-engraver.cc b/lily/bend-engraver.cc index 44b0f21eaa..83c98a94e0 100644 --- a/lily/bend-engraver.cc +++ b/lily/bend-engraver.cc @@ -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 */ diff --git a/lily/book-scheme.cc b/lily/book-scheme.cc index cf35a7c1bd..af0cb62632 100644 --- a/lily/book-scheme.cc +++ b/lily/book-scheme.cc @@ -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?"; diff --git a/lily/box.cc b/lily/box.cc index 629b8010fa..6569493419 100644 --- a/lily/box.cc +++ b/lily/box.cc @@ -133,4 +133,4 @@ Box::print () /****************************************************************/ -const char Box::type_p_name_[] = "ly:box?"; +const char * const Box::type_p_name_ = "ly:box?"; diff --git a/lily/break-align-engraver.cc b/lily/break-align-engraver.cc index f9090c8e08..55a638da87 100644 --- a/lily/break-align-engraver.cc +++ b/lily/break-align-engraver.cc @@ -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}" diff --git a/lily/breathing-sign-engraver.cc b/lily/breathing-sign-engraver.cc index 34b296d10b..ade1b15f29 100644 --- a/lily/breathing-sign-engraver.cc +++ b/lily/breathing-sign-engraver.cc @@ -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 index 531029543b..0000000000 --- a/lily/callback.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - This file is part of LilyPond, the GNU music typesetter. - - Copyright (C) 2016 David Kastrup - - 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 . -*/ - -#include "callback.hh" - -const char * const Callback_wrapper::type_p_name_ = 0; diff --git a/lily/chord-name-engraver.cc b/lily/chord-name-engraver.cc index db8493e2a5..3a14ff4b07 100644 --- a/lily/chord-name-engraver.cc +++ b/lily/chord-name-engraver.cc @@ -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 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.", diff --git a/lily/chord-tremolo-engraver.cc b/lily/chord-tremolo-engraver.cc index 3855c350d7..7a17c1350e 100644 --- a/lily/chord-tremolo-engraver.cc +++ b/lily/chord-tremolo-engraver.cc @@ -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.", diff --git a/lily/clef-engraver.cc b/lily/clef-engraver.cc index 940a18d201..00b3c3e55a 100644 --- a/lily/clef-engraver.cc +++ b/lily/clef-engraver.cc @@ -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.", diff --git a/lily/cluster-engraver.cc b/lily/cluster-engraver.cc index bb5ed0dc54..0c84d1cb65 100644 --- a/lily/cluster-engraver.cc +++ b/lily/cluster-engraver.cc @@ -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.", diff --git a/lily/collision-engraver.cc b/lily/collision-engraver.cc index d1eb2dd3c0..ca6a52d320 100644 --- a/lily/collision-engraver.cc +++ b/lily/collision-engraver.cc @@ -31,7 +31,7 @@ class Collision_engraver : public Engraver vector 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 */ diff --git a/lily/completion-note-heads-engraver.cc b/lily/completion-note-heads-engraver.cc index 34a985d32d..ef3a5012a2 100644 --- a/lily/completion-note-heads-engraver.cc +++ b/lily/completion-note-heads-engraver.cc @@ -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" diff --git a/lily/completion-rest-engraver.cc b/lily/completion-rest-engraver.cc index 8f809fde70..2b5693916e 100644 --- a/lily/completion-rest-engraver.cc +++ b/lily/completion-rest-engraver.cc @@ -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" diff --git a/lily/concurrent-hairpin-engraver.cc b/lily/concurrent-hairpin-engraver.cc index aa167b7de4..3fdf6524c2 100644 --- a/lily/concurrent-hairpin-engraver.cc +++ b/lily/concurrent-hairpin-engraver.cc @@ -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 */ diff --git a/lily/context-def.cc b/lily/context-def.cc index 3258297b49..402bd80b6e 100644 --- a/lily/context-def.cc +++ b/lily/context-def.cc @@ -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 diff --git a/lily/context-mod.cc b/lily/context-mod.cc index a533da2cbd..892d692bbf 100644 --- a/lily/context-mod.cc +++ b/lily/context-mod.cc @@ -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 diff --git a/lily/context-property.cc b/lily/context-property.cc index e0acae1455..6e22b2f808 100644 --- a/lily/context-property.cc +++ b/lily/context-property.cc @@ -66,7 +66,7 @@ class Grob_properties : public Simple_smob { 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 diff --git a/lily/context.cc b/lily/context.cc index a6b1da6a36..7de61c5796 100644 --- a/lily/context.cc +++ b/lily/context.cc @@ -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 + (), + Callback0_wrapper::make_smob + (), + 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 diff --git a/lily/control-track-performer.cc b/lily/control-track-performer.cc index 82beebe122..db6efe649e 100644 --- a/lily/control-track-performer.cc +++ b/lily/control-track-performer.cc @@ -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 */ "", diff --git a/lily/cue-clef-engraver.cc b/lily/cue-clef-engraver.cc index 383c9a1b1f..53640afadc 100644 --- a/lily/cue-clef-engraver.cc +++ b/lily/cue-clef-engraver.cc @@ -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.", diff --git a/lily/custos-engraver.cc b/lily/custos-engraver.cc index 5893dc205b..a21ad4eb78 100644 --- a/lily/custos-engraver.cc +++ b/lily/custos-engraver.cc @@ -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 */ diff --git a/lily/default-bar-line-engraver.cc b/lily/default-bar-line-engraver.cc index 4eeb230367..a8b9898276 100644 --- a/lily/default-bar-line-engraver.cc +++ b/lily/default-bar-line-engraver.cc @@ -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" diff --git a/lily/dispatcher.cc b/lily/dispatcher.cc index 8f938d6f91..b1b076759f 100644 --- a/lily/dispatcher.cc +++ b/lily/dispatcher.cc @@ -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 () { diff --git a/lily/dot-column-engraver.cc b/lily/dot-column-engraver.cc index c646ed038c..c5c8001524 100644 --- a/lily/dot-column-engraver.cc +++ b/lily/dot-column-engraver.cc @@ -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" diff --git a/lily/dots-engraver.cc b/lily/dots-engraver.cc index 5465f460f6..cbd6c718a9 100644 --- a/lily/dots-engraver.cc +++ b/lily/dots-engraver.cc @@ -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" diff --git a/lily/double-percent-repeat-engraver.cc b/lily/double-percent-repeat-engraver.cc index d85648293e..d1717f8314 100644 --- a/lily/double-percent-repeat-engraver.cc +++ b/lily/double-percent-repeat-engraver.cc @@ -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.", diff --git a/lily/drum-note-engraver.cc b/lily/drum-note-engraver.cc index 09a58fa24b..16b089cb70 100644 --- a/lily/drum-note-engraver.cc +++ b/lily/drum-note-engraver.cc @@ -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 */ diff --git a/lily/drum-note-performer.cc b/lily/drum-note-performer.cc index 0285de6504..93f648f3d7 100644 --- a/lily/drum-note-performer.cc +++ b/lily/drum-note-performer.cc @@ -33,7 +33,7 @@ public: protected: void stop_translation_timestep (); void process_music (); - DECLARE_TRANSLATOR_LISTENER (note); + void listen_note (Stream_event *); private: vector 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.", diff --git a/lily/duration.cc b/lily/duration.cc index 0b10019540..0c6fa4dd5f 100644 --- a/lily/duration.cc +++ b/lily/duration.cc @@ -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 diff --git a/lily/dynamic-align-engraver.cc b/lily/dynamic-align-engraver.cc index 0abb39a7f2..c276e21759 100644 --- a/lily/dynamic-align-engraver.cc +++ b/lily/dynamic-align-engraver.cc @@ -34,11 +34,11 @@ 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.", diff --git a/lily/dynamic-engraver.cc b/lily/dynamic-engraver.cc index edfd35fcb5..5d4ef33de3 100644 --- a/lily/dynamic-engraver.cc +++ b/lily/dynamic-engraver.cc @@ -33,10 +33,10 @@ 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.", diff --git a/lily/dynamic-performer.cc b/lily/dynamic-performer.cc index 6a6f8b8cf9..46a8a446d3 100644 --- a/lily/dynamic-performer.cc +++ b/lily/dynamic-performer.cc @@ -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 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 */ "", diff --git a/lily/engraver.cc b/lily/engraver.cc index 25ae579bd7..5a1486927a 100644 --- a/lily/engraver.cc +++ b/lily/engraver.cc @@ -175,20 +175,3 @@ ly_is_grob_cause (SCM obj) { return unsmob (obj) || unsmob (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 */ - "" - ); - diff --git a/lily/episema-engraver.cc b/lily/episema-engraver.cc index a62ed3726f..d2fc2f398f 100644 --- a/lily/episema-engraver.cc +++ b/lily/episema-engraver.cc @@ -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 */ diff --git a/lily/extender-engraver.cc b/lily/extender-engraver.cc index 3f3ef3b3ff..39fa7788de 100644 --- a/lily/extender-engraver.cc +++ b/lily/extender-engraver.cc @@ -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.", diff --git a/lily/figured-bass-engraver.cc b/lily/figured-bass-engraver.cc index 2ed07e3e83..9785f3fef4 100644 --- a/lily/figured-bass-engraver.cc +++ b/lily/figured-bass-engraver.cc @@ -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.", diff --git a/lily/figured-bass-position-engraver.cc b/lily/figured-bass-position-engraver.cc index c1df4623e6..66fabb1ffb 100644 --- a/lily/figured-bass-position-engraver.cc +++ b/lily/figured-bass-position-engraver.cc @@ -36,12 +36,12 @@ class Figured_bass_position_engraver : public Engraver vector support_; vector 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 */ diff --git a/lily/fingering-column-engraver.cc b/lily/fingering-column-engraver.cc index 1c5b904809..a2a37143b3 100644 --- a/lily/fingering-column-engraver.cc +++ b/lily/fingering-column-engraver.cc @@ -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" diff --git a/lily/fingering-engraver.cc b/lily/fingering-engraver.cc index d5b4102d8b..8de44e9698 100644 --- a/lily/fingering-engraver.cc +++ b/lily/fingering-engraver.cc @@ -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 */ diff --git a/lily/font-metric.cc b/lily/font-metric.cc index f2b6a0e147..c9daa95f3e 100644 --- a/lily/font-metric.cc +++ b/lily/font-metric.cc @@ -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 diff --git a/lily/font-size-engraver.cc b/lily/font-size-engraver.cc index b9250358dd..4dfd24d014 100644 --- a/lily/font-size-engraver.cc +++ b/lily/font-size-engraver.cc @@ -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.", diff --git a/lily/footnote-engraver.cc b/lily/footnote-engraver.cc index 636379125f..e80d9b64ce 100644 --- a/lily/footnote-engraver.cc +++ b/lily/footnote-engraver.cc @@ -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 > 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 */ diff --git a/lily/forbid-break-engraver.cc b/lily/forbid-break-engraver.cc index db0e254739..9cfdef24c8 100644 --- a/lily/forbid-break-engraver.cc +++ b/lily/forbid-break-engraver.cc @@ -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" diff --git a/lily/fretboard-engraver.cc b/lily/fretboard-engraver.cc index 2ce799bf0f..18843fc87c 100644 --- a/lily/fretboard-engraver.cc +++ b/lily/fretboard-engraver.cc @@ -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" diff --git a/lily/glissando-engraver.cc b/lily/glissando-engraver.cc index c7744d1f4b..878e7f88b3 100644 --- a/lily/glissando-engraver.cc +++ b/lily/glissando-engraver.cc @@ -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.", diff --git a/lily/grace-engraver.cc b/lily/grace-engraver.cc index 5279cab4c0..57ccb1e0fa 100644 --- a/lily/grace-engraver.cc +++ b/lily/grace-engraver.cc @@ -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.", diff --git a/lily/grace-spacing-engraver.cc b/lily/grace-spacing-engraver.cc index 5da9c90b5c..445d2b0f81 100644 --- a/lily/grace-spacing-engraver.cc +++ b/lily/grace-spacing-engraver.cc @@ -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.", diff --git a/lily/grid-line-span-engraver.cc b/lily/grid-line-span-engraver.cc index a61f61df78..efecf67622 100644 --- a/lily/grid-line-span-engraver.cc +++ b/lily/grid-line-span-engraver.cc @@ -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" diff --git a/lily/grid-point-engraver.cc b/lily/grid-point-engraver.cc index f436195787..d67fb191b6 100644 --- a/lily/grid-point-engraver.cc +++ b/lily/grid-point-engraver.cc @@ -48,6 +48,12 @@ Grid_point_engraver::Grid_point_engraver () { } +void +Grid_point_engraver::boot () +{ + +} + ADD_TRANSLATOR (Grid_point_engraver, /* doc */ "Generate grid points.", diff --git a/lily/grob-array.cc b/lily/grob-array.cc index ec0ee43e18..f5228dfd71 100644 --- a/lily/grob-array.cc +++ b/lily/grob-array.cc @@ -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 diff --git a/lily/grob-pq-engraver.cc b/lily/grob-pq-engraver.cc index 45b4ff2b35..25392a4355 100644 --- a/lily/grob-pq-engraver.cc +++ b/lily/grob-pq-engraver.cc @@ -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" diff --git a/lily/grob-smob.cc b/lily/grob-smob.cc index 066b700a25..72949973b1 100644 --- a/lily/grob-smob.cc +++ b/lily/grob-smob.cc @@ -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 diff --git a/lily/horizontal-bracket-engraver.cc b/lily/horizontal-bracket-engraver.cc index cd46817904..d50146a2d0 100644 --- a/lily/horizontal-bracket-engraver.cc +++ b/lily/horizontal-bracket-engraver.cc @@ -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" diff --git a/lily/hyphen-engraver.cc b/lily/hyphen-engraver.cc index be43665556..19ff388963 100644 --- a/lily/hyphen-engraver.cc +++ b/lily/hyphen-engraver.cc @@ -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 */ diff --git a/lily/include/all-font-metrics.hh b/lily/include/all-font-metrics.hh index f206a3b95d..a2d090a6df 100644 --- a/lily/include/all-font-metrics.hh +++ b/lily/include/all-font-metrics.hh @@ -48,7 +48,6 @@ class All_font_metrics : public Smob 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, diff --git a/lily/include/book.hh b/lily/include/book.hh index 3ea6c2c550..0a71a6b9e4 100644 --- a/lily/include/book.hh +++ b/lily/include/book.hh @@ -30,7 +30,7 @@ class Book : public Smob { 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_; diff --git a/lily/include/box.hh b/lily/include/box.hh index 7d5745d696..d4a8655a42 100644 --- a/lily/include/box.hh +++ b/lily/include/box.hh @@ -12,7 +12,7 @@ class Box : public Simple_smob { public: - static const char type_p_name_[]; + static const char * const type_p_name_; private: Interval interval_a_[NO_AXES]; public: diff --git a/lily/include/callback.hh b/lily/include/callback.hh index b797baf062..671140673f 100644 --- a/lily/include/callback.hh +++ b/lily/include/callback.hh @@ -44,10 +44,10 @@ class Callback_wrapper : public Simple_smob // 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 +{ + // 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 + static SCM make_smob () + { + static SCM res = + scm_permanent_object (Callback2_wrapper (trampoline).smobbed_copy ()); + return res; + } +}; + +class Callback0_wrapper : public Simple_smob +{ + // 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 + 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 + static SCM trampoline (SCM target) + { + T *t = LY_ASSERT_SMOB (T, target, 1); + return (t->*p) (); + } + + template + static SCM trampoline (SCM target) + { + T *t = LY_ASSERT_SMOB (T, target, 1); + (t->*p) (); + return SCM_UNSPECIFIED; + } + + template + static SCM make_smob () + { + return make_smob > (); + } + + template + static SCM make_smob () + { + return make_smob > (); + } +}; + +// The following will usually be used unsmobbified, relying on its +// constituents being protected independently. + +class Method_instance : public Simple_smob +{ + 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 diff --git a/lily/include/coherent-ligature-engraver.hh b/lily/include/coherent-ligature-engraver.hh index 19e731815a..78bfef8897 100644 --- a/lily/include/coherent-ligature-engraver.hh +++ b/lily/include/coherent-ligature-engraver.hh @@ -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, diff --git a/lily/include/context-def.hh b/lily/include/context-def.hh index c49fee1e30..b068e204c0 100644 --- a/lily/include/context-def.hh +++ b/lily/include/context-def.hh @@ -35,7 +35,7 @@ struct Context_def : public Smob { 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: /* diff --git a/lily/include/context-mod.hh b/lily/include/context-mod.hh index c9f0caa8fb..81b1f34e36 100644 --- a/lily/include/context-mod.hh +++ b/lily/include/context-mod.hh @@ -38,7 +38,7 @@ struct Context_mod : public Simple_smob { 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: diff --git a/lily/include/context.hh b/lily/include/context.hh index 130a304f93..468f612061 100644 --- a/lily/include/context.hh +++ b/lily/include/context.hh @@ -33,7 +33,7 @@ class Context : public Smob 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; diff --git a/lily/include/dispatcher.hh b/lily/include/dispatcher.hh index f0eb30ba6d..98a8626fd8 100644 --- a/lily/include/dispatcher.hh +++ b/lily/include/dispatcher.hh @@ -29,7 +29,7 @@ class Dispatcher : public Smob 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. */ diff --git a/lily/include/duration.hh b/lily/include/duration.hh index 7a57cf53af..6233fc1b2d 100644 --- a/lily/include/duration.hh +++ b/lily/include/duration.hh @@ -29,7 +29,7 @@ struct Duration : public Simple_smob { 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); diff --git a/lily/include/engraver.hh b/lily/include/engraver.hh index 956f49365b..928f6a969d 100644 --- a/lily/include/engraver.hh +++ b/lily/include/engraver.hh @@ -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 + 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__) diff --git a/lily/include/font-metric.hh b/lily/include/font-metric.hh index d74c8157ca..e385a1e7af 100644 --- a/lily/include/font-metric.hh +++ b/lily/include/font-metric.hh @@ -35,7 +35,7 @@ class Font_metric : public Smob 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); diff --git a/lily/include/gregorian-ligature-engraver.hh b/lily/include/gregorian-ligature-engraver.hh index 5aea42662b..d7011bda99 100644 --- a/lily/include/gregorian-ligature-engraver.hh +++ b/lily/include/gregorian-ligature-engraver.hh @@ -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 const &primitives); virtual void transform_heads (Spanner *ligature, diff --git a/lily/include/grob-array.hh b/lily/include/grob-array.hh index 1a755fe661..ca925b4291 100644 --- a/lily/include/grob-array.hh +++ b/lily/include/grob-array.hh @@ -29,7 +29,7 @@ class Grob_array : public Simple_smob 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 grobs_; bool ordered_; diff --git a/lily/include/grob-interface.hh b/lily/include/grob-interface.hh index 9c3eadb4b0..bde5f5263d 100644 --- a/lily/include/grob-interface.hh +++ b/lily/include/grob-interface.hh @@ -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 -SCM Grob_interface::interface_symbol_; +Protected_scm Grob_interface::interface_symbol_; #endif /* INTERFACE_HH */ diff --git a/lily/include/grob.hh b/lily/include/grob.hh index db51e02e73..a9408f09a2 100644 --- a/lily/include/grob.hh +++ b/lily/include/grob.hh @@ -32,7 +32,7 @@ class Grob : public Smob 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); diff --git a/lily/include/input.hh b/lily/include/input.hh index b77db2d66f..aab0d117a6 100644 --- a/lily/include/input.hh +++ b/lily/include/input.hh @@ -32,7 +32,7 @@ class Input : public Simple_smob 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; diff --git a/lily/include/ligature-engraver.hh b/lily/include/ligature-engraver.hh index 6f53331a4e..1f8fd8b85f 100644 --- a/lily/include/ligature-engraver.hh +++ b/lily/include/ligature-engraver.hh @@ -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 events_drul_; diff --git a/lily/include/lily-imports.hh b/lily/include/lily-imports.hh index 97982895f5..d930f69cf9 100644 --- a/lily/include/lily-imports.hh +++ b/lily/include/lily-imports.hh @@ -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; diff --git a/lily/include/lily-lexer.hh b/lily/include/lily-lexer.hh index 0e001ec187..626d24efa6 100644 --- a/lily/include/lily-lexer.hh +++ b/lily/include/lily-lexer.hh @@ -36,7 +36,7 @@ class Lily_lexer : public Smob, 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&); diff --git a/lily/include/lily-parser.hh b/lily/include/lily-parser.hh index b08df7c7a4..e4ff2969b9 100644 --- a/lily/include/lily-parser.hh +++ b/lily/include/lily-parser.hh @@ -36,7 +36,7 @@ class Lily_parser : public Smob 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_; diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh index f574b39c3f..ee3946e0fd 100644 --- a/lily/include/lily-proto.hh +++ b/lily/include/lily-proto.hh @@ -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; diff --git a/lily/include/listener.hh b/lily/include/listener.hh index b9042ba301..a13fdc66e1 100644 --- a/lily/include/listener.hh +++ b/lily/include/listener.hh @@ -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) { } diff --git a/lily/include/misc.hh b/lily/include/misc.hh index 7226aceef8..174b2f4c01 100644 --- a/lily/include/misc.hh +++ b/lily/include/misc.hh @@ -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 +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) diff --git a/lily/include/moment.hh b/lily/include/moment.hh index d84a992b40..c29032f99d 100644 --- a/lily/include/moment.hh +++ b/lily/include/moment.hh @@ -32,7 +32,7 @@ class Moment : public Simple_smob 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); diff --git a/lily/include/music-function.hh b/lily/include/music-function.hh index f2c349a3e1..80239a61aa 100644 --- a/lily/include/music-function.hh +++ b/lily/include/music-function.hh @@ -27,7 +27,7 @@ class Music_function : public Smob2 { 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 (); } diff --git a/lily/include/music-iterator.hh b/lily/include/music-iterator.hh index 810d230aac..bb095df718 100644 --- a/lily/include/music-iterator.hh +++ b/lily/include/music-iterator.hh @@ -63,7 +63,7 @@ class Music_iterator : public Smob 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_; diff --git a/lily/include/music-output.hh b/lily/include/music-output.hh index dc1111b78a..208c01a831 100644 --- a/lily/include/music-output.hh +++ b/lily/include/music-output.hh @@ -31,7 +31,7 @@ class Music_output : public Smob 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); diff --git a/lily/include/output-def.hh b/lily/include/output-def.hh index 5de672e67a..8c188f2707 100644 --- a/lily/include/output-def.hh +++ b/lily/include/output-def.hh @@ -51,7 +51,7 @@ class Output_def : public Smob 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); diff --git a/lily/include/page-marker.hh b/lily/include/page-marker.hh index 02233d30a6..33f3a38c06 100644 --- a/lily/include/page-marker.hh +++ b/lily/include/page-marker.hh @@ -27,7 +27,7 @@ class Page_marker : public Smob { 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 */ diff --git a/lily/include/paper-book.hh b/lily/include/paper-book.hh index b105cdb3de..9530c94b70 100644 --- a/lily/include/paper-book.hh +++ b/lily/include/paper-book.hh @@ -31,7 +31,7 @@ class Paper_book : public Smob { public: SCM mark_smob () const; - static const char type_p_name_[]; + static const char * const type_p_name_; virtual ~Paper_book (); private: SCM systems_; diff --git a/lily/include/paper-column-engraver.hh b/lily/include/paper-column-engraver.hh index 1279ff17c9..a176fc48eb 100644 --- a/lily/include/paper-column-engraver.hh +++ b/lily/include/paper-column-engraver.hh @@ -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 break_events_; diff --git a/lily/include/paper-outputter.hh b/lily/include/paper-outputter.hh index 8683b4c6d1..cd1a5e2c92 100644 --- a/lily/include/paper-outputter.hh +++ b/lily/include/paper-outputter.hh @@ -33,7 +33,6 @@ class Paper_outputter : public Smob { public: - static const char * const type_p_name_; // = 0 SCM mark_smob () const; virtual ~Paper_outputter (); private: diff --git a/lily/include/performer.hh b/lily/include/performer.hh index a640e240aa..70354fdbf2 100644 --- a/lily/include/performer.hh +++ b/lily/include/performer.hh @@ -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; diff --git a/lily/include/pitch.hh b/lily/include/pitch.hh index daade82e81..dad2bc1246 100644 --- a/lily/include/pitch.hh +++ b/lily/include/pitch.hh @@ -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_; diff --git a/lily/include/prob.hh b/lily/include/prob.hh index cb850555fb..a9a485b550 100644 --- a/lily/include/prob.hh +++ b/lily/include/prob.hh @@ -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); diff --git a/lily/include/protected-scm.hh b/lily/include/protected-scm.hh index 48a26b15c9..0115cb9f9f 100644 --- a/lily/include/protected-scm.hh +++ b/lily/include/protected-scm.hh @@ -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 */ diff --git a/lily/include/scale.hh b/lily/include/scale.hh index 7c990e5034..19cd175c79 100644 --- a/lily/include/scale.hh +++ b/lily/include/scale.hh @@ -26,7 +26,6 @@ struct Scale : public Smob { - static const char * const type_p_name_; // = 0 virtual ~Scale (); Scale (vector const &); Scale (Scale const &); diff --git a/lily/include/scheme-engraver.hh b/lily/include/scheme-engraver.hh index 3cd691578f..59cab571fb 100644 --- a/lily/include/scheme-engraver.hh +++ b/lily/include/scheme-engraver.hh @@ -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 interface_acknowledger_hash_; // Alist of listened-symbol . scheme-function SCM per_instance_listeners_; }; #endif /* SCHEME_ENGRAVER_HH */ - diff --git a/lily/include/scm-hash.hh b/lily/include/scm-hash.hh index 241f316c4e..3453904f71 100644 --- a/lily/include/scm-hash.hh +++ b/lily/include/scm-hash.hh @@ -46,7 +46,6 @@ class Scheme_hash_table : public Smob1 { 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; diff --git a/lily/include/score.hh b/lily/include/score.hh index b3ece8960a..a5918242f1 100644 --- a/lily/include/score.hh +++ b/lily/include/score.hh @@ -31,7 +31,7 @@ class Score : public Smob { public: SCM mark_smob () const; - static const char type_p_name_[]; + static const char * const type_p_name_; virtual ~Score (); private: SCM music_; diff --git a/lily/include/skyline-pair.hh b/lily/include/skyline-pair.hh index 6d7cea0ac2..f7946c1851 100644 --- a/lily/include/skyline-pair.hh +++ b/lily/include/skyline-pair.hh @@ -25,7 +25,7 @@ class Skyline_pair : public Simple_smob { public: - static const char type_p_name_[]; + static const char * const type_p_name_; private: Drul_array skylines_; diff --git a/lily/include/skyline.hh b/lily/include/skyline.hh index 21693420c8..43feb40761 100644 --- a/lily/include/skyline.hh +++ b/lily/include/skyline.hh @@ -51,7 +51,7 @@ struct Building class Skyline : public Simple_smob { public: - static const char type_p_name_[]; + static const char * const type_p_name_; private: list buildings_; Direction sky_; diff --git a/lily/include/slur-proto-engraver.hh b/lily/include/slur-proto-engraver.hh index c11926b21a..97ed1a6637 100644 --- a/lily/include/slur-proto-engraver.hh +++ b/lily/include/slur-proto-engraver.hh @@ -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 diff --git a/lily/include/smobs.hh b/lily/include/smobs.hh index 889d86a8ca..7ef46b23e4 100644 --- a/lily/include/smobs.hh +++ b/lily/include/smobs.hh @@ -120,7 +120,7 @@ debugging purposes. If the class does not define this function, the output will be # 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 diff --git a/lily/include/smobs.tcc b/lily/include/smobs.tcc index b8dfc1f67f..818c0900a5 100644 --- a/lily/include/smobs.tcc +++ b/lily/include/smobs.tcc @@ -113,6 +113,9 @@ Scm_init Smob_base::scm_init_ (init); template string Smob_base::smob_name_; +template +const char * const Smob_base::type_p_name_ = 0; + template void Smob_base::init () { diff --git a/lily/include/source-file.hh b/lily/include/source-file.hh index 6686389289..fc5bf2f541 100644 --- a/lily/include/source-file.hh +++ b/lily/include/source-file.hh @@ -40,7 +40,7 @@ class Source_file : public Smob 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 newline_locations_; diff --git a/lily/include/spring.hh b/lily/include/spring.hh index fd01ca048c..d4ebee23cd 100644 --- a/lily/include/spring.hh +++ b/lily/include/spring.hh @@ -27,7 +27,7 @@ class Spring : public Simple_smob { 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_; diff --git a/lily/include/stencil.hh b/lily/include/stencil.hh index 6ccb9252bb..8af67c0f76 100644 --- a/lily/include/stencil.hh +++ b/lily/include/stencil.hh @@ -59,7 +59,7 @@ class Stencil : public Simple_smob { public: SCM mark_smob () const; - static const char type_p_name_[]; + static const char * const type_p_name_; private: Box dim_; SCM expr_; diff --git a/lily/include/translator-dispatch-list.hh b/lily/include/translator-dispatch-list.hh index 6fd03beecf..b6124572fc 100644 --- a/lily/include/translator-dispatch-list.hh +++ b/lily/include/translator-dispatch-list.hh @@ -21,21 +21,15 @@ #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 { - vector dispatch_entries_; + vector 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); diff --git a/lily/include/translator-group.hh b/lily/include/translator-group.hh index d90c2929de..d4500ef2b4 100644 --- a/lily/include/translator-group.hh +++ b/lily/include/translator-group.hh @@ -20,48 +20,22 @@ #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 { 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 + vector 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); diff --git a/lily/include/translator.hh b/lily/include/translator.hh index 118220772a..dd0659bf50 100644 --- a/lily/include/translator.hh +++ b/lily/include/translator.hh @@ -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" @@ -31,18 +32,17 @@ #define TRANSLATOR_FAMILY_DECLARATIONS(NAME) \ public: \ VIRTUAL_COPY_CONSTRUCTOR (Translator, NAME); \ - static Drul_array > 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 \ + static SCM method_finder () { return method_find_base (); } \ /* end #define */ /* @@ -53,11 +53,19 @@ */ #define TRANSLATOR_DECLARATIONS(NAME) \ - TRANSLATOR_FAMILY_DECLARATIONS(NAME) \ + public: \ + TRANSLATOR_FAMILY_DECLARATIONS (NAME); \ + static Drul_array 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 { 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 + static SCM + method_find_base () { return Callback0_wrapper::make_smob (); } + + // Fallback for non-overriden callbacks for which &T::x degrades to + // &Translator::x + template + 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); diff --git a/lily/include/translator.icc b/lily/include/translator.icc index 250a923137..b649a1a197 100644 --- a/lily/include/translator.icc +++ b/lily/include/translator.icc @@ -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 ()); \ @@ -44,24 +45,19 @@ { \ 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 > 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 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 */ @@ -72,78 +68,52 @@ 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 (&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 (&T::stop_translation_timestep); \ - \ + method_finder <&T::stop_translation_timestep> (); \ + \ ptrs[PROCESS_MUSIC] = \ - (&T::process_music == &Translator::process_music) \ - ? 0 \ - : static_cast (&T::process_music); \ + method_finder <&T::process_music> (); \ \ ptrs[PROCESS_ACKNOWLEDGED] = \ - (&T::process_acknowledged == &Translator::process_acknowledged) \ - ? 0 \ - : static_cast (&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 *ack_array); - -Translator::Grob_info_callback -generic_get_acknowledger (SCM sym, - vector const *ack_array); + SCM &ack_hash); #define ADD_ACKNOWLEDGER(CLASS, NAME) \ - void CLASS ## NAME ## _ack_adder () \ - { \ - add_acknowledger (static_cast (&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 \ + > (), \ + #NAME, acknowledge_static_array_drul_[START]) -#define ADD_END_ACKNOWLEDGER(CLASS, NAME) \ - void CLASS ## NAME ## _end_ack_adder () \ - { \ - add_acknowledger (static_cast (&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 \ + > (), \ + #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 \ - > (), listener_list_); \ -} \ - \ -ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m); + > (), listener_list_) #endif /* TRANSLATOR_ICC */ diff --git a/lily/include/unpure-pure-container.hh b/lily/include/unpure-pure-container.hh index 92974fe8f0..7accff9a88 100644 --- a/lily/include/unpure-pure-container.hh +++ b/lily/include/unpure-pure-container.hh @@ -26,7 +26,7 @@ class Unpure_pure_container : public Smob2 { 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. diff --git a/lily/input-smob.cc b/lily/input-smob.cc index f9de264277..6f5fc18a54 100644 --- a/lily/input-smob.cc +++ b/lily/input-smob.cc @@ -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 diff --git a/lily/instrument-name-engraver.cc b/lily/instrument-name-engraver.cc index d339fbce61..ec37d6bcbf 100644 --- a/lily/instrument-name-engraver.cc +++ b/lily/instrument-name-engraver.cc @@ -43,7 +43,7 @@ protected: vector 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 */ diff --git a/lily/instrument-switch-engraver.cc b/lily/instrument-switch-engraver.cc index 67a58c7e6f..59cbb4f13c 100644 --- a/lily/instrument-switch-engraver.cc +++ b/lily/instrument-switch-engraver.cc @@ -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.", diff --git a/lily/keep-alive-together-engraver.cc b/lily/keep-alive-together-engraver.cc index 79fedc96df..9b1cbe4a23 100644 --- a/lily/keep-alive-together-engraver.cc +++ b/lily/keep-alive-together-engraver.cc @@ -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 */ diff --git a/lily/key-engraver.cc b/lily/key-engraver.cc index 971f553172..8c907dc7cc 100644 --- a/lily/key-engraver.cc +++ b/lily/key-engraver.cc @@ -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 */ diff --git a/lily/key-performer.cc b/lily/key-performer.cc index 06666ac532..219454115a 100644 --- a/lily/key-performer.cc +++ b/lily/key-performer.cc @@ -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 */ "", diff --git a/lily/kievan-ligature-engraver.cc b/lily/kievan-ligature-engraver.cc index 25582c6a39..cdb51de3ad 100644 --- a/lily/kievan-ligature-engraver.cc +++ b/lily/kievan-ligature-engraver.cc @@ -36,22 +36,15 @@ protected: virtual Spanner *create_ligature_spanner (); virtual void build_ligature (Spanner *ligature, vector const &primitives); - DECLARE_TRANSLATOR_LISTENER (ligature); public: TRANSLATOR_DECLARATIONS (Kievan_ligature_engraver); + TRANSLATOR_INHERIT (Coherent_ligature_engraver); private: void fold_up_primitives (vector 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 */ diff --git a/lily/laissez-vibrer-engraver.cc b/lily/laissez-vibrer-engraver.cc index 6e57a7e9df..e84ea36bca 100644 --- a/lily/laissez-vibrer-engraver.cc +++ b/lily/laissez-vibrer-engraver.cc @@ -32,9 +32,9 @@ class Laissez_vibrer_engraver : public Engraver vector 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.", diff --git a/lily/ledger-line-engraver.cc b/lily/ledger-line-engraver.cc index 8e871c1abf..869720cca4 100644 --- a/lily/ledger-line-engraver.cc +++ b/lily/ledger-line-engraver.cc @@ -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" diff --git a/lily/ligature-bracket-engraver.cc b/lily/ligature-bracket-engraver.cc index bc3d379c22..4919071d97 100644 --- a/lily/ligature-bracket-engraver.cc +++ b/lily/ligature-bracket-engraver.cc @@ -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 */ diff --git a/lily/lily-imports.cc b/lily/lily-imports.cc index adc9124fb7..62e58b603c 100644 --- a/lily/lily-imports.cc +++ b/lily/lily-imports.cc @@ -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"); diff --git a/lily/lily-lexer.cc b/lily/lily-lexer.cc index 221d048cc0..6db0e653e5 100644 --- a/lily/lily-lexer.cc +++ b/lily/lily-lexer.cc @@ -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 diff --git a/lily/lily-parser.cc b/lily/lily-parser.cc index 3188974284..d2499d4c41 100644 --- a/lily/lily-parser.cc +++ b/lily/lily-parser.cc @@ -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 diff --git a/lily/listener.cc b/lily/listener.cc index 2a8d28d8cb..836f8cdc6f 100644 --- a/lily/listener.cc +++ b/lily/listener.cc @@ -19,4 +19,4 @@ #include "listener.hh" -const char Listener::type_p_name_[] = "ly:listener?"; +const char * const Listener::type_p_name_ = "ly:listener?"; diff --git a/lily/lookup.cc b/lily/lookup.cc index b6d13fc356..3e592516c5 100644 --- a/lily/lookup.cc +++ b/lily/lookup.cc @@ -246,9 +246,9 @@ Lookup::round_filled_polygon (vector 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++) { diff --git a/lily/lyric-engraver.cc b/lily/lyric-engraver.cc index cdee61517e..08c9306693 100644 --- a/lily/lyric-engraver.cc +++ b/lily/lyric-engraver.cc @@ -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.", diff --git a/lily/lyric-performer.cc b/lily/lyric-performer.cc index 0ad69ae053..6a25d62a3f 100644 --- a/lily/lyric-performer.cc +++ b/lily/lyric-performer.cc @@ -30,7 +30,7 @@ protected: void stop_translation_timestep (); void process_music (); - DECLARE_TRANSLATOR_LISTENER (lyric); + void listen_lyric (Stream_event *); private: vector 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 */ "", diff --git a/lily/mark-engraver.cc b/lily/mark-engraver.cc index 7db0a781cc..a849ec11ce 100644 --- a/lily/mark-engraver.cc +++ b/lily/mark-engraver.cc @@ -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 */ diff --git a/lily/measure-grouping-engraver.cc b/lily/measure-grouping-engraver.cc index e7fc3c6726..2ab7a7bcc6 100644 --- a/lily/measure-grouping-engraver.cc +++ b/lily/measure-grouping-engraver.cc @@ -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.", diff --git a/lily/melody-engraver.cc b/lily/melody-engraver.cc index 2d982056d3..a97d13755f 100644 --- a/lily/melody-engraver.cc +++ b/lily/melody-engraver.cc @@ -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 */ diff --git a/lily/mensural-ligature-engraver.cc b/lily/mensural-ligature-engraver.cc index ac1eb1f10a..41652a1006 100644 --- a/lily/mensural-ligature-engraver.cc +++ b/lily/mensural-ligature-engraver.cc @@ -59,10 +59,10 @@ protected: virtual Spanner *create_ligature_spanner (); virtual void build_ligature (Spanner *ligature, vector const &primitives); - DECLARE_TRANSLATOR_LISTENER (ligature); public: TRANSLATOR_DECLARATIONS (Mensural_ligature_engraver); + TRANSLATOR_INHERIT (Coherent_ligature_engraver); private: void transform_heads (vector 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 */ diff --git a/lily/metronome-engraver.cc b/lily/metronome-engraver.cc index e1de3e23e0..241a2da44a 100644 --- a/lily/metronome-engraver.cc +++ b/lily/metronome-engraver.cc @@ -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 */ diff --git a/lily/midi-control-function-performer.cc b/lily/midi-control-function-performer.cc index 90ea063f73..a112e6bcef 100644 --- a/lily/midi-control-function-performer.cc +++ b/lily/midi-control-function-performer.cc @@ -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 */ "", diff --git a/lily/misc.cc b/lily/misc.cc index b930fd521a..6cafa2b50b 100644 --- a/lily/misc.cc +++ b/lily/misc.cc @@ -22,25 +22,6 @@ #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) { diff --git a/lily/moment.cc b/lily/moment.cc index 81ab30e3ae..20c1f58a0b 100644 --- a/lily/moment.cc +++ b/lily/moment.cc @@ -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 diff --git a/lily/multi-measure-rest-engraver.cc b/lily/multi-measure-rest-engraver.cc index 274746b845..04ef91fc88 100644 --- a/lily/multi-measure-rest-engraver.cc +++ b/lily/multi-measure-rest-engraver.cc @@ -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" diff --git a/lily/music-function.cc b/lily/music-function.cc index 969d5ff7b5..c252291736 100644 --- a/lily/music-function.cc +++ b/lily/music-function.cc @@ -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 diff --git a/lily/music-iterator.cc b/lily/music-iterator.cc index b89e92c28e..a7a06ff0d8 100644 --- a/lily/music-iterator.cc +++ b/lily/music-iterator.cc @@ -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 diff --git a/lily/music-output.cc b/lily/music-output.cc index 7b89b853f6..9e8cc9ff9a 100644 --- a/lily/music-output.cc +++ b/lily/music-output.cc @@ -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 diff --git a/lily/new-fingering-engraver.cc b/lily/new-fingering-engraver.cc index 3ecad3a89e..75eccf69fc 100644 --- a/lily/new-fingering-engraver.cc +++ b/lily/new-fingering-engraver.cc @@ -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 *, 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 */ diff --git a/lily/note-head-line-engraver.cc b/lily/note-head-line-engraver.cc index 4b21bb2767..b09fe66361 100644 --- a/lily/note-head-line-engraver.cc +++ b/lily/note-head-line-engraver.cc @@ -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" diff --git a/lily/note-heads-engraver.cc b/lily/note-heads-engraver.cc index 6322dfa2b9..5839a827eb 100644 --- a/lily/note-heads-engraver.cc +++ b/lily/note-heads-engraver.cc @@ -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.", diff --git a/lily/note-name-engraver.cc b/lily/note-name-engraver.cc index 3ae9840e0d..2b8fa87000 100644 --- a/lily/note-name-engraver.cc +++ b/lily/note-name-engraver.cc @@ -30,12 +30,11 @@ public: TRANSLATOR_DECLARATIONS (Note_name_engraver); vector 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.", diff --git a/lily/note-performer.cc b/lily/note-performer.cc index aa46440006..468210d20d 100644 --- a/lily/note-performer.cc +++ b/lily/note-performer.cc @@ -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 note_evs_; + vector note_evs_, script_evs_; vector notes_; vector 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 (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 */ "", diff --git a/lily/note-spacing-engraver.cc b/lily/note-spacing-engraver.cc index f0bca862d9..414e1ee761 100644 --- a/lily/note-spacing-engraver.cc +++ b/lily/note-spacing-engraver.cc @@ -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 */ diff --git a/lily/open-type-font-scheme.cc b/lily/open-type-font-scheme.cc index 79370fa698..365ccb1a63 100644 --- a/lily/open-type-font-scheme.cc +++ b/lily/open-type-font-scheme.cc @@ -17,8 +17,19 @@ along with LilyPond. If not, see . */ +#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; +} diff --git a/lily/ottava-engraver.cc b/lily/ottava-engraver.cc index d236ed779d..e681e73af6 100644 --- a/lily/ottava-engraver.cc +++ b/lily/ottava-engraver.cc @@ -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 */ diff --git a/lily/output-def-scheme.cc b/lily/output-def-scheme.cc index e78eff0673..65673c8a9e 100644 --- a/lily/output-def-scheme.cc +++ b/lily/output-def-scheme.cc @@ -101,8 +101,8 @@ LY_DEFINE (ly_output_description, "ly:output-description", { Context_def *td = unsmob (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))); diff --git a/lily/output-property-engraver.cc b/lily/output-property-engraver.cc index c14a6ee563..7a0fa2d3c3 100644 --- a/lily/output-property-engraver.cc +++ b/lily/output-property-engraver.cc @@ -31,13 +31,12 @@ class Output_property_engraver : public Engraver protected: vector 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.", diff --git a/lily/page-marker.cc b/lily/page-marker.cc index 02b9c4ad19..af62bdc95e 100644 --- a/lily/page-marker.cc +++ b/lily/page-marker.cc @@ -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 diff --git a/lily/page-turn-engraver.cc b/lily/page-turn-engraver.cc index dd90ba71cf..c77dc9b2a5 100644 --- a/lily/page-turn-engraver.cc +++ b/lily/page-turn-engraver.cc @@ -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 */ diff --git a/lily/paper-book.cc b/lily/paper-book.cc index e23ef52777..3a672198b5 100644 --- a/lily/paper-book.cc +++ b/lily/paper-book.cc @@ -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 diff --git a/lily/paper-column-engraver.cc b/lily/paper-column-engraver.cc index 7c44f173d7..8cb99ecbb6 100644 --- a/lily/paper-column-engraver.cc +++ b/lily/paper-column-engraver.cc @@ -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 */ diff --git a/lily/paper-outputter.cc b/lily/paper-outputter.cc index 471a36a41a..a72ea59ccd 100644 --- a/lily/paper-outputter.cc +++ b/lily/paper-outputter.cc @@ -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; diff --git a/lily/parenthesis-engraver.cc b/lily/parenthesis-engraver.cc index 1479aa4c0b..dcbd506a4a 100644 --- a/lily/parenthesis-engraver.cc +++ b/lily/parenthesis-engraver.cc @@ -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" diff --git a/lily/parser.yy b/lily/parser.yy index b8849e8f4a..1695aea625 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -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 ($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 ($4); sc->origin ()->set_spot (@$); diff --git a/lily/part-combine-engraver.cc b/lily/part-combine-engraver.cc index eaae218c1b..33c10f5966 100644 --- a/lily/part-combine-engraver.cc +++ b/lily/part-combine-engraver.cc @@ -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" diff --git a/lily/percent-repeat-engraver.cc b/lily/percent-repeat-engraver.cc index 895e06981e..b620cdccb5 100644 --- a/lily/percent-repeat-engraver.cc +++ b/lily/percent-repeat-engraver.cc @@ -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.", diff --git a/lily/pfb-scheme.cc b/lily/pfb-scheme.cc index 4a13515472..f708c098a0 100644 --- a/lily/pfb-scheme.cc +++ b/lily/pfb-scheme.cc @@ -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); diff --git a/lily/phrasing-slur-engraver.cc b/lily/phrasing-slur-engraver.cc index 479be1df22..ee7a96a2d7 100644 --- a/lily/phrasing-slur-engraver.cc +++ b/lily/phrasing-slur-engraver.cc @@ -34,13 +34,13 @@ 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}.", diff --git a/lily/piano-pedal-align-engraver.cc b/lily/piano-pedal-align-engraver.cc index 7134a6cfc7..7c120a1bc1 100644 --- a/lily/piano-pedal-align-engraver.cc +++ b/lily/piano-pedal-align-engraver.cc @@ -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 */ diff --git a/lily/piano-pedal-engraver.cc b/lily/piano-pedal-engraver.cc index 2fb99407d5..cbdf5244d1 100644 --- a/lily/piano-pedal-engraver.cc +++ b/lily/piano-pedal-engraver.cc @@ -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.", diff --git a/lily/piano-pedal-performer.cc b/lily/piano-pedal-performer.cc index 49ec0dd7fe..a8273980e9 100644 --- a/lily/piano-pedal-performer.cc +++ b/lily/piano-pedal-performer.cc @@ -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 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 */ "", diff --git a/lily/pitch-squash-engraver.cc b/lily/pitch-squash-engraver.cc index d9796ff0e0..0750c59495 100644 --- a/lily/pitch-squash-engraver.cc +++ b/lily/pitch-squash-engraver.cc @@ -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" diff --git a/lily/pitch.cc b/lily/pitch.cc index e34562fecc..9e46bba70e 100644 --- a/lily/pitch.cc +++ b/lily/pitch.cc @@ -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 diff --git a/lily/pitched-trill-engraver.cc b/lily/pitched-trill-engraver.cc index 30d734346e..1ec4da9aeb 100644 --- a/lily/pitched-trill-engraver.cc +++ b/lily/pitched-trill-engraver.cc @@ -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 */ diff --git a/lily/prob.cc b/lily/prob.cc index 938f106861..d05a33e4f3 100644 --- a/lily/prob.cc +++ b/lily/prob.cc @@ -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) diff --git a/lily/protected-scm.cc b/lily/protected-scm.cc index 225c64dc60..75091e1901 100644 --- a/lily/protected-scm.cc +++ b/lily/protected-scm.cc @@ -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_); } diff --git a/lily/pure-from-neighbor-engraver.cc b/lily/pure-from-neighbor-engraver.cc index e147f53cca..3bd0fa1091 100644 --- a/lily/pure-from-neighbor-engraver.cc +++ b/lily/pure-from-neighbor-engraver.cc @@ -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.", diff --git a/lily/repeat-acknowledge-engraver.cc b/lily/repeat-acknowledge-engraver.cc index 67477b1f01..d11b633fd5 100644 --- a/lily/repeat-acknowledge-engraver.cc +++ b/lily/repeat-acknowledge-engraver.cc @@ -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" diff --git a/lily/repeat-tie-engraver.cc b/lily/repeat-tie-engraver.cc index 4eea8e5800..fb2c8bb584 100644 --- a/lily/repeat-tie-engraver.cc +++ b/lily/repeat-tie-engraver.cc @@ -32,8 +32,8 @@ class Repeat_tie_engraver : public Engraver vector 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.", diff --git a/lily/rest-collision-engraver.cc b/lily/rest-collision-engraver.cc index a70641cfd0..56a6783fbf 100644 --- a/lily/rest-collision-engraver.cc +++ b/lily/rest-collision-engraver.cc @@ -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.", diff --git a/lily/rest-engraver.cc b/lily/rest-engraver.cc index b40aeee8a3..d691c2e98c 100644 --- a/lily/rest-engraver.cc +++ b/lily/rest-engraver.cc @@ -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.", diff --git a/lily/rhythmic-column-engraver.cc b/lily/rhythmic-column-engraver.cc index 28a06f79b0..04281231d5 100644 --- a/lily/rhythmic-column-engraver.cc +++ b/lily/rhythmic-column-engraver.cc @@ -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 */ diff --git a/lily/scale.cc b/lily/scale.cc index d6f566b9ed..02c1dc5f8e 100644 --- a/lily/scale.cc +++ b/lily/scale.cc @@ -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 { diff --git a/lily/scheme-engraver.cc b/lily/scheme-engraver.cc index ec4197641b..c322a6d255 100644 --- a/lily/scheme-engraver.cc +++ b/lily/scheme-engraver.cc @@ -25,20 +25,19 @@ #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(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); diff --git a/lily/scm-hash.cc b/lily/scm-hash.cc index 3eb40ada7b..0b1e0b4e25 100644 --- a/lily/scm-hash.cc +++ b/lily/scm-hash.cc @@ -21,8 +21,6 @@ #include -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 diff --git a/lily/score-engraver.cc b/lily/score-engraver.cc index 3e4fb97315..88ea4af86f 100644 --- a/lily/score-engraver.cc +++ b/lily/score-engraver.cc @@ -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 (), + Callback0_wrapper::make_smob (), + UP); } #define MUSIC_FONT "emmentaler-20" diff --git a/lily/score-performer.cc b/lily/score-performer.cc index 4ea42ed143..b44bb489f5 100644 --- a/lily/score-performer.cc +++ b/lily/score-performer.cc @@ -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 (), + Callback0_wrapper::make_smob (), + UP); } void diff --git a/lily/score.cc b/lily/score.cc index da48e8f103..d10023dd85 100644 --- a/lily/score.cc +++ b/lily/score.cc @@ -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 diff --git a/lily/script-column-engraver.cc b/lily/script-column-engraver.cc index dc34098664..6310f3b540 100644 --- a/lily/script-column-engraver.cc +++ b/lily/script-column-engraver.cc @@ -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" diff --git a/lily/script-engraver.cc b/lily/script-engraver.cc index 62c3de482c..8a7b122f1f 100644 --- a/lily/script-engraver.cc +++ b/lily/script-engraver.cc @@ -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 */ diff --git a/lily/script-row-engraver.cc b/lily/script-row-engraver.cc index 35b5038020..20af8d1cbb 100644 --- a/lily/script-row-engraver.cc +++ b/lily/script-row-engraver.cc @@ -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.", diff --git a/lily/separating-line-group-engraver.cc b/lily/separating-line-group-engraver.cc index 08069afda8..5eb1407a31 100644 --- a/lily/separating-line-group-engraver.cc +++ b/lily/separating-line-group-engraver.cc @@ -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 */ diff --git a/lily/skyline-pair.cc b/lily/skyline-pair.cc index b3c2b96df4..bab43494a6 100644 --- a/lily/skyline-pair.cc +++ b/lily/skyline-pair.cc @@ -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); diff --git a/lily/skyline.cc b/lily/skyline.cc index f46b2f3e84..6ef2069c39 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -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 diff --git a/lily/slash-repeat-engraver.cc b/lily/slash-repeat-engraver.cc index f9f0bfb76a..b1bdf9c0da 100644 --- a/lily/slash-repeat-engraver.cc +++ b/lily/slash-repeat-engraver.cc @@ -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.", diff --git a/lily/slur-engraver.cc b/lily/slur-engraver.cc index 581136791d..2ea4595fc1 100644 --- a/lily/slur-engraver.cc +++ b/lily/slur-engraver.cc @@ -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.", diff --git a/lily/slur-performer.cc b/lily/slur-performer.cc index 222a9d75fa..47fed784fe 100644 --- a/lily/slur-performer.cc +++ b/lily/slur-performer.cc @@ -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 */ "", diff --git a/lily/source-file.cc b/lily/source-file.cc index 5a94927a7f..14fdf2beb3 100644 --- a/lily/source-file.cc +++ b/lily/source-file.cc @@ -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 diff --git a/lily/spacing-engraver.cc b/lily/spacing-engraver.cc index cc5b1e31d1..d77a55b757 100644 --- a/lily/spacing-engraver.cc +++ b/lily/spacing-engraver.cc @@ -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 */ diff --git a/lily/span-arpeggio-engraver.cc b/lily/span-arpeggio-engraver.cc index f66c8770b5..9cece4a6fe 100644 --- a/lily/span-arpeggio-engraver.cc +++ b/lily/span-arpeggio-engraver.cc @@ -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.", diff --git a/lily/span-bar-engraver.cc b/lily/span-bar-engraver.cc index 63c245e70c..e74528535b 100644 --- a/lily/span-bar-engraver.cc +++ b/lily/span-bar-engraver.cc @@ -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" diff --git a/lily/span-bar-stub-engraver.cc b/lily/span-bar-stub-engraver.cc index 304564398f..a0c10f8594 100644 --- a/lily/span-bar-stub-engraver.cc +++ b/lily/span-bar-stub-engraver.cc @@ -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.", diff --git a/lily/spanner-break-forbid-engraver.cc b/lily/spanner-break-forbid-engraver.cc index 4a47aade98..8d64b40ce8 100644 --- a/lily/spanner-break-forbid-engraver.cc +++ b/lily/spanner-break-forbid-engraver.cc @@ -31,8 +31,8 @@ class Spanner_break_forbid_engraver : public Engraver TRANSLATOR_DECLARATIONS (Spanner_break_forbid_engraver); vector 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.", diff --git a/lily/spring-smob.cc b/lily/spring-smob.cc index 77b01bb158..a389df2efd 100644 --- a/lily/spring-smob.cc +++ b/lily/spring-smob.cc @@ -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?"; diff --git a/lily/staff-collecting-engraver.cc b/lily/staff-collecting-engraver.cc index 2ff2b79caf..88680943d3 100644 --- a/lily/staff-collecting-engraver.cc +++ b/lily/staff-collecting-engraver.cc @@ -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 */ diff --git a/lily/staff-performer.cc b/lily/staff-performer.cc index 26781f0dcd..3a05cbd0e2 100644 --- a/lily/staff-performer.cc +++ b/lily/staff-performer.cc @@ -79,6 +79,12 @@ map 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 */ "", diff --git a/lily/staff-symbol-engraver.cc b/lily/staff-symbol-engraver.cc index cad91e76c3..c8f528f0f5 100644 --- a/lily/staff-symbol-engraver.cc +++ b/lily/staff-symbol-engraver.cc @@ -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 */ diff --git a/lily/stanza-number-align-engraver.cc b/lily/stanza-number-align-engraver.cc index c32653abe0..39eae99831 100644 --- a/lily/stanza-number-align-engraver.cc +++ b/lily/stanza-number-align-engraver.cc @@ -35,8 +35,8 @@ protected: vector lyrics_; vector 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 */ diff --git a/lily/stanza-number-engraver.cc b/lily/stanza-number-engraver.cc index 892bae633c..0a4539e8f1 100644 --- a/lily/stanza-number-engraver.cc +++ b/lily/stanza-number-engraver.cc @@ -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.", diff --git a/lily/stem-engraver.cc b/lily/stem-engraver.cc index 2f2eaf82da..8907c34bc3 100644 --- a/lily/stem-engraver.cc +++ b/lily/stem-engraver.cc @@ -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 */ diff --git a/lily/stencil.cc b/lily/stencil.cc index 3da1869541..0cf49296f0 100644 --- a/lily/stencil.cc +++ b/lily/stencil.cc @@ -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 diff --git a/lily/system-start-delimiter-engraver.cc b/lily/system-start-delimiter-engraver.cc index 7eadbb0eec..2979e11a19 100644 --- a/lily/system-start-delimiter-engraver.cc +++ b/lily/system-start-delimiter-engraver.cc @@ -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 */ diff --git a/lily/tab-note-heads-engraver.cc b/lily/tab-note-heads-engraver.cc index 4d47d77982..4294a2e5fe 100644 --- a/lily/tab-note-heads-engraver.cc +++ b/lily/tab-note-heads-engraver.cc @@ -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" diff --git a/lily/tab-staff-symbol-engraver.cc b/lily/tab-staff-symbol-engraver.cc index be0b343de3..cde9e82bbb 100644 --- a/lily/tab-staff-symbol-engraver.cc +++ b/lily/tab-staff-symbol-engraver.cc @@ -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" diff --git a/lily/tab-tie-follow-engraver.cc b/lily/tab-tie-follow-engraver.cc index b26bf0f6f6..58c5203ef0 100644 --- a/lily/tab-tie-follow-engraver.cc +++ b/lily/tab-tie-follow-engraver.cc @@ -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 */ diff --git a/lily/tempo-performer.cc b/lily/tempo-performer.cc index b17e9202cb..683f133d64 100644 --- a/lily/tempo-performer.cc +++ b/lily/tempo-performer.cc @@ -85,6 +85,12 @@ Tempo_performer::stop_translation_timestep () } } +void +Tempo_performer::boot () +{ + +} + ADD_TRANSLATOR (Tempo_performer, /* doc */ "", diff --git a/lily/text-engraver.cc b/lily/text-engraver.cc index 2a12e75a7a..982b61a287 100644 --- a/lily/text-engraver.cc +++ b/lily/text-engraver.cc @@ -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 */ diff --git a/lily/text-spanner-engraver.cc b/lily/text-spanner-engraver.cc index 249fdce04a..f63e19a059 100644 --- a/lily/text-spanner-engraver.cc +++ b/lily/text-spanner-engraver.cc @@ -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 */ diff --git a/lily/tie-engraver.cc b/lily/tie-engraver.cc index 56fb4a337d..2a016b31be 100644 --- a/lily/tie-engraver.cc +++ b/lily/tie-engraver.cc @@ -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.", diff --git a/lily/tie-performer.cc b/lily/tie-performer.cc index b1aa15ffeb..e93b3e6b0c 100644 --- a/lily/tie-performer.cc +++ b/lily/tie-performer.cc @@ -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.", diff --git a/lily/time-signature-engraver.cc b/lily/time-signature-engraver.cc index df6ae6dd1b..d57b35bf6e 100644 --- a/lily/time-signature-engraver.cc +++ b/lily/time-signature-engraver.cc @@ -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" diff --git a/lily/time-signature-performer.cc b/lily/time-signature-performer.cc index d9c25554fd..3a3bbd2ca3 100644 --- a/lily/time-signature-performer.cc +++ b/lily/time-signature-performer.cc @@ -81,6 +81,12 @@ Time_signature_performer::stop_translation_timestep () #include "translator.icc" +void +Time_signature_performer::boot () +{ + +} + ADD_TRANSLATOR (Time_signature_performer, /* doc */ "", diff --git a/lily/timing-translator.cc b/lily/timing-translator.cc index 9bd7e758d8..4716eceb24 100644 --- a/lily/timing-translator.cc +++ b/lily/timing-translator.cc @@ -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" diff --git a/lily/translator-dispatch-list.cc b/lily/translator-dispatch-list.cc index 41d5a17182..eeee8d2483 100644 --- a/lily/translator-dispatch-list.cc +++ b/lily/translator-dispatch-list.cc @@ -21,19 +21,18 @@ #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 (retval); - Engraver_dispatch_entry entry; - bool found = false; for (SCM s = trans_list; scm_is_pair (s); s = scm_cdr (s)) { - Engraver *eng - = unsmob (scm_car (s)); + Engraver *eng = unsmob (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; } diff --git a/lily/translator-group.cc b/lily/translator-group.cc index e3f8cba3e8..a9f1690f62 100644 --- a/lily/translator-group.cc +++ b/lily/translator-group.cc @@ -36,10 +36,10 @@ #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 (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 (), + Callback0_wrapper::make_smob (), + 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 (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 (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 &bindings (precomputed_method_bindings_[idx]); + vector &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 diff --git a/lily/translator.cc b/lily/translator.cc index 370f7771c0..bdc55f0f05 100644 --- a/lily/translator.cc +++ b/lily/translator.cc @@ -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 *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 (ack_hash) + ->set (ly_symbol2scm (interface_name.c_str ()), ptr); } -Translator::Grob_info_callback -generic_get_acknowledger (SCM sym, vector 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 (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. diff --git a/lily/trill-spanner-engraver.cc b/lily/trill-spanner-engraver.cc index eb36aff7e6..6634b5ea43 100644 --- a/lily/trill-spanner-engraver.cc +++ b/lily/trill-spanner-engraver.cc @@ -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 */ diff --git a/lily/tuplet-engraver.cc b/lily/tuplet-engraver.cc index 369389200f..92e018aece 100644 --- a/lily/tuplet-engraver.cc +++ b/lily/tuplet-engraver.cc @@ -63,17 +63,16 @@ protected: vector stopped_tuplets_; vector 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.", diff --git a/lily/tweak-engraver.cc b/lily/tweak-engraver.cc index 81138b3670..5f97b1e4cb 100644 --- a/lily/tweak-engraver.cc +++ b/lily/tweak-engraver.cc @@ -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," diff --git a/lily/undead.cc b/lily/undead.cc index a328c66caf..4aed7a6023 100644 --- a/lily/undead.cc +++ b/lily/undead.cc @@ -24,7 +24,7 @@ class Undead : public Simple_smob 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), diff --git a/lily/unpure-pure-container.cc b/lily/unpure-pure-container.cc index 7a7d6d48d1..143b2fd47d 100644 --- a/lily/unpure-pure-container.cc +++ b/lily/unpure-pure-container.cc @@ -25,7 +25,6 @@ class Unpure_pure_call : public Smob1 { 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), diff --git a/lily/vaticana-ligature-engraver.cc b/lily/vaticana-ligature-engraver.cc index 2d94c03892..ddd1386872 100644 --- a/lily/vaticana-ligature-engraver.cc +++ b/lily/vaticana-ligature-engraver.cc @@ -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 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" diff --git a/lily/vertical-align-engraver.cc b/lily/vertical-align-engraver.cc index 6a47809fd7..0226173a2e 100644 --- a/lily/vertical-align-engraver.cc +++ b/lily/vertical-align-engraver.cc @@ -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" diff --git a/lily/volta-engraver.cc b/lily/volta-engraver.cc index bd198cbb67..2f95ac7ac1 100644 --- a/lily/volta-engraver.cc +++ b/lily/volta-engraver.cc @@ -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.", diff --git a/ly/Welcome-to-LilyPond-MacOS.ly b/ly/Welcome-to-LilyPond-MacOS.ly index 87ae51855d..972b6abd4a 100644 --- a/ly/Welcome-to-LilyPond-MacOS.ly +++ b/ly/Welcome-to-LilyPond-MacOS.ly @@ -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" diff --git a/ly/Welcome_to_LilyPond.ly b/ly/Welcome_to_LilyPond.ly index 526bb56eb4..8f3351a705 100644 --- a/ly/Welcome_to_LilyPond.ly +++ b/ly/Welcome_to_LilyPond.ly @@ -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" diff --git a/ly/articulate.ly b/ly/articulate.ly index 78acdbfe1f..0414bd926b 100644 --- a/ly/articulate.ly +++ b/ly/articulate.ly @@ -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 diff --git a/mf/99-lilypond-fonts.conf.in b/mf/99-lilypond-fonts.conf.in index 83f8b5376e..0831bf062c 100644 --- a/mf/99-lilypond-fonts.conf.in +++ b/mf/99-lilypond-fonts.conf.in @@ -16,4 +16,45 @@ + + + + + + */NotoSansCJK*.ttc + + + */SourceHanSans*.ttc + + + */SourceHanCodeJP.ttc + + + diff --git a/mf/feta-flags.mf b/mf/feta-flags.mf index 1be31ef4ee..b7fe2f0951 100644 --- a/mf/feta-flags.mf +++ b/mf/feta-flags.mf @@ -554,7 +554,7 @@ fet_endchar; %%%%%%%% % -% Single Stroke for Short Appogiatura +% Single Stroke for Short Appoggiatura % fet_beginchar ("grace dash (up)", "ugrace"); diff --git a/po/lilypond.pot b/po/lilypond.pot index a55d9d3bb0..d10065e32d 100644 --- a/po/lilypond.pot +++ b/po/lilypond.pot @@ -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 \n" "Language-Team: LANGUAGE \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 "" diff --git a/python/musicexp.py b/python/musicexp.py index f6b47c3c93..e8cbcb0167 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -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"': + + + Allegretto + + + + 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} + """ + 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) - diff --git a/python/musicxml.py b/python/musicxml.py index a061b6ea6e..f0b82f1333 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -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 ('\n' % self._name) + ly.debug_output(indent) + ly.debug_output('\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 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 blocks with a inside. This class is only +# for the inner 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 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 blocks with a inside. This class is only -# for the inner 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 index 0000000000..67df2add83 --- /dev/null +++ b/python/musicxml2ly_conversion.py @@ -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 index 0000000000..da2386bcde --- /dev/null +++ b/python/utilities.py @@ -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') diff --git a/scm/chord-entry.scm b/scm/chord-entry.scm index 1d41c973e8..23601a8dea 100644 --- a/scm/chord-entry.scm +++ b/scm/chord-entry.scm @@ -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}. diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index 3ee68e5e6a..75f1807e61 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -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) diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm index 4eebdfac0e..8695bc5b78 100644 --- a/scm/define-event-classes.scm +++ b/scm/define-event-classes.scm @@ -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 diff --git a/scm/define-music-display-methods.scm b/scm/define-music-display-methods.scm index 10aecbd1db..42637cd16c 100644 --- a/scm/define-music-display-methods.scm +++ b/scm/define-music-display-methods.scm @@ -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))))) diff --git a/scm/define-note-names.scm b/scm/define-note-names.scm index 5825967428..e7d208a511 100644 --- a/scm/define-note-names.scm +++ b/scm/define-note-names.scm @@ -33,11 +33,16 @@ ;;; 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. diff --git a/scm/framework-ps.scm b/scm/framework-ps.scm index ca3372ca92..a781055f50 100644 --- a/scm/framework-ps.scm +++ b/scm/framework-ps.scm @@ -340,9 +340,15 @@ ((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) "")))) diff --git a/scm/lily.scm b/scm/lily.scm index 5ead4e6c9c..d1248cdd92 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -86,6 +86,7 @@ ;; (define lilypond-declarations '()) +(define lilypond-exports '()) (define after-session-hook (make-hook)) (define-public (call-after-session thunk) @@ -93,7 +94,16 @@ (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)))) diff --git a/scm/output-ps.scm b/scm/output-ps.scm index 69f2772039..70b13848e4 100644 --- a/scm/output-ps.scm +++ b/scm/output-ps.scm @@ -157,6 +157,10 @@ (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))) @@ -171,7 +175,7 @@ ;; 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) diff --git a/scm/output-svg.scm b/scm/output-svg.scm index ca086318d7..78bda3c35b 100644 --- a/scm/output-svg.scm +++ b/scm/output-svg.scm @@ -485,14 +485,18 @@ (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 "\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)))))))) diff --git a/scripts/build/create-weblinks-itexi.py b/scripts/build/create-weblinks-itexi.py index e529ca7327..e631c27fd8 100644 --- a/scripts/build/create-weblinks-itexi.py +++ b/scripts/build/create-weblinks-itexi.py @@ -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" diff --git a/scripts/midi2ly.py b/scripts/midi2ly.py index f4a47fb79a..5358fc4698 100644 --- a/scripts/midi2ly.py +++ b/scripts/midi2ly.py @@ -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 diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index b1cc496f6e..766214bd76 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -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 . + # 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! # 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 , or 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()) + + # ... 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 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 and the # 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 # 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 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. angled and + # 2. -- 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 ( in MusicXML) are not yet implemented.")) + ly.warning(_("Metronome marks with complex relations ( 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 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 ! - 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 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 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 , Jan Nieuwenhuizen and Reinhold Kainhofer + Patrick L. Schmidt """ + """ @@ -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 '' 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 , or 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() diff --git a/stepmake/stepmake/executable-rules.make b/stepmake/stepmake/executable-rules.make index 785be9ef6f..daf2d8659d 100644 --- a/stepmake/stepmake/executable-rules.make +++ b/stepmake/stepmake/executable-rules.make @@ -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) diff --git a/stepmake/stepmake/test-rules.make b/stepmake/stepmake/test-rules.make index e10e83c7d8..7fbb413c78 100644 --- a/stepmake/stepmake/test-rules.make +++ b/stepmake/stepmake/test-rules.make @@ -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) diff --git a/tex/texinfo.tex b/tex/texinfo.tex index d164d451b8..d7e6b1f6b8 100644 --- a/tex/texinfo.tex +++ b/tex/texinfo.tex @@ -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, @@ -67,6 +67,10 @@ \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}% }% % diff --git a/vim/lilypond-ftplugin.vim b/vim/lilypond-ftplugin.vim index c822c43f01..0c3a8dc7e2 100644 --- a/vim/lilypond-ftplugin.vim +++ b/vim/lilypond-ftplugin.vim @@ -18,10 +18,10 @@ setlocal shiftwidth=2 " some handy key mappings " " save & make and play midi with timidity -map :w:se makeprg=lilypond\ \"%<\":make:!timidity "%<.midi" +map :w:setl makeprg=lilypond\ \"%<\":make:!timidity "%<.midi" " " save & make -map :w:se makeprg=lilypond\ \"%<\":make +map :w:setl makeprg=lilypond\ \"%<\":make " " view pdf with ghostview map :!gv --watch "%<.pdf" & @@ -33,7 +33,7 @@ map :cp map :cn " " make -map :w:se makeprg=make\ -k:make +map :w:setl makeprg=make\ -k:make " " menu source $VIMRUNTIME/menu.vim