lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Using one identifier or another


From: Dan Eble
Subject: Re: Using one identifier or another
Date: Mon, 18 Aug 2008 22:28:08 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Johan Vromans <jvromans <at> squirrel.nl> writes:

> 
> Dan Eble <dan <at> faithful.be> writes:
> 
> > These two functions should help.
> 
> Thanks! I can use this.
> 
> > You will either need to define your optional music to be empty when
> > it is not required, as in this example, or provide a function to
> > create empty music if it is not already defined.
> 
> I would be very interested in the latter.

Johan,

I have a framework for creating collections of many short pieces.
The music for each piece is in its own file, along with metadata
pertaining to the music.  For example,

    composer = "William H. Monk"
    compositionDate = "1861"
    tune = "Eventide"
    meter = "10.10.10.10"

Four voices are supported: sNotes, aNotes, tNotes, and bNotes.
(If I were to start over, I would use aNotes, bNotes, cNotes, etc.)
Shared notation (e.g. rehearsal marks) is defined in staffItems.

The variable names are the same in every piece, and would normally
conflict when included in the top-level file.  I use some functions
 to work around that problem:

    \include "notes/tune/Eventide.ly"
    title = "Abide with Me"
    secRefBook = "Gospel Hymns"
    secRefPage = "317"
    \headerStore "AWM"
    \fourpartStore "AWM"

    \include "notes/tune/Diadem.ly"
    title = "All Hail the Power of Jesus' Name"
    secRefBook = "Apostolic Christian Hymnal"
    secRefPage = "320"
    \headerStore "AHTPOJN"
    \fourpartStore "AHTPOJN"

Conceptually, headerStore and fourpartStore move the metadata
variables and music variables into a named scope.  Actually,
they just rename the variables. In the example above, sNotes
defined in Eventide.ly becomes AWMsNotes. (Notice that some
header variables are defined outside the notes file.  This is
because they relate to the lyrics rather than the music, so
they could differ in other contexts.)

This does half the job.  The variables for every song can live
together in peace and harmony, waiting to be used in the \score
blocks.  But the staff definition files included from each \score
block refer to the original names (e.g. sNotes), so two more
functions are required.

  \score
  {
    <<
      \fourpartLoad "AWM"
      \include "staff/satb_hymn.ly"
    >>

    \header
    {
      #(header-load "AWM")
    }

    \layout { }

    \midi { }
  }

fourpartLoad and header-load remove the prefixes from the
necessary variable names, so that satb_hymn.ly can simply use
sNotes etc.  (I tried defining a \headerLoad function for
symmetry; as I recall, it would not parse.)

How does all this connect to your situation?  The functions make
sure that all the variables which could be used are defined
(possibly empty) in the top-level file, even if they had not been
defined in the included files.  So, without further ado, here are
the functions.  I store them in a file called namespace-functions.ly.
I hope this will serve you well.

% For the given symbols that are defined in the module, rename each by
% prepending the prefix.
#(define (module-add-symbol-prefix module symbols prefix)
   (for-each
    (lambda (genSym)
      (if (module-defined? module genSym)
          (let* ((var (module-variable module genSym))
                 (val (variable-ref var))
                 (specSym (string->symbol
                           (string-append prefix (symbol->string genSym)))))
            (module-define! module specSym val)
            (module-remove! module genSym))))
    symbols))

% For the given symbols with the prefix that are defined in the module,
% rename each by removing the prefix.  For those that are not defined,
% define them with the default value.
#(define (module-remove-symbol-prefix module symbols prefix defval)
   (for-each
    (lambda (genSym)
      (let* ((specSym
              (string->symbol (string-append prefix (symbol->string genSym)))))
        (if (module-defined? module specSym)
            (let* ((val (variable-ref (module-variable module specSym))))
              (module-define! module genSym val)
              (module-remove! module specSym))
            (module-define! module genSym defval))))
    symbols))

#(define fourpart-vars '(sNotes aNotes tNotes bNotes staffItems))

fourpartLoad =
#(define-music-function (parser location prefix) (string?)
  (module-remove-symbol-prefix (current-module) fourpart-vars prefix
                               (make-void-skip-music))
  (make-music 'SequentialMusic 'void #t)
)

fourpartStore =
#(define-music-function (parser location prefix) (string?)
  (module-add-symbol-prefix (current-module) fourpart-vars prefix)
  (make-music 'SequentialMusic 'void #t)
)

#(define header-vars
   '(title subtitle subsubtitle
     poet poemDate
     translator translationDate
     musicPub musicPubDate
     composer compositionDate
     arranger arrangementDate
     opus tune meter secRefBook secRefPage))

headerStore =
#(define-music-function (parser location prefix) (string?)
  (module-add-symbol-prefix (current-module) header-vars prefix)
  (make-music 'SequentialMusic 'void #t)
)

#(define-public (header-load prefix)
   (module-remove-symbol-prefix (current-module) header-vars prefix #f))
-- 
Dan






reply via email to

[Prev in Thread] Current Thread [Next in Thread]