Am So., 24. Mai 2020 um 16:36 Uhr schrieb Franz-Rudolf Kuhnen <p...@kuhnen-musik.de>: > > 914/5000 > > Hi, > > I'm in the process of transcribing the suites from Charles Dieupart from the > original. Like Rameau, Dieupart also uses special ornaments that are aligned > directly with the notehead. ("Port de voix" and "Pincé"). > > I found an interesting article about the realization under Lilypond by > Nicolas Sceaux: > https://lilypondblog.org/2013/08/adding-ornamentations-to-note-heads-part-1/ > > This is actually exactly what I need. Unfortunately, this method no longer > works with lilypond-2.20. Lilypond reports > > > "Warning: Type check for" HeadOrnamation "failed; value" # <Grob_properties> > "must be of the type" list " > Interpretation of the music ... > Programming error: No rough definition found for `HeadOrnamation’. > Continued, fingers crossed " > > Crossing the fingers didn't help. :-( > > Maybe someone can help me. > > Thank you in advance. > > > > Regards > > Franz-Rudolf
Iirc switch (set-object-property! grob-name 'translation-type? list?) to (set-object-property! grob-name 'translation-type? ly:grob-properties?) and you're done. Attached my version of his code working with 2.20.0. Please compare with his original, I don't remember, if I changed other things (for testings or the like). The provided examples are demonstrating some issues ... Cheers, Harm
\version "2.19.42" %% taken from: %% https://github.com/nsceaux/nenuvar/blob/master/common/side-ornementations.ily %% and adapted for v2.19.42 %%% %%% Utilities for defining new grobs, grob properties and music event types %%% (there should be built-in commands to do that in LilyPond) %%% #(define (define-grob-definition grob-name grob-entry) "Define a new grob and add it to `all-grob-definitions', after scm/define-grobs.scm fashion. After grob definitions are added, use: \\layout { \\context { \\Global \\grobdescriptions #all-grob-descriptions } } to register them." (let* ((meta-entry (assoc-get 'meta grob-entry)) (class (assoc-get 'class meta-entry)) (ifaces-entry (assoc-get 'interfaces meta-entry))) (set-object-property! grob-name 'translation-type? ly:grob-properties?) (set-object-property! grob-name 'is-grob? #t) (set! ifaces-entry (append (case class ((Item) '(item-interface)) ((Spanner) '(spanner-interface)) ((Paper_column) '((item-interface paper-column-interface))) ((System) '((system-interface spanner-interface))) (else '(unknown-interface))) ifaces-entry)) (set! ifaces-entry (uniq-list (sort ifaces-entry symbol<?))) (set! ifaces-entry (cons 'grob-interface ifaces-entry)) (set! meta-entry (assoc-set! meta-entry 'name grob-name)) (set! meta-entry (assoc-set! meta-entry 'interfaces ifaces-entry)) (set! grob-entry (assoc-set! grob-entry 'meta meta-entry)) (set! all-grob-descriptions (cons (cons grob-name grob-entry) all-grob-descriptions)))) #(define-public (define-grob-property symbol type? description) "Define a new grob property. `symbol': the property name `type?': the type predicate for this property `description': the type documentation" (set-object-property! symbol 'backend-type? type?) (set-object-property! symbol 'backend-doc description) symbol) #(define-public (define-music-type type-name properties) "Add a new music type description to `music-descriptions' and `music-name-to-property-table'." (set-object-property! type-name 'music-description (cdr (assq 'description properties))) (let ((properties (list-copy properties))) (set! properties (assoc-set! properties 'name type-name)) (set! properties (assq-remove! properties 'description)) (hashq-set! music-name-to-property-table type-name properties) (set! music-descriptions (cons (cons type-name properties) music-descriptions)))) %%% %%% HeadOrnementation grob type %%% #(define (head-ornementation::print me) "Prints a HeadOrnementation grob (at a note head side)" (let* ((notes (ly:grob-object me 'elements)) (staff-pos (ly:grob-staff-position (ly:grob-array-ref notes 0))) (y-ref (ly:grob-common-refpoint-of-array me notes Y)) (x-ref (ly:grob-common-refpoint-of-array me notes X)) (x-ext (ly:relative-group-extent notes x-ref X)) (y-ext (ly:relative-group-extent notes y-ref Y)) (y-coord (+ (interval-center y-ext) (if (and (eq? (ly:grob-property me 'shift-when-on-line) #t) (memq staff-pos '(-2 0 2))) 0.5 0))) (padding (ly:grob-property me 'padding 0.1)) (direction (ly:grob-property me 'direction LEFT)) (text (ly:text-interface::print me)) (width (/ (interval-length (ly:stencil-extent text X)) 2.0)) (x-coord (if (= direction LEFT) (- (car x-ext) width padding) (+ (cdr x-ext) width padding)))) (ly:stencil-translate text (cons (- x-coord (ly:grob-relative-coordinate me x-ref X)) (- y-coord (ly:grob-relative-coordinate me y-ref Y)))))) %% a new grob property (used to shift an ornementation when the %% note head is on a staff line) #(define-grob-property 'shift-when-on-line boolean? "If true, then the ornementation is vertically shifted when the note head is on a staff line.") %% HeadOrnemenation grob definition: %% a piece of text attached to a note head side. #(define-grob-definition 'HeadOrnementation `((font-size . 0) (padding . 0.1) (shift-when-on-line . #f) (stencil . ,head-ornementation::print) (meta . ((class . Item) (interfaces . (font-interface)))))) \layout { \context { \Global \grobdescriptions #all-grob-descriptions } } %%% Head-ornementation Engraver %%% #(define (make-head-ornementation engraver note-grob markp direction is-inside shift-on-line) "Creates a HeadOrnementation grob attached to a note head. `note-grob': the note head the ornementation is attached to `markp': the ornementation markup `direction': where the ornementation should be printed (LEFT or RIGHT of the note head) `is-inside': if true, then the ornemenation is printed between accidental or dots and the note head (in this case the accidental or dots are shifted to the outside); otherwise it is printed outside dots or accidentals. `shift-on-line': if true, and when the note head is on a staff line, then the ornementation is vertically shifted." (let ((ornementation (ly:engraver-make-grob engraver 'HeadOrnementation note-grob))) (set! (ly:grob-property ornementation 'direction) direction) (set! (ly:grob-property ornementation 'text) markp) (set! (ly:grob-property ornementation 'shift-when-on-line) shift-on-line) (ly:pointer-group-interface::add-grob ornementation 'elements note-grob) (set! (ly:grob-parent ornementation Y) note-grob) (set! (ly:grob-property ornementation 'font-size) (+ (ly:grob-property ornementation 'font-size 0.0) (ly:grob-property note-grob 'font-size 0.0))) (let* ((orn-stencil (ly:text-interface::print ornementation)) (orn-width (interval-length (ly:stencil-extent orn-stencil X))) (note-column (ly:grob-object note-grob 'axis-group-parent-X)) (accidentals (ly:note-column-accidentals note-column)) (dot-column (ly:note-column-dot-column note-column)) (dot-column-x-off (if (ly:grob? dot-column) (ly:grob-property dot-column 'X-offset 'foo) 0))) ;(format #t "\naccidentals: ~a" accidentals) (cond ;((and (= direction LEFT) (ly:grob? accidentals) is-inside) ; ;; if ornementation on the left side of the note is "inside", ; ;; then shift the accidental to the left to make room for ; ;; the ornementation ; (set! ;(ly:grob-property accidentals 'padding) ; (ly:grob-property accidentals 'right-padding) ; ;(ly:grob-property accidentals 'X-offset) ; ;(ly:grob-property note-column 'X-offset) ; (+ orn-width (* 2 (ly:grob-property ornementation 'padding))))) ((and (= direction RIGHT) (ly:grob? dot-column) is-inside) ;; if ornementation on the right side of the note is "inside", ;; then shift the dots to the right to make room for ;; the ornementation ;; see discussion at ;; http://lilypond.1069038.n5.nabble.com/crash-moving-DotColumn-td190493.html (set! (ly:grob-property dot-column 'positioning-done) (lambda (grob) (ly:dot-column::calc-positioning-done grob) (ly:grob-translate-axis! grob orn-width X) #t))))) ornementation)) #(define (head-ornementation-engraver-acknowledge-note-head engraver note-grob source-engraver) "Note head acknowledge method for the head ornementation engraver. When the note head event attached to the note head grob has ornementation events among its articulations, then create a HeadOrnementation grob" (let* ((note-event (ly:grob-property note-grob 'cause))) (for-each (lambda (articulation) (if (memq 'head-ornementation-event (ly:event-property articulation 'class)) (begin (if (markup? (ly:event-property articulation 'text-left)) (make-head-ornementation engraver note-grob (ly:event-property articulation 'text-left) LEFT (ly:event-property articulation 'is-inside) (ly:event-property articulation 'shift-when-on-line))) (if (markup? (ly:event-property articulation 'text-right)) (make-head-ornementation engraver note-grob (ly:event-property articulation 'text-right) RIGHT (ly:event-property articulation 'is-inside) (ly:event-property articulation 'shift-when-on-line))) ))) (ly:event-property note-event 'articulations)))) %% The head-ornementation engraver, with its note-head acknowledger %% (which creates the HeadOrnementation grobs) #(define head-ornementation-engraver `((acknowledgers (note-head-interface . ,head-ornementation-engraver-acknowledge-note-head)))) \layout { \context { \Score \consists #head-ornementation-engraver } } %%% %%% HeadOrnementationEvent definition %%% #(define-event-class 'head-ornementation-event 'music-event) %% a post script event for ornementations attached to note heads #(define-music-type 'HeadOrnementationEvent '((description . "Print an ornementation at a note head side") (types . (general-music post-event event head-ornementation-event)))) %%% %%% Head ornementation music functions %%% %% Helper music function for defining head-ornementation events #(define (make-head-ornementation-event text-left text-right is-inside shift-on-line) "Makes a head ornementation" (make-music 'HeadOrnementationEvent 'text-left text-left 'text-right text-right 'is-inside is-inside 'shift-when-on-line shift-on-line)) #(define (make-left-head-ornementation-event text is-inside shift-on-line) "Makes a head ornementation" (make-head-ornementation-event text #f is-inside shift-on-line)) #(define (make-right-head-ornementation-event text is-inside shift-on-line) "Makes a head ornementation" (make-head-ornementation-event #f text is-inside shift-on-line)) %%% %%% Ornementation definitions %%% %% Parenthesis before note head parb = #(make-left-head-ornementation-event (markup #:fontsize -4 #:musicglyph "accidentals.leftparen") #t #f) %% Parenthesis after note head para = #(make-right-head-ornementation-event (markup #:fontsize -4 #:musicglyph "accidentals.rightparen") #t #f) %% Parenthesis before and after note head parc = #(make-head-ornementation-event (markup #:fontsize -4 #:musicglyph "accidentals.leftparen") (markup #:fontsize -4 #:musicglyph "accidentals.rightparen") #t #f) %% Prall after note head pralla = #(make-right-head-ornementation-event (markup #:concat (#:hspace 0.2 #:musicglyph "scripts.prall")) #t #t) %% Prall before note head prallb = #(make-left-head-ornementation-event (markup #:concat (#:musicglyph "scripts.prall" #:hspace 0.2)) #t #t) %% ^ sign after note head circA = #(make-right-head-ornementation-event (markup #:concat (#:hspace 1 #:raise 0.5 #:musicglyph "scripts.umarcato")) #f #f) %%%%%%%%%%%% %% TEST %%%%%%%%%%%% { a'4.\para gis'8\parb a'2\parc } { a'4.\pralla gis'8\prallb \voiceOne \textLengthOff %% TODO: DotColumn is moved too much <>^\markup { \with-color #red \fontsize #4 "!" } < gis' a' c''\pralla e''\pralla >4. aes'8\prallb } { a'4.\circA a' } %% Your example \markup "\\shape the Slur" \relative c'' { g8 a!16 b^( a4.)\parb \prall b8 } \markup "In my printed edition (Henle Urtext 1956/1984) it looks more like:" pard = #(make-left-head-ornementation-event (markup #:raise 0.3 #:rotate 80 #:concat ( #:fontsize -4 #:musicglyph "accidentals.leftparen" #:hspace 0.3 #:raise 0.05 #:fontsize -4 #:musicglyph "accidentals.rightparen" #:hspace -0.4)) #t #f) \relative c'' { g8 a!16 b \override Staff.NoteColumn.X-offset = #0.5 a4.\pard \prall b8 } po = #(make-left-head-ornementation-event (markup #:override '(thickness . 2) #:draw-line '(-1 . -0.5)) #t #f) { \key ces \major %\override HeadOrnementation.padding = 25 \override Score.HeadOrnementation.extra-offset = #'(-4.5 . 0) %\override Score.HeadOrnementation.padding = 3.5 \override Score.HeadOrnementation.color = #red %\override Score.HeadOrnementation.X-offset = -3.5 < cis' eis'\po gis' >\arpeggio }