On 09/09/2016 05:27 PM, Thomas Morley wrote:

Attached you'll find a different version.

I noticed that text-only tempos (\tempo "Andante") caused problems. See attached revision which fixes this. It also has improved code for detecting a missing initial tempo (to then supply the default one). See attached diff file for changes.

Cheers,
-Paul
\version "2.19.47"

printScoreDuration = {
  \once \override Score.RehearsalMark.direction = #DOWN
  \once \override Score.RehearsalMark.self-alignment-X = #RIGHT
  \mark "print-score-duration"
}

formatScoreDuration =
#(define-scheme-function (dur)(exact?)
   "Returns the given duration as a formated markup containing minutes and
seconds."
   (let* ((minutes (floor dur))
          ;; Is using floor correct?
          (seconds (floor (* (- dur minutes ) 60)))
          (duration-string
           (format #f "Duration: ~a:~2,,,'0@a" minutes seconds)))
     #{
       \markup \rounded-box \fontsize #-3 #duration-string
     #}))

#(define (get-seconds lst rl)
   "Takes a list of kind
'((#<Mom 17> 1/15) 
  (#<Mom 31/2> 1/30) 
  (#<Mom 0> 1/15))
Calculates the time passed between each moment.
Returns the addition of it as an exact numerical value.
  "
   (if (null? (cdr lst))
       (apply + rl)
       (get-seconds
        (cdr lst)
        (cons
         (* (cdr (cadr lst))
           (ly:moment-main (ly:moment-sub (caar lst) (caadr lst))))
         rl))))


#(define (score-duration-engraver context)
   (let* ((evts '())
          (last-evt #f)
          (tempo-change-evts '())
          (duration-marks '()))
     (make-engraver
      (listeners
       ((rhythmic-event engraver event)
        (set! last-evt (ly:event-property event 'length))
        (set! evts (cons (ly:context-current-moment context) evts)))
       ((tempo-change-event engraver event)
        (let ((tempo-unit (ly:event-property event 'tempo-unit))
              (metronome-count (ly:event-property event 'metronome-count)))
          ;; Accumulate pairs of "moment when it happens" and
          ;; "quotient of tempo-unit and metronome-count"in `tempo-change-evts'
          ;; for use in `get-seconds'
          ;; text-only tempo changes like \tempo "Andante" have no tempo-unit
          (if (and tempo-unit metronome-count)
              (set! tempo-change-evts
                    (cons
                     (cons
                      (ly:context-current-moment context)
                      ;; Hmm, ugly code...
                      (/ (string->number (ly:duration->string tempo-unit))
                        metronome-count))
                     tempo-change-evts))))))
      (acknowledgers
       ((mark-interface engraver grob source-engraver)
        (let ((mark-text (ly:grob-property grob 'text)))
          (if (and (string? mark-text)
                   (string=? mark-text "print-score-duration"))
              (set! duration-marks (cons grob duration-marks))))))
      ((finalize translator)
       (if (not (null? duration-marks))
           (let* ((moment-zero (ly:make-moment 0))
                  ; add default tempo at moment zero, if one does not already exist
                  (tempo-changes
                   (if (or (null? tempo-change-evts)
                           (not (equal? moment-zero
                                        (car (last tempo-change-evts)))))
                       ;; 1/15 is default tempo, could this be accessed somewhere?
                       (append tempo-change-evts (list (cons moment-zero 1/15)))
                       tempo-change-evts))
                  (duration-before-last-tempo-change
                   (get-seconds tempo-changes '()))
                  (duration-after-last-tempo-change-without-last-dur
                   (* (cdr (car tempo-changes))
                     (ly:moment-main
                      (ly:moment-sub (car evts) (caar tempo-changes)))))
                  (last-ev-duration
                   (* (cdar tempo-changes) (ly:moment-main last-evt)))
                  (final-duration
                   (+
                    duration-before-last-tempo-change
                    duration-after-last-tempo-change-without-last-dur
                    last-ev-duration)))
             (for-each
              (lambda (g)
                (ly:grob-set-property! g 'text
                  (formatScoreDuration final-duration)))
              duration-marks)
             (set! evts '())
             (set! last-evt #f)
             (set! tempo-change-evts '())
             (set! duration-marks '())))))))

\layout {
  \context {
    \Score
    \consists \score-duration-engraver
  }
}

%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%

voiceI =
\new Voice {
  \partial 4
  c'4
  \repeat unfold 61 c'4
  \tempo 4=120
  c'2. d'2
  \tempo 8=120
  c'2~ |
  \tuplet 3/2 { c'2 2 2 }
  \tempo "Andante"
  c'2 c'2
}

voiceII = {
  \partial 4
  cis'4
  \printScoreDuration
  \repeat unfold 17 cis'1
  %% fiddling with two simultaneous RehearsalMarks...
  cis'1*31/32
  \printScoreDuration
  s1*1/32
  \mark \default
  cis'1
}

\score {
  <<
    \voiceI
    \voiceII
  >>
  \layout { }
  \midi {}
}
51,54c51
<         (let ((tempo-unit
<                ;; Hmm, ugly code...
<                (string->number
<                 (ly:duration->string (ly:event-property event 'tempo-unit))))
---
>         (let ((tempo-unit (ly:event-property event 'tempo-unit))
59,64c56,66
<           (set! tempo-change-evts
<                 (cons
<                  (cons
<                   (ly:context-current-moment context)
<                   (/ tempo-unit metronome-count))
<                  tempo-change-evts)))))
---
>           ;; text-only tempo changes like \tempo "Andante" have no tempo-unit
>           (if (and tempo-unit metronome-count)
>               (set! tempo-change-evts
>                     (cons
>                      (cons
>                       (ly:context-current-moment context)
>                       ;; Hmm, ugly code...
>                       (/ (string->number (ly:duration->string tempo-unit))
>                         metronome-count))
>                      tempo-change-evts))))))
72,95c74,96
<        (if duration-marks
<            (let* (;; default tempo, could this be grapped somewhere?
<                    (default-tempo-setting (cons (ly:make-moment 0) 1/15))
<                    ; add default tempo, if not introduced at score-begin
<                    (tempo-changes
<                     (if (or (null? tempo-change-evts)
<                             (not (equal? (last tempo-change-evts)
<                                          default-tempo-setting)))
<                         (append
<                          tempo-change-evts (list default-tempo-setting))
<                         tempo-change-evts))
---
>        (if (not (null? duration-marks))
>            (let* ((moment-zero (ly:make-moment 0))
>                   ; add default tempo at moment zero, if one does not already exist
>                   (tempo-changes
>                    (if (or (null? tempo-change-evts)
>                            (not (equal? moment-zero
>                                         (car (last tempo-change-evts)))))
>                        ;; 1/15 is default tempo, could this be accessed somewhere?
>                        (append tempo-change-evts (list (cons moment-zero 1/15)))
>                        tempo-change-evts))
126a128,129
>   \tempo "Andante"
>   c'2 c'2
139c142
< 
---
>   cis'1
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to