@c -*- coding: utf-8; mode: texinfo; -*- @ignore Translation of GIT committish: e5a609e373eae846857f9a6d70a402a3d42b7d94 When revising a translation, copy the HEAD committish of the version that you are working on. For details, see the Contributors' Guide, node Updating translation committishes.. @end ignore @c \version "2.17.6" @c Translators: Till Paala @node Schnittstellen für Programmierer @chapter Schnittstellen für Programmierer @translationof 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 @ref{Scheme-Übung}. @menu * LilyPond-Codeabschnitte:: * Scheme-Funktionen:: * Musikalische Funktionen:: * Ereignisfunktionen:: * Textbeschriftungsfunktionen:: * Kontexte für Programmierer:: * Callback-Funktionen:: * Scheme-Code innerhalb LilyPonds:: * Schwierige Korrekturen:: @end menu @node LilyPond-Codeabschnitte @section LilyPond-Codeabschnitte @translationof Lilypond code blocks Codeabschnitte in LilyPond sehen etwa so aus: @example #@{ @var{Lilypond code} #@} @end example Sie können überall eingesetzt werden, wo man Scheme-Code schreiben kann: der Scheme-Einleser wurde geändert, um LilyPond-Codeabschnitte zu akzeptieren und kann mit eingebetteten Scheme-Ausdrücken umgehen, die mit @code{$} und@w{ }@code{#} beginnen. Er extrahiert den LilyPond-Codeabschnitt und erstellt einen Aufruf zum LilyPond-Parser, welcher während der Prorammausführung zur Interpretation des LilyPond-Codeabschnittes aufgerufen wird. Alle eingebetteten Scheme-Ausdrücke werden in der lokalen Umgebung des LilyPond-Codeabschnittes ausgeführt, sodass man Zugruff auf lokale Variablen und Funktionsparameter zu dem Zeitpunkt hat, an dem der LilyPond-Codeabschnitt geschrieben wird. Ein LilyPond-Codeabschnitt kann jeden Inhalt haben, den man auf der rechten Seite einer Zuweisung einsetzt. Zusätzlich entspricht ein leerer LilyPond-Abschnitt einem gültigen musikalischen Ausdruck, und ein LilyPond-Abschnitt, der mehrere musikalische Ereignisse enthält, wird in einen sequenziellen musikalischen Ausdruck umgewandelt. @node Scheme-Funktionen @section Scheme-Funktionen @translationof Scheme functions @cindex Scheme-Funktionen (LilyPond syntax) @emph{Scheme-Funktionen} sind Scheme-Prozeduren, die Scheme-Ausdrücke aus einer Eingabe erstellen können, die in LilyPond-Syntax geschrieben wurde. Sie können in so gut wie allen Fällen aufgerufen werden, in denen es erlaubt ist, @code{#} zur Angabe eines Wertes in Scheme-Syntax einzusetzen. Während Scheme auch eigene Funktionen besitzt, handelt % dieses kapitel von @emph{syntaktischen} Funktionen, Funktionen, die Argumente in LilyPond-Syntax annehmen. @menu * Definition von Scheme-Funktionen:: * Benutzung von Scheme-Funktionen:: * Leere Scheme-Funktionen:: @end menu @node Definition von Scheme-Funktionen @subsection Definition von Scheme-Funktionen @translationof Scheme function definitions @funindex define-scheme-function Die übliche Form zur Definition von Scheme-Funktionen ist: @example function = #(define-scheme-function (parser location @var{Arg1} @var{Arg2} @dots{}) (@var{Typ1?} @var{Typ2?} @dots{}) @var{body}) @end example @noindent wobei @multitable @columnfractions .33 .66 @item @code{parser} @tab ganz genau das Wort @code{parser} sein muss, damit LilyPond eine Umgebung (@code{#@{}@dots{}@code{#@}}) mit Zugriff auf den Parser bekommt. @item @code{@var{ArgN}} @tab @var{n}te Argument @item @code{@var{TypN?}} @tab eine Scheme-@emph{Typenprädikat}, für welches @code{@var{argN}} @code{#t} ausgeben muss. Manche dieser Prädikate werden vom Parser besonders erkannt, siehe unten. Es gibt auch eine Spezialform @code{(@emph{predicate?} @emph{default})}, um optionale Argumente anzugeben. Wenn das eigentlich Argument fehlt, während die Funktion aufgerufen wird, wird der Standardwert anstelle eingesetzt. Standardwerte werden bei ihrer Definition evaluiert (gilt auch für LilyPond-Codeabschnitte), so dass man besser einen speziellen Wert schreibt, den man einfach erkennen kann, wenn der Wert während der Ausführung der Position evaluiert weren soll. Wenn man das Prädikat in Klammern setzt, aber kein Standardwert folt, wird @code{#f} als Standard eingesetzt. Standardwerte werden weder bei der Definition noch bei der Ausführung mit @emph{predicate?} verifiziert, sodass man selber verantworlich für funktionsfähige Werte ist. Standardwerte, die musikalische Ausdrücke darstellen, werden kopiert und @code{origin} auf den Parameter @code{location} gesetzt. @item @code{@var{body}} @tab Eine Folge von Scheme-Formeln, die der Reihe nach ausgewertet werden, wobei die letzte als Ausgabewert der Scheme-Funktion eingesetzt wird. Sie kann LilyPond-Codeabschnitte enthalten, eingeschlossen mit Raute-Klammern (@tie{}@w{@code{#@{@dots{}#@}}}@tie{}), wie beschrieben in @ref{LilyPond-Codeabschnitte}. Innerhalb von LilyPond-Codeabschnitten wird mit @code{#} auf Funktionsargumente (etwa @samp{#Arg1}) verwiesen oder ein neuer Scheme-Ausdruck mit Funktionsargumenten begonnen (etwa @w{@samp{#(cons Arg1 Arg2)}}). Wo normale Scheme-Ausdrücke mit @code{#} nicht funktionieren, kann man auf direkte Scheme-Ausdrücke zurückgreifen, die mit @code{$} begonnen werden (etwa @samp{$music}). Wenn die Funktion eine musikalische Funktion ausgibt, bekommt sie einen Wert von @code{origin}. zugewiesen. @end multitable @noindent Einige Typenprädikate werden vom Parser besonders behandelt, weil er sonst die Argumente nicht zuverlässig erkennen könnte. Im Moment handelt es sich um @code{ly:pitch?} und @code{ly:duration?}. Die Eignung der Argumente für alle anderen Prädikate wird festgestellt, indem das Prädikat aufgerufen wird, nachdem LilyPond es schon in einen Scheme-Ausdruck umgewandelt hat. Demzufolge kann das Argument in Scheme-Syntax angegeben werden, wenn nötig (beginnend mit @code{#} oder als Result des Aufrufes einer Scheme-Funktion), aber LilyPond konvertiert auch eine Reihe von LilyPond-Strukturen nach Scheme, bevor dann tatsächlich die Prädikate überprüft werden. Bei den letzteren handelt es sich im Moment um music (Noten), postevents, simple strings (einfache Zeichenketten mit oder ohne Anführungszeichen) numbers (Zahlen), markup (Beschriftung) und markup lists (Beschriftungslisten), score (Partitur), book (Buch), bookpart (Buchteil), Kontextdefinitions- und Ausgabedefinitionsumgebungen. Für einige Arten von Ausdrücken (wie die meisten Noten, die nicht in Klammern geschrieben werden) muss LilyPond weiter nach vorne schauen als der Ausdruck selber reicht, um das Ende des Ausdrucks zu bestimmen. Wenn solche Ausdrücke für optionale Argumente mit einbezogen würden, indem ihre Prädikate ausgewählt würden, könnte LilyPond nicht mehr zurückgehen, wenn es feststellt, dass der Ausdruck nicht zu dem Parameter passt. Darum müssen manche Formen von Noten möglicherweise in Klammern eingeschlossen werden, damit LilyPond sie akzeptiert. Es gibt auch einige andere Mehrdeutigkeiten, die LilyPond durch Testen von Prädikatfunktionen eingrenzt: ist etwa @samp{-3} die Anmerkung für einen Fingersatz oder eine negative Zahl? Ist @code{"a" 4} im Gesangskontext eine Zeichenkette gefolgt von einer Zahl oder ein Gesangstextereignis mit der Dauer @code{4}? LilyPond entscheidet, indem es Prädaikate befragt. Das heißt, dass man zu durchlässige Prädikate wie @code{scheme?} vermeiden sollte, wenn man eine bestimmmte Verwendung beabsichtigt und nicht nur eine Funktion für die allgemeine Verwendung schreibt. Eine Liste der möglichen vordefinierten Typenprädikte findet sich in @ruser{Vordefinierte Typenprädikate}. @seealso Notationsreferenz @ruser{Vordefinierte Typenprädikate}. Installierte Dateien: @file{lily/music-scheme.cc}, @file{scm/c++.scm}, @file{scm/lily.scm}. @node Benutzung von Scheme-Funktionen @subsection Benutzung von Scheme-Funktionen @translationof Scheme function usage Scheme-Funktionen können überall aufgerufen werden, wo ein Scheme-Ausdruck beginnend mit @code{#} geschrieben werden kann. Man kann eine Scheme-Funktion aufrufen, indem man ihrer Bezeichnung @code{\} voranstellt und Argumente hinten anfügt. Wenn ein optionales Argumentenprädikat nicht mit einem Argument übereinstimmt, lässt LilyPond dieses und alle folgenden Argumente aus und ersetzt sie durch ihre Standardwerte und @qq{speichert} das Argument, das nicht gepasst hat, bis zum nächsten zwingenden Argument. Da das gespeicherte Argument auch noch irgendwo untergebracht werden muss, werden optionale Argumente nicht wirklich als optional angesehen, es sei denn, sie werden von einem zwingenden Argument gefolgt. Es gibt eine Ausnahme: Wenn man @code{\default} anstelle eines optionalen Arguments schreibt, wird dieses und alle folgenden Argumente ausgelassen und durch ihre Standardwerte ersetzt. Das funktioniert auch, wenn kein zwingendes Argument folgt, weil @code{\default} nicht gespeichert werden muss. Die Befehle @code{mark} und @code{key} benützten diesen Trick, um ihr Standardverhalten zur verfügung zu stellen, wenn sie @code{\default} nachgestellt haben. Abgesehen von Stellen, wo ein Scheme-Wert benötigt ist, gibt es wenige Stellen, wo @code{#}-Ausdrücke zwar für ihre (Neben-)Wirkung akzeptiert und ausgewertet, aber ansonsten ignoriert werden. Meistens handelt es sich dabei um Stellen, wo eine Zuweisung auch in Ordnung wäre. Weil es eine schlechte Idee ist, einen Wert auszugeben, der in einigen Kontexten misinterpretiert werden könnte, sollte man Scheme-Funktionen nur in den Fällen benutzen, in welchen sie immer einen sinnvollen Wert ausgeben, und leere Scheme-Funktionen an anderen stellen einsetzen. Siehe auch @pxref{Leere Scheme-Funktionen}. @node Leere Scheme-Funktionen @subsection Leere Scheme-Funktionen @translationof Void scheme functions @funindex define-void-function @funindex \void Manchmal wird eine Prozedur ausgeführt, um eine Aktion zu machen und nicht, um einen Wert auszugeben. Einige Programmiersprachen (wie C oder Scheme) setzen Funktionen für beide Konzepte ein und verwerfen einfach den Rückgabewert (normalerweise, indem einem Ausdruck erlaubt wird, als Aussage zu funktionieren und das Ergebnis ignoriert wird). Das ist klug, aber auch fehleranfällig: die meisten C-Kompilierer haben heutzutage Warnungen für verschiedene nicht-@qq{gültige} Ausdrücke, die verworfen werden. Viele Funktionen, die eine Aktion ausführen, werden von den Scheme-Standards als Funktionen betrachtet, deren Wiedergabewert unspezifiert ist. Der Scheme-Interpreter von LilyPond, Guile, hat den eindeutigen Wert @code{*unspecified*}, der normalerweise (etwa wenn man @code{set!} direkt auf eine Variable anwendet), aber leider nicht konsistent in diesen Fällen ausgegeben wird. Indem man eine LilyPond-Funktion mit @code{define-void-function} definiert, geht man sicher, dass dieser Spezialwert (der einzige Wert, der das Prädikat @code{void?} erfüllt) wiedergegeben wird. @example noPointAndClick = #(define-void-function (parser location) () (ly:set-option 'point-and-click #f)) ... \noPointAndClick % Point and Click deaktivieren @end example Wenn man einen Ausdruck nur wegen seiner Nebeneffekte evaluieren will und keinen der möglicherweise ausgegebenen Werte interpretiert haben will, kann man dem Ausdruck @code{\void} voranstellen: @example \void #(hashq-set! eine-Tabelle ein-Schlüssel ein-Wert) @end example Auf diese Weise kann man sicher sein, dass LilyPond dem ausgegebenen Wert keine Bedeutung zuweist, unabhängig davon, wo er angetroffen wird. Das funktioniert auch für musikalische Funktionen wie @code{\displayMusic}. @node Musikalische Funktionen @section Musikalische Funktionen @translationof Music functions @cindex musikalische Funktionen @emph{Musikalische Funktionen} sind Scheme-Prozeduren, die musikalische Ausdrücke automatisch erstellen können und dadurch die Eingabedatei maßgeblich vereinfachen können. @menu * Definition der musikalischen Funktionen:: * Benutzung von musikalischen Funktionen:: * Einfache Ersetzungsfunktionen:: * Mittlere Ersetzungsfunktionen:: * Mathematik in Funktionen:: * Funktionen ohne Argumente:: * Leere musikalische Funktionen:: @end menu @node Definition der musikalischen Funktionen @subsection Definition der musikalischen Funktionen @translationof Music function definitions Die allgemeine Form zur Definition musikalischer Funktionen ist: @example function = #(define-music-function (parser location @var{Arg1} @var{Arg2} @dots{}) (@var{Typ1?} @var{Typ2?} @dots{}) @var{body}) @end example @noindent analot zu Scheme-Funktionen, siehe @ref{Definition von Scheme-Funktionen}. In der Mehrzahl der Fälle ist @var{body} ein LilyPond-Codeabschnitt (siehe @ref{LilyPond-Codeabschnitte}. Eine Liste der möglichen Typenprädikate findet sich in @ruser{Vordefinierte Typenprädikate}. @seealso Notationsreferenz: @ruser{Vordefinierte Typenprädikate}. Installierte Dateien: @file{lily/music-scheme.cc}, @file{scm/c++.scm}, @file{scm/lily.scm}. @node Benutzung von musikalischen Funktionen @subsection Benutzung von musikalischen Funktionen @translationof Music function usage Musikalische Funktionen können zur Zeit an verschiedenen Stellen benützt werden. Abhängig davon, wo sie eingesetzt werden, gibt es Begrenzungen, damit die Funktionen eindeutig interpretiert werden können. Das Resultat, das eine musikalische Funktion wiedergibt, muss mit dem Kontext kompatibel sein, indem sie aufgerufen wird. @itemize @item Auf höchster Ebene in einer musikalischen Funktion. Keine Begrenzungen. @item Als ein Nach-Ereignis, explizit begonnen mit einem Richtungsindikator (einer von @code{-}, @code{^}, @w{und @code{_}}). Wichtig dabei ist, dass musikalische Funktionen, die das Nachereignis ausgeben, als normale Noten akzeptiert werden. Dabei erhält man ein Resultat, das etwa folgendem entspricht: @example s 1*0-\fun @end example In diesem Fall kann man keinen @emph{offenen} musikalischen Ausdruck als letztes Argument einsetzen, also ein Argument, das in einem musikalischen Ausdruck schließt, der weitere Nach-Ereignisse akzeptieren kann. @item Als Element eines Akkordes. Der ausgegebene Ausdruck muss vom Typ @code{rhythmic-event} sein, wahrscheinlich auch @code{NoteEvent}. @end itemize @noindent Die besonderen Regeln für noch nicht abgearbeitete Argumente machen es möglich, polymorphe Funktionen wie @code{\tweak} zu schreiben, die auf unterschiedliche Konstruktionen angewendet werden können. @node Einfache Ersetzungsfunktionen @subsection Einfache Ersetzungsfunktionen @translationof Simple substitution functions Einfache Ersetzungsfunktionen sind musikalische Funktionen, deren musikalische Ausgabe-Funktion im LilyPond-Format geschrieben ist und Funktionsargumente in der Ausgabefunktion enthält. Sie werden beschrieben in @ruser{Beispiele der Ersetzungsfunktionen} @node Mittlere Ersetzungsfunktionen @subsection Mittlere Ersetzungsfunktionen @translationof Intermediate substitution functions Mittlere Ersetzungsfunktionen setzen sich aus einer Mischung von Scheme-Code und LilyPond-Code in der musikalischen Ausgabe-Funktion zusammen. Einige @code{\override}-Befehle benötigen ein Zahlenpaar (als @code{cons}-Zelle in Scheme bezeichnet). Das Paar kann direkt an die musikalische Funktion mit der Variable @code{pair?} weitergeleitet werden: @example manualBeam = #(define-music-function (parser location beg-end) (pair?) #@{ \once \override Beam.positions = #beg-end #@}) \relative c' @{ \manualBeam #'(3 . 6) c8 d e f @} @end example Anstelle dessen können auch die Zahlen, aus denen das Paar besteht, einzeln als eigenständige Argumente weitergeleitet und der Scheme-Code, der das Paar erstellt, in die musikalische Funktion augenommen werden: @lilypond[quote,verbatim,ragged-right] manualBeam = #(define-music-function (parser location beg end) (number? number?) #{ \once \override Beam.positions = #(cons beg end) #}) \relative c' { \manualBeam #3 #6 c8 d e f } @end lilypond @node Mathematik in Funktionen @subsection Mathematik in Funktionen @translationof 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 } \relative c' { c2 \AltOn #0.5 c4 c \AltOn #1.5 c c \AltOff c2 } @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 #}) \relative c' { c2 \withAlt #0.5 { c4 c } \withAlt #1.5 { c c } c2 } @end lilypond @node Funktionen ohne Argumente @subsection Funktionen ohne Argumente @translationof 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 Leere musikalische Funktionen @subsection Leere musikalische Funktionen @translationof Void music functions Eine musikalische Funktion muss einen musikalischen Ausdruck ausgeben. Wenn man eine Funktion nur für ihre Nebeneffekte ausführt, sollte man @code{define-void-function} benützen. Es kann aber auch Fälle geben, in denen man teilweise eine musikalische Funktion erstellen will, teilweise aber nicht (wie im vorherigen Beispiel). Indem man eine leere (@code{void}) Funktion mit @code{#@{ #@}} ausgibt, wird das erreicht. @node Ereignisfunktionen @section Ereignisfunktionen @translationof Event functions @funindex define-event-function @cindex Ereignisfunktionen Damit man eine musikalische Funktion anstelle eines Ereignisses benützen kann, muss man ihr einen Richtungsindikator voranstellen. Manchmal entspricht dies jedoch nicht der Syntax der Konstruktionen, die man ersetzen will. Dynamikbefehle beispielsweise werden normalerweise ohne Richtungsangabe angehängt, wie @code{c'\pp}. Das Folgende ist eine Möglichkeit, beliebige Dynamikbefehle zu schreiben: @lilypond[quote,verbatim,ragged-right] dyn=#(define-event-function (parser location arg) (markup?) (make-dynamic-script arg)) \relative c' { c\dyn pfsss } @end lilypond Man kann das Gleiche auch mit einer musikalischen Funktion erreichen, aber dann muss man immer einen Richtungsindikator voranstellen, wie @code{@w{c-\dyn pfsss}}. @node Textbeschriftungsfunktionen @section Textbeschriftungsfunktionen @translationof Markup functions Textbeschriftungselemente sind als besondere Scheme-Funktionen definiert, die ein @code{Stencil}-Objekt erstellen, dem eine Anzahl an Argumenten übergeben wird. @menu * Beschriftungskonstruktionen in Scheme:: * Wie Beschriftungen intern funktionieren:: * Neue Definitionen von Beschriftungsbefehlen:: * Neue Definitionen von Beschriftungslistenbefehlen:: @end menu @node Beschriftungskonstruktionen in Scheme @subsection Beschriftungskonstruktionen in Scheme @translationof 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. Es ist meistens der beste Weg, @code{#@{ @dots{} #@}} zur Eingabe von LilyPond-Syntax zu benützen, aber es soll auch erklärt werden, wie man das @code{markup}-Makro einsetzt, um eine Lösung nur in Scheme zu bekommen. @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{\Beschriftungsbefehl} @tab @code{#:Beschriftungsbefehl} @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{Neue Definitionen von Beschriftungsbefehlen}). @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 Wie Beschriftungen intern funktionieren @subsection Wie Beschriftungen intern funktionieren @translationof 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ächst 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 Neue Definitionen von Beschriftungsbefehlen @subsection Neue Definitionen von Beschriftungsbefehlen @translationof New markup command definition Dieser Abschnitt behandelt die Definition von neuen Textbeschriftungsbefehlen. @menu * Syntax der Definition von Textbeschriftungsbefehlen:: * Über Eigenschaften:: * Ein vollständiges Bespiel:: * Eingebaute Befehle anpassen:: @end menu @node Syntax der Definition von Textbeschriftungsbefehlen @unnumberedsubsubsec Syntax der Definition von Textbeschriftungsbefehlen @translationof Markup command definition syntax 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-typ?} @var{Arg2-typ?} ...) [ #:properties ((@var{Eigenschaft1} @var{Standard-Wert1}) ...) ] ..Befehlkörper..) @end lisp Die Argumente sind: @table @var @item @var{befehl-bezeichnung} die Bezeichnung des Befehls @item @var{layout} die @q{layout}-Definition @item props eine Liste an assoziativen Listen, in der alle aktiven Eigenschaften enthalten sind @item @var{argi} das @var{i}te Befehlsargument @item @var{argi-type?} eine Eigenschaft für das @var{i}te Argument @end table Wenn der Befehl Eigenschaften des @code{props}-Arguments benutzt, kann das @code{#:properties}-Schlüsselwort benutzt werden um zu bestimmen, welche Eigenschaften mit welchen Standard-Werten benutzt werden. Argumente werden nach ihrem Typ unterschieden: @itemize @item eine Textbeschriftung entspricht einem Typenprädikat @code{markup?}; @item eine Textbeschriftungsliste entspricht einem Typenprädikat @code{markup-list?}; @item jedes andere Scheme-Objekt entspricht Typenprädikaten wie etwa @code{list?}, @code{number?}, @code{boolean?}, usw. @end itemize Es gibt keine Einschränkung in der Reihenfolge der Argumente (nach den Standard-Argumenten @code{layout} und @code{props}). Textbeschriftungsfunktionen, die als letztes Argument eine Textbeschriftung haben, haben die Besonderheit, dass sie auf Textbeschriftungslisten angewendet werden können, und das Resultat ist eine Textbeschriftungsliste, in der die Textbeschriftungsfuktion (mit den angegebenen Argumenten am Anfang) auf jedes Element der originalen Textbeschriftungsliste angewendet wurde. Da das Wiederholen der Argumente am Anfang bei der Anwendung einer Textbeschriftungsfunktion auf eine Textbeschriftungsliste for allem für Scheme-Argumente sparsam ist, kann man Leistungseinbußen vermeiden, indem man nur Scheme-Argumente für die Argumente am Anfang einsetzt, wenn es sich um Textbeschriftungsfunktionen handelt, die eine Textbeschriftung als letztes Argument haben. @node Über Eigenschaften @unnumberedsubsubsec Über Eigenschaften @translationof On properties Die @code{layout}- und @code{props}-Argumente der Textbeschriftungsbefehle bringen einen Kontext für die Interpretation der Beschriftung: Schriftgröße, Zeilenlänge usw. Das @code{layout}-Argument greift auf Eigenschaften zu, die in der @code{paper}-Umgebung definiert werden, indem man die @code{ly:output-def-lookup}-Funktion benutzt. Beispielsweise liest man die Zeilenlänge (die gleiche, die auch in Partituren benutzt wird) aus mit: @example (ly:output-def-lookup layout 'line-width) @end example Das @code{props}-Argument stellt einige Eigenschaften für die Textbeschriftungsbefehle zur Verfügung. Beispielsweise wenn der Überschrifttext einer @code{book}-Umgebung interpretiert wird, werden alle Variablen, die in der @code{\header}-Umgebung definiert werden, automatisch zu @code{props} hinzugefügt, sodass die Beschriftung auf Titel, Komponist usw. der @code{book}-Umgebung zugreifen kann. Das ist auch eine Möglichkeit, das Verhalten eines Beschriftungsbefehls zu konfigurieren: Wenn etwa ein Befehl die Schriftgröße während der Verarbeitung einsetzt, wird die Schriftgröße aus den @code{props} ausgelesen und nicht mit einem eigenen @code{font-size}-Argument definiert. Beim Aufruf des Beschriftungsbefehls kann der Wert der Schriftgröße geändert werden, womit sich auch das Verhalten des Befehls verändert. Benutzen Sie das @code{#:properties}-Schlüsselwort von @code{define-markup-command} um zu definieren, welche Eigenschaften aus den @code{props}-Argumenten ausgelesen werden sollen. Das Beispiel im nächsten Abschnitt illustriert, wie man auf Eigenschaften in einem Beschriftungsbefehl zugreifen und sie verändern kann. @node Ein vollständiges Bespiel @unnumberedsubsubsec Ein vollständiges Bespiel @translationof A complete example Das folgende Beispiel definiert einen Beschriftungsbefehl, der einen doppelten Kasten um einen Text zeichnet. Zuerst wollen wir ein annäherndes Ergebnis mit Textbeschriftungen definieren. Nach Stöbern in @ruser{Textbeschriftungsbefehle} finden wir den Befehl @code{\box}: @lilypond[quote,verbatim,ragged-right] \markup \box \box HELLO @end lilypond Wir wollen aber etwas mehr Abstand (engl. padding) zwischen dem Text und dem Kasten. Nach der Dokumentation von @code{\box} hat der Befehl eine @code{box-padding}-Eigenschaft, die den Standardwert von 0.2 hat. Die Dokumentation zeit auch, wir man den Wert verändert: @lilypond[quote,verbatim,ragged-right] \markup \box \override #'(box-padding . 0.6) \box A @end lilypond Auch der Abstand zwischen den zwei Kästen ist uns zu klein und soll auch vergrößert werden: @lilypond[quote,verbatim,ragged-right] \markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box A @end lilypond Diese lange Textbeschriftung immer wieder schreiben zu müssen, ist anstrengend. Hier kömmt ein Textbeschriftungsbefehl ins Spiel. Wir schreiben uns alle einen @code{double-box}-Beschriftungsbefehl, der ein Argument annimmt (den Text). Er zeichnet zwei Kästen mit genügend Abstand: @lisp #(define-markup-command (double-box layout props text) (markup?) "Draw a double box around text." (interpret-markup layout props #@{\markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box @{ #text @}#@})) @end lisp oder äquivalent @lisp #(define-markup-command (double-box layout props text) (markup?) "Draw a double box around text." (interpret-markup layout props (markup #:override '(box-padding . 0.4) #:box #:override '(box-padding . 0.6) #:box text))) @end lisp @code{text} ist die Bezeichnung des Arguments dieses Befehls, und @code{markup?} ist seine Art: hiermit wird der Befehl als Beschriftungsbefehl identifiziert. Die @code{interpret-markup}-Funktion wird in den meisten Beschriftungsbefehlen benutzt: sie erstellt einen Stencil, wobei @code{layout}, @code{props} und eine Beschriftung benutzt werden. Im zweiten Fall wird diese Beschriftung durch das @code{markup}-Scheme-Makro erstellt, siehe auche @ref{Beschriftungskonstruktionen in Scheme}. Die Transformation des @code{\markup}-Ausdrucks in einen Scheme-Beschriftungsausdruck geschieht durch Umschreiben des LilyPond-Codes in Scheme-Code. Der neue Befehl kann wie folgt benutzt werden: @example \markup \double-box A @end example Es wäre schön, den @code{double-box}-Befehl noch konfigurierbar zu gestalten: in unserem Fall sind die Werte von @code{box-padding} direkt definiert und können nicht mehr vom Benutzer verändert werden. Es wäre auch besser, wenn der Abstand zwischen den beiden Kästen vom Abstand zwischen dem inneren Kasten und dem Text unterschieden werden könnte. Eine neue Eigenschaft muss also definiert werden: @code{inter-box-padding} für den Abstand zwischen den Kästen. @code{box-padding} wird für den inneren Abstand benutzt. Der neue Befehl wird so definiert: @lisp #(define-markup-command (double-box layout props text) (markup?) #:properties ((inter-box-padding 0.4) (box-padding 0.6)) "Draw a double box around text." (interpret-markup layout props #@{\markup \override #`(box-padding . ,inter-box-padding) \box \override #`(box-padding . ,box-padding) \box @{ #text @} #@})) @end lisp Wiederum wäre die entsprechende Version mit dem @code{markup}-Makro so aussehen: @lisp #(define-markup-command (double-box layout props text) (markup?) #:properties ((inter-box-padding 0.4) (box-padding 0.6)) "Draw a double box around text." (interpret-markup layout props (markup #:override `(box-padding . ,inter-box-padding) #:box #:override `(box-padding . ,box-padding) #:box text))) @end lisp In diesem Code wird das @code{#:properties}-Schlüsselwort benutzt, sodass die Eigenschaften @code{inter-box-padding} und @code{box-padding} aus dem @code{props}-Argument ausgelesen werden, und Standardwerte werden gegeben, falls die Eigenschaften nicht definiert sein sollten. Dann werden diese Werte benutzt, um die @code{box-padding}-Eigenschaft zu verändert, die von beiden @code{\box}-Befehlen benutzt wird. Beachten Sie Akzent und das Komma des @code{\override}-Arguments: hiermit kann man einen Variablenwert in einen wörtlichen Ausdruck überführen. Jetzt kann der Befehl in Beschriftungen benutzt werden und der Abstand der Kästen kann angepasst werden: @lilypond[quote,verbatim,ragged-right] #(define-markup-command (double-box layout props text) (markup?) #:properties ((inter-box-padding 0.4) (box-padding 0.6)) "Draw a double box around text." (interpret-markup layout props #{\markup \override #`(box-padding . ,inter-box-padding) \box \override #`(box-padding . ,box-padding) \box { #text } #})) \markup \double-box A \markup \override #'(inter-box-padding . 0.8) \double-box A \markup \override #'(box-padding . 1.0) \double-box A @end lilypond @node Eingebaute Befehle anpassen @unnumberedsubsubsec Eingebaute Befehle anpassen @translationof Adapting builtin commands Ein guter Weg, einen neuen Beschriftungsbefehl zu schreiben, ist es, als Vorbild einen existierenden zu nehmen. Die meisten Beschriftungsbefehle, die LilyPond mitbringt, finden sich in der Datei @file{scm/define-markup-commands.scm}. Man könnte beispielsweise den Befehl @code{\draw-line}, der eine Linie zeichnet, anpassen, sodass er eine Doppellinie zeichnet. Der Befehl @code{\draw-line} ist wie folgend definiert (Dokumentation entfernt): @lisp (define-markup-command (draw-line layout props dest) (number-pair?) #:category graphic #:properties ((thickness 1)) "..documentation.." (let ((th (* (ly:output-def-lookup layout 'line-thickness) thickness)) (x (car dest)) (y (cdr dest))) (make-line-stencil th 0 0 x y))) @end lisp Um einen neuen Befehl, der auf einem existierenden basiert, zu definieren, wird die Befehlsdefinition kopiert und die Bezeichnung des Befehls geändert. Das @code{#:category}-Schlagwort kann entfernt werden, weil es nur zur Erstellung der LilyPond-Dokumentation eingesetzt wird und keine Bedeutung für selbstdefinierte Befehle hat. @lisp (define-markup-command (draw-double-line layout props dest) (number-pair?) #:properties ((thickness 1)) "..documentation.." (let ((th (* (ly:output-def-lookup layout 'line-thickness) thickness)) (x (car dest)) (y (cdr dest))) (make-line-stencil th 0 0 x y))) @end lisp Dann braucht man eine Eigenschaft, um den Abstand zwischen den zwei Linien zu definieren, als @code{line-gap} bezeichnet und etwa mit dem Standardwert 0.6: @lisp (define-markup-command (draw-double-line layout props dest) (number-pair?) #:properties ((thickness 1) (line-gap 0.6)) "..documentation.." ... @end lisp Schließlich wird der Code, der die zwei Linien zeichnet, hinzugefügt. Zwei Aufrufe an @code{make-line-stencil} werden benutzt, um beide Linien zu zeichnen, und die beiden sich daraus ergebenden Stencils werden mit @code{ly:stencil-add} kombiniert: @lilypond[quote,verbatim,ragged-right] #(define-markup-command (my-draw-line layout props dest) (number-pair?) #:properties ((thickness 1) (line-gap 0.6)) "..documentation.." (let* ((th (* (ly:output-def-lookup layout 'line-thickness) thickness)) (dx (car dest)) (dy (cdr dest)) (w (/ line-gap 2.0)) (x (cond ((= dx 0) w) ((= dy 0) 0) (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy)))))))) (y (* (if (< (* dx dy) 0) 1 -1) (cond ((= dy 0) w) ((= dx 0) 0) (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx)))))))))) (ly:stencil-add (make-line-stencil th x y (+ dx x) (+ dy y)) (make-line-stencil th (- x) (- y) (- dx x) (- dy y))))) \markup \my-draw-line #'(4 . 3) \markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3) @end lilypond @node Neue Definitionen von Beschriftungslistenbefehlen @subsection Neue Definitionen von Beschriftungslistenbefehlen @translationof 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{Neue Definitionen von Beschriftungsbefehlen}. Ein Unterschied ist, dass bei diesem Listen-Makro eine ganze Liste an Stencils 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?) #:properties ((par-indent 2)) (interpret-markup-list layout props #@{\markuplist \justified-lines @{ \hspace #par-indent #args @} #@})) @end example Die Version nur in Scheme ist etwas komplexer: @example #(define-markup-list-command (paragraph layout props args) (markup-list?) #:properties ((par-indent 2)) (interpret-markup-list layout props (make-justified-lines-markup-list (cons (make-hspace-markup par-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 der eingebaute @code{\justified-lines}-Beschriftungslistenbefehl eingesetzt wird, der verwandt ist mit der @code{make-justified-lines-markup-list}-Funktion. Horizontaler Platz wird zu Beginn eingefügt mit @code{\hspace} (oder 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 \markuplist @{ \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 Kontexte für Programmierer @section Kontexte für Programmierer @translationof Contexts for programmers @menu * Kontextauswertung:: * Eine Funktion auf alle Layout-Objekte anwenden:: @end menu @node Kontextauswertung @subsection Kontextauswertung @translationof 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 Taktzahl 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 Eine Funktion auf alle Layout-Objekte anwenden @subsection Eine Funktion auf alle Layout-Objekte anwenden @translationof 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}. Das funktioniert, indem ein musikalisches Ereignis in den angegebenen Kontext eingefügt wird (@rinternals{ApplyOutputEvent}). 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 @code{@var{proc}} für jedes Layoutobjekt aufgerufen, dass im Kontext @code{@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 ist es ein @rinternals{Stem}-Objekt. Hier ist eine Funktion, die mit @code{\applyOutput} benutzt werden kann; sie macht Notenköpfe auf und neben der Mittellinie unsichtbar: @lilypond[quote,verbatim,ragged-right] #(define (blanker grob grob-origin context) (if (and (memq 'note-head-interface (ly:grob-interfaces grob)) (< (abs (ly:grob-property grob 'staff-position)) 2)) (set! (ly:grob-property grob 'transparent) #t))) \relative c' { a'4 e8 <<\applyOutput #'Voice #blanker a c d>> b2 } @end lilypond @node Callback-Funktionen @section Callback-Funktionen @translationof Callback functions Eigenschaften (wie Dicke (@code{thickness}), Richtung (@code{direction}) 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, sobald der Wert der Eigenschaft während das Formatierungsprozesses angefordert wird. Der größte Teil der Satzmaschinierie funktioniert mit derartigen Callbacks. Eigenschaften, die üblicherweise Callbacks benutzen, sind u. A.: @table @code @item stencil Die Druckfunktion, die eine Ausgabe des Symbols hervorruft @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. Aus dem Callback heraus kann man eine Beschriftung am einfachsten mit @code{grob-interpret-markup} auswerten. Beispielsweise: @example mein-callback = #(lambda (grob) (grob-interpret-markup grob (markup "foo"))) @end example @node Scheme-Code innerhalb LilyPonds @section Scheme-Code innerhalb LilyPonds @translationof Inline Scheme code TODO: das Beispiel für diesen Abschnitt ist nicht gut gewähtl: @example F = -\tweak font-size #-3 -\flageolet @end example (beachte @samp{-}, was ein Nachereignis anzeigt) funktioniert für den geschilderten Zweck sehr gut. Aber bis der Abschnitt neu geschrieben wird, nehmen wir einfach an, dass wir das nicht wissen. 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 Durch die Verwendung von Scheme kann dieses Problem umgangen werden. Der Weg zum Resultat wird gezeigt in @ref{Artikulationszeichen zu Noten hinzufügen (Beispiel)}, 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 Schwierige Korrekturen @section Schwierige Korrekturen @translationof 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, damit der letzte Teil eines gebrochenen Bindebogens neu ausgerichtet wird. @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:spanner::kill-zero-spanned-time} 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, immer noch innerhalb der @code{\context}-Umgebung funktioniert. @end itemize @node LilyPond Scheme-Schnittstellen @chapter LilyPond Scheme-Schnittstellen @translationof LilyPond Scheme interfaces Dieses Kapitel behandelt die verschiedenen Werkzeuge, die LilyPond als Hilfe für Scheme-Programmierer zur Verfügung stellt, um Information in den Musik-Stream zu senden und aus ihm herauszubekommen. TODO: was gehört hier eigentlich hin?