\dynamicH und lilypond 2.24

Begonnen von PietDip4, Freitag, 19. Januar 2024, 18:08

« vorheriges - nächstes »

PietDip4

Hallo,

mit lilypond Version 2.22 hat folgender Code noch wunderbar funktioniert:
\version "2.22"

\include "dynamicH.ily"
pDolce = \dynamicH 1 "{p} dolce"
{a'1_\pDolce}

Mit Version 2.24 hingegen, erhalte ich folgenden Fehler:
GNU LilyPond 2.24.3 (running Guile 2.2)
»testdynh.ly« wird verarbeitet
Analysieren...
Interpretation der Musik...
Vorverarbeitung der grafischen Elemente...
/usr/share/lilypond/2.24.3/ly/init.ly:65:2: Fehler: Guile signaled an error for the expression beginning here
#
 (let ((book-handler (if (defined? 'default-toplevel-book-handler)
In procedure list-head: Wrong type argument in position 1 (expecting pair): ()

Wer kann diesen Fehler erklären? Was muss ich ändern damit wieder alles läuft?


Gruß,

PietDip4


dynamicH.ily:
%%% -*- coding: utf-8 -*-
%%%
%%% Copyright © 2016-2019 Thomas "Harm" Morley
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
%%% You may obtain a copy of the License at
%%%
%%%    http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Unless required by applicable law or agreed to in writing, software
%%% distributed under the License is distributed on an "AS IS" BASIS,
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.

\version "2.20"

#(define (note-column::main-extent grob)
"Return extent of the noteheads in the 'main column', (i.e. excluding any
suspended noteheads), or extent of the rest (if there are no heads)."
  (let* ((note-heads (ly:grob-object grob 'note-heads))
         (stem (ly:grob-object grob 'stem))
         (rest (ly:grob-object grob 'rest)))
    (cond ((ly:grob-array? note-heads)
           (let (;; get the cdr from all note-heads-extents, where the car
                 ;; is zero
                 (n-h-right-coords
                   (filter-map
                     (lambda (n-h)
                       (let ((ext (ly:grob-extent n-h grob X)))
                          (and (= (car ext) 0) (cdr ext))))
                     (ly:grob-array->list note-heads))))
             ;; better be paranoid, find the max of n-h-right-coords and return
             ;; a pair with (cons 0 <max>)
             (cons 0.0 (reduce max 0 n-h-right-coords))))
          ((ly:grob? rest)
           (ly:grob-extent rest grob X))
          ;; better be paranoid
          (else '(0 . 0)))))

#(define remove-empty
  ;; Remove empty strings and empty lists from the given list 'lst'
  (lambda (lst)
    (remove
      (lambda (e)
        (or
          (and (string? e) (string-null? e))
          (and (list? e) (null? e))))
      lst)))

#(define char-set:dynamics
  (char-set #\f #\m #\p #\r #\s #\z))

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% DynamicText, created on the fly
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% Reads
%%%%  DynamicText.details.separator-pair
%%%%  DynamicText.details.dyn-rest-font-sizes
%%%%  DynamicText.details.markup-commands
%%%%  DynamicText.details.inner-x-space
%%%%  DynamicText.details.outer-x-space


#(use-modules (srfi srfi-11))
#(use-modules (ice-9 regex))

#(define (make-reg-exp separator-pair)
  (format #f "\\~a[^~a~a]*\\~a"
    (car separator-pair)
    (car separator-pair)
    (cdr separator-pair)
    (cdr separator-pair)))

#(define (dynamics-list separator-pair strg)
  (let ((reg-exp (make-reg-exp separator-pair))
        (separators (char-set (car separator-pair) (cdr separator-pair))))
    (map
      (lambda (s)
        (let* ((match (string-match reg-exp s)))
           (if match
               (let* ((poss-dyn (match:substring match))
                      (cand (string-trim-both poss-dyn separators)))
                 (if (string-every char-set:dynamics cand)
                       (list
                         (match:prefix match)
                         cand
                         (match:suffix match))
                     s))
               s)))
      (string-split strg #\space))))

#(define (dynamic-text::format-text
           fontsizes inner-kern outer-kern text-markup-command lst)
  (let* ((mrkp-cmnd
           (lambda (arg) (make-normal-text-markup (text-markup-command arg))))
         (txt-font-size (if (pair? fontsizes) (cdr fontsizes) #f))
         (txt-mrkp-cmnd
           (lambda (txt)
             (if (number? txt-font-size)
                 (make-fontsize-markup txt-font-size (mrkp-cmnd txt))
                 (mrkp-cmnd txt))))
         (left-out (if (pair? outer-kern) (car outer-kern) #f))
         (left-inner (if (pair? inner-kern) (car inner-kern) #f))
         (right-inner (if (pair? inner-kern) (cdr inner-kern) #f))
         (right-out (if (pair? outer-kern) (cdr outer-kern) #f))
         (space-mrkp-cmd
           (lambda (space)
             (if (number? space)
                 (txt-mrkp-cmnd (make-hspace-markup space))
                 ""))))
    (map
      (lambda (e)
        (if (list? e)
            (remove-empty
              (list
                (cond ((and (string-null? (car e)) (equal? e (car lst))) '())
                      ((string-null? (car e))
                        (space-mrkp-cmd left-out))
                      ((and (not (string-null? (car e))) (equal? e (car lst)))
                        (make-concat-markup
                        (remove-empty
                          (list
                            (txt-mrkp-cmnd (car e))
                            (space-mrkp-cmd left-inner)))))
                      (else
                        (make-concat-markup
                        (remove-empty
                          (list
                            (space-mrkp-cmd left-out)
                            (txt-mrkp-cmnd (car e))
                            (space-mrkp-cmd left-inner))))))
                (second e)
                (cond ((and (string-null? (last e)) (equal? e (last lst))) '())
                      ((string-null? (last e))
                        (space-mrkp-cmd right-out))
                      ((and (not (string-null? (last e)))
                            (equal? e (last lst)))
                        (make-concat-markup
                        (remove-empty
                          (list
                            (space-mrkp-cmd right-inner)
                            (txt-mrkp-cmnd (last e))))))
                      (else
                        (make-concat-markup
                        (remove-empty
                          (list
                            (space-mrkp-cmd right-inner)
                            (txt-mrkp-cmnd (last e))
                            (space-mrkp-cmd right-out))))))))
            (make-line-markup (list (txt-mrkp-cmnd e)))))
      lst)))

#(define (get-string-indices lst)
  (filter-map
    (lambda (e c) (if (string? e) c #f))
    lst
    (iota (length lst))))

#(define (dynamic-text::structered-list
           separators fontsizes inner-kern outer-kern markup-commands idx strg)
  (let* ((ls (dynamics-list separators strg))
         (dynamic-fontsize (if (pair? fontsizes) (car fontsizes) #f))
         (dyn-mrkp-cmnd (car markup-commands))
         (dynamic-mrkp-cmnd
           (lambda (txt)
             (if (number? dynamic-fontsize)
                 (make-fontsize-markup dynamic-fontsize
                   (make-normal-text-markup (dyn-mrkp-cmnd txt)))
                 (make-normal-text-markup (dyn-mrkp-cmnd txt)))))
         (formated-dyns
           (dynamic-text::format-text
             fontsizes
             inner-kern
             outer-kern
             (cdr markup-commands)
             ls))
         (spaced-formated-dyns
           (list-insert-separator formated-dyns (make-simple-markup " ")))
         (spaced-plain
           (append-map
             (lambda (y) (if (markup-list? y) y (list y)))
             spaced-formated-dyns))
         (spaced-with-dyn
           (map
             (lambda (e)
               (if (string? e)
                   (dynamic-mrkp-cmnd e)
                   e))
             spaced-plain))
         (string-spaced-indices (get-string-indices spaced-plain))
         ;; if idx exceeds, print a warning and use first possible
         ;; dynamic
         ;; if idx is negative, due to (1- idx) in the function-body of dynamicH
         ;; return #f, same for if (null? string-spaced-indices). Meaning no
         ;; dynamics are indicated.
         ;; This will finally return (with dynamicH) a left align dynamic.
         (dyn-pos
           (cond ((or (negative? idx) (null? string-spaced-indices)) #f)
                 ((>= idx (length string-spaced-indices))
                   (begin
                     (ly:warning
                       "requested dynamic to align does not exist, ignoring")
                     (car string-spaced-indices)))
                 (else (list-ref string-spaced-indices idx))))
         ;(foo (format #t "##########: ~a\n"  dyn-pos))
         ;; NB: values!
         (splitted-at-dyn-index
           (if dyn-pos
               (split-at spaced-with-dyn dyn-pos)
               spaced-with-dyn)))
    (if (list? splitted-at-dyn-index)
        splitted-at-dyn-index
        (let-values (((before dyn&else) splitted-at-dyn-index))
          (cons*
             before
             (if (pair? dyn&else)
                 (list (car dyn&else) (cdr dyn&else))
                 dyn&else))))))

dynamicH =
#(define-event-function (parser location idx strg)
  ((index? 1) string?)
  "Returns customized DynamicText derived from @var{strg}.
Parts which should be rendered with as dynamics should be entered by
surrounding them with the elements of @code{details.separator-pair}, default is
@code{(cons #\\{ #\\})}.
The output is done by using the procedures from @code{details.markup-commands},
defaulting to @code{(cons make-dynamic-markup make-italic-markup)}.
Further customizing is possible by using
@code{details.dyn-rest-font-sizes}, needs a pair, default is unset
@code{details.inner-x-space}, needs a pair, default is unset
@code{details.outer-x-space}, needs a pair, default is is unset
The optional @var{idx} determines which dynamic part is centered under the
NoteColumn (in case @var{strg} contains multiple dynamics).
"
  (let* ((dynamic (make-music 'AbsoluteDynamicEvent))
         (tweak-proc
           (lambda (grob)
             (let* (
                    (separator-pair
                      (assoc-get
                        'separator-pair
                        (ly:grob-property grob 'details)
                        (cons #\{ #\})))
                    ;; get the fontsizes to use from the relevant
                    ;; details-sub-property, i.e. 'dyn-rest-font-sizes
                    (dyn-rest-font-sizes
                      (assoc-get
                        'dyn-rest-font-sizes
                        (ly:grob-property grob 'details)))
                    ;; get the markup-commands to use from the relevant
                    ;; details-sub-property, i.e. 'markup-commands, a pair
                    ;; car for dynamic, cdr for the rest
                    (markup-commands
                      (assoc-get
                        'markup-commands
                        (ly:grob-property grob 'details)
                        (cons make-dynamic-markup make-italic-markup)))
                    ;; get the pair-value to use for inserting some space to the
                    ;; left and/or right of the dynamic, usefull for bracketed
                    ;; dynamics or dynamics with punctuations
                    (inner-kern
                      (assoc-get
                        'inner-x-space
                        (ly:grob-property grob 'details)))
                    ;; get the pair-value to use for inserting some space
                    ;; between the dynamic expression and other text.
                    (outer-kern
                      (assoc-get
                        'outer-x-space
                        (ly:grob-property grob 'details)))
                    (stil-candidates
                      (dynamic-text::structered-list
                        separator-pair
                        dyn-rest-font-sizes
                        inner-kern
                        outer-kern
                        markup-commands
                        (1- idx)
                        strg))
                    (all-stils
                      (map
                        (lambda (mrkp)
                          (if (null? mrkp)
                              empty-stencil
                              (grob-interpret-markup grob
                                (if (markup-list? mrkp)
                                    (make-concat-markup mrkp)
                                    mrkp))))
                          stil-candidates))
                    (prev-self-alignment-X-tweaks
                      (filter
                        (lambda (tw)
                          (eq? (car tw) 'self-alignment-X))
                        (ly:prob-property
                          (ly:grob-property grob 'cause)
                          'tweaks))))

             (begin
               ;; Next line should be used for 2.19.65 and above
               ;(ly:grob-set-property! grob 'stencil
               ;  (stack-stencils X RIGHT 0 all-stils))
               ;; This line is for 2.18.2, though sometimes the offset in x-axis
               ;; is a little off
               (ly:grob-set-property! grob 'text
                 (make-stencil-markup (stack-stencils X RIGHT 0 all-stils)))
               ;; if previous tweak for self-alignment-X is present return '()
               (if (pair? prev-self-alignment-X-tweaks)
                   '()
                   (ly:grob-set-property! grob 'X-offset
                     (let* ((x-exts
                              (map
                                (lambda (stil) (ly:stencil-extent stil X))
                                (take all-stils 2)))
                            (x-par (ly:grob-parent grob X))
                            (parent-x-ext-center
                              (interval-center
                                (if (ly:grob-property grob
                                      'X-align-on-main-noteheads)
                                    (note-column::main-extent x-par)
                                    (ly:grob-extent x-par x-par X))))
                            ;; Get previous tweaks for X-offset and add their
                            ;; values
                            ;; They are added to the final result
                            (prev-x-offset-tweaks
                              (filter
                                (lambda (tw)
                                  (and (number? (cdr tw))
                                       (eq? (car tw) 'X-offset)))
                                (ly:prob-property
                                  (ly:grob-property grob 'cause)
                                  'tweaks)))
                            (prev-x-off
                              (apply + (map cdr prev-x-offset-tweaks))))
                       (if (markup-list? stil-candidates)
                           ;; For text only or if idx is set zero: align center.
                           ;; Also possible would be to left align, by switching
                           ;; to zero.
                           (ly:grob-property grob 'X-offset)
                           ;
                           (+
                              prev-x-off
                              (-
                                 parent-x-ext-center
                                 (interval-length (car x-exts))
                                 (/ (interval-length (second x-exts)) 2)
                                 (cond ((and (ly:stencil-empty? (car all-stils))
                                          (negative? (car (second x-exts))))
                                        (car (second x-exts)))
                                       ((negative? (car (first x-exts)))
                                        (car (first x-exts)))
                                       (else 0)))))))))))))

    (set! (ly:music-property dynamic 'tweaks)
          (acons 'before-line-breaking
                 tweak-proc
                 (ly:music-property dynamic 'tweaks)))
    dynamic))

harm6

Hallo,

es handelt sich ja um meinen code. Ich schau mir später an was mit neueren Versionen schief geht.
Aber wo hast Du ihn her??
Ich den Code nie lizensiert!!
Wenn dann GPL3.

-Harm

PietDip4

Hallo Harm,

ich habe den Code mal zufällig auf der Lilypond-E-Mail-Liste ohne Angabe einer Lizenz gefunden und von dort in eine Datei extrahiert. Ich war sehr froh über diesen Fund, denn dynamicH ist viel besser und einfacher als die Vorschläge aus der Lilypond-Schnipsel-Sammlung. Wäre super wenn sich dynamicH auch mit Lilypond 2.24/Guile 2 verwenden ließe. Lizenz kann ich gerne ändern. Bitte füge dazu in deine Antwort einen Patch ein, der den Fehler behebt und die Lizenz nach deinen Wünschen ändert.


Vielen Dank,

PietDip4

harm6

Zitatich habe den Code mal zufällig auf der Lilypond-E-Mail-Liste ohne Angabe einer Lizenz gefunden und von dort in eine Datei extrahiert.
Wahrscheinlich:
https://lists.gnu.org/archive/html/lilypond-user/2022-10/msg00127.html

Schau mal, ob folgendes besser funktioniert:
%%% -*- coding: utf-8 -*-
%%%
%%% Copyright © 2016-2024 Thomas "Harm" Morley <thomasmorley65@gmail.com>
%%%
%%% This program is free software: you can redistribute it and/or modify it
%%% under the terms of the GNU General Public License as published by
%%% the Free Software Foundation, either version 3 of the License, or
%%% (at your option) any later version.
%%% This program is distributed in the hope that it will be useful, but
%%% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
%%% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
%%% more details.
%%% You should have received a copy of the GNU General Public License along
%%% with this program. If not, see <https://www.gnu.org/licenses/>.

\version "2.25.12"

#(define (note-column::main-extent grob)
"Return extent of the noteheads in the 'main column', (i.e. excluding any
suspended noteheads), or extent of the rest (if there are no heads)."
  (let* ((note-heads (ly:grob-object grob 'note-heads))
         (stem (ly:grob-object grob 'stem))
         (rest (ly:grob-object grob 'rest)))
    (cond ((ly:grob-array? note-heads)
           (let (;; get the cdr from all note-heads-extents, where the car
                 ;; is zero
                 (n-h-right-coords
                   (filter-map
                     (lambda (n-h)
                       (let ((ext (ly:grob-extent n-h grob X)))
                          (and (= (car ext) 0) (cdr ext))))
                     (ly:grob-array->list note-heads))))
             ;; better be paranoid, find the max of n-h-right-coords and return
             ;; a pair with (cons 0 <max>)
             (cons 0.0 (reduce max 0 n-h-right-coords))))
          ((ly:grob? rest)
           (ly:grob-extent rest grob X))
          ;; better be paranoid
          (else '(0 . 0)))))

#(define remove-empty
  ;; Remove empty strings and empty lists from the given list 'lst'
  (lambda (lst)
    (remove
      (lambda (e)
        (or
          (and (string? e) (string-null? e))
          (and (list? e) (null? e))))
      lst)))

#(define char-set:dynamics
  (char-set #\f #\m #\p #\r #\s #\z))

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% DynamicText, created on the fly
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% Reads
%%%%  DynamicText.details.separator-pair
%%%%  DynamicText.details.dyn-rest-font-sizes
%%%%  DynamicText.details.markup-commands
%%%%  DynamicText.details.inner-x-space
%%%%  DynamicText.details.outer-x-space


#(use-modules (srfi srfi-11))
#(use-modules (ice-9 regex))

#(define (make-reg-exp separator-pair)
  (format #f "\\~a[^~a~a]*\\~a"
    (car separator-pair)
    (car separator-pair)
    (cdr separator-pair)
    (cdr separator-pair)))

#(define (dynamics-list separator-pair strg)
  (let ((reg-exp (make-reg-exp separator-pair))
        (separators (char-set (car separator-pair) (cdr separator-pair))))
    (map
      (lambda (s)
        (let* ((match (string-match reg-exp s)))
           (if match
               (let* ((poss-dyn (match:substring match))
                      (cand (string-trim-both poss-dyn separators)))
                 (if (string-every char-set:dynamics cand)
                       (list
                         (match:prefix match)
                         cand
                         (match:suffix match))
                     s))
               s)))
      (string-split strg #\space))))

#(define (dynamic-text::format-text
           fontsizes inner-kern outer-kern text-markup-command lst)
  (let* ((mrkp-cmnd
           (lambda (arg) (make-normal-text-markup (text-markup-command arg))))
         (txt-font-size (if (pair? fontsizes) (cdr fontsizes) #f))
         (txt-mrkp-cmnd
           (lambda (txt)
             (if (number? txt-font-size)
                 (make-fontsize-markup txt-font-size (mrkp-cmnd txt))
                 (mrkp-cmnd txt))))
         (left-out (if (pair? outer-kern) (car outer-kern) #f))
         (left-inner (if (pair? inner-kern) (car inner-kern) #f))
         (right-inner (if (pair? inner-kern) (cdr inner-kern) #f))
         (right-out (if (pair? outer-kern) (cdr outer-kern) #f))
         (space-mrkp-cmd
           (lambda (space)
             (if (number? space)
                 (txt-mrkp-cmnd (make-hspace-markup space))
                 ""))))
    (map
      (lambda (e)
        (if (list? e)
            (remove-empty
              (list
                (cond ((and (string-null? (car e)) (equal? e (car lst))) '())
                      ((string-null? (car e))
                        (space-mrkp-cmd left-out))
                      ((and (not (string-null? (car e))) (equal? e (car lst)))
                        (make-concat-markup
                        (remove-empty
                          (list
                            (txt-mrkp-cmnd (car e))
                            (space-mrkp-cmd left-inner)))))
                      (else
                        (make-concat-markup
                        (remove-empty
                          (list
                            (space-mrkp-cmd left-out)
                            (txt-mrkp-cmnd (car e))
                            (space-mrkp-cmd left-inner))))))
                (second e)
                (cond ((and (string-null? (last e)) (equal? e (last lst))) '())
                      ((string-null? (last e))
                        (space-mrkp-cmd right-out))
                      ((and (not (string-null? (last e)))
                            (equal? e (last lst)))
                        (make-concat-markup
                        (remove-empty
                          (list
                            (space-mrkp-cmd right-inner)
                            (txt-mrkp-cmnd (last e))))))
                      (else
                        (make-concat-markup
                        (remove-empty
                          (list
                            (space-mrkp-cmd right-inner)
                            (txt-mrkp-cmnd (last e))
                            (space-mrkp-cmd right-out))))))))
            (make-line-markup (list (txt-mrkp-cmnd e)))))
      lst)))

#(define (get-string-indices lst)
  (filter-map
    (lambda (e c) (if (string? e) c #f))
    lst
    (iota (length lst))))

#(define (dynamic-text::structered-list
           separators fontsizes inner-kern outer-kern markup-commands idx strg)
  (let* ((ls (dynamics-list separators strg))
         (dynamic-fontsize (if (pair? fontsizes) (car fontsizes) #f))
         (dyn-mrkp-cmnd (car markup-commands))
         (dynamic-mrkp-cmnd
           (lambda (txt)
             (if (number? dynamic-fontsize)
                 (make-fontsize-markup dynamic-fontsize
                   (make-normal-text-markup (dyn-mrkp-cmnd txt)))
                 (make-normal-text-markup (dyn-mrkp-cmnd txt)))))
         (formated-dyns
           (dynamic-text::format-text
             fontsizes
             inner-kern
             outer-kern
             (cdr markup-commands)
             ls))
         (spaced-formated-dyns
           (list-insert-separator formated-dyns (make-simple-markup " ")))
         (spaced-plain
           (append-map
             (lambda (y) (if (markup-list? y) y (list y)))
             spaced-formated-dyns))
         (spaced-with-dyn
           (map
             (lambda (e)
               (if (string? e)
                   (dynamic-mrkp-cmnd e)
                   e))
             spaced-plain))
         (string-spaced-indices (get-string-indices spaced-plain))
         ;; if idx exceeds, print a warning and use first possible
         ;; dynamic
         ;; if idx is negative, due to (1- idx) in the function-body of dynamicH
         ;; return #f, same for if (null? string-spaced-indices). Meaning no
         ;; dynamics are indicated.
         ;; This will finally return (with dynamicH) a left align dynamic.
         (dyn-pos
           (cond ((or (negative? idx) (null? string-spaced-indices)) #f)
                 ((>= idx (length string-spaced-indices))
                   (begin
                     (ly:warning
                       "requested dynamic to align does not exist, ignoring")
                     (car string-spaced-indices)))
                 (else (list-ref string-spaced-indices idx)))))
    (if dyn-pos
        (let* ((lst
                 (call-with-values
                   (lambda () (split-at spaced-with-dyn dyn-pos))
                   list))
               (lst-tail (cadr lst)))
          (cons*
            (car lst)
            (if (pair? lst-tail)
                (list (car lst-tail) (cdr lst-tail))
                lst-tail)))
        spaced-with-dyn)))

dynamicH =
#(define-event-function (parser location idx strg)
  ((index? 1) string?)
  "Returns customized DynamicText derived from @var{strg}.
Parts which should be rendered with as dynamics should be entered by
surrounding them with the elements of @code{details.separator-pair}, default is
@code{(cons #\\{ #\\})}.
The output is done by using the procedures from @code{details.markup-commands},
defaulting to @code{(cons make-dynamic-markup make-italic-markup)}.
Further customizing is possible by using
@code{details.dyn-rest-font-sizes}, needs a pair, default is unset
@code{details.inner-x-space}, needs a pair, default is unset
@code{details.outer-x-space}, needs a pair, default is is unset
The optional @var{idx} determines which dynamic part is centered under the
NoteColumn (in case @var{strg} contains multiple dynamics).
"
  (let* ((dynamic (make-music 'AbsoluteDynamicEvent))
         (tweak-proc
           (lambda (grob)
             (let* (
                    (separator-pair
                      (assoc-get
                        'separator-pair
                        (ly:grob-property grob 'details)
                        (cons #\{ #\})))
                    ;; get the fontsizes to use from the relevant
                    ;; details-sub-property, i.e. 'dyn-rest-font-sizes
                    (dyn-rest-font-sizes
                      (assoc-get
                        'dyn-rest-font-sizes
                        (ly:grob-property grob 'details)))
                    ;; get the markup-commands to use from the relevant
                    ;; details-sub-property, i.e. 'markup-commands, a pair
                    ;; car for dynamic, cdr for the rest
                    (markup-commands
                      (assoc-get
                        'markup-commands
                        (ly:grob-property grob 'details)
                        (cons make-dynamic-markup make-italic-markup)))
                    ;; get the pair-value to use for inserting some space to the
                    ;; left and/or right of the dynamic, usefull for bracketed
                    ;; dynamics or dynamics with punctuations
                    (inner-kern
                      (assoc-get
                        'inner-x-space
                        (ly:grob-property grob 'details)))
                    ;; get the pair-value to use for inserting some space
                    ;; between the dynamic expression and other text.
                    (outer-kern
                      (assoc-get
                        'outer-x-space
                        (ly:grob-property grob 'details)))
                    (stil-candidates
                      (dynamic-text::structered-list
                        separator-pair
                        dyn-rest-font-sizes
                        inner-kern
                        outer-kern
                        markup-commands
                        (1- idx)
                        strg))
                    (all-stils
                      (map
                        (lambda (mrkp)
                          (if (null? mrkp)
                              empty-stencil
                              (grob-interpret-markup grob
                                (if (markup-list? mrkp)
                                    (make-concat-markup mrkp)
                                    mrkp))))
                          stil-candidates))
                    (prev-self-alignment-X-tweaks
                      (filter
                        (lambda (tw)
                          (eq? (car tw) 'self-alignment-X))
                        (ly:prob-property
                          (ly:grob-property grob 'cause)
                          'tweaks))))

             (begin
               ;; Next line should be used for 2.19.65 and above
               (ly:grob-set-property! grob 'stencil
                 (stack-stencils X RIGHT 0 all-stils))
               ;; This line is for 2.18.2, though sometimes the offset in x-axis
               ;; is a little off
               ;(ly:grob-set-property! grob 'text
               ;  (make-stencil-markup (stack-stencils X RIGHT 0 all-stils)))
               ;; if previous tweak for self-alignment-X is present return '()
               (if (pair? prev-self-alignment-X-tweaks)
                   '()
                   (ly:grob-set-property! grob 'X-offset
                     (let* ((x-exts
                              (if (pair? (cdr all-stils))
                                  (map
                                    (lambda (stil) (ly:stencil-extent stil X))
                                    (take all-stils 2))
                                  (list (ly:stencil-extent (car all-stils) X))))
                            (x-par (ly:grob-parent grob X))
                            (parent-x-ext-center
                              (interval-center
                                (if (ly:grob-property grob
                                      'X-align-on-main-noteheads)
                                    (note-column::main-extent x-par)
                                    (ly:grob-extent x-par x-par X))))
                            ;; Get previous tweaks for X-offset and add their
                            ;; values
                            ;; They are added to the final result
                            (prev-x-offset-tweaks
                              (filter
                                (lambda (tw)
                                  (and (number? (cdr tw))
                                       (eq? (car tw) 'X-offset)))
                                (ly:prob-property
                                  (ly:grob-property grob 'cause)
                                  'tweaks)))
                            (prev-x-off
                              (apply + (map cdr prev-x-offset-tweaks))))
                       (if (markup-list? stil-candidates)
                           ;; For text only or if idx is set zero: align center.
                           ;; Also possible would be to left align, by switching
                           ;; to zero.
                           (ly:grob-property grob 'X-offset)
                           ;
                           (+
                              prev-x-off
                              (-
                                 parent-x-ext-center
                                 (interval-length (car x-exts))
                                 (/ (interval-length (second x-exts)) 2)
                                 (cond ((and (ly:stencil-empty? (car all-stils))
                                          (negative? (car (second x-exts))))
                                        (car (second x-exts)))
                                       ((negative? (car (first x-exts)))
                                        (car (first x-exts)))
                                       (else 0)))))))))))))

    (set! (ly:music-property dynamic 'tweaks)
          (acons 'before-line-breaking
                 tweak-proc
                 (ly:music-property dynamic 'tweaks)))
    dynamic))

HTH,
  Harm