'Zwischentitel' rechts- linksbündig

Begonnen von loph, Freitag, 29. November 2019, 13:06

« vorheriges - nächstes »

loph

Hallo!

Ähnlich wie in dem Post von hurrlipurr beschrieben, benutze ich gerne 'Zwischentitel' um verschiedene Songteile zu kennzeichnen.

Jetzt stoße ich regelmäßig auf das Problem, dass sich ein Coda-Marker am Ende einer Zeile befinden soll und am Anfang der nächsten Zeile ein neuer Songteil angegeben werden soll.
Dabei scheint aber Lilypond nicht mit der Art und Weise zurecht zu kommen, wie ich zwei Text-Markups, die nur durch ein \break getrennt sind, anzeigen lassen möchte: Der zweite Marker wird von Lilypond einfach ignoriert.


\version "2.18.2"

\relative c' {
    c4 c c c |
    c4 c c c |
    c4 c c c |
    c4 c c c |
\once \override Score.RehearsalMark.break-visibility = #begin-of-line-invisible
  \once \override Score.RehearsalMark.self-alignment-X = #RIGHT
  \mark \markup { \musicglyph #"scripts.coda" }
  \break
  \mark \markup { \box  "Instrumental" }
    c4 c c c |
    c4 c c c |
    c4 c c c |
    c4 c c c |
}



Als 'Workaround' habe ich die Coda immer an die vorletzte Note der Zeile angehängt, was aber nicht sehr schön ist (und manchmal auch nicht praktikabel).

Gibt es einen 'sauberen Weg' mein Vorhaben umzusetzen?

Grüße und vielen Dank,
Johannes

harm6

#1
Hallo Johannes,

willkommen im Forum.

Zitatwie in dem Post von hurrlipurr
Bitte gib immer den link an, sobald Du auf etwas verweist.

Eigentlich redest Du über gleichzeitige RehearsalMarks, insoweit ist der thread-Titel irreführend.

Gleichzeitig sind sie, da sie zu selben Zeit gesetzt sind. Der Zeilenumbruch spielt da keine Rolle, er erfolgt ebenfalls zur selben Zeit.

Das Problem ist bekannt.
Die weitest gehenden Lösungsansätze sind:
http://lsr.di.unimi.it/LSR/Item?id=977
http://lsr.di.unimi.it/LSR/Item?id=976
Beide von Arnold.

Schau mal, ob Du damit klar kommst. Falls nicht meld Dich ;)

Gruß,
  Harm



loph

Vielen Dank für die schnelle und überaus kompetente Antwort, harm6!

Uff, das scheint ja gar nicht so trivial zu sein wie ich hoffte - aber ich probier das mal am Wochenende aus. :)

harm6


Vielleicht hilft es, wenn das zu Grunde liegende Problem deutlicher wird.

Es gibt verschiedene items, die beim Zeilenumbruch sowohl ans Ende der vorangegangenen Zeile als als auch an den Anfang der neuen Zeile gedruckt werden sollen.
Beim Schlüsselwechsel erscheint dieser zweifach. Also dasselbe Verhalten am Ende und am Anfang der entsprechenden Zeilen.
Beim Tonartwechsel ist es schon etwas komplexer. Die KeyCancellation erscheint nur am Ende der Zeile. Siehe:

{
  \key cis \major
  R1
  \break
  \clef alto
  \key ces \major
  R1
}


