@c -*- coding: utf-8; mode: texinfo; -*- @c This file is part of lilypond.tely @ignore Translation of GIT committish: d79348b1cda7e897422c58d5b9a4a6be1da03731 When revising a translation, copy the HEAD committish of the version that you are working on. See TRANSLATION for details. @end ignore @c \version "2.12.0" @node Interfaces for programmers @chapter Interfaces for programmers Fortgeschrittene Anpassungen können mithilfe der Programmiersprache Scheme vorgenommen werden. Wenn Sie Scheme nicht kennen, gibt es eine grundlegende Einleitung in LilyPonds @rlearning{Scheme tutorial}. @menu * Music functions:: * Programmer interfaces:: * Building complicated functions:: * Markup programmer interface:: * Contexts for programmers:: * Scheme procedures as properties:: * Using Scheme code instead of \tweak:: * Difficult tweaks:: @end menu @node Music functions @section Music functions Dieser Abschnitt behandelt die Erstellung von musikalischen Funktionen innerhalb von LilyPond. @menu * Overview of music functions:: * Simple substitution functions:: * Paired substitution functions:: * Mathematics in functions:: * Void functions:: * Functions without arguments:: * Overview of available music functions:: @end menu @node Overview of music functions @subsection Overview of music functions Es ist einfach, eine Funktion zu erstellen, die Variablen im LilyPond-Code ersetzt. Die allgemeine Form derartiger Funktionen ist @example function = #(define-music-function (parser location @var{var1} @var{var2}...@var{vari}... ) (@var{var1-type?} @var{var2-type?}...@var{vari-type?}...) #@{ @emph{...Noten...} #@}) @end example @noindent wobei @multitable @columnfractions .33 .66 @item @var{vari} @tab die @var{i}te Variable @item @var{vari-type?} @tab die Art der @var{i}ten Variable @item @var{...Noten...} @tab normaler LilyPond-Code, in dem Variablen wie @code{#$var1} usw. benutzt werden. @end multitable Die folgenden Eingabetypen können als Variablen in einer musikalischen Funktion benutzt werden. Diese Liste ist nicht vollständig -- siehe auch andere Dokumentationen überScheme für weitere Variablenarten. @multitable @columnfractions .33 .66 @headitem Eingabetyp @tab @var{vari-type?}-Notation @item Ganzzahl @tab @code{integer?} @item Float (Dezimalzahl) @tab @code{number?} @item Zeichenkette @tab @code{string?} @item Textbeschriftung @tab @code{markup?} @item Musikalischer Ausdruck @tab @code{ly:music?} @item Ein Variablenpaar @tab @code{pair?} @end multitable Die Argumente @code{parser} und @code{location} sind zwingend erforderlich und werden in einigen fortgeschrittenen Situationen eingesetzt. Das Argument @code{parser} wird benutzt, um auf den Wert einer weiteren LilyPond-Variable zuzugreifen. Das Argument @code{location} wird benutzt, um den @qq{Ursprung} des musikalischen Ausdrucks zu definieren, der von der musikalischen Funktion erzeugt wird. Das hilft, wenn ein Syntaxfehler auftaucht: in solchen Fällen kann LilyPond mitteilen, an welcher Stelle in der Eingabedatei sich der Fehler befindet. @node Simple substitution functions @subsection Simple substitution functions Hier ist ein einfaches Beispiel: @lilypond[quote,verbatim,ragged-right] padText = #(define-music-function (parser location padding) (number?) #{ \once \override TextScript #'padding = #$padding #}) \relative c''' { c4^"piu mosso" b a b \padText #1.8 c4^"piu mosso" d e f \padText #2.6 c4^"piu mosso" fis a g } @end lilypond Musikalische Ausdrücke können auch ersetzt werden: @lilypond[quote,verbatim,ragged-right] custosNote = #(define-music-function (parser location note) (ly:music?) #{ \once \override Voice.NoteHead #'stencil = #ly:text-interface::print \once \override Voice.NoteHead #'text = \markup \musicglyph #"custodes.mensural.u0" \once \override Voice.Stem #'stencil = ##f $note #}) { c' d' e' f' \custosNote g' } @end lilypond Mehrere Variablen können benutzt werden: @lilypond[quote,verbatim,ragged-right] tempoPadded = #(define-music-function (parser location padding tempotext) (number? string?) #{ \once \override Score.MetronomeMark #'padding = $padding \tempo \markup { \bold $tempotext } #}) \relative c'' { \tempo \markup { "Low tempo" } c4 d e f g1 \tempoPadded #4.0 #"High tempo" g4 f e d c1 } @end lilypond @node Paired substitution functions @subsection Paired substitution functions Einige @code{\override}-Befehle benötigen ein Zahlenpaar (als @code{cons}-Zelle in Scheme bezeichnet). Um beide Zahlen einer Funktion zuzuweisen, kann entweder die Variable @code{pair?} benutzt werden oder die @code{cons} in die musikalische Funktion eingefügt werden. @quotation @example manualBeam = #(define-music-function (parser location beg-end) (pair?) #@{ \once \override Beam #'positions = #$beg-end #@}) \relative @{ \manualBeam #'(3 . 6) c8 d e f @} @end example @end quotation @noindent oder @lilypond[quote,verbatim,ragged-right] manualBeam = #(define-music-function (parser location beg end) (number? number?) #{ \once \override Beam #'positions = #(cons $beg $end) #}) \relative { \manualBeam #3 #6 c8 d e f } @end lilypond @node Mathematics in functions @subsection Mathematics in functions Musikalische Funktionen können neben einfachen Ersetzungen auch Scheme-Programmcode enthalten: @lilypond[quote,verbatim,ragged-right] AltOn = #(define-music-function (parser location mag) (number?) #{ \override Stem #'length = #$(* 7.0 mag) \override NoteHead #'font-size = #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) #}) AltOff = { \revert Stem #'length \revert NoteHead #'font-size } { c'2 \AltOn #0.5 c'4 c' \AltOn #1.5 c' c' \AltOff c'2 } @end lilypond @noindent Dieses Beispiel kann auch umformuliert werden, um musikalische Ausdrücke zu integrieren: @lilypond[quote,verbatim,ragged-right] withAlt = #(define-music-function (parser location mag music) (number? ly:music?) #{ \override Stem #'length = #$(* 7.0 mag) \override NoteHead #'font-size = #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) $music \revert Stem #'length \revert NoteHead #'font-size #}) { c'2 \withAlt #0.5 {c'4 c'} \withAlt #1.5 {c' c'} c'2 } @end lilypond @node Void functions @subsection Void functions Eine musikalische Funktion muss einen musikalischen Ausdruck ausgeben, aber in manchen Fällen müssen Funktionen erstellt werden, die keine Notation enthalten (wie etwa eine Funktion, mit der man @qq{Point and Click} ausschalten kann). Um das vornehmen zu können, wird ein @code{leere}r musikalischer Ausdruck ausgegeben. Das ist der Grund, warum die Form, die ausgegeben wird, @code{(make-music ...)} heißt. Wird die Eigenschaft @code{'void} (engl. für @qq{leer}) auf @code{#t} gesetzt, wird der Parser angewiesen, den ausgegebenen musikalischen Ausdruck zu ignorieren. Der maßgebliche Teil der @code{'void}-Funktion ist also die Verarbeitung, die die Funktion vornimmt, nicht der musikalische Ausdruck, der ausgegeben wird. @example noPointAndClick = #(define-music-function (parser location) () (ly:set-option 'point-and-click #f) (make-music 'SequentialMusic 'void #t)) ... \noPointAndClick % disable point and click @end example @node Functions without arguments @subsection Functions without arguments In den meisten Fällen sollten Funktionen ohne Argumente mit einer Variable notiert werden: @example dolce = \markup@{ \italic \bold dolce @} @end example In einigen wenigen Fällen kann es aber auch sinnvoll sein, eine musikalische Funktion ohne Argumente zu erstellen: @example displayBarNum = #(define-music-function (parser location) () (if (eq? #t (ly:get-option 'display-bar-numbers)) #@{ \once \override Score.BarNumber #'break-visibility = ##f #@} #@{#@})) @end example Damit auch wirklich Taktzahlen angezeigt werden, wo die Funktion eingesetzt wurde, muss @command{lilypond} mit der Option @example lilypond -d display-bar-numbers Dateiname.ly @end example @noindent aufgerufen werden. @node Overview of available music functions @subsection Overview of available music functions @c fixme ; this should be move somewhere else? Die folgenden Befehle sind musikalische Funktionen: @include identifiers.tely @node Programmer interfaces @section Programmer interfaces Dieser Abschnitt zeigt, wie LilyPond und Scheme gemischt werden können. @menu * Input variables and Scheme:: * Internal music representation:: @end menu @node Input variables and Scheme @subsection Input variables and Scheme Das Eingabeformat unterstützt die Notation von Variablen: im folgenden Beispiel wird ein musikalischer Ausdruck einer Variable mit der Bezeichnung @code{traLaLa} zugewiesen: @example traLaLa = @{ c'4 d'4 @} @end example Der Geltungsbereich von Variablen ist beschränkt: im folgenden Beispiel enthält die @code{\layout}-Umgebung auch eine @code{traLaLa}-vVariable, die unabhängig von der äußeren @code{\traLaLa}-Variable ist: @example traLaLa = @{ c'4 d'4 @} \layout @{ traLaLa = 1.0 @} @end example Grundsätzlich ist jede Eingabedatei ein Geltungsbereich, und alle @code{\header}-, @code{\midi}- und @code{\layout}-Umgebungen sind Geltungsbereiche, die unterhalb des globalen Geltungsbereiches angeordnet sind. Sowohl Variablen als auch Geltungsbereiche sind in Form des GUILE-Modulsystems implementiert. Ein anonymes Scheme-Modul wird an jeden Geltunsbereich angehängt. Eine Zuweisung der form @example traLaLa = @{ c'4 d'4 @} @end example @noindent wird intern in die Scheme-Definition @example (define traLaLa @var{Scheme-Wert von `@code{... }'}) @end example @noindent umgewandelt. Das bedeutet, dass Eingabe- und Scheme-Variablen frei vermischt werden können. Im nächsten Beispiel wird ein Notenfragment in der Variable @code{traLaLa} gespeichert und mithilfe von Schme dupliziert. Das Ergebnis wird in eine @code{\score}-Umgebung mit der zweiten Variable @code{twice} integriert: @lilypond[verbatim] traLaLa = { c'4 d'4 } %% dummy action to deal with parser lookahead #(display "this needs to be here, sorry!") #(define newLa (map ly:music-deep-copy (list traLaLa traLaLa))) #(define twice (make-sequential-music newLa)) { \twice } @end lilypond In diesem Beispiel geschieht die Zuweisung, nachdem der Parser festgestellt hat, dass nichts interessantes mehr nach @code{traLaLa = @{ ... @}} vorkommt. Ohne die Pseudovariable in dem Beispiel würde die @code{newLa}-Devinition ausgeführt werden, bevor @code{traLaLa} definiert ist, was zu einem Syntax-Fehler führen würde. Das obige Beispiel zeigt, wie man musikalische Ausdrücke von der Eingabe in den Scheme-Interpretierer @qq{exportieren} kann. Es geht auch in die andere Richtung. Indem man einen Scheme-Wert in die Funktion @code{ly:export} einpackt, wird der Scheme-Wert interpretiert als ob er in LilyPond-Syntax notiert worden wäre. Anstatt @code{\twice} zu definieren, hätte man also auch schreiben können: @example ... @{ #(ly:export (make-sequential-music (list newLa))) @} @end example Scheme-Code wird sofort ausgewertet, wenn der Parser darauf stößt. Um Scheme-Code in einem Makro zu definieren (das dann erst später aufgerufen werden soll), müssen leere Funktionen benutzt werden (siehe @ref{Void functions}) oder das Folgende: @example #(define (nopc) (ly:set-option 'point-and-click #f)) ... #(nopc) @{ c'4 @} @end example @knownissues Scheme- und LilyPond-Variablen können im LilyPond-Modus mit der @code{--safe}-Option nicht vermischt werden. @node Internal music representation @subsection Internal music representation Wenn ein musikalischer Ausdruck ausgewertet wird, wird er in eine Anzahl von musikalischen Scheme-Objekten konvertiert. Die Eigenschaft, die ein musikalisches Objekt definiert, ist, dass es Zeit einnimmt. Zeit ist eine rationale Zahl, die die Länge eines Stückes in ganzen Noten misst. Ein musikalisches Objekt hat drei Typusarten: @itemize @item musikalische Bezeichnung: Jeder musikalische Ausdruck hat eine Bezeichnung. Eine Note beispielsweise führt zu einem @rinternals{NoteEvent} und @code{\simultaneous} führt zu @rinternals{SimultaneousMusic}. Eine Liste aller möglichen Ausdrücke findet sich in der Referenz der Interna, unter @rinternals{Music expressions}. @item @q{Typ} oder Schnittstelle: Jede musikalische Bezeichnung hat mehrere @qq{Typen} oder Schnittstellten, beispielsweise ist eine Note ein @code{event}, ober sie ist auch ein @code{note-event}, ein @code{rhythmic-event} und ein @code{melodic-event}. Alle diese Notationsklassen finden sich in der Referenz der Interna unter @rinternals{Music classes}. @item C++-Objekt: Jedes musikalische Objekt wird von einem Objekt der C++-Klasse @code{Music} repräsentiert. @end itemize Die eigentlich Information eines musikalischen Ausdrucks ist in Eigenschaften gespeichert. Ein @rinternals{NoteEvent} hat zum Beispiel @code{pitch}- und @code{duration}-Eigenschaften, die die Tonhöhe und die Dauer dieser Note speichern. Eine Liste aller verfügbaren Eigenschaften findet sich in der Referenz der Interna unter @rinternals{Music properties}. Ein zusammengesetzter musikalischer Ausdruck ist ein musikalisches Objekt, das andere Objekte in seinen Eigenschaften enthält. Eine Liste der Objekte kann in der @code{elements}-Eigenschaft eines musikalischen Objektes gespeichert werden, oder ein einziges @qq{Kind}-Objekt in der @code{element}-Eigenschaft. Sa hat etwa @rinternals{SequentialMusic} seine @qq{Kinder} in @code{elements}, und @rinternals{GraceMusic} hat sein einziges Argument in @code{element}. Der Hauptteil einer Wiederholung wird in der @code{element}-Eigenschaft von @rinternals{RepeatedMusic} gespeichert, und die Alternativen in @code{elements}. @node Building complicated functions @section Building complicated functions Dieser Abschnitt zeigt, wie man Information zusammensucht, um komplizierte musikalische Funktionen zu erstellen. @menu * Displaying music expressions:: * Music properties:: * Doubling a note with slurs (example):: * Adding articulation to notes (example):: @end menu @node Displaying music expressions @subsection Displaying music expressions @cindex interne Speicherung @funindex \displayMusic Wenn man eine musikalische Funktion erstellt, ist es oft hilfreich sich anzuschauen, wie musikalische Funktionen intern gespeichert werden. Das kann mit der Funktion @code{\displayMusic} erreicht werden: @example @{ \displayMusic @{ c'4\f @} @} @end example @noindent zeigt: @example (make-music 'SequentialMusic 'elements (list (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 0 0)) (make-music 'AbsoluteDynamicEvent 'text "f"))))) @end example Normalerweise gibt LilyPond diese Ausgabe auf der Konsole mit allen anderen Nachrichten aus. Um die wichtigen Nachrichten in einer Datei zu speichern, kann die Ausgabe in eine Datei umgeleitet werden: @example lilypond file.ly >display.txt @end example Mit etwas Umformatierung ist die gleiche Information sehr viel einfacher zu lesen: @example (make-music 'SequentialMusic 'elements (list (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 0 0)) (make-music 'AbsoluteDynamicEvent 'text "f"))))) @end example Eine musikalische @code{@{ ... @}}-Sequenz hat die Bezeichnung @code{SequentialMusic} und ihre inneren Ausdrücke werden als Liste in seiner @code{'elements}-Eigenschaft gespeichert. Eine Note ist als als ein @code{EventChord}-Ausdruck dargestellt, der ein @code{NoteEvent}-Objekt (welches Dauer und Tonhöhe speichert) und zusätzliche Information enthält (in diesem Fall ein @code{AbsoluteDynamicEvent} mit einer @code{"f"}-Text-Eigenschaft. @node Music properties @subsection Music properties Das @code{NoteEvent}-Objekt ist das erste Objekt der @code{'elements}-Eigenschaft von @code{someNote}. @example someNote = c' \displayMusic \someNote ===> (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 0 0)))) @end example Die @code{display-scheme-music}-Funktion ist die Funktion, die von @code{\displayMusic} eingesetzt wird, um die Scheme-Repräsentation eines musikalischen Ausdrucks anzuzeigen. @example #(display-scheme-music (first (ly:music-property someNote 'elements))) ===> (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 0 0)) @end example Danach wird die Tonhöhe der Note von der @code{'pitch}-Eigenschaft des @code{NoteEvent}-Objektes gelesen: @example #(display-scheme-music (ly:music-property (first (ly:music-property someNote 'elements)) 'pitch)) ===> (ly:make-pitch 0 0 0) @end example Die Tonhöhe einer Note kann geändert werden, indem man diese @code{'pitch}-Eigenschaft umdefiniert: @funindex \displayLilyMusic @funindex displayLilyMusic @example #(set! (ly:music-property (first (ly:music-property someNote 'elements)) 'pitch) (ly:make-pitch 0 1 0)) ;; Die Tonhöhen auf d' verändern. \displayLilyMusic \someNote ===> d' @end example @node Doubling a note with slurs (example) @subsection Doubling a note with slurs (example) In diesem Abschnitt soll gezeigt, werden, wie man eine Funktion erstellt, die eine Eingabe wie @code{a} nach @code{a( a)} umdefiniert. Dazu wird zuerst die interne Repräsentation der Musik betrachtet, die das Endergebnis darstellt: @example \displayMusic@{ a'( a') @} ===> (make-music 'SequentialMusic 'elements (list (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 5 0)) (make-music 'SlurEvent 'span-direction -1))) (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 5 0)) (make-music 'SlurEvent 'span-direction 1))))) @end example Eine schlechte Nachricht ist, dass die @code{SlurEvent}-Ausdrücke @qq{innerhalb} der Noten (bzw. innerhalb der @code{EventChord}-Ausdrücke) hinzugefügt werden müssen. Jetzt folgt eine Betrachtung der Eingabe: @example (make-music 'SequentialMusic 'elements (list (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 5 0)))))) @end example In der gewünschten Funktion muss also dieser Ausdruck kopiert werden (sodass zwei Noten vorhanden sind, die eine Sequenz bilden), dann müssen @code{SlurEvent} zu der @code{'elements}-Eigenschaft jeder Noten hinzugefügt werden, und schließlich muss eine @code{SequentialMusic} mit den beiden @code{EventChords} erstellt werden. @example doubleSlur = #(define-music-function (parser location note) (ly:music?) "Return: @{ note ( note ) @}. `note' is supposed to be an EventChord." (let ((note2 (ly:music-deep-copy note))) (set! (ly:music-property note 'elements) (cons (make-music 'SlurEvent 'span-direction -1) (ly:music-property note 'elements))) (set! (ly:music-property note2 'elements) (cons (make-music 'SlurEvent 'span-direction 1) (ly:music-property note2 'elements))) (make-music 'SequentialMusic 'elements (list note note2)))) @end example @node Adding articulation to notes (example) @subsection Adding articulation to notes (example) Am einfachsten können Artikulationszeichen zu Noten hinzugefügt werden, indem man zwei musikalische Funktionen in einen Kontext einfügt, wie erklärt in @ref{Creating contexts}. Hier soll jetzt eine musikalische Funktion entwickelt werden, die das vornimmt. Eine @code{$variable} innerhalb von @code{#@{...#@}} ist das gleiche wie die normale Befehlsform @code{\variable} in üblicher LilyPond-Notation. Es ist bekannt dass @example @{ \music -. -> @} @end example @noindent in LilyPond nicht funktioniert. Das Problem könnte vermieden werden, indem das Artikulationszeichen an eine Pseudonote gehängtwird: @example @{ << \music s1*0-.-> @} @end example @noindent aber in diesem Beispiel soll gezeigt werden, wie man das in Scheme vornimmt. Zunächst wird die Eingabe und die gewünschte Ausgabe examiniert: @example % Eingabe \displayMusic c4 ===> (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch -1 0 0)))) ===== % gewünschte Ausgabe \displayMusic c4-> ===> (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch -1 0 0)) (make-music 'ArticulationEvent 'articulation-type "marcato"))) @end example Dabei ist zu sehen, dass eine Note (@code{c4}) als @code{EventChord} repräsentiert ist, mit einem @code{NoteEvent}-Ausdruck in ihrer Elementenliste. Um eine Marcato-Artikulation hinzuzufügen, muss ein @code{ArticulationEvent}-Ausdrcuk zu der Elementeigenschaft des @code{EventChord}-Ausdrucks hinzugefügt werden. Um diese Funktion zu bauen, wird folgerndermaßen begonnen: @example (define (add-marcato event-chord) "Add a marcato ArticulationEvent to the elements of `event-chord', which is supposed to be an EventChord expression." (let ((result-event-chord (ly:music-deep-copy event-chord))) (set! (ly:music-property result-event-chord 'elements) (cons (make-music 'ArticulationEvent 'articulation-type "marcato") (ly:music-property result-event-chord 'elements))) result-event-chord)) @end example Die erste Zeile definiert eine Funktion in Scheme: Die Bezeichnung der Funktion ist @code{add-marcato} und sie hat eine Variable mit der Bezeichnung @code{event-chord}. In Scheme geht der Typ einer Variable oft direkt aus der Bezeichnung hervor (das ist auch eine gute Methode für andere Programmiersprachen). @example "Add a marcato..." @end example @noindent ist eine (englische) Beschreibung, was diese Funktion tut. Sie ist nicht unbedingt notwendig, aber genauso wie klare Variablen-Bezeichnungen ist auch das eine gute Methode. @example (let ((result-event-chord (ly:music-deep-copy event-chord))) @end example @code{let} wird benutzt, um die lokalen Variablen zu definieren. Hier wird eine lokale Variable benutzt: @code{result-event-chord}. Sie erhält den Wert @code{(ly:music-deep-copy event-chord)}. @code{ly:music-deep-copy} ist eine LilyPond-spezifische Funktion, die wie alle Funktionen mit dem Präfix @code{ly:} versehen ist. Sie wird benutzt, um eine Kopie eines musikalischen Ausdrucks anzufertigen. Hier wird @code{event-chord} (der Parameter der Funktion) kopiert. Die Funktion soll ja nur ein Artikulationszeichen an einen @code{EventChord} gehängt werden, deshalb ist es besser, den @code{EventChord}, der als Argument gegeben wurde, nicht zu verändern, weil er woanders benutzt werden könnte. Jetzt gibt es @code{result-event-chord}, wobei es sich um einen @code{NoteEventChord}-Ausdruck handelt, welcher gleichzeigt eine Kopie von @code{event-chord} ist. Das Makro wird seiner Eigenschaftsliste hinzugefügt: @example (set! place new-value) @end example Was in diesem Fall @qq{gesetzt} werden soll (@qq{place}) ist die @q{elements}-Eigenschaft des @code{result-event-chord}-Ausdrucks. @example (ly:music-property result-event-chord 'elements) @end example @code{ly:music-property} ist die Funktion, mit der musikalische Eigenschaften erreicht werden können (die @code{'elements}, @code{'duration}, @code{'pitch} usw., die in der Ausgabe von @code{\displayMusic} weiter oben angezeigt werden). Der neue Wert ist, was ehemals die Elemtneigenschaft war, mit einem zusätzlichen Element: dem @code{ArticulationEvent}-Ausdruck, der aus der Ausgabe von @code{\displayMusic} kopiert werden kann: @example (cons (make-music 'ArticulationEvent 'articulation-type "marcato") (ly:music-property result-event-chord 'elements)) @end example @code{cons} wird benutzt, um ein Element zu einer Liste hinzuzufügen, ohne dass die originale Liste verändert wird. Das ist es, was die Funktion tun soll: die gleiche Liste, aber mit dem neuen @code{ArticulationEvent}-Ausdruck. Die Reihenfolge innerhalb der Elementeeigenschaft ist hier nicht relevant. Wenn schließlich die Marcato-Artikulation zu der entsprechenden @code{elements}-Eigenschaft hinzuzugefügt ist, kann @code{result-event-chord} ausgegeben werden, darum die letzte Zeile der Funktion. Jetzt wird die @code{add-marcato}-Funktion in eine musikalische Funktion umgewandelt: @example addMarcato = #(define-music-function (parser location event-chord) (ly:music?) "Add a marcato ArticulationEvent to the elements of `event-chord', which is supposed to be an EventChord expression." (let ((result-event-chord (ly:music-deep-copy event-chord))) (set! (ly:music-property result-event-chord 'elements) (cons (make-music 'ArticulationEvent 'articulation-type "marcato") (ly:music-property result-event-chord 'elements))) result-event-chord)) @end example Eine Überprüfung, dass die Funktion richtig arbeitet, geschieht folgendermaßen: @example \displayMusic \addMarcato c4 @end example @node Markup programmer interface @section Markup programmer interface Textbeschriftungselemente sind als besondere Scheme-Funktionen definiert, die ein Stencil-Objekt erstellen, dem eine Anzahl an Argumenten übergeben wird. @menu * Markup construction in Scheme:: * How markups work internally:: * New markup command definition:: * New markup list command definition:: @end menu @node Markup construction in Scheme @subsection Markup construction in Scheme @cindex Textbeschriftungsbefehle, definieren @cindex Textbeschriftung, eigene Befehle @cindex eigene Befehle, Textbeschriftung @cindex markup, eigene Befehle @cindex Befehle definieren, Textbeschriftung Das @code{markup}-(Textbeschriftungs)Makro erstellt Textbeschriftungs-Ausdrücke in Scheme, wobei eine LilyPond-artige Syntax benutzt wird. Beispielsweise ist @example (markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world") #:larger #:line ("foo" "bar" "baz"))) @end example @noindent identisch mit @example \markup \column @{ \line @{ \bold \italic "hello" \raise #0.4 "world" @} \larger \line @{ foo bar baz @} @} @end example @noindent Dieses Beispiel zeigt die hauptsächlichen Übersetzungsregeln zwischen normaler Textbeschriftungssyntax von LilyPond und der Textbeschriftungssyntax in Scheme. @quotation @multitable @columnfractions .3 .3 @item @b{LilyPond} @tab @b{Scheme} @item @code{\markup Text1} @tab @code{(markup Text1)} @item @code{\markup @{ Text1 Text2 ... @}} @tab @code{(markup Text1 Text2 ... )} @item @code{\Befehl} @tab @code{#:Befehl} @item @code{\Variable} @tab @code{Variable} @item @code{\center-column @{ ... @}} @tab @code{#:center-column ( ... )} @item @code{Zeichenkette} @tab @code{"Zeichenkette"} @item @code{#scheme-arg} @tab @code{scheme-arg} @end multitable @end quotation Die gesamte Scheme-Sprache ist innerhalb des @code{markup}-Makros zugänglich. Man kann also beispielsweise Funktionen innerhalb eines @code{markup} aufrufen, um Zeichenketten zu manipulieren. Das ist nützlich, wenn neue Beschriftungsbefehle definiert werden sollen (siehe auch @ref{New markup command definition}). @knownissues Das Beschriftungslistenargument von Befehlen wie @code{#:line}, @code{#:center} und @code{#:column} kann keine Variable oder das Resultat eines Funktionsaufrufen sein. @lisp (markup #:line (Funktion-die-Textbeschriftung-ausgibt)) @end lisp @noindent ist ungültig. Man sollte anstatt dessen die Funktionen @code{make-line-markup}, @code{make-center-markup} oder @code{make-column-markup} benutzen: @lisp (markup (make-line-markup (Funktion-die-Textbeschriftung-ausgibt))) @end lisp @node How markups work internally @subsection How markups work internally In einer Textbeschriftung wie @example \raise #0.5 "Textbeispiel" @end example @noindent ist @code{\raise} unter der Haube durch die @code{raise-markup}-Funktion repräsentiert. Der Beschriftungsausdruck wird gespeichert als @example (list raise-markup 0.5 (list simple-markup "Textbeispiel")) @end example Wenn die Beschriftung in druckbare Objekte (Stencils) umgewandelt ist, wir die @code{raise-markup}-Funktion folgendermaßen aufgerufen: @example (apply raise-markup @var{\layout object} @var{Liste der Eigenschafts-alists} 0.5 @var{die "Textbeispiel"-Beschriftung}) @end example Die @code{raise-markup}-Funktion erstellt zunächt den Stencil für die @code{Textbeispiel}-Beschriftung und verschiebt dann diesen Stencil um 0.5 Notenlinienzwischenräume nach oben. Das ist ein einfaches Beispiel. Weitere, kompliziertere Beispiele finden sich nachfolgend in diesem Abschnitt und in der Datei @file{scm/@/define@/-markup@/-commands@/.scm}. @node New markup command definition @subsection New markup command definition Neue Textbeschriftungsbefehle können mit dem @code{define-markup-command}-Scheme-Makro definiert werden. @lisp (define-markup-command (@var{befehl-bezeichnung} @var{layout} @var{props} @var{arg1} @var{arg2} ...) (@var{arg1-type?} @var{arg2-type?} ...) ..Befehlkörper..) @end lisp Die Argumente sind: @table @var @item argi @var{i}te Befehlsargument @item argi-type? eine Eigenschaft für das @var{i}te Argument @item layout die @q{layout}-Definition @item props eine Liste an alists, in der alle aktiven Eigenschaften enthalten sind @end table Als einfaches Beispiel soll gezeigt werden, wie man einen @code{\smallcaps}-Befehl hinzufügen kann, der die Kapitälchen für die Schriftzeichen auswählt. Normalerweise würde man Kapitälchen folgendermaßen auswählen: @example \markup @{ \override #'(font-shape . caps) Text-in-Kapitälchen @} @end example @noindent Damit wird die Kapitälchenschriftart ausgewählt, indem die @code{font-shape}-Eigesnchaft auf @code{#'caps} gesetzt wird, während @code{Text-in-caps} interpretiert wird. Damit diese Funkion als @code{\smallcaps}-Befehl zur Verfügung gestellt werden kann, muss eine Funktion mit @code{define-markup-command} definiert werden. Der Befehl braucht ein Argument vom Typ @code{markup}. Darum sollte der Beginn der Funktion lauten: @example (define-markup-command (smallcaps layout props argument) (markup?) @end example @noindent Was jetzt folgt, ist der eigentliche Inhalt des Befehls: das @code{argument} soll als Beschriftung (markup) interpretiert werden, also: @example (interpret-markup layout @dots{} argument) @end example @noindent Diese Interpretation sollte @code{'(font-shape . caps)} zu den aktiven Eigenschaften hinzufügen, weshalb wir das Folgende anstelle der @dots{} in dem Beispiel einfügen: @example (cons (list '(font-shape . caps) ) props) @end example @noindent Die Variable @code{props} ist eine Liste an alists, und mit @code{cons} wird ihr eine zusätzliche Einstellung hinzugefügt. Man könnte sich auch vorstellen, dass ein Rezitativ einer Oper gesetzt werden soll, und ein Befehl wäre sehr bequem, mit dem man die Namen der Charaktere auf eine eigene Art darstellen könnte. Namen sollen in Kapitälchen gesetzt werden und etwas nach links und oben verschoben werden. Man kann also einen @code{\character}-Befehl definieren, der die nötige Verschiebung berücksichtigt und den neuen @code{\smallcaps}-Befehl einsetzt: @example #(define-markup-command (character layout props name) (string?) "Print the character name in small caps, translated to the left and top. Syntax: \\character #\"name\"" (interpret-markup layout props (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name))) @end example Hier ist eine Komplikation, die erklärt werden muss: Text über oder unter dem Notensystem wird vertikal verschoben um in einem bestimmten Abstand von dem System und den Noten zu sein (das wird als @qq{padding} bezeichnet). Um sicherzugehen, dass dieser Mechanismus nicht die vertikale Verschiebung von @code{#:translate} annulliert, wird die leere Zeichenkette (@code{#:hspace 0}) vor den zu verschiebenden Text gesetzt. Das @code{#:hspace 0} wird jetzt also über die Noten gesetzt und @code{name} dann relativ zu der leeren Zeichenkette verschoben. Im Endeffekt wird der Text nach links oben verschoben. Das Resultat sieht folgendermaßen aus: @example @{ c''^\markup \character #"Cleopatra" e'^\markup \character #"Giulio Cesare" @} @end example @lilypond[quote,ragged-right] #(define-markup-command (smallcaps layout props str) (string?) "Print the string argument in small caps. Syntax: \\smallcaps #\"string\"" (interpret-markup layout props (make-line-markup (map (lambda (s) (if (= (string-length s) 0) s (markup #:large (string-upcase (substring s 0 1)) #:translate (cons -0.6 0) #:tiny (string-upcase (substring s 1))))) (string-split str #\Space))))) #(define-markup-command (character layout props name) (string?) "Print the character name in small caps, translated to the left and top. Syntax: \\character #\"name\"" (interpret-markup layout props (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name))) { c''^\markup \character #"Cleopatra" c'' c'' c'' e'^\markup \character #"Giulio Cesare" e' e' e' } @end lilypond In diesen Befehlen wurden Kapitälchen eingesetzt, aber es kann vorkommen, dass die Schriftart keine Kapitälchen zur Verfügung stellt. In diesem Fall können die Kapitälchen nachempfunden werden, indem man Großbuchstaben setzt, deren Anfangsbuchstabe etwas größer gesetzt wird: @example #(define-markup-command (smallcaps layout props str) (string?) "Print the string argument in small caps." (interpret-markup layout props (make-line-markup (map (lambda (s) (if (= (string-length s) 0) s (markup #:large (string-upcase (substring s 0 1)) #:translate (cons -0.6 0) #:tiny (string-upcase (substring s 1))))) (string-split str #\Space))))) @end example Der @code{smallcaps}-Befehl spaltet die Argumente zuerst in Einzelstücke auf, die von Leerzeichen getrennt sind (@code{(string-split str #\Space)}); für jedes Einzelstück wird dann eine Beschriftung aufgebaut, deren erster Buchstabe vergrößert wird und als Versalbuchstabe gesetzt wird (@code{#:large (string-upcase (substring s 0 1))}), und eine zweite Versalbuchstaben gesetzt werden (@code{#:tiny (string-upcase (substring s 1))}). Wenn LilyPond ein Leerzeichen zwischen Beschriftungen einer Zeile entdeckt, wird die zweite Beschriftung nach links verschoben (@code{#:translate (cons -0.6 0) ...}). Dann werden die Beschriftungen für jedes Einzelstück in eine Zeile gesetzt @code{(make-line-markup ...)}. Schließlich wird die resultierende Beschriftung an die @code{interpret-markup}-Funktion zusammen mit den Argumenten @code{layout} und @code{props} weitergereicht. Achtung: ist gibt keinen internen Befehl @code{\smallCaps}, der benutzt werden kann, um Text in Kapitälchen zu setzen. Siehe auch @ref{Text markup commands}. @knownissues Im Moment sind die möglichen Kombinationen von Argumenten (nach den Standardargumenten @var{layout} und @var{props}), die mit @code{define-markup-command} definiert werden, wie folgt limitiert: @table @asis @item (kein Argument) @itemx @var{list} @itemx @var{markup} @itemx @var{markup markup} @itemx @var{scm} @itemx @var{scm markup} @itemx @var{scm scm} @itemx @var{scm scm markup} @itemx @var{scm scm markup markup} @itemx @var{scm markup markup} @itemx @var{scm scm scm} @end table @noindent Hier stellt @var{scm} native Scheme-Datentypen dar wie @q{number} oder @q{string}. Es ist beispielsweise nicht möglich, einen Beschriftungsbefehl @code{foo} mit vier Argumenten in folgender Weise zu nutzen: @example #(define-markup-command (foo layout props num1 str1 num2 str2) (number? string? number? string?) ...) @end example @noindent Wenn es folgendermaßen eingesetzt wird: @example \markup \foo #1 #"bar" #2 #"baz" @end example @cindex Scheme signature @cindex Signatur, Scheme @noindent beschwert sich @command{lilypond}, dass @code{foo} wegen einer ungekannten Scheme Signatur nicht analysiert werden kann. @node New markup list command definition @subsection New markup list command definition Beschriftungslistenbefehle können mit dem Scheme-Makro @code{define-markup-list-command} definiert werden, welches sich ähnlich verhält wie das @code{define-markup-command}-Makro, das schon beschrieben wurde in @ref{New markup command definition}. Ein Unterschied ist, dass bei diesem Listen-Makro eine ganze Liste an Stecils ausgegeben wird. Im folgenden Beispiel wird ein @code{\paragraph}-Beschriftungslistenbefehl definiert, welcher eine Liste von Zeilen im Blocksatz ausgibt, von denen die erste Zeile eingerückt ist. Der Einzug wird aus dem @code{props}-Argument entnommen. @example #(define-markup-list-command (paragraph layout props args) (markup-list?) (let ((indent (chain-assoc-get 'par-indent props 2))) (interpret-markup-list layout props (make-justified-lines-markup-list (cons (make-hspace-markup indent) args))))) @end example Neben den üblichen @code{layout} und @code{props}-Argumenten, nimmt der @code{paragraph}-Beschriftungslistenbefehl als Argument eine Beschriftungsliste, die @code{args} genannt wird. Das Prädikat für Beschriftungslisten ist @code{markup-list?}. Zuerst errechnet die Funktion die Breite des Einzugs, eine Eigenschaft mit der Bezeichnung @code{par-indent} anhand der Eigenschaftsliste @code{props}. Wenn die Eigenschaft nicht gefunden wird, ist der Standardwert @code{2}. Danach wird eine Liste von Zeilen im Blocksatz erstellt, wobei die @code{make-justified-lines-markup-list}-Funktion eingesetzt wird, die verwandt ist mit dem eingebauten @code{\justified-lines}-Beschriftungslistenbefehl. Horizontaler Platz wird zu Beginn eingefügt mit der @code{make-hspace-markup}-Funktion. Zuletzt wird die Beschriftungsliste ausgewertet durch die @code{interpret-markup-list}-Funktion. Dieser neue Beschriftungslistenbefehl kann wie folgt benutzt werden: @example \markuplines @{ \paragraph @{ Die Kunst des Notensatzes wird auch als \italic @{Notenstich@} bezeichnet. Dieser Begriff stammt aus dem traditionellen Notendruck. Noch bis vor etwa 20 Jahren wurden Noten erstellt, indem man sie in eine Zink- oder Zinnplatte schnitt oder mit Stempeln schlug. @} \override-lines #'(par-indent . 4) \paragraph @{ Diese Platte wurde dann mit Druckerschwärze versehen, so dass sie in den geschnittenen und gestempelten Vertiefungen blieb. Diese Vertiefungen schwärzten dann ein auf die Platte gelegtes Papier. Das Gravieren wurde vollständig von Hand erledigt. @} @} @end example @node Contexts for programmers @section Contexts for programmers @menu * Context evaluation:: * Running a function on all layout objects:: @end menu @node Context evaluation @subsection Context evaluation @cindex Aufrufen von Code während der Interpretation @cindex On-the-fly Code ausführen @funindex \applyContext Kontexte können während ihrer Interpretation mit Scheme-Code modifiziert werden. Die Syntax hierfür ist @example \applyContext @var{function} @end example @var{function} sollte eine Scheme-Funktion sein, die ein einziges Argument braucht, welches der Kontext ist, auf den sie ausgeführt werden soll. Der folgende Code schreibt die aktuelle Taktzahlshould in die Standardausgabe während der Kompilation. @example \applyContext #(lambda (x) (format #t "\nWe were called in barnumber ~a.\n" (ly:context-property x 'currentBarNumber))) @end example @node Running a function on all layout objects @subsection Running a function on all layout objects @cindex Aufruf von Code für Layoutobjekte @funindex \applyOutput Der vielfältigste Weg, ein Objekt zu beeinflussen, ist @code{\applyOutput}. Die Syntax lautet: @example \applyOutput @var{Kontext} @var{proc} @end example @noindent wobei @var{proc} eine Scheme-Funktion ist, die drei Argumente benötigt. Während der Interpretation wird die Funktion @var{proc} für jedes Layoutobjekt aufgerufen, dass im Kontext @var{Kontext} vorgefunden wird, und zwar mit folgenden Argumenten: @itemize @item dem Layoutobjekt @item dem Kontext, in dem das Objekt erstellt wurde @item dem Kontext, in welchem @code{\applyOutput} bearbeitet wird. @end itemize Zusätzlich findet sich der Grund für das Layoutobjekt, etwa der musikalische Ausdruck oder das Objekt, das für seine Erstellung verantwortlich war, in der Objekteigenschaft @code{cause}. Für einen Notenkopf beispielsweise ist das ein @rinternals{NoteHead}-Ereignis, und für einen Notenhals (ein @rinternals{Stem}-Objekt) ist es ein @rinternals{NoteHead}-Objekt. Hier ist eine Funktion, die mit @code{\applyOutput} benutzt werden kann; sie macht Notenköpfe auf der Mittellinie unsichtbar: @example (define (blanker grob grob-origin context) (if (and (memq (ly:grob-property grob 'interfaces) note-head-interface) (eq? (ly:grob-property grob 'staff-position) 0)) (set! (ly:grob-property grob 'transparent) #t))) @end example @node Scheme procedures as properties @section Scheme procedures as properties Eigenschaften (wie Dicke, Richtung usw.) können mit @code{\override} auf feste Werte gesetzt werden, etwa: @example \override Stem #'thickness = #2.0 @end example Eigenschaften können auch auf eine Scheme-Prozedur gesetzt werden: @lilypond[fragment,verbatim,quote,relative=2] \override Stem #'thickness = #(lambda (grob) (if (= UP (ly:grob-property grob 'direction)) 2.0 7.0)) c b a g b a g b @end lilypond @noindent In diesem Fall wird die Prozedur ausgeführt, sobal der Wert der Eigenschaft während das Formatierungsprozesses angefordert wird. Der größte Teil der Satzmaschinierie funtioniert mit derartigen Callbacks. Eigenschaften, die üblicherweise Callbacks benutzen, sind u. A.: @table @code @item stencil Die Druckfunktion, die eine Ausgabe des Symbols ervorruft @item X-offset Die Funktion, die die horizontale Position setzt @item X-extent Die Funktion, die die Breite eines Objekts errechnet @end table Die Funktionen brauchen immer ein einziges Argument, das der Grob ist. Wenn Funktionen mit mehreren Argumenten aufgerufen werden müssen, kann der aktuelle Grob mit einer Grob-Einschließung eingefügt werden. Hier eine Einstellung aus @code{AccidentalSuggestion}: @example (X-offset . ,(ly:make-simple-closure `(,+ ,(ly:make-simple-closure (list ly:self-alignment-interface::centered-on-x-parent)) ,(ly:make-simple-closure (list ly:self-alignment-interface::x-aligned-on-self))))) @end example @noindent In diesem Beispiel werden sowohl @code{ly:self-alignment-interface::x-aligned-on-self} als auch @code{ly:self-alignment-interface::centered-on-x-parent} mit dem Grob als Argument aufgerufen. Die Resultate werden mit der @code{+}-Funktion addiert. Um sicherzugehen, dass die Addition richtig ausgeführt wird, wird das ganze Konstrukt in @code{ly:make-simple-closure} eingeschlossen. In der Tat ist die Benutzung einer einzelnen Funktion als Eigenschaftswert äquivalent zu @example (ly:make-simple-closure (ly:make-simple-closure (list @var{proc}))) @end example @noindent Das innere @code{ly:make-simple-closure} stellt den Grob als Argument für @var{proc} zur Verfügung, das äußere stellt sicher, dass das Resultat der Funktion ausgegeben wird und nicht das @code{simple-closure}-Objekt. @node Using Scheme code instead of \tweak @section Using Scheme code instead of @code{\tweak} Der hauptsächliche Nachteil von @code{\tweak} ist seine syntaktische Inflexibilität. Folgender Code beispielsweise ergibt einen Syntaxfehler: @example F = \tweak #'font-size #-3 -\flageolet \relative c'' @{ c4^\F c4_\F @} @end example @noindent Anders gesagt verhält sich @code{\tweak} nicht wie eine Artikulation und kann auch nicht deren Syntax verwenden: man kann es nicht mit @code{^} oder @code{_} anfügen. Durch die Verwendung von Scheme kann dieses Problem umgangen werden. Der Weg zum Resultat wird gezeigt in @ref{Adding articulation to notes (example)}, insbesondere wie @code{\displayMusic} benutzt wird, hilft hier weiter. @example F = #(let ((m (make-music 'ArticulationEvent 'articulation-type "flageolet"))) (set! (ly:music-property m 'tweaks) (acons 'font-size -3 (ly:music-property m 'tweaks))) m) \relative c'' @{ c4^\F c4_\F @} @end example @noindent In diesem Beispiel werden die @code{tweaks}-Eigenschaften des Flageolet-Objekts @code{m} (mit @code{make-music} erstellt) werden mit @code{ly:music-property} ausgelesen, ein neues Schlüssel-Wert-Paar, um die Schriftgröße zu ändern, wird der Eigenschaftenliste mithilfe der @code{acons}-Schemefunktion vorangestellt, und das Resultat wird schließlich mit @code{set!} zurückgeschrieben. Das letzte Element des @code{let}-Blocks ist der Wiedergabewert, @code{m}. @node Difficult tweaks @section Difficult tweaks Hier finden sich einige Klassen an schwierigeren Anpassungen. @itemize @item Ein Typ der schwierigen Anpassungen ist die Erscheinung von Strecker-Objekten wie Binde- oder Legatobögen. Zunächst wird nur eins dieser Objekte erstellt, und sie können mit dem normalen Mechanismus verändert werden. In einigen Fällen reichen die Strecker jedoch über Zeilenumbrüche. Wenn das geschieht, werden diese Objekte geklont. Ein eigenes Objekt wird für jedes System erstellt, in dem es sich befindet. Sie sind Klone des originalen Objektes und erben alle Eigenschaften, auch @code{\override}-Befehle. Anders gesagt wirkt sich ein @code{\override} immer auf alle Stücke eines geteilten Streckers aus. Um nur einen Teil eines Streckers bei einem Zeilenumbruch zu verändern, ist es notwendig, in den Formatierungsprozess einzugreifen. Das Callback @code{after-line-breaking} enthält die Schemefunktion, die aufgerufen wird, nachdem Zeilenumbrüche errechnet worden sind und die Layout-Objekte über die unterschiedlichen Systeme verteilt wurden. Im folgenden Beispiel wird die Funktion @code{my-callback} definiert. Diese Funktion @itemize @item bestimmt, ob das Objekt durch Zeilenumbrüche geteilt ist, @item wenn ja, ruft sie alle geteilten Objekte auf, @item testet, ob es sich um das letzte der geteilten Objekte handelt, @item wenn ja, wird @code{extra-offset} gesetzt. @end itemize Diese Funktion muss in @rinternals{Tie} (Bindebogen) installiert werden, und der letzte Teil eines gebrochenen Bindebogens wird nach oben verschoben. @lilypond[quote,verbatim,ragged-right] #(define (my-callback grob) (let* ( ; have we been split? (orig (ly:grob-original grob)) ; if yes, get the split pieces (our siblings) (siblings (if (ly:grob? orig) (ly:spanner-broken-into orig) '() ))) (if (and (>= (length siblings) 2) (eq? (car (last-pair siblings)) grob)) (ly:grob-set-property! grob 'extra-offset '(-2 . 5))))) \relative c'' { \override Tie #'after-line-breaking = #my-callback c1 ~ \break c2 ~ c } @end lilypond @noindent Wenn man diesen Trick anwendet, sollte das neue @code{after-line-breaking} auch das alte @code{after-line-breaking}-Callback aufrufen, wenn es vorhanden ist. Wenn diese Funktion etwa mit @code{Hairpin} (Crescendo-Klammer) eingesetzt wird, sollte auch @code{ly:hairpin::after-line-breaking} aufgerufen werden. @item Manche Objekte können aus technischen Gründen nicht mit @code{\override} verändert werden. Beispiele hiervon sind @code{NonMusicalPaperColumn} und @code{PaperColumn}. Sie können mit der @code{\overrideProperty}-Funktion geändert werden, die ähnlich wie @code{\once \override} funktioniert, aber eine andere Syntax einsetzt. @example \overrideProperty #"Score.NonMusicalPaperColumn" % Grob-Bezeichnung #'line-break-system-details % Eigenschaftsbezeichnung #'((next-padding . 20)) % Wert @end example Es sollte angemerkt werden, dass @code{\override}, wenn man es auf @code{NonMusicalPaperColumn} und @code{PaperColumn} anwendet, immernoch innerhalb der @code{\context}-Umgebung funktioniert. @end itemize