Hi Xavier,

2011/11/20 Xavier Scheuer <[email protected]>

> Hi,
>
> Someone on the French users mailing list basically wants the features of
>  \override RestCollision #'positioning-done = #merge-rests-on-positioning
>
> Issue #1228 is tagged as "Patch-abandoned", LSR #336 is not working
> with current version.
>

I had no problems compiling the LSR-Snippet with "2.14.2" and "2.15.13".
Of course this snippet doesn't define merging MultiMeasureRests.

http://code.google.com/p/lilypond/issues/detail?id=1228
> http://lsr.dsi.unimi.it/LSR/Item?id=336
>
> However, the code given by Wilbert in the first comment works, except
> that the MMRs appears below the 3rd (middle) line, instead of below the
> 4th line (normal position).  Apparently
>  MultiMeasureRest #'staff-position  changed from #0 to #2 for the
> normal position between 2.12 and 2.14/2.15.
>
> Could a "power user" give some help in order to make it work correctly
> with 2.14/2.15?  Even better if a dev could implement it (correctly) in
> LilyPond, but in the meantime I'm sure the French users would be happy
> with a hack!
> http://codereview.appspot.com/4005046/
> http://lists.gnu.org/archive/html/bug-lilypond/2011-03/msg00291.html
>
> Thanks in advance.
>
> Cheers,
> Xavier <https://lists.gnu.org/mailman/listinfo/lilypond-user>


Also, I didn't notice any problem with the code given by Wilbert when using
"2.14.2".

In the code below I integrated Neil's suggestion making the second MMR
transparent. (To avoid printing a second MultiMeasureNumber I made the
second number transparent manually. As Neil remarked an engraver would be
better, but this is beyond my knowledge.)
But with "2.15.13" there is a difference between merging a single MMR and
merging \compressFullBarRests R1*9. Perhaps a bug?

I added some conditions reading out the measure-count and the used
lilypond-version to deal with the behaviour of the different versions.

It's a hack, but I hope it will work with "2.14." and "2.15". Please let me
know.

AmitiƩs,
  Harm
%{
  Based on http://lsr.dsi.unimi.it/LSR/Snippet?id=336
  
  Merges rests and multi-measure rests that occur on the same moment inside a
  staff with two voices.
  
  Usage:
  
  \include "merge-rests"
  
  \layout {
    \mergeRests
  }
  
  or inside the music:
  
  \new Staff <<
    \relative c' {
      \mergeRestsOn	%% in one of the voices is sufficient
      c4 d e f g r r2
    }
    \\
    \relative c' {
      a4 b c d e r r2
    }
  >>
 
%}

\version "2.14.2"
%\version "2.15.13"

