\version "2.19.15" \header { tagline = ##f } #(define-event-class 'music-boxer-event 'span-event) #(define-event-class 'box-event 'music-event) #(define (add-grob-definition grob-name grob-entry) (set! all-grob-descriptions (cons ((@@ (lily) completize-grob-entry) (cons grob-name grob-entry)) all-grob-descriptions))) #(add-grob-definition 'LyricWord `(;(stencil . ,ly:lyric-word::print) (meta . ((class . Spanner) (interfaces . (lyric-hyphen-interface lyric-word-interface text-interface)))))) #(define (make-box thick padding xext yext) (let ((xext (interval-widen xext padding)) (yext (interval-widen yext padding))) (ly:stencil-add (make-filled-box-stencil xext (cons (- (car yext) thick) (car yext))) (make-filled-box-stencil xext (cons (cdr yext) (+ (cdr yext) thick))) (make-filled-box-stencil (cons (cdr xext) (+ (cdr xext) thick)) yext) (make-filled-box-stencil (cons (- (car xext) thick) (car xext)) yext)))) #(define (music-boxer-stencil grob) (let* ((elts (ly:grob-object grob 'elements)) (refp-X (ly:grob-common-refpoint-of-array grob elts X)) (X-ext (ly:relative-group-extent elts refp-X X)) (refp-Y (ly:grob-common-refpoint-of-array grob elts Y)) (Y-ext (ly:relative-group-extent elts refp-Y Y)) (padding (ly:grob-property grob 'padding 0.3)) (stil (make-box 0.1 padding X-ext Y-ext)) (offset (ly:grob-relative-coordinate grob refp-X X))) (ly:stencil-translate-axis stil (- offset) X))) #(define box-stil music-boxer-stencil) #(add-grob-definition 'Box `( (stencil . ,box-stil) (meta . ((class . Item) (interfaces . ()))))) #(add-grob-definition 'MusicBoxer `( (stencil . ,music-boxer-stencil) (meta . ((class . Spanner) (interfaces . ()))))) #(define box-types '( (BoxEvent . ((description . "A box encompassing music at a single timestep.") (types . (general-music box-event music-event event)) )) )) #(define music-boxer-types '( (MusicBoxerEvent . ((description . "Used to signal where boxes encompassing music start and stop.") (types . (general-music music-boxer-event span-event event)) )) )) #(set! music-boxer-types (map (lambda (x) (set-object-property! (car x) 'music-description (cdr (assq 'description (cdr x)))) (let ((lst (cdr x))) (set! lst (assoc-set! lst 'name (car x))) (set! lst (assq-remove! lst 'description)) (hashq-set! music-name-to-property-table (car x) lst) (cons (car x) lst))) music-boxer-types)) #(set! box-types (map (lambda (x) (set-object-property! (car x) 'music-description (cdr (assq 'description (cdr x)))) (let ((lst (cdr x))) (set! lst (assoc-set! lst 'name (car x))) (set! lst (assq-remove! lst 'description)) (hashq-set! music-name-to-property-table (car x) lst) (cons (car x) lst))) box-types)) #(set! music-descriptions (append music-boxer-types music-descriptions)) #(set! music-descriptions (append box-types music-descriptions)) #(set! music-descriptions (sort music-descriptions alist1 \musicBoxerStart d8-4 g,-0 d' g, d'-4 g,-0 d' \musicBoxerEnd g, } %2 \repeat volta 2 { \box 1\f\fermata \musicBoxerStart g8-3 d-0 g d g8-4 d-0 g \musicBoxerEnd d\accent } } \score { \new Staff \melody } \layout { \context { \Global \grobdescriptions #all-grob-descriptions } \context { \Score \consists \musicBoxerEngraver % for spans \consists \boxEngraver } }