2014-07-25 21:34 GMT+02:00 David Kastrup <d...@gnu.org>:
> Janek Warchoł <janek.lilyp...@gmail.com> writes:
>
>> newInstrument =
>> #(define-scheme-function
>>   (parser location instrName parentName settings)(string? ly:context-mod?)
>>   ;; ...
>>     #{
>>       \layout {
>>         \context {
>             $(module-ref (current-module) (string->symbol parentName))

Ha!
Exactly as i thought: as a higher-level mage than me, you know more
(and more powerful) magic incantations than i do.  Kudos!

>>           ;; create "instrNameStaff" context, derived from "parentNameStaff",
>>           ;; with default child "instrNameVoice", and modifications specified
>>           ;; in "settings" argument
>             \name #instrName
>             \defaultchild #instrNameVoice
>             #settings
>>         }
>>         \context {
>>           ;; create "instrNameVoice" context, derived from "parentNameVoice",
>>         }
>>       }
>>     #})
>>
>> I managed to write a function that does something like this, but I
>> have two problems:
>> 1) inside the function, i don't know how to get a context definition
>> from its name (i.e. from a string).  Right now i have to pass parent
>> contexts' definitions as separate arguments, but this means that i
>> have three arguments instead of one.
>> 2) i didn't manage to get midi stuff done inside the same function as
>> the layout stuff - but i think that i'll be able to solve that if i
>> have a solution to 1).
>
> You basically need to collect just the context definitions and apply
> those (a context definition is applied by looking up its \name and
> overwriting the variable with that name).
>
> Frankly, I am tempted to create something like
> #{
>    \output {
>      \context ...
>      xxx = 3\cm
>    }
> #}
>
> that will either execute a number of assignments or alternatively return
> an anonymous lambda or define-void-function doing the same so that you
> can easily splice it into different output definitions.
>
> Something like that would apparently serve a need.

I don't fully understand this yet, but for now i'm very happy that I
have a better version of the function (see attached) :)
I haven't gotten rid of all the duplication yet, but the user
interface at least seems nice!

Any further improvements are welcome! It would be great if you managed
to fix \addlyrics so that it would work nice with these custom
contexts (see comments in the attachment) - i'd gladly give another
€15 for that (or maybe more...).

thanks & good night for now! :)
Janek
\version "2.19.10"

% Create a new xxxStaff and xxxVoice contexts with specified settings,
% derived from specified yyyStaff and yyyVoice contexts.

% TODO:
%
% 1) make \addLyrics smarter so that it could be used here (see test below)
%
% 2) remove code duplication; general cleanup.

newLayoutInstrument =
#(define-scheme-function
  (parser location name parent-name group-name staff-settings voice-settings)
  (string? string? string? ly:context-mod? ly:context-mod?)
  (let* ((staff-name (string-append name "Staff"))
         (voice-name (string-append name "Voice"))
         (parent-name (if (string=? parent-name "default") "" parent-name))
         (parent-staff-name (string-append parent-name "Staff"))
         (parent-voice-name (string-append parent-name "Voice")))
    (ly:parser-define! parser '$defaultlayout
      #{
        \layout {
          \context {
            $(module-ref (current-module) (string->symbol group-name))
            \accepts #staff-name
          }
          \context {
            $(module-ref (current-module) (string->symbol parent-staff-name))
            \name #staff-name
            \alias #parent-staff-name
            % is it possible to make it accept Voices of derived instruments?
            \accepts #voice-name
            \defaultchild #voice-name

            #staff-settings
          }
          \context {
            $(module-ref (current-module) (string->symbol parent-voice-name))
            \name #voice-name
            \alias #parent-voice-name

            #voice-settings
          }
        }
      #})
    ;; UGH! code duplication!
    (ly:parser-define! parser '$defaultmidi
      #{
        \midi {
          \context {
            $(module-ref (current-module) (string->symbol group-name))
            \accepts #staff-name
          }
          \context {
            $(module-ref (current-module) (string->symbol parent-staff-name))
            \name #staff-name
            \alias #parent-staff-name
            % is it possible to make it accept Voices of derived instruments?
            \accepts #voice-name
            \defaultchild #voice-name

            #staff-settings
          }
          \context {
            $(module-ref (current-module) (string->symbol parent-voice-name))
            \name #voice-name
            \alias #parent-voice-name

            #voice-settings
          }
        }
      #})))


% define "instruments" - one generic and another one derived:

\newLayoutInstrument "Vocal" "default" "ChoirStaff"
\with {
  \consists "Ambitus_engraver"
  instrumentName = "Vocals"
  shortInstrumentName = "Voc."
  \dynamicUp
  \tupletUp
  \remove "Staff_performer"
}
\with {
  \consists "Staff_performer"
  midiInstrument = "voice oohs"
}

\newLayoutInstrument "Soprano" "Vocal" "ChoirStaff"
\with {
  instrumentName = "Soprano"
  shortInstrumentName = "S"
  \clef G
}
\with { }


% test:

\score {
  <<
    \new SopranoVoice = sop \relative f' {
      c f c' f
    }
    % replacing this with \addlyrics { la la la la }
    % results in ordinary Voice being created (instead of SopranoVoice)
    \new Lyrics \lyricsto sop { la la la la }
  >>
  \layout {
    \override Staff.Stem.thickness = 4
    \override VocalStaff.Stem.color = #blue
    \override SopranoVoice.NoteHead.color = #green
  }
  \midi {
    \set SopranoVoice.midiInstrument = "clarinet"
  }
}
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to