#(define (rest-score r)
  (let ((score 0)
	(yoff (ly:grob-property-data r 'Y-offset))
	(sp (ly:grob-property-data r 'staff-position)))
    (if (number? yoff)
	(set! score (+ score 2))
	(if (eq? yoff 'calculation-in-progress)
	    (set! score (- score 3))))
    (and (number? sp)
	 (<= 0 2 sp)
	 (set! score (+ score 2))
	 (set! score (- score (abs (- 1 sp)))))
    score))

#(define (merge-rests-on-positioning grob)
  (let* ((can-merge #f)
	 (elts (ly:grob-object grob 'elements))
	 (num-elts (and (ly:grob-array? elts)
			(ly:grob-array-length elts)))
	 (two-voice? (= num-elts 2)))
    (if two-voice?
	(let* ((v1-grob (ly:grob-array-ref elts 0))
	       (v2-grob (ly:grob-array-ref elts 1))
	       (v1-rest (ly:grob-object v1-grob 'rest))
	       (v2-rest (ly:grob-object v2-grob 'rest)))
	  (and
	   (ly:grob? v1-rest)
	   (ly:grob? v2-rest)
	   (let* ((v1-duration-log (ly:grob-property v1-rest 'duration-log))
		  (v2-duration-log (ly:grob-property v2-rest 'duration-log))
		  (v1-dot (ly:grob-object v1-rest 'dot))
		  (v2-dot (ly:grob-object v2-rest 'dot))
		  (v1-dot-count (and (ly:grob? v1-dot)
				     (ly:grob-property v1-dot 'dot-count -1)))
		  (v2-dot-count (and (ly:grob? v2-dot)
				     (ly:grob-property v2-dot 'dot-count -1))))
	     (set! can-merge
		   (and
		    (number? v1-duration-log)
		    (number? v2-duration-log)
		    (= v1-duration-log v2-duration-log)
		    (eq? v1-dot-count v2-dot-count)))
	     (if can-merge
		 ;; keep the rest that looks best:
		 (let* ((keep-v1? (>= (rest-score v1-rest)
				      (rest-score v2-rest)))
			(rest-to-keep (if keep-v1? v1-rest v2-rest))
			(dot-to-kill (if keep-v1? v2-dot v1-dot)))
		   ;; uncomment if you're curious of which rest was chosen:
		   ;;(ly:grob-set-property! v1-rest 'color green)
		   ;;(ly:grob-set-property! v2-rest 'color blue)
		   (ly:grob-suicide! (if keep-v1? v2-rest v1-rest))
		   (if (ly:grob? dot-to-kill)
		       (ly:grob-suicide! dot-to-kill))
		   (ly:grob-set-property! rest-to-keep 'direction 0)
		   (ly:rest::y-offset-callback rest-to-keep)))))))
    (if can-merge
	#t
	(ly:rest-collision::calc-positioning-done grob))))

#(define merge-multi-measure-rest-on-Y-offset
  ;; Call this to get the 'Y-offset of a MultiMeasureRest.
  ;; It keeps track of other MultiMeasureRests in the same NonMusicalPaperColumn
  ;; and StaffSymbol. If two are found, make transparent one and return 1 for Y-offset of
  ;; the other one.
  (let ((table (make-weak-key-hash-table)))
    (lambda (grob)
      (let* ((ssymb (ly:grob-object grob 'staff-symbol))
             (nmcol (ly:grob-parent grob X))
             (ssymb-hash (begin
               (if (not (hash-ref table ssymb))
                   (hash-set! table ssymb (make-hash-table 1)))
               (hash-ref table ssymb)))
             (othergrob (hash-ref ssymb-hash nmcol))
             (measure-count (if (ly:grob? grob) 
             	 	(ly:grob-property grob 'measure-count)
             	 	0)))

            (if (ly:grob? othergrob)
              (begin 
                ;; Make merged rest transparent instead of suiciding
                ;; in case it supports text/counter
                    
                (set! (ly:grob-property othergrob 'transparent) #t)
                (hash-remove! ssymb-hash nmcol)
                (if (<= (string->number (cadr (string-split (lilypond-version) #\.))) 14)
                    0
                    (if (< 1 measure-count)
                        0
                        1))
                )
              (begin
                ;; Just save this grob and return the default value
                (hash-set! ssymb-hash nmcol grob)
                (ly:staff-symbol-referencer::callback grob)))
                ))))

mergeRestsOn = {
  \override Staff.RestCollision #'positioning-done = #merge-rests-on-positioning
  \override Staff.MultiMeasureRest #'Y-offset = #merge-multi-measure-rest-on-Y-offset
}

mergeRestsOff = {
  \revert Staff.RestCollision #'positioning-done
  \revert Staff.MultiMeasureRest #'Y-offset
}

mergeRests = \with {
  \override RestCollision #'positioning-done = #merge-rests-on-positioning
  \override MultiMeasureRest #'Y-offset = #merge-multi-measure-rest-on-Y-offset
}

mmrtr =  \override Voice.MultiMeasureRestNumber #'transparent = ##t

%------ Test 

\score {
  \new Score <<
    
    \new Staff \with {
    } <<
      s4-\markup{ "LilyPond default, Rests in both voices." }
      \relative c'' { c4 d e r | r2  e4 g | R1 } \\
      \relative c'' { c4 b a r | r a g2   | R1 }
    >>
    \new Staff \with { \mergeRests  } 
   <<
     s4-\markup{ "Merge Rests and MultiMeasureRests in both voices." }
     \relative c'' { c4 d e r | r2  e4 g | R1 \mmrtr\compressFullBarRests R1*9 } \\
     \relative c'' { c4 b a r | r a g2   | R1 \compressFullBarRests R1*9 }
   >>   
  >>
  \layout {}
}

_______________________________________________
lilypond-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to