Trio-Umgebung definieren, Positionierung von Text

Begonnen von jonas, Sonntag, 27. Mai 2018, 19:16

« vorheriges - nächstes »

jonas

Hallo zusammen,
ein Marsch besteht häufig aus drei Teilen: Teil 1, Teil 2 und Trio.  Das Trio beginnt immer in einer neuen Zeile und wird mit Text (Trio) gezeigt.
Leider habe ich keine schöne Funktion in Lilypond gefunden, die einem Text an eine bestimmte Stelle setzt und ich bin auf der Suche auf folgendes Snippet gestoßen: http://lilypond.org/doc/v2.18/Documentation/snippets/repeats Abschnitt Positioning segno and coda (with line break)

Ich habe nun versucht, mir auf Basis dieses Snippets einen musikalischen Ausdruck TrioText, der in "leerem Raum" ohne Linien, Taktzahlen usw. sitzt, zu bauen, siehe Anhang. Mein Problem ist nun folgendes: Kann ich den Text Trio irgenwie so positionieren, dass

  • er auf der linken Seite immer bündig mit dem restlichen System ist
  • er vertikal immer zentriert zu den Notenlinien der Zeile ist
  • von rechts kein Notensystem in den Text hineinragen kann?

Ist das technisch realisierbar? Ich hatte mir das nachher so gedacht, dass ich diesen Ausdruck dann wie unten in test.ly aufrufe.

Danke im Vorraus!

Gruß
Jonas

ingmar

#1
Hallo Jonas,

mir ist leider nicht klar, wo dein Problem liegt. Einfach eine zweite Partitur (\score) daruntersetzen, in deren Header piece gefüllt ist, reicht nicht?

--ingmar
\version "2.18.2"

\language deutsch

\header{
  title = "Titel"
  composer = ""
  tagline = #f
}

Trio =  \relative c'''{
    \repeat unfold 20 { c4 }
    \repeat unfold 20 { c4 }
}

TeilEins = \relative c'''{
    \repeat unfold 20 { b4 }
}

TeilZwei = \relative c'''{
    \repeat unfold 20 { a4 }
   
}


\score {
    \new Staff {
        \TeilEins
        \TeilZwei
    }
}
\score {
    \new Staff {
        \Trio
    }
    \header {
    piece = "Trio"
    }
}

jonas

Zitat von: ingmar am Sonntag, 27. Mai 2018, 21:23
Hallo Jonas,

mir ist leider nicht klar, wo dein Problem liegt. Einfach eine zweite Partitur (\score) daruntersetzen, in deren Header piece gefüllt ist, reicht nicht?

--ingmar

Hab ich auch schon versucht (ich hatte instrumentName = Trio, weil das von der Position besser passte), aber gestaltet sich als hinderlich, weil das Trio ja zum Stück gehört und ich dann zum Beispiel die Taktanzahl der Teile davor wissen muss, damit es da weitergehen kann.
Es gibt bestimmt einen besseren und einfacheren Weg :-)

ingmar

...und Zeilenumbruch erzwingen und in der neuen Zeile einfach "Trio" darüberschreiben?

--ingmar
\version "2.18.2"

\language deutsch

\header{
  title = "Titel"
  composer = ""
  tagline = #f
}

Trio =  \relative c'''{
    \tempo "Trio"
    \repeat unfold 20 { c4 }
    \repeat unfold 20 { c4 }
}

TeilEins = \relative c'''{
    \repeat unfold 20 { b4 }
}

TeilZwei = \relative c'''{
    \repeat unfold 20 { a4 }
    \bar "||"
}


\score {
    \new Staff {
        \TeilEins
        \TeilZwei
        \break
        \Trio
    }
}


Arnold

Hallo,

bisher habe ich auch nur TRIO darüber platziert.
Natürlich könnte man "TRIO" als shortInstrumentName vor die Zeile setzen, aber dann müßte man den Wert für short-indent nur für diesen Zeilenumbruch ändern, doch dieses ist eine Paper-Variable, keine im Score-Kontext.

