X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scm%2Ftranslation-functions.scm;h=33acfbc7b42178a6f2c5ca585a989d73d6c27bdf;hb=c11f496ac9e637cf9a6c6794c631b148560548fa;hp=314e66ff59b8783263efcbcaa36f0f721a240f18;hpb=7129b9a1b73c400593ccc08418b294afef1513a1;p=lilypond.git diff --git a/scm/translation-functions.scm b/scm/translation-functions.scm index 314e66ff59..33acfbc7b4 100644 --- a/scm/translation-functions.scm +++ b/scm/translation-functions.scm @@ -1,6 +1,6 @@ ;;;; This file is part of LilyPond, the GNU music typesetter. ;;;; -;;;; (c) 1998--2011 Han-Wen Nienhuys +;;;; (c) 1998--2012 Han-Wen Nienhuys ;;;; Jan Nieuwenhuizen ;;;; ;;;; LilyPond is free software: you can redistribute it and/or modify @@ -276,13 +276,17 @@ dot placement entries." along with @var{minimum-fret}, @var{maximum-stretch}, and @var{tuning}. Returns a list of @code{(string fret finger) lists." + + (define restrain-open-strings (ly:context-property context + 'restrainOpenStrings + #f)) (define specified-frets '()) (define free-strings (iota (length tuning) 1)) (define (calc-fret pitch string tuning) "Calculate the fret to play @var{pitch} on @var{string} with @var{tuning}." - (- (ly:pitch-semitones pitch) (ly:pitch-semitones (list-ref tuning (1- string))))) + (* 2 (- (ly:pitch-tones pitch) (ly:pitch-tones (list-ref tuning (1- string)))))) (define (note-pitch note) "Get the pitch (in semitones) from @var{note}." @@ -296,7 +300,7 @@ if no fingering is present." (map (lambda (art) (let* ((num (ly:event-property art 'digit))) - (if (and (eq? 'fingering-event (ly:event-property art 'class)) + (if (and (ly:in-event-class? art 'fingering-event) (number? num) (> num 0)) (set! finger-found num)))) @@ -326,6 +330,8 @@ if no string-number is present." #t (map (lambda (specced-fret) (or (eq? 0 specced-fret) + (and (not restrain-open-strings) + (eq? 0 fret)) (>= maximum-stretch (abs (- fret specced-fret))))) specified-frets)))) @@ -333,7 +339,10 @@ if no string-number is present." "Can @var{pitch} be played on @var{string}, given already placed notes?" (let* ((fret (calc-fret pitch string tuning))) - (and (>= fret minimum-fret) + (and (or (and (not restrain-open-strings) + (eq? fret 0)) + (>= fret minimum-fret)) + (integer? fret) (close-enough fret)))) (define (open-string string pitch) @@ -348,7 +357,10 @@ the current tuning?" tuning))) (if (< this-fret 0) (ly:warning (_ "Negative fret for pitch ~a on string ~a") - (car pitch-entry) string)) + (car pitch-entry) string) + (if (not (integer? this-fret)) + (ly:warning (_ "Missing fret for pitch ~a on string ~a") + (car pitch-entry) string))) (delete-free-string string) (set! specified-frets (cons this-fret specified-frets)) (list-set! string-fret-fingers @@ -407,7 +419,7 @@ the current tuning?" (ly:context-property context 'handleNegativeFrets 'recalculate))) - (cond ((or (>= this-fret 0) + (cond ((or (and (>= this-fret 0) (integer? this-fret)) (eq? handle-negative 'include)) (set-fret! pitch-entry string finger)) ((eq? handle-negative 'recalculate) @@ -599,10 +611,10 @@ only ~a fret labels provided") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; bar numbers -(define-public ((every-nth-bar-number-visible n) barnum) +(define-public ((every-nth-bar-number-visible n) barnum mp) (= 0 (modulo barnum n))) -(define-public ((modulo-bar-number-visible n m) barnum) +(define-public ((modulo-bar-number-visible n m) barnum mp) (and (> barnum 1) (= m (modulo barnum n)))) (define-public ((set-bar-number-visibility n) tr) @@ -610,9 +622,44 @@ only ~a fret labels provided") (ly:context-set-property! tr 'barNumberVisibility (modulo-bar-number-visible n (modulo bn n))))) -(define-public (first-bar-number-invisible barnum) (> barnum 1)) - -(define-public (all-bar-numbers-visible barnum) #t) +(define-public (first-bar-number-invisible barnum mp) + (> barnum 1)) + +(define-public (first-bar-number-invisible-save-broken-bars barnum mp) + (or (> barnum 1) + (> (ly:moment-main-numerator mp) 0))) + +(define-public (first-bar-number-invisible-and-no-parenthesized-bar-numbers barnum mp) + (and (> barnum 1) + (= (ly:moment-main-numerator mp) 0))) + +(define-public (robust-bar-number-function barnum measure-pos alt-number context) + (define (get-number-and-power an pow) + (if (<= an alt-number) + (get-number-and-power (+ an (expt 26 (1+ pow))) (1+ pow)) + (cons (+ alt-number (- (expt 26 pow) an)) (1- pow)))) + (define (make-letter so-far an pow) + (if (< pow 0) + so-far + (let ((pos (modulo (quotient an (expt 26 pow)) 26))) + (make-letter (string-append so-far + (substring "abcdefghijklmnopqrstuvwxyz" + pos + (1+ pos))) + an + (1- pow))))) + (let* ((number-and-power (get-number-and-power 0 0)) + (begin-measure (= 0 (ly:moment-main-numerator measure-pos))) + (maybe-open-parenthesis (if begin-measure "" "(")) + (maybe-close-parenthesis (if begin-measure "" ")"))) + (markup (string-append maybe-open-parenthesis + (number->string barnum) + (make-letter "" + (car number-and-power) + (cdr number-and-power)) + maybe-close-parenthesis)))) + +(define-public (all-bar-numbers-visible barnum mp) #t) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -622,3 +669,39 @@ only ~a fret labels provided") (= 0 (modulo count n))) (define-public (all-repeat-counts-visible count context) #t) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; make-engraver helper macro + +(defmacro-public make-engraver forms + "Helper macro for creating Scheme engravers. + +The usual form for an engraver is an association list (or alist) +mapping symbols to either anonymous functions or to another such +alist. + +@code{make-engraver} accepts forms where the first element is either +an argument list starting with the respective symbol, followed by the +function body (comparable to the way @code{define} is used for +defining functions), or a single symbol followed by subordinate forms +in the same manner. You can also just make an alist pair +literally (the @samp{car} is quoted automatically) as long as the +unevaluated @samp{cdr} is not a pair. This is useful if you already +have defined your engraver functions separately. + +Symbols mapping to a function would be @code{initialize}, +@code{start-translation-timestep}, @code{process-music}, +@code{process-acknowledged}, @code{stop-translation-timestep}, and +@code{finalize}. Symbols mapping to another alist specified in the +same manner are @code{listeners} with the subordinate symbols being +event classes, and @code{acknowledgers} and @code{end-acknowledgers} +with the subordinate symbols being interfaces." + (let loop ((forms forms)) + (if (cheap-list? forms) + `(list + ,@(map (lambda (form) + (if (pair? (car form)) + `(cons ',(caar form) (lambda ,(cdar form) ,@(cdr form))) + `(cons ',(car form) ,(loop (cdr form))))) + forms)) + forms)))