Tatsächlich werden die bislang erwähnten items von LilyPond erstmal an beide Stellen "gedacht", dann aber mit Blick aufs grob-property `break-visibility´, bzw beim Tonartwechsel auch aufs context-property `explicitKeySignatureVisibility´ zugelassen oder unterdrückt.
Diese properties verlangen einen `vector´ mit drei booleans,
#(zeilen-ende zeilen-mitte zeilen-anfang), z.B. drucke nur am Ende einer Zeile: #(#t #f #f)
Es gibt auch mehr "sprechende" Definitionen dafür, z.B. end-of-line-visible, etc siehe NR

Soweit ist es noch relativ einfach. Es gibt aber auch ein item welches sein Aussehen wechselt je nachdem, ob es am Anfang, Mitte oder Ende einer Zeile auftaucht: BarLines.
Z.B. ".|:"
Am Anfang und in der Mitte einer Zeile möchte man das genauso haben, nicht aber am Ende einer Zeile.
Da soll ja "|" i.d.R. geschrieben werden.
Insoweit ist die Definition einer BarLine bereits eine Art Liste in der diese Glyphs aufgeführt sind.
Natürlich braucht man auch die entsprechende "Infrastruktur" um das jeweils gewünschte auszuwählen.
Du kannst ja mal einen Blick in bar-line.scm werfen. Nicht um nachzuvollziehen was da gemacht ist, sondern um einen groben Eindruck über das Verfahren zu bekommen.

Du kannst es aber auch lassen, es steht halt auch viel drin was nur für BarLine gilt. Und die Analogie RehearsalMark <-> BarLine sollte man auch nicht zu weit treiben, sonst verliert man noch das Ziel aus den Augen.


Denn das Ziel ist ja RehearsalMark so zu setzen, daß sie am Zeilenende/Zeilenanfang/Zeilenmitte ein anderes Verhalten zeigen.

Um dahin zu kommen, muß man erstmal wissen wo in der Zeile man sich denn befindet und man kann nicht davon ausgehen, daß ein explizites \break immer da ist.
Da hilft die procedure ly:item-break-dir. Sie retourniert
-1 (für Zeilenende)
  oder
  0 (für Zeilenmitte)
  oder
  1 (für Zeilenanfang).

  Siehe:

{
R1
\override Score.RehearsalMark.break-visibility = ##(#t #f #f)
\override Score.RehearsalMark.after-line-breaking =
#(lambda (grob)
  (pretty-print (cons 'item-break-dir (ly:item-break-dir grob))))
\mark \default
\break
R
}


Die ausgewählte Setzung für break-visibility schreibt die RehearsalMark nur ans Ende einer Zeile.
Im terminal erscheint (item-break-dir . -1)
Wie erwartet und gewünscht.
Aber wir haben schon eine Erkenntnis gewonnen: Um RehearsalMark an das Ende und den Anfang der (neuen) Zeile  zu setzen brauchen wir entspreche Setzungen für break-visibility. In der Zeilenmitte wollen wir es natürlich auch haben, also muß break-visibility auf
#(#t #t #t)
gesetzt werden:

{
  \override Score.RehearsalMark.break-visibility = ##(#t #t #t)
  R1
  \mark \default
  R1
  \break
  \mark \default
  R1
}


Alle RehearsalMarks werden gedruckt, die beim Zeilenumbruch sowohl davor als auch danach.
Wie gewünscht.

Allerdings wollen wir ein unterschiedliches Aussehen bein Zeilenumbruch.
Da kommt dann ly:item-break-dir ins Spiel.
Wir können dann per Fallunterscheidung vorgehen:
Falls
  Zeilenende -> Aussehen-1
  Zeilenanfang -> Aussehen-2
  Zeilenmitte -> Aussehen-3
 
In scheme (als pures proof-of-concept habe ich foo, bar, buzz genommen):

  (lambda (grob)
    (let ((break-dir (ly:item-break-dir grob)))
      (case break-dir
        ((-1) "foo")
        ((0) "bar")
        ((1) "buzz"))))

Im ly-code:

{
  \override Score.RehearsalMark.break-visibility = ##(#t #t #t)
  \override Score.RehearsalMark.stencil =
   #(lambda (grob)
      (let ((break-dir (ly:item-break-dir grob)))
        ;; Diese Zeile kommt hinzu, wir wollen den jeweiligen string ja für den
        ;; stencil verwenden.
        (grob-interpret-markup grob
          (case break-dir
            ((-1) "foo")
            ((0) "bar")
            ((1) "buzz")))))
 
  R1
  \mark \default
  R1
  \break
  \mark \default
  R1
}


Soviel zur Problemdarstellung.
Wir könnten jetzt den stencil-override ausbauen, indem wir ihn in eine music-function transformieren, um  anstatt foo, bar, buzz bequem durch die tatsächlich gewünschten strings/markups zu ersetzen oder wir erfinden ein paar grob- oder auch music-properties dafür.
Allerdings müssen wir auch Sorge dafür tragen, daß overrides für RehearsalMark-properties wirklich nur das Zielobjekt treffen...
Kombination von \mark \default mit \mark "custom" stellt ein gesondertes Problem dar.
etc.

Die von mir verlinkten LSR-snippets machen das und noch mehr ...
Du könntest natürlich auch selbst versuchen den von mir skizzierten Weg
(Fallunterscheidung mittels `ly:item-break-dir´) für jedes gewünschte property weiter zu verfolgen.
Das Verständnis für LilyPond line-break-Verhalten würde enorm anwachsen ;)

HTH,
  Harm