Am Mi., 1. Juli 2020 um 11:08 Uhr schrieb Maurits Lamers
<maur...@weidestraat.nl>:
>
> Hi all,
>
> Follow up question: is there a way to know the "parent" of the voices as they 
> are defined in the code?
> In the following example, I would like to determine that voice "two" splits 
> off from voice "one" without relying on the context-id.
> (ly:context-parent ctx) gives me the staff, not the "parent voice"...
>
> \score {
>   \new Staff {
>     \time 2/2
>
>     <<
>       \new Voice = "one" {
>         \relative c'' {
>           \voiceOne
>           g8 e
>         }
>         <<
>           \new Voice = "two" {
>             \voiceOne
>             \relative c'' { a8. g16 f8 e16 f g f e d }
>           }
>           \new Voice = "three" {
>             \voiceTwo
>             \relative c' { c8 a d8. c16 b8 a16 b }
>           }
>         >>
>       }
>       \new Voice = bottom {
>         \voiceTwo
>         \relative c' { g1 }
>       }
>     >>
>
>   }
> }
>
> Thanks in advance!
>

Hi Maurits,

I second Aaron, saying Voices are not parent of each other.
Below some other code I once made. Not exactly what you need, maybe
some addition to the fine code Aaron already provided, though.

#(define (my-engraver ctx)
  (let ((new-contexts '()))
     `(
       (listeners
        (AnnounceNewContext
          .
          ,(lambda (engraver event)
            (set! new-contexts (cons event new-contexts)))))
       (finalize
        .
        ,(lambda (trans)
          (let ((ctx-type-id
                  (map
                    (lambda (c)
                      (let ((creator (ly:event-property c 'creator)))
                        (list
                          (ly:event-property creator 'type)
                          (ly:event-property creator 'id))))
                    (delete-duplicates (reverse new-contexts)))))
          (format #t
"\nInside this score ~a new contexts are created. Type and id are:\n~y"
            (length ctx-type-id)
            ctx-type-id)
          (set! ctx-type-id '()))))

          )))

#(define (single-context-parent-tree ctx)
  (if (and (ly:context? ctx) (ly:context? (ly:context-parent ctx)))
      (single-context-parent-tree (ly:context-parent ctx))
      (format #f "~a" ctx)))

printBottomContextParents =
\context Bottom
\applyContext
  #(lambda (a)
    (let ((ls (drop-right
                (string-split
                  (single-context-parent-tree a)
                  (car (string->list "(")))
                1)))
    (format #t "\n\nThe Context-parent-tree:")
    (format #t
      "\n(Only contexts of type Global, Score, Staff and Voice are printed)")
    (for-each
      (lambda (s)
        (format #t "\n~a~a"
          (cond ((string-contains s "Score")
                 (make-string 1 #\tab))
                ((string-contains s "Staff")
                 (make-string 2 #\tab))
                ((string-contains s "Voice")
                 (make-string 3 #\tab))
                (else ""))
          (string-trim-both s (lambda (c)
                                (or (eqv? c #\>)
                                    (eqv? c #\sp)
                                    (eqv? c #\)))))))
      ls)))

\score {
  \new Staff {
    \time 2/2


    <<
      \new Voice = "one" {
        \relative c'' {
          \voiceOne
          g8 e
        }
        <<
          \new Voice = "two" {
            \voiceOne
            \relative c'' { a8. g16 f8 e16 f g f e d }
          }
          \new Voice = "three" {
            \voiceTwo
            \relative c' { c8 a d8. c16 b8 a16 b }
          }
        >>
      }
      \new Voice = bottom {
        \voiceTwo

        \relative c' { g1 }
      }
    >>

  }

  \layout {
    \context {
      \Score
      \consists \my-engraver
    }
    \printBottomContextParents
  }
}

Cheers,
  Harm

Reply via email to