Re: engraver to change staff name based on visibility of related staff?

2017-07-07 Thread Thomas Morley
2017-07-07 2:41 GMT+02:00 Shevek :
> Sorry for the repeat messages. [...]

Hi Saul,

no problem. I'm interested in the topic, though I've not the time to
look deeper into it yet. Maybe the upcoming weekend...

Cheers,
  Harm

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: engraver to change staff name based on visibility of related staff?

2017-07-06 Thread Shevek
Sorry for the repeat messages. I now have a working version. This is a
callback for InstrumentName.after-line-breaking. It looks at whether the
next Staff below is alive on the current system, and if it's not, displays
the instrumentName for this Staff instead of the shortInstrumentName. This
is a bit simpler than automatically combining the names of hidden staves,
but it serves more or less the same purpose. It might be a little nicer to
define a new property for the combined/apart names, but I'm not sure how to
do that.

\version "2.18.2"
\language "english"

\paper {
  left-margin = 1.5\cm
}

#(define change-instr-names
   (lambda (grob)
 (let* (
 ;; Get the VerticalAxisGroup grob belonging to me
 (my-vaxis-arr (ly:grob-object grob 'elements))
 (my-vaxis 
  (car (if (ly:grob-array? my-vaxis-arr)
   (ly:grob-array->list my-vaxis-arr)
   '(

 ;; Get all the VerticalAxisGroup grobs per system
 (sys (ly:grob-system grob))
 (sys-all-elts (ly:grob-object sys 'all-elements))
 (sys-all-elts-list
  (if (ly:grob-array? sys-all-elts)
  (ly:grob-array->list sys-all-elts)
  '()))
 (vertical-axis-group-list
  (filter
   (lambda (g)
 (grob::has-interface g 'hara-kiri-group-spanner-interface))
   sys-all-elts-list))
   
 ;; Check if a VerticalAxisGroup is the next one below me
 (my-vindex (ly:grob-get-vertical-axis-group-index my-vaxis))
 (next-vaxis? (lambda (v)
  (equal? (+ 1 my-vindex)
(ly:grob-get-vertical-axis-group-index v)))
  )
 ;; Get the next Staff below me
 (next-vaxis
  (car (filter next-vaxis? vertical-axis-group-list)))
 
 ;; Is it alive this system?
 (alive-next?
  (interval-sane? (ly:grob-property next-vaxis 'Y-extent)))
   
 )
   ; (display alive-next?)
   ; (display "\n\n")
   
   (if (not alive-next?)
   (ly:grob-set-property! grob 'text
 (ly:grob-property grob 'long-text))
   )
   )
 )
   )

%% Example starts here

global = {
  s1
  \break
  s1
  \break
  s1
}

fluteI = {
  c'''1
  \partcombineApart 
  \oneVoice
  c'''1
  \partcombineChords
  c'''1
}

fluteII = {
  e''1
  \change Staff = "Fl2" 
  \oneVoice 
  e''1
  e''1
}

oboeI = {
  %  For parts that begin on separate staves, this is necessary:
  \once\set Staff.instrumentName = "1"
  
  \partcombineApart 
  \oneVoice
  c'''1
  \partcombineChords
  c'''1
  \partcombineApart
  c'''1
}

oboeII = {
  \change Staff = "Ob2" 
  \oneVoice
  e''1
  e''1
  e''1
}

\score {
  <<
\new StaffGroup \with { 
  instrumentName = "Flute  " 
  shortInstrumentName = "Fl.  " 
} << 
  \new Staff = "Fl1" \with { 
instrumentName = \markup\column { "1" "2" } 
shortInstrumentName = "1" 
\override InstrumentName.after-line-breaking = #change-instr-names
  } << \global \partcombine \fluteI \fluteII >> 
  \new Staff = "Fl2" \with { 
instrumentName = \markup\column { "2" } 
shortInstrumentName = \markup\column { "2" } 
\override VerticalAxisGroup.remove-empty = ##t 
\override VerticalAxisGroup.remove-first = ##t 

  } << \global >> 
>>
\new StaffGroup \with { 
  instrumentName = "Oboe  " 
  shortInstrumentName = "Ob.  " 
} << 
  \new Staff = "Ob1" \with { 
instrumentName = \markup\column { "1" "2" } 
shortInstrumentName = "1" 
\override InstrumentName.after-line-breaking = #change-instr-names
  } << \global \partcombine \oboeI \oboeII >> 
  \new Staff = "Ob2" \with { 
instrumentName = \markup\column { "2" } 
shortInstrumentName = \markup\column { "2" } 
\override VerticalAxisGroup.remove-empty = ##t 
    \override VerticalAxisGroup.remove-first = ##t 

  } << \global >> 
>>
  >> 
  \layout {
\context {
  \Staff
  \override InstrumentName.self-alignment-X = #1
}
  }
}





--
View this message in context: 
http://lilypond.1069038.n5.nabble.com/engraver-to-change-staff-name-based-on-visibility-of-related-staff-tp203905p204291.html
Sent from the Dev mailing list archive at Nabble.com.

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: engraver to change staff name based on visibility of related staff?

2017-07-06 Thread Shevek
Making some progress on this. I've managed to figure out how to use
ly:grob-get-vertical-axis-group-index to only look at the current Staff and
the next one below. That's clunkier than finding the VerticalAxisGroups that
belong to the same StaffGroup, but it's a start.

My problem now is finding a way to grab the InstrumentName grob that belongs
to the current Staff, not just the list of all the InstrumentName grobs on
the current system. Once you start hiding staves, it's no longer guaranteed
that the list of InstrumentNames will line up correctly with the list of
VerticalAxisGroups.

Here's the code I'm working with now, modified from Harm's:

\version "2.18.2"

%% NB
%% It's a proof of concept, nothing more!!
%% Currently it will fail for various reasons with extended examples
#(define change-instr-names
  (lambda (grob)
(let* ((sys (ly:grob-system grob))
   (sys-all-elts (ly:grob-object sys 'all-elements))
   (sys-all-elts-list
 (if (ly:grob-array? sys-all-elts)
 (ly:grob-array->list sys-all-elts)
 '()))
   ;; get all VerticalAxisGroup-grobs per System
   (vertical-axis-group-list
 (filter
   (lambda (g)
 (grob::has-interface g 'hara-kiri-group-spanner-interface))
   sys-all-elts-list))

   ;; get all InstrumentName-grobs per System
   (instrument-names-list
 (filter
   (lambda (g)
 (grob::has-interface g 'system-start-text-interface))
   sys-all-elts-list))
   
   ;; Make a list of pairs of VerticalAxisGroup and InstrumentName
grobs
   ;; This assumes the correspondence will be correct, 
   ;; but that is NOT guaranteed to be true
   (instr-axis-list
(zip vertical-axis-group-list instrument-names-list))
   
   ;; Check if a VerticalAxisGroup is me or the next one below me
   ;; Keep if yes, ignore the rest
   (my-vindex (ly:grob-get-vertical-axis-group-index grob))
   (cousin-vaxis? (lambda (v)
  (let ((vindex
(ly:grob-get-vertical-axis-group-index v)))
(or (equal? my-vindex vindex)
(equal? (+ 1 my-vindex) vindex)))
  ))
   
   (cousin-instr-list
(filter
 (lambda (x)
   (cousin-vaxis? (car x)))
 instr-axis-list))
   
;; construct a nested list like
;;   ((#t #)
;;(#f #))
;; the boolean indicates whether the Staff is alive, derived
from
;; VerticalAxisGroup.Y-extent
(alive?-instr-list
  (map
(lambda (x)
  (list (interval-sane? (ly:grob-property (car x)
'Y-extent)) (cadr x))
  )
cousin-instr-list))
   )

;(display alive?-instr-list)
;(display (map-in-order ly:grob-get-vertical-axis-group-index
instrument-names-list))
;(display (map-in-order (lambda (g) (ly:grob-property (cadr g)
'text)) instr-axis-list))
;(display "\n\n")
   

;; First constructing a list and then fragmenting it in various ways
is
;; not elegant, to say the least.
;; Just a proof of concept...
(if (any not (map car alive?-instr-list))
(let* ((instr-to-set
 (filter car alive?-instr-list)
 ))
  (for-each (lambda (inst) (ly:grob-set-property! (cadr inst)
'text
(make-column-markup
  (map
(lambda (arg)
  (ly:grob-property arg 'text))
(map cadr alive?-instr-list)
instr-to-set
  )))
  )))


%% Example


\layout {
  \context {
\Staff
\RemoveEmptyStaves
  }
}
<<
  \new StaffGroup = "foo" <<
\new Staff = "1" \with { 
  \override VerticalAxisGroup.after-line-breaking = #change-instr-names
  instrumentName = "One" shortInstrumentName = "1" 
}
  { R1 \break c \break c }
\new Staff = "2" \with { 
  instrumentName = "Two" shortInstrumentName = "2" 
}
  { c1 c c }
  >>
  \new StaffGroup = "baz" <<
\new Staff = "3" \with { 
  \override VerticalAxisGroup.after-line-breaking = #change-instr-names
  instrumentName = "One" shortInstrumentName = "3" }
  { R1 \break c \break c }
\new Staff = "4" \with { instrumentName = "Two" shortInstrumentName =
"4" }
  { c1 R c }
  >>
>>



--
View this 

Re: engraver to change staff name based on visibility of related staff?

2017-07-05 Thread Saul Tobin
Hi,

Finally getting a chance to play around with this. Thanks for writing up
this proof of concept! I'm learning a lot.

A few questions:

1) When you build alive?-instr-list you seem to assume a correspondence
between vertical-axis-group-list and instrument-names-list. But is that
actually guaranteed? Is the list of all grobs ordered that way to begin
with, and does filter preserve that ordering?

2) Is there a way to check if two VerticalAxisGroups belong to the same
StaffGroup, for instance? What I want to do is modify this so for each
staff with the callback defined, it only looks at the other staves within
the same lowest-level staff grouping. That way, it could be used in a score
with multiple groups of staves. My first shot at just grabbing the related
staves was:

(filter
 (lambda (x)
   (equal? (ly:grob-parent grob 1) (ly:grob-parent x 1)))
 vertical-axis-group-list)

But it seems all VerticalAlignments are the same or something? Hopefully
it's sort of clear what I'm trying to do?

Thanks!

On Sat, Jun 17, 2017 at 3:42 AM, Thomas Morley 
wrote:

> 2017-06-16 23:47 GMT+02:00 Shevek :
> > Following up on an aspect of the discussion on parts sharing a staff
> > (http://lilypond.1069038.n5.nabble.com/parts-sharing-a-
> staff-tt203873.html).
> >
> > I've spent quite a few hours over the last day trying to figure out how
> > engravers work and how I might take a crack at writing something to
> > automatically handle changing Staff names for divisi staves. I feel like
> > I've understood most of what I've read, but I'm still totally befuddled.
> > This seems like a difficult problem because:
> >
> > 1) It's completely opaque to me how one would check if a Staff is
> visible or
> > not on a given system. The hara-kiri-group-spanner, as far as I can tell,
> > does its work without telling anybody about it. There's not like a
> boolean
> > function you can call to find out if a context will be visible.
> >
> > 2) One needs to do something in one context depending on what happens in
> a
> > different context. Most of the example engravers just do something in one
> > context. Keep_alive_together_engraver collects grobs from different
> contexts
> > and tells them about each other, but then relies on on them to figure out
> > what to do with that information. That doesn't seem adequate here.
> >
> > 3) Such an engraver would need to step through the score by system, after
> > breaking, rather than event by event, and it might need to be able to
> > backtrack to insert an event to change the instrument name prior to the
> most
> > recent system break. The code and documentation I've read has not given
> me
> > any insight into how one might do such a thing.
> >
> > I'd love some feedback and guidance.
>
>
>
> Hi,
>
> I doubt an engraver will ever work for this purpose. As far as I
> understand an engraver usually puts in stuff far too early. You can
> assign a procedure to a grob via 'after-line-breaking, but you will
> not be able to access whatever the procedure returns _in_ the
> engraver.
> I may be proven wrong, though.
>
> Nevertheless, I tried a different approach:
>
> \version "2.19.62"
>
> %% NB
> %% It's a proof of concept, nothing more!!
> %% Currently it will fail for various reasons with extended examples
> #(define change-instr-names
>   (lambda (grob)
> (let* ((sys (ly:grob-system grob))
>(sys-all-elts (ly:grob-object sys 'all-elements))
>(sys-all-elts-list
>  (if (ly:grob-array? sys-all-elts)
>  (ly:grob-array->list sys-all-elts)
>  '()))
>;; get all VerticalAxisGroup-grobs per System
>(vertical-axis-group-list
>  (filter
>(lambda (g)
>  (grob::has-interface g 'hara-kiri-group-spanner-
> interface))
>sys-all-elts-list))
>;; get all InstrumentName-grobs per System
>(instrument-names-list
>  (filter
>(lambda (g)
>  (grob::has-interface g 'system-start-text-interface))
>sys-all-elts-list))
>;; construct a nested list like
>;;   ((#t #)
>;;(#f #))
>;; the boolean indicates whether the Staff is alive, derived
> from
>;; VerticalAxisGroup.Y-extent
>(alive?-instr-list
>  (map
>(lambda (v i)
>  (list (interval-sane? (ly:grob-property v 'Y-extent)) i))
>vertical-axis-group-list
>instrument-names-list)))
>
>;(pretty-print alive?-instr-list)
>
>   ;; First constructing a list and then fragmenting it in various ways
> is
>   ;; not elegant, to say the least.
>   ;; Just a proof of concept...
>   (if (any not (map car alive?-instr-list))
>   (let* ((instr-to-set
>(remove
>  (lambda (e)
>   

Re: engraver to change staff name based on visibility of related staff?

2017-06-17 Thread Thomas Morley
2017-06-16 23:47 GMT+02:00 Shevek :
> Following up on an aspect of the discussion on parts sharing a staff
> (http://lilypond.1069038.n5.nabble.com/parts-sharing-a-staff-tt203873.html).
>
> I've spent quite a few hours over the last day trying to figure out how
> engravers work and how I might take a crack at writing something to
> automatically handle changing Staff names for divisi staves. I feel like
> I've understood most of what I've read, but I'm still totally befuddled.
> This seems like a difficult problem because:
>
> 1) It's completely opaque to me how one would check if a Staff is visible or
> not on a given system. The hara-kiri-group-spanner, as far as I can tell,
> does its work without telling anybody about it. There's not like a boolean
> function you can call to find out if a context will be visible.
>
> 2) One needs to do something in one context depending on what happens in a
> different context. Most of the example engravers just do something in one
> context. Keep_alive_together_engraver collects grobs from different contexts
> and tells them about each other, but then relies on on them to figure out
> what to do with that information. That doesn't seem adequate here.
>
> 3) Such an engraver would need to step through the score by system, after
> breaking, rather than event by event, and it might need to be able to
> backtrack to insert an event to change the instrument name prior to the most
> recent system break. The code and documentation I've read has not given me
> any insight into how one might do such a thing.
>
> I'd love some feedback and guidance.



Hi,

I doubt an engraver will ever work for this purpose. As far as I
understand an engraver usually puts in stuff far too early. You can
assign a procedure to a grob via 'after-line-breaking, but you will
not be able to access whatever the procedure returns _in_ the
engraver.
I may be proven wrong, though.

Nevertheless, I tried a different approach:

\version "2.19.62"

%% NB
%% It's a proof of concept, nothing more!!
%% Currently it will fail for various reasons with extended examples
#(define change-instr-names
  (lambda (grob)
(let* ((sys (ly:grob-system grob))
   (sys-all-elts (ly:grob-object sys 'all-elements))
   (sys-all-elts-list
 (if (ly:grob-array? sys-all-elts)
 (ly:grob-array->list sys-all-elts)
 '()))
   ;; get all VerticalAxisGroup-grobs per System
   (vertical-axis-group-list
 (filter
   (lambda (g)
 (grob::has-interface g 'hara-kiri-group-spanner-interface))
   sys-all-elts-list))
   ;; get all InstrumentName-grobs per System
   (instrument-names-list
 (filter
   (lambda (g)
 (grob::has-interface g 'system-start-text-interface))
   sys-all-elts-list))
   ;; construct a nested list like
   ;;   ((#t #)
   ;;(#f #))
   ;; the boolean indicates whether the Staff is alive, derived from
   ;; VerticalAxisGroup.Y-extent
   (alive?-instr-list
 (map
   (lambda (v i)
 (list (interval-sane? (ly:grob-property v 'Y-extent)) i))
   vertical-axis-group-list
   instrument-names-list)))

   ;(pretty-print alive?-instr-list)

  ;; First constructing a list and then fragmenting it in various ways is
  ;; not elegant, to say the least.
  ;; Just a proof of concept...
  (if (any not (map car alive?-instr-list))
  (let* ((instr-to-set
   (remove
 (lambda (e)
   (not (car e)))
 alive?-instr-list)))
(ly:grob-set-property! (cadar instr-to-set) 'text
  (make-column-markup
(map
  (lambda (arg)
(ly:grob-property arg 'text))
  (map cadr alive?-instr-list)


%% Example


\layout {
  \context {
  \Staff
  \override VerticalAxisGroup.after-line-breaking = #change-instr-names
\RemoveEmptyStaves
  }
}

<<
  \new Staff \with { instrumentName = "One" shortInstrumentName = "one" }
{ R1 \break c \break c }
  \new Staff \with { instrumentName = "Two" shortInstrumentName = "two" }
{ c1 R c }
>>


Cheers,
  Harm

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


engraver to change staff name based on visibility of related staff?

2017-06-17 Thread Shevek
Following up on an aspect of the discussion on parts sharing a staff
(http://lilypond.1069038.n5.nabble.com/parts-sharing-a-staff-tt203873.html).

I've spent quite a few hours over the last day trying to figure out how
engravers work and how I might take a crack at writing something to
automatically handle changing Staff names for divisi staves. I feel like
I've understood most of what I've read, but I'm still totally befuddled.
This seems like a difficult problem because:

1) It's completely opaque to me how one would check if a Staff is visible or
not on a given system. The hara-kiri-group-spanner, as far as I can tell,
does its work without telling anybody about it. There's not like a boolean
function you can call to find out if a context will be visible.

2) One needs to do something in one context depending on what happens in a
different context. Most of the example engravers just do something in one
context. Keep_alive_together_engraver collects grobs from different contexts
and tells them about each other, but then relies on on them to figure out
what to do with that information. That doesn't seem adequate here.

3) Such an engraver would need to step through the score by system, after
breaking, rather than event by event, and it might need to be able to
backtrack to insert an event to change the instrument name prior to the most
recent system break. The code and documentation I've read has not given me
any insight into how one might do such a thing.

I'd love some feedback and guidance.



--
View this message in context: 
http://lilypond.1069038.n5.nabble.com/engraver-to-change-staff-name-based-on-visibility-of-related-staff-tp203905.html
Sent from the Dev mailing list archive at Nabble.com.

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel