openlilylib / snippets

A place to store useful pieces of LilyPond code - custom functions, engravers, hacks, templates, examples etc.
Other
119 stars 39 forks source link

“Wrong type argument” when pasting bending snippet into a tablature #175

Closed Beakerboy closed 4 years ago

Beakerboy commented 4 years ago

I have taken the bending.ily and bends.ly files and combined them together, removing the calls to \include \useModule and \useLibrary

When compiling the combined file, I’m given the following error:

Wrong type argument in position 1 (expecting Prob): #f

This corresponds with the line:

(right-pitch (ly:event-property (event-cause right-bound) 'pitch))

Beakerboy commented 4 years ago

It appears to be the semitone bends causing the error. If \bendOff is added before that line, and then \bendOn is added after it, the file renders without error. Does the example file need to have that line commented out? I’m using Lilypond 2.20.0. The microtones snippet stated that microtones support is in lilypond core.

fedelibre commented 4 years ago

I haven't checked but I think the snippet in this repository is not up-to-date.

And you seem to want to use a simple .ly file without the Openlilylib infrastructure. Then I suggest you clone the default repository for the bend spanner. You can find more information in this blog post.

I can compile my scores fine using LilyPond 2.20.

Beakerboy commented 4 years ago

Thanks for the quick reply. I’ve looked at the bend spanner too, and it displays 1/4 bends without error. I just wish there was a way to add a quarter bend as a decoration to a note without having to specify the duration of the fretted and semitone notes. Every guitar tab I’ve ever seen does not display the semitone note on a quarter bend.

fedelibre commented 4 years ago

Specifying the duration in the lilypond input and controlling the display of notes are two different matters. The first is mandatory, while the second can be adjusted by the user. But I may have not well understood your question.

If you want to give feedback on the bend spanner, please write to the lilypond-user mailing list, where Harm - the original author of the code - will be happy to answer your questions.

I'm closing this issue.

Beakerboy commented 4 years ago

Surprised that you’re closing this when you acknowledge the snippet is out of date and causes errors for users.

fedelibre commented 4 years ago

I think this snippet should be removed from openlilylib. Or maybe a warning might be added in the README. IIRC it was kept mainly for people using lilypond 2.18. The code should be developed in one place, that is the repository on pagure.io.

There's only one person hacking on this bending code. He doesn't follow github nor pagure.io. The only way to send feedback and requests to Harm is writing on lilypond-user. My role is only maintaining the repository up-to-date with his work.

If any valid feature request comes up,I can add it to the tracker in the pagure repository. @Beakerboy that's why I suggested to write on lilypond-user

I suggest you write a minimal example and show exactly what doesn't work for you, because it's not easy to understand.

Beakerboy commented 4 years ago

Changing cis to cih in the test section causes the script to fail. The snippet, as published, has cih, which causes it to always fail.

%%% sizes and values (to be changed/adapted):

#(define bend-line-thickness 0.1)

#(define bend-arrow-curvature-factor 0.35)

#(define y-distance-from-tabstaff-to-arrow-tip 2.75)

#(define consecutive-bends-arrow-height 2.75)

#(define bend-arrowhead-height 1.25)

#(define bend-arrowhead-width 0.8)

#(define y-distance-from-staffline-to-arrow 0.35)

%%% internal commands
#(define (quarterdiff->string quarterdiff)
   (let ((wholesteps (floor (/ quarterdiff 4))))

     (string-append (case wholesteps
                      ((0) "")
                      (else (number->string wholesteps)))
       (case (modulo quarterdiff 4)
         ((1) "¼")
         ((2) "½")
         ((3) "¾")
         (else "")))))

%%% markup commands

#(define-markup-command (pointedSlur layout props thickness bx by mx my ex ey)
   (number? number? number? number? number? number? number?)
   (interpret-markup layout props
     (markup #:postscript
       (ly:format "~f setlinewidth
                        ~f ~f moveto
                        ~f ~f lineto
                        ~f ~f lineto stroke" thickness bx by mx my ex ey))))

#(define-markup-command (drawBendArrow layout props
                          thickness begin-x middle-x end-x begin-y end-y arrow-lx arrow-rx arrow-y outstring)
   (number? number? number? number? number? number? number? number? number? string?)
   (interpret-markup layout props
     (markup #:postscript
       (ly:format "~f setlinewidth
                        ~f ~f moveto
                        ~f ~f lineto
                        ~f ~f ~f ~f ~f ~f curveto
                        stroke
                        ~f ~f moveto
                        ~f ~f lineto
                        ~f ~f lineto
                        closepath fill"
thickness
begin-x begin-y
middle-x begin-y
middle-x begin-y end-x begin-y end-x arrow-y
arrow-lx arrow-y
end-x end-y
arrow-rx arrow-y)
       #:hspace 0
       #:translate (cons (- end-x 1.2) (+ end-y 0.5))
       #:fontsize -2
       #:bold
       ;; changed:
       ;#:center-column (outstring)
       outstring
       )))
#(define-markup-command (drawHoldBendWithArrow layout props
                          thickness begin-x begin-y end-x end-y arrow-lx arrow-rx arrow-y outstring)
   (number? number? number? number? number? number? number? number? string?)
   (interpret-markup layout props
     (markup #:postscript
       (ly:format "~f setlinewidth
                        ~f ~f moveto
                        ~f ~f lineto
                        stroke
                        ~f ~f moveto
                        ~f ~f lineto
                        ~f ~f lineto
                        closepath fill
                        ~f ~f moveto
                        ~f ~f lineto
                        stroke"
thickness
begin-x begin-y
begin-x arrow-y
arrow-lx arrow-y
begin-x end-y
arrow-rx arrow-y
begin-x end-y
end-x end-y)
       #:hspace 0
       #:translate (cons (- begin-x 1.2) (+ end-y 0.5))
       #:fontsize -2
       ;; Why does it work here??
       #:bold #:center-column (outstring))))

#(define-markup-command (drawHoldBendArrowOnly layout props
                          thickness begin-x begin-y end-x end-y arrow-lx arrow-rx arrow-y outstring)
   (number? number? number? number? number? number? number? number? string?)
   (interpret-markup layout props
     (markup #:postscript
       (ly:format "~f setlinewidth
                        ~f ~f moveto
                        ~f ~f lineto
                        stroke
                        ~f ~f moveto
                        ~f ~f lineto
                        ~f ~f lineto
                        closepath fill"
thickness
begin-x begin-y
begin-x arrow-y
arrow-lx arrow-y
begin-x end-y
arrow-rx arrow-y)
       #:hspace 0
       #:translate (cons (- begin-x 1.2) (+ end-y 0.5))
       #:fontsize -2
       ;; Why does it work here??
       #:bold #:center-column (outstring))))

%% The markup-command 'draw-dashed-line' was implemented with version 2.17.x
%% TODO: use 'draw-dashed-line' instead. See also 'tie::draw-hold-bend' below.
#(define-markup-command (drawDashedLine layout props
                          thickness begin-x end-x line-y)
   (number? number? number? number?)
   ;; TODO: draws a full line instead of a dashed line
   (interpret-markup layout props
     (markup #:postscript
       (ly:format "~f setlinewidth
                        ~f ~f moveto
                        ~f ~f lineto
                        stroke"
thickness begin-x line-y end-x line-y))))

%%% callbacks

#(define (slur::draw-pointed-slur grob)
   (let* ((control-points (ly:grob-property grob 'control-points))
          (direction (ly:grob-property grob 'direction))
          (first-point (car control-points))
          (second-point (cadr control-points))
          (third-point (caddr control-points))
          (forth-point (cadddr control-points))
          (first-x (+ (car first-point) 0.125)) ;; due to David's proposals
          (first-y (cdr first-point))
          (second-x (car second-point))
          (second-y (cdr second-point))
          (third-x (car third-point))
          (third-y (cdr third-point))
          (forth-x (- (car forth-point) 0.125))
          (forth-y (cdr forth-point))

          (middle-x (/ (+ third-x second-x) 2))
          (middle-y (/ (+ third-y second-y) 2)))

     (grob-interpret-markup grob
       (make-pointedSlur-markup bend-line-thickness
         first-x first-y middle-x middle-y forth-x forth-y))))

#(define (slur::draw-bend-arrow grob)
   (let* ((staff-symbol (ly:grob-object grob 'staff-symbol))
          (line-count (ly:grob-property staff-symbol 'line-count))
          (staff-space (ly:grob-property staff-symbol 'staff-space))
          (left-bound (ly:spanner-bound grob LEFT))
          (right-bound (ly:spanner-bound grob RIGHT))
          (left-tab-note-head (ly:grob-property left-bound 'cause))
          (right-tab-note-head (ly:grob-property right-bound 'cause))
          (control-points (ly:grob-property grob 'control-points))
          (left-point (car control-points))
          ;; changed: cadddr changed to last
          (right-point (last control-points))
          (left-pitch  (ly:event-property (event-cause left-bound) 'pitch))
          (right-pitch (ly:event-property (event-cause right-bound) 'pitch))
          (quarterdiff (- (ly:pitch-quartertones right-pitch)
                         (ly:pitch-quartertones left-pitch)))
          (begin-x (car left-point))
          (begin-y (+ (* (/ (ly:grob-property left-tab-note-head 'staff-position) 2)
                        staff-space)
                     y-distance-from-staffline-to-arrow))
          ;; cdr left-point doesn't work, because invisible stems are included
          (end-x (car right-point))
          (end-y (+ (* (/ (- line-count 1) 2) staff-space) y-distance-from-tabstaff-to-arrow-tip))
          (arrow-lx (- end-x (/ bend-arrowhead-width 2)))
          (arrow-rx (+ end-x (/ bend-arrowhead-width 2)))
          (arrow-y (- end-y bend-arrowhead-height))
          (middle-x (+ begin-x (* bend-arrow-curvature-factor (- end-x begin-x))))
          (bend-amount (quarterdiff->string quarterdiff)))

     (if (< quarterdiff 0)
         ;; bend down
         (let* ((y-offset (cdr (ly:grob-extent left-tab-note-head left-tab-note-head Y)))
                (temp begin-y))
           (set! begin-y end-y) ;; swap begin-y/end-y
           (set! end-y (+ temp y-offset))
           (set! arrow-y (+ end-y bend-arrowhead-height))
           (set! bend-amount "")
           (ly:grob-set-property! right-tab-note-head 'display-cautionary #t)
           (ly:grob-set-property! right-tab-note-head 'stencil tab-note-head::print))
         ;; bend up
         (let* ((x-offset (/ (cdr (ly:grob-extent left-tab-note-head left-tab-note-head X))
                            2)))

           (set! begin-x (+ begin-x x-offset))
           (for-each
             (lambda (tab-note-head)
               (if (grob::has-interface tab-note-head 'tab-note-head-interface)
                   (ly:grob-set-property! tab-note-head 'transparent #t)))
             (ly:grob-array->list (ly:grob-object right-bound 'note-heads)))))

     ;; draw resulting bend arrow
     (grob-interpret-markup grob
       (make-drawBendArrow-markup
        0.1
        begin-x middle-x end-x begin-y end-y
        arrow-lx arrow-rx arrow-y
        bend-amount))))

%%% music functions

bendOn =
#(define-music-function (parser location note) (ly:music?)
#{
  \override Voice.Slur #'stencil = #slur::draw-pointed-slur
  \override TabVoice.Slur #'stencil = #slur::draw-bend-arrow
  $note \noBreak
#})

\layout {
  \context {
    \Staff
    \override StringNumber #'stencil = ##f
    \override VerticalAxisGroup #'default-staff-staff-spacing =
    #'((basic-distance . 12)
       (minimum-distance . 12)
       (padding . 1))
  }
}

% TODO: this should be split into separate cases, and
% comments turned into description markups:

test = \relative c'' {
  \bendOn
  % quarter tone bends are not yet supported as they should be, but
  % the bend amount is calculated correctly ;-)
  c,4\2 ( cis\2 )
}

\markup \wordwrap {
  The coordinates of the point are half-way between the
  second and the third point of the control points for the slur's bezier
  curve.
}

\score {
  <<
    \new Staff {
      \new Voice {
        \clef "G_8"
        \test
      }
    }
    \new TabStaff {
      \new TabVoice {
        \clef "tab"
        \test
      }
    }
  >>
}