Auch habe ich in der Vergangenheit schon Texte in eine Unterbrechung der Notenzeile gesetzt - aber am Anfang einer Zeile kommt ja eigentlich erst Schlüssel und Tonart, und erst danach die Unterbrechung. Also könnte ich dir nur helfen, wenn ich es noch schaffe, vor einem \stopStaff dieses zu unterdrücken, aber nach dem \startStaff Schlüssel und Tonart forciert wieder darzustellen.

Kann etwas länger dauern, das zu probieren.

Arnold.

jonas

Es gibt wahrscheinlich keine Vorgabe, wo Trio stehen muss, aber bei den meisten Märschen, die ich setzen muss, steht's in derselben Zeile. Finde ich auch persönlich hübscher.

Wenn es allerdings keine leichte Lösung gibt, werde ich wahrscheinlich die Lösung mit zwei Scores nehmen und Trio als InstrumentName nehmen. Gibts es denn eine Möglichkeit, die Taktzahl aus dem ersten Score zu übernehmen?

harm6

Hallo,

das ist mal wieder so eine täuschend einfache Frage. Das Problem ist aber auf Grund der Art und Weise wie LilyPond organisiert ist kaum zu lösen.
Arnold hat ja schon die Probleme umrissen.

Ich versuche sie in meinem Coding unten zu umgehen.
Das Resultat ist dreist wie sonst was. :)
Obs wirklich funktioniert mußt Du testen. Ich habe nur das einzelne Code-Beispiel versucht.

Die Funktion \trio muß zweimal aufgerufen werden.
Ganz am Anfang und an der Stelle an der das Trio tatsächlich beginnen soll. Am Anfang mit der Taktzahl des Triostarts.


\version "2.19.81"

\layout {
  \context {
    \Staff
    instrumentName = "Violine"
    shortInstrumentName = "vl "
  }
}

trio =
#(define-music-function (at-bar mus)((number? #f) ly:music?)
(let ((trio-text #{ \markup \large \bold "TRIO" #})
      (do-it-now #f)
      (value #f))
  #{
 
    \once \override Score.LeftEdge.before-line-breaking =
      #(lambda (grob)
         (let* ((dummy
                  (grob-interpret-markup grob trio-text))
                (dummy-x-ext (ly:stencil-extent dummy X)))
               
           (set! value (1+ (cdr dummy-x-ext)))
             
           (if (> (car (grob::rhythmic-location grob)) 1)
               (ly:grob-set-nested-property! grob
                 '(space-alist clef) (cons 'extra-space (1+ value))))))
             
    \once \override Staff.InstrumentName.after-line-breaking =
      #(lambda (grob)
        (if do-it-now
            (let* ((text-stil
                     (grob-interpret-markup grob trio-text))
                   (text-stil-x-ext (ly:stencil-extent text-stil X)))
                   
            (ly:grob-set-property! grob 'stencil text-stil)
           
            (ly:grob-translate-axis! grob (car text-stil-x-ext) X)
           
            (set! do-it-now #f))))
             
    \override Score.StaffSymbol.after-line-breaking =
      #(lambda (grob)
       (let* ((orig (ly:grob-original grob))
              (siblings (if (ly:grob? orig)
                            (ly:spanner-broken-into orig) '()))
              (relevant-staff
                (if (pair? siblings)
                    (filter
                      (lambda (staff)
                        (eqv? (car (grob::rhythmic-location staff)) at-bar))
                      siblings)
                      #f)))

         (if (equal? grob (car relevant-staff))
             (let* ((layout (ly:grob-layout grob))
                    (line-width (ly:output-def-lookup layout 'line-width))
                    (nmpc (ly:grob-parent grob X))
                    (nmpc-elts-array (ly:grob-object nmpc 'elements))
                    (nmpc-elts (ly:grob-array->list nmpc-elts-array))
                    ;;(axis-group-items
                    ;;  (filter
                    ;;    (lambda (elt)
                    ;;      (grob::has-interface elt 'axis-group-interface))
                    ;;    nmpc-elts))
                    (items-to-move
                      (filter
                        (lambda (elt)
                          (grob::has-interface elt 'break-alignable-interface))
                        nmpc-elts)))

               (for-each
                 (lambda (item) (ly:grob-translate-axis! item value X))
                 items-to-move)
               
               (ly:grob-set-property! grob 'width (- line-width value))
               
               (ly:grob-set-property! grob 'stencil
                 (ly:stencil-translate-axis
                   (ly:staff-symbol::print grob)
                   value
                   X))
                   
               (set! do-it-now #t)))))
    $mus
  #}))
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\new Staff {
  \key a \major
  \trio 3
  c'1
  \break
  cis'1
  \break
  \trio
  \key fis \minor
  \time 8/8
  c'1 d'1
  \break
  R1
  \break
}


Gruß,
  Harm

harm6

Und jetzt klappt es auch mit einem auftaktigen Trio, bei dem der Auftakt zu Begin der Zeile notiert ist:


\version "2.19.81"

\layout {
  \context {
    \Staff
    instrumentName = "Violine"
    shortInstrumentName = "vl "
  }
}

trio =
#(define-music-function (at-bar mus)((number-or-pair? #f) ly:music?)
(let ((trio-text #{ \markup \large \bold "MY WONDERFUL TRIO" #})
      (do-it-now #f)
      (value #f))
  #{
 
    \once \override Score.LeftEdge.before-line-breaking =
      #(lambda (grob)
         (let* ((dummy
                  (grob-interpret-markup grob trio-text))
                (dummy-x-ext (ly:stencil-extent dummy X)))
               
           (set! value (1+ (cdr dummy-x-ext)))
             
           (if (> (car (grob::rhythmic-location grob)) 1)
               (ly:grob-set-nested-property! grob
                 '(space-alist clef) (cons 'extra-space (1+ value))))))
             
    \once \override Staff.InstrumentName.after-line-breaking =
      #(lambda (grob)
        (if do-it-now
            (let* ((text-stil
                     (grob-interpret-markup grob trio-text))
                   (text-stil-x-ext (ly:stencil-extent text-stil X)))
                   
            (ly:grob-set-property! grob 'stencil text-stil)
           
            (ly:grob-translate-axis! grob (car text-stil-x-ext) X)
           
            (set! do-it-now #f))))
             
    \override Score.StaffSymbol.after-line-breaking =
      #(lambda (grob)
       (let* ((orig (ly:grob-original grob))
              (siblings (if (ly:grob? orig)
                            (ly:spanner-broken-into orig) '()))
              (relevant-staff
                (if (pair? siblings)
                    (filter
                      (lambda (staff)
                        (let ((loc (grob::rhythmic-location staff)))
                        (if (number? at-bar)
                            (eqv? (car loc) at-bar)
                            (equal?
                              loc
                              (cons (car at-bar)
                                    (ly:make-moment (cdr at-bar)))))))
                      siblings)
                      #f)))

         (if (and (pair? relevant-staff) (equal? grob (car relevant-staff)))
             (let* ((layout (ly:grob-layout grob))
                    (line-width (ly:output-def-lookup layout 'line-width))
                    (nmpc (ly:grob-parent grob X))
                    (nmpc-elts-array (ly:grob-object nmpc 'elements))
                    (nmpc-elts (ly:grob-array->list nmpc-elts-array))
                    ;;(axis-group-items
                    ;;  (filter
                    ;;    (lambda (elt)
                    ;;      (grob::has-interface elt 'axis-group-interface))
                    ;;    nmpc-elts))
                    (items-to-move
                      (filter
                        (lambda (elt)
                          (grob::has-interface elt 'break-alignable-interface))
                        nmpc-elts)))

               (for-each
                 (lambda (item) (ly:grob-translate-axis! item value X))
                 items-to-move)
               
               (ly:grob-set-property! grob 'width (- line-width value))
               
               (ly:grob-set-property! grob 'stencil
                 (ly:stencil-translate-axis
                   (ly:staff-symbol::print grob)
                   value
                   X))
                   
               (set! do-it-now #t)))))
    $mus
  #}))
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\new Staff {
  \key a \major
  \trio #'(2 . 3/4)
  c'1
  \break
  cis'2.
  \bar ""
  \break
  \trio
  \key a \minor
  cis'4
  \time 8/8
  c'1 d'1
  \break
  R1
  \break
}


Gruß,
  Harm

Arnold

Hallo,

und das ist mein Versuchsergebnis, ohne Rücksprache mit Harm entstanden.
Es kann Probleme geben, wenn man andere Werte für Score.barNumberVisibility wählt.
Anstelle der Unterschiede bei »Autakt oder nicht« könnte ich mir vorstellen, daß es mit einer ApplyContext-Prozedur lösbar wäre.
Und, sicher nur für Einzelstimmen geeignet.
\version "2.18.2"

\paper {
  line-width = 100 \mm
}

ShowBarNumber = \once \override Score.BarNumber.break-visibility = #end-of-line-invisible

#(define (nochange-calc-glyph-name grob)
  (let* ((calculated-name (ly:clef::calc-glyph-name grob))
         (its-length (string-length calculated-name))
         (its-terminator (if (> its-length 7)
          (string-take-right calculated-name 7)
          ""))
         (new-name (if (equal? its-terminator "_change")
          (string-drop-right calculated-name 7)
          calculated-name)))
   ;;;; Wen es interessiert:
   ; (for-each display (list "\n calculated: " calculated-name
   ;                         "\n its-length: " its-length
   ;                         "\n its-terminator: " its-terminator
   ;                         "\n new-name: " new-name
   ;                         "\n"))
   new-name))

\score {
  \new Staff {
    \set Score.barNumberVisibility = #first-bar-number-invisible-and-no-parenthesized-bar-numbers
    \clef treble \key d \major \time 2/2
    \partial 4
    \repeat volta 2 {
      a4 d'1 g' e' d'2.
    }
    \key a \major
    \repeat volta 2 {
      a'4 \ShowBarNumber a'1 e' gis' a'2.
    }

    \once \override Score.Clef.break-visibility = #all-invisible
    \once \override Score.KeySignature.break-visibility = #all-invisible
    \break
    \stopStaff
    \markLengthOn
    \cadenzaOn
    s64
    \once \override Score.RehearsalMark #'extra-spacing-width = #'(0.0 . 0.0)
    \once \override Score.RehearsalMark #'extra-spacing-height = #'(-inf.0 . +inf.0)
    \once \override Score.RehearsalMark #'outside-staff-priority = ##f
    \once \override Score.RehearsalMark #'Y-offset = #-1.0
    \once \override Score.RehearsalMark.self-alignment-X = ##f
    \mark "TRIO"
    \set Staff.explicitClefVisibility = #all-visible
    s64
    \cadenzaOff
    \markLengthOff
    \startStaff
    \bar ""
    \set Staff.forceClef = ##t
    \once \override Staff.Clef.glyph-name = #nochange-calc-glyph-name

    \clef treble \key g \major
    \times 2/3 { d'8[ e' fis'] } \ShowBarNumber g'2 g' g' r4
    \repeat volta 2 {
      d'4 g'1 b' a' g' d' e' fis' g'2.
    }
  }
  \layout {
    indent = 0 \mm
    short-indent = 0 \mm
  }
  \header { piece = "Marsch — mit Auftakt im Trio" }
}


\score {
  \new Staff {
    \set Score.barNumberVisibility = #first-bar-number-invisible-and-no-parenthesized-bar-numbers
    \clef treble \key d \major \time 2/2
    \repeat volta 2 {
      d'1 g' e' d'
    }
    \key a \major
    \repeat volta 2 {
      \ShowBarNumber a'1 e' gis' a'
    }

    \once \override Score.Clef.break-visibility = #all-invisible
    \once \override Score.KeySignature.break-visibility = #all-invisible
    \break
    \stopStaff
    \markLengthOn
    \set Score.measurePosition = #(ly:make-moment -1/32) % no \cadenzaOn at barline!
    s64
    \once \override Score.RehearsalMark #'extra-spacing-width = #'(0.0 . 0.0)
    \once \override Score.RehearsalMark #'extra-spacing-height = #'(-inf.0 . +inf.0)
    \once \override Score.RehearsalMark #'outside-staff-priority = ##f
    \once \override Score.RehearsalMark #'Y-offset = #-1.0
    \once \override Score.RehearsalMark.self-alignment-X = ##f
    \mark "TRIO"
    \set Staff.explicitClefVisibility = #all-visible
    s64
    % no \cadenzaOff at barline!
    \markLengthOff
    \startStaff
    \bar ""
    \set Staff.forceClef = ##t
    \once \override Staff.Clef.glyph-name = #nochange-calc-glyph-name

    \clef treble \key g \major
    \ShowBarNumber
    d'2 r8 d' e' fis' g'2 g' g' r
    \repeat volta 2 {
      g'1 b' a' g' d' e' fis' g'
    }
  }
  \layout {
    indent = 0 \mm
    short-indent = 0 \mm
  }
  \header { piece = "Marsch — ohne Auftakt im Trio" }
}


Arnold

harm6

Hallo Arnold,

Zitatund das ist mein Versuchsergebnis, ohne Rücksprache mit Harm entstanden.
:)
Es führen doch mehrere Wege nach Rom ...

Eine Anmerkung:
Ich denke `nochange-calc-glyph-name' braucht man nicht. Soweit ich das auf die Schnelle verstanden habe kann man die Anwendung durch
\once \override Staff.Clef.full-size-change = ##t
ersetzen.

Gruß,
  Harm

jonas

Danke für eure Lösungen. Es ist immer sehr lehrreich, fremden Lilypond-Code zu lesen.

Harm, deine Lösung kann ich nicht kompilieren, denn sie benötigt eine neuere Version von Lilypond, wenn ich die Fehlermeldung richtig verstehe:
Parsing.../usr/share/lilypond/2.18.2/scm/ly-syntax-constructors.scm:56:23: In expression (apply (ly:music-function-extract fun) parser ...):
/usr/share/lilypond/2.18.2/scm/ly-syntax-constructors.scm:56:23: Wrong number of arguments to #<procedure #f (at-bar mus)>


Könnt ihr das Wechseln auf den dev branch empfehlen? Ich werde das morgen mal machen, heute habe ich dafür keine Zeit mehr.

Arnold, deine Lösung sieht so aus, wie ich mir das vorgestellt hab. Wie sieht es denn mit der Wiederverwertbarkeit aus? Ich werde mal versuchen, das ganze in eine Variable zu speichern oder in einem File, das included wird, wenn ich einen neuen Marsch beginne.


harm6

Zitat
Harm, deine Lösung kann ich nicht kompilieren, denn sie benötigt eine neuere Version von Lilypond, wenn ich die Fehlermeldung richtig verstehe:


Parsing.../usr/share/lilypond/2.18.2/scm/ly-syntax-constructors.scm:56:23: In expression (apply (ly:music-function-extract fun) parser ...):
/usr/share/lilypond/2.18.2/scm/ly-syntax-constructors.scm:56:23: Wrong number of arguments to #<procedure #f (at-bar mus)>


In der Fehlermeldung geht es darum, daß die beiden default-Argumente einer Musikfunktion (parser, location) von 2.18.2 erwartet werden. Sie können in 2.19.x weggelassen werden. Allerdings verwendet mein Coding noch andere 2.19.-features...

ZitatKönnt ihr das Wechseln auf den dev branch empfehlen?
Mit einem Wort: Ja

Falls Du irgendwelche Zweifel hast, installiere die devel-Version zusätzlich.

Gruß,
  Harm