]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/user/programming-interface.itely
The grand \paper -> \layout, \bookpaper -> \paper renaming.
[lilypond.git] / Documentation / user / programming-interface.itely
index ff923a66c66005873e11a4e270f6677d82e62c07..f4a3f43eed03a22690541e6973d4619f33459b26 100644 (file)
@@ -1,59 +1,62 @@
+@c -*-texinfo-*-
 @node Interfaces for programmers
-@appendix Interfaces for programmers
+@chapter Interfaces for programmers
 
 
 
 @menu
 * Programmer interfaces for input ::  
-* Markup programmer interface::         
-* Contexts for programmers::   
+* Markup programmer interface::  
+* Contexts for programmers::    
 @end menu
 
 @node Programmer interfaces for input 
-@appendixsec Programmer interfaces for input 
+@section Programmer interfaces for input 
 
 @menu
-* Input variables and Scheme:: 
+* Input variables and Scheme::  
 * Internal music representation::  
+* Extending music syntax::      
 * Manipulating music expressions::  
+* Using LilyPond syntax inside Scheme::  
 @end menu
 
 @node Input variables and Scheme
-@appendixsubsec Input variables and Scheme
+@subsection Input variables and Scheme
 
 
 The input format supports the notion of variable: in the following
 example, a music expression is assigned to a variable with the name
 @code{traLaLa}.
 @example
-  traLaLa = \notes @{ c'4 d'4 @}
+  traLaLa = @{ c'4 d'4 @}
 @end example
 
 @noindent
 
 There is also a form of scoping: in the following example, the
-@code{\paper} block also contains a @code{traLaLa} variable, which is
+@code{\layout} block also contains a @code{traLaLa} variable, which is
 independent of the outer @code{\traLaLa}.
 @example
-  traLaLa = \notes @{ c'4 d'4 @}
-  \paper @{ traLaLa = 1.0 @}
+  traLaLa = @{ c'4 d'4 @}
+  \layout @{ traLaLa = 1.0 @}
 @end example
 @c
 In effect, each input file is a scope, and all @code{\header},
-@code{\midi} and @code{\paper} blocks are scopes nested inside that
+@code{\midi} and @code{\layout} blocks are scopes nested inside that
 toplevel scope.
 
 Both variables and scoping are implemented in the GUILE module system.
 An anonymous Scheme module is attached to each scope. An assignment of
 the form
 @example
- traLaLa = \notes @{ c'4 d'4 @}
+ traLaLa = @{ c'4 d'4 @}
 @end example
 
 @noindent
 is internally converted to a Scheme definition
 @example
- (define traLaLa @var{Scheme value of ``@code{\notes ... }''})
+ (define traLaLa @var{Scheme value of ``@code{... }''})
 @end example
 
 This means that input variables and Scheme variables may be freely
@@ -62,30 +65,34 @@ variable @code{traLaLa}, and duplicated using Scheme. The result is
 imported in a @code{\score} by means of a second variable
 @code{twice}:
 @example
-  traLaLa = \notes @{ c'4 d'4 @}
+  traLaLa = @{ c'4 d'4 @}
 
   #(define newLa (map ly:music-deep-copy
     (list traLaLa traLaLa)))
   #(define twice
     (make-sequential-music newLa))
 
-  \score @{ \twice @}
+  @{ \twice @}
 @end example
 
 In the above example, music expressions can be `exported' from the
 input to the Scheme interpreter. The opposite is also possible. By
 wrapping a Scheme value in the function @code{ly:export}, a Scheme
-value is interpreted as if it were entered in LilyPond syntax: instead
+value is interpreted as if it were entered in LilyPond syntax.  Instead
 of defining @code{\twice}, the example above could also have been
 written as
 @example
   @dots{}
-  \score @{ #(ly:export (make-sequential-music newLa)) @}
+  @{ #(ly:export (make-sequential-music newLa)) @}
 @end example
 
+@refbugs
+
+Mixing Scheme and LilyPond identifiers is not possible with the
+@code{--safe} option.
 
 @node Internal music representation
-@appendixsubsec Internal music representation
+@subsection Internal music representation
 
 When a music expression is parsed, it is converted into a set of
 Scheme music objects. The defining property of a music object is that
@@ -98,21 +105,22 @@ A music object has three kinds of types:
   music name: Each music expression has a name, for example, a note
 leads to a @internalsref{NoteEvent}, and @code{\simultaneous} leads to
 a @internalsref{SimultaneousMusic}. A list of all expressions
-available is in the internals manual, under @internalsref{Music
-expressions}.
+available is in the internals manual, under
+@hyphenatedinternalsref{Music expressions,Music-expressions}.
 
 @item
-  `type' or interface: Each music name has several `types' or interface,
-  for example, a note is an @code{event}, but it is also a @code{note-event},
-  a @code{rhythmic-event} and a @code{melodic-event}.
+  `type' or interface: Each music name has several `types' or
+interfaces, for example, a note is an @code{event}, but it is also a
+@code{note-event}, a @code{rhythmic-event} and a @code{melodic-event}.
 
   All classes of music are listed in the internals manual, under
-  @internalsref{Music classes}.
-@item
-C++ object: Each music object is represented by a C++ object. For technical
-reasons, different music objects may be represented by different C++
-object types. For example, a note is @code{Event} object, while
-@code{\grace} creates a @code{Grace_music} object.
+  @hyphenatedinternalsref{Music classes,Music-classes}.
+
+  @item
+C++ object: Each music object is represented by a C++ object. For
+technical reasons, different music objects may be represented by
+different C++ object types. For example, a note is @code{Event}
+object, while @code{\grace} creates a @code{Grace_music} object.
 
 We expect that distinctions between different C++ types will disappear
 in the future.
@@ -130,48 +138,121 @@ the @code{elements} property of a music object, or a single `child'
 music object in the @code{element} object. For example,
 @internalsref{SequentialMusic} has its children in @code{elements},
 and @internalsref{GraceMusic} has its single argument in
-@code{element}. The body of a repeat is in @code{element} property of
-@internalsref{RepeatedMusic}, and the alternatives in @code{elements}.
+@code{element}. The body of a repeat is stored in the @code{element}
+property of @internalsref{RepeatedMusic}, and the alternatives in
+@code{elements}.
+
+
+
+
+@node Extending music syntax
+@subsection Extending music syntax
+
+The syntax of composite music expressions, like
+@code{\repeat}, @code{\transpose} and @code{\context}
+follows the general form of
+
+@example
+  \@code{keyword} @var{non-music-arguments} @var{music-arguments}
+@end example
+
+Such syntax can also be defined as user code. To do this, it is
+necessary to create a @emph{music function}. This is a specially marked
+Scheme function. For example, the music function @code{\applymusic} applies
+a user-defined function to a music expression.  Its syntax is
+
+@example
+\applymusic #@var{func} @var{music}
+@end example
+
+A music function is created with @code{ly:make-music-function},
+
+@example
+  (ly:make-music-function
+@end example
+
+@code{\applymusic} takes a Scheme function and a Music expression as
+argument. This is encoded in its first argument,
+
+@example
+   (list procedure? ly:music?)
+@end example
+
+The function itself takes another argument, an Input location
+object. That object is used to provide error messages with file names
+and line numbers.  The definition is the second argument of
+@code{ly:make-music-function}. The body is function simply calls the
+function
+
+@example
+  (lambda (where func music)
+   (func music))
+@end example
+
+The above Scheme code only defines the functionality. The tag
+@code{\applymusic} is selected by defining
+
+@example
+  applymusic = #(ly:make-music-function
+                  (list procedure? ly:music?)
+                  (lambda (location func music)
+                    (func music)))
+@end example
+
+A @code{def-music-function} macro is introduced on top of
+@code{ly:make-music-function} to ease the definition of music
+functions:
+
+@example
+  applymusic = #(def-music-function (location func music)
+                  (procedure? ly:music?)
+                  (func music))
+@end example
+
+Examples of the use of @code{\applymusic} are in the next section.
+
+@seealso
+@file{ly/music-functions-init.ly}.
 
 @node Manipulating music expressions
-@appendixsubsec Manipulating music expressions
+@subsection Manipulating music expressions
 
 Music objects and their properties can be accessed and manipulated
-directly, through the @code{\apply} mechanism.
-The syntax for @code{\apply} is
+directly, through the @code{\applymusic} mechanism.
+The syntax for @code{\applymusic} is
 @example
-\apply #@var{func} @var{music}
+\applymusic #@var{func} @var{music}
 @end example
 
 @noindent
-This means that the scheme function @var{func} is called with
+This means that the Scheme function @var{func} is called with
 @var{music} as its argument.  The return value of @var{func} is the
 result of the entire expression.  @var{func} may read and write music
 properties using the functions @code{ly:music-property} and
 @code{ly:music-set-property!}.
 
 An example is a function that reverses the order of elements in
-its argument:
+its argument,
 @lilypond[verbatim,raggedright]
   #(define (rev-music-1 m)
      (ly:music-set-property! m 'elements (reverse
        (ly:music-property m 'elements)))
      m)
-  \score { \notes \apply #rev-music-1 { c4 d4 } }
+  \applymusic #rev-music-1 { c4 d4 } 
 @end lilypond
 
 The use of such a function is very limited. The effect of this
 function is void when applied to an argument which is does not have
-multiple children.  The following function application has no effect:
+multiple children.  The following function application has no effect
 
 @example
-  \apply #rev-music-1 \grace @{ c4 d4 @}
+  \applymusic #rev-music-1 \grace @{ c4 d4 @}
 @end example
 
 @noindent
 In this case, @code{\grace} is stored as @internalsref{GraceMusic}, which has no
 @code{elements}, only a single @code{element}. Every generally
-applicable function for @code{\apply} must -- like music expressions
+applicable function for @code{\applymusic} must---like music expressions
 themselves -- be recursive.
 
 The following example is such a recursive function: It first extracts
@@ -211,11 +292,17 @@ above by the internal equivalent of
     \context Voice = "2" @{ \voiceTwo b @} >>
 @end example
 
-Other applications of @code{\apply} are writing out repeats
+Other applications of @code{\applymusic} are writing out repeats
 automatically (@inputfileref{input/test,unfold-all-repeats.ly}),
 saving keystrokes (@inputfileref{input/test,music-box.ly}) and
-exporting
-LilyPond input to other formats  (@inputfileref{input/test,to-xml.ly})
+exporting LilyPond input to other formats
+(@inputfileref{input/test,to-xml.ly})
+
+@cindex internal storage
+@cindex @code{\displayMusic}
+When writing a music function, it is often instructive to inspect how
+a music expression is stored internally. This can be done with the
+music function @code{\displayMusic}
 
 @seealso
 
@@ -225,18 +312,121 @@ LilyPond input to other formats  (@inputfileref{input/test,to-xml.ly})
 @inputfileref{input/test,music-box.ly}.
 
 
+@node Using LilyPond syntax inside Scheme
+@subsection Using LilyPond syntax inside Scheme
+
+Creating music expressions in Scheme can be tedious, as they are
+heavily nested and the resulting Scheme code is large. For some
+simple tasks, this can be avoided, using LilyPond usual syntax inside
+Scheme, with the dedicated @code{#@{ ... #@}} syntax.
+
+The following two expressions give equivalent music expressions:
+@example
+  mynotes = @{ \override Stem #'thickness = #4
+              @{ c'8 d' @} @}
+  
+  #(define mynotes #@{ \override Stem #'thickness = #4
+                      @{ c'8 d' @} #@})
+@end example
+
+The content of @code{#@{ ... #@}} is enclosed in an implicit @code{@{
+... @}} block, which is parsed. The resulting music expression, a
+@code{SequentialMusic} music object, is then returned and usable in Scheme.
+
+Arbitrary Scheme forms, including variables, can be used in @code{#@{ ... #@}}
+expressions with the @code{$} character (@code{$$} can be used to
+produce a single $ character). This makes the creation of simple
+functions straightforward. In the following example, a function
+setting the TextScript's padding is defined:
+
+@lilypond[verbatim,raggedright]
+  #(use-modules (ice-9 optargs))
+  #(define* (textpad padding #:optional once?)
+    (ly:export   ; this is necessary for using the expression
+                 ; directly inside a block
+      (if once?
+          #{ \once \override TextScript #'padding = #$padding #}
+          #{ \override TextScript #'padding = #$padding #})))
+  
+      {
+          c'^"1"
+          #(textpad 3.0 #t) % only once
+          c'^"2"
+          c'^"3"
+          #(textpad 5.0)
+          c'^"4"
+          c'^"5"
+          
+      }
+@end lilypond
+
+Here, the variable @code{padding} is a number; music expression
+variables may also be used in a similar fashion, as in the following
+example:
+
+@lilypond[verbatim,raggedright]
+  #(define (with-padding padding)
+     (lambda (music)
+       #{ \override TextScript #'padding = #$padding
+          $music
+          \revert TextScript #'padding #}))
+  
+      {
+          c'^"1"
+          \applymusic #(with-padding 3)
+            { c'^"2" c'^"3"}
+          c'^"4"
+      }
+@end lilypond
+
+The function created by @code{(with-padding 3)} adds @code{\override} and
+@code{\revert} statements around the music given as an argument, and returns
+this new expression. Thus, this example is equivalent to:
+
+@example
+      @{
+          c'^"1"
+          @{ \override TextScript #'padding = #3
+            @{ c'^"2" c'^"3"@}
+            \revert TextScript #'padding
+          @}
+          c'^"4"
+      @}
+@end example
+
+This function may also be defined as a music function:
+
+@lilypond[verbatim,raggedright]
+  withPadding = #(def-music-function (location padding music) (number? ly:music?)
+                   #{ \override TextScript #'padding = #$padding
+                      $music 
+                      \revert TextScript #'padding #})
+  
+      {
+          c'^"1"
+          \withPadding #3
+            { c'^"2" c'^"3"}
+          c'^"4"
+      }
+@end lilypond
+
 
 @node Markup programmer interface
-@appendixsec Markup programmer interface
+@section Markup programmer interface
 
+Markups implemented as special Scheme functions. When applied with as
+arguments an output definition (@code{\layout} or @code{\paper}),
+and a list of properties and other arguments, produce a Stencil
+object.
 
 @menu
-* Markup construction in scheme::  
-* Markup command definition::  
+* Markup construction in Scheme::  
+* How markups work internally ::  
+* Markup command definition::   
 @end menu
 
-@node Markup construction in scheme
-@appendixsubsec Markup construction in scheme
+@node Markup construction in Scheme
+@subsection Markup construction in Scheme
 
 @cindex defining markup commands 
 
@@ -256,7 +446,7 @@ is equivalent to:
 
 @noindent
 This example exposes the main translation rules between regular
-LilyPond markup syntax and scheme markup syntax, which are summed up
+LilyPond markup syntax and Scheme markup syntax, which are summed up
 is this table:
 @multitable @columnfractions .5 .5
 @item @b{LilyPond} @tab @b{Scheme}
@@ -278,32 +468,78 @@ instance. This proves useful when defining new markup commands (see
 
 One can not feed the @code{#:line} (resp @code{#:center},
 @code{#:column}) command with a variable or the result of a function
-call. Eg:
+call. E.g.:
 @lisp
 (markup #:line (fun-that-returns-markups))
 @end lisp
 is illegal. One should use the @code{make-line-markup} (resp
 @code{make-center-markup}, @code{make-column-markup}) function
-instead:
+instead,
 @lisp
 (markup (make-line-markup (fun-that-returns-markups)))
 @end lisp
 
+@node How markups work internally 
+@subsection How markups work internally 
+
+In a markup like
+
+@example
+  \raise #0.5 "foo"
+@end example
+
+@noindent
+@code{\raise} is actually represented by the @code{raise-markup}
+function. The markup expression is stored as
+
+@example
+  (list raise-markup 0.5 (list simple-markup 'latin1 "foo"))
+@end example
+
+@noindent
+In this case, @code{latin1} is the input encoding, which is set with
+the @code{\encoding} command.
+
+When the markup is converted to printable objects (Stencils), the
+raise markup is called as
+
+@example
+  (apply raise-markup
+         @var{\layout object}
+         @var{list of property alists}
+         0.5
+         @var{the "foo" markup})
+@end example
+
+The @code{raise-markup} first creates the stencil for the @code{foo}
+string, and then it raises that Stencil by 0.5 staff space. This is a
+rather simple example; more complex examples are in the rest of this
+section, and in @file{scm/define-markup-commands.scm}.
+
 @node Markup command definition
-@appendixsubsec Markup command definition
+@subsection Markup command definition
 
-New markup commands can be defined thanks to the @code{def-markup-command} scheme macro.
+New markup commands can be defined
+with  the @code{def-markup-command} scheme macro.
 @lisp
-(def-markup-command (@var{command-name} @var{paper} @var{props} @var{arg1} @var{arg2} ...)
+(def-markup-command (@var{command-name} @var{layout} @var{props} @var{arg1} @var{arg2} ...)
             (@var{arg1-type?} @var{arg2-type?} ...)
   ..command body..)
-
-    @var{argi}: i@var{th} command argument
-    @var{argi-type?}: a type predicate for the i@var{th} argument
-    @var{paper}: the `paper' definition
-    @var{props}: a list of alists, containing all active properties. 
 @end lisp
 
+The arguments signify
+
+@table @var
+@item argi
+@var{i}th command argument
+@item argi-type?
+a type predicate for the i@var{th} argument
+@item layout
+the `layout' definition
+@item props
+a list of alists, containing all active properties. 
+@end table
+
 As a simple example, we show how to add a @code{\smallcaps} command,
 which selects @TeX{}'s small caps font.  Normally, we could select the
 small caps font as follows:
@@ -320,7 +556,7 @@ define a function using @code{def-markup-command}. The command should
 take a single argument, of markup type. Therefore, the start of the
 definition should read
 @example
-  (def-markup-command (smallcaps paper props argument) (markup?)
+  (def-markup-command (smallcaps layout props argument) (markup?)
 @end example
 
 @noindent
@@ -329,12 +565,12 @@ What follows is the content of the command: we should interpret
 the @code{argument} as a markup, i.e.
 
 @example
-    (interpret-markup paper  @dots{} argument)
+    (interpret-markup layout  @dots{} argument)
 @end example
 
 @noindent
 This interpretation should add @code{'(font-shape . caps)} to the active
-properties, so we substitute the the following for the @dots{} in the
+properties, so we substitute the  following for the @dots{} in the
 above example:
 
 @example
@@ -345,38 +581,8 @@ above example:
 The variable @code{props} is a list of alists, and we prepend to it by
 consing a list with the extra setting.
 
-However, suppose that we are using a font that does not have a
-small-caps variant. In that case, we have to fake the small caps font,
-by setting a string in upcase, with the first letter a little larger:
-
-@example
-#(def-markup-command (smallcaps paper props str) (string?)
-   "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
-   (interpret-markup paper props
-    (make-line-markup
-     (map (lambda (s)
-            (if (= (string-length s) 0)
-                s
-                (markup #:large (string-upcase (substring s 0 1))
-                        #:translate (cons -0.6 0)
-                        #:tiny (string-upcase (substring s 1)))))
-          (string-split str #\Space)))))
-@end example
-
-The @code{smallcaps} command first splits its string argument into
-tokens separated by spaces (@code{(string-split str #\Space)}); for
-each token, a markup is built with the first letter made large and
-upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
-second markup built with the following letters made tiny and upcased
-(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond
-introduces a space between markups on a line, the second markup is
-translated to the left (@code{#:translate (cons -0.6 0) ...}). Then,
-the markups built for each token are put in a line
-(@code{(make-line-markup ...)}). Finally, the resulting markup is
-passed to the @code{interpret-markup} function, with the @code{paper}
-and @code{props} arguments.
 
-Finally, suppose that we are typesetting a recitative in an opera, and
+Suppose that we are typesetting a recitative in an opera, and
 we would like to define a command that will show character names in a
 custom manner. Names should be printed with small caps and translated a
 bit to the left and top.  We will define a @code{\character} command
@@ -384,10 +590,10 @@ that takes into account the needed translation, and uses the newly
 defined @code{\smallcaps} command:
 
 @verbatim
-#(def-markup-command (character paper props name) (string?)
+#(def-markup-command (character layout props name) (string?)
    "Print the character name in small caps, translated to the left and
    top. Syntax: \\character #\"name\""
-   (interpret-markup paper props 
+   (interpret-markup layout props 
     (markup "" #:translate (cons -4 2) #:smallcaps name)))
 @end verbatim
 
@@ -402,18 +608,16 @@ that the text is moved to the upper left.
 
 The final result is as follows:
 @verbatim
-\score {
-    \notes { \fatText
+    { \fatText
         c''^\markup \character #"Cleopatra"
         e'^\markup \character #"Giulio Cesare"
     }
-}
 @end verbatim
 
 @lilypond[raggedright]
-#(def-markup-command (smallcaps paper props str) (string?)
+#(def-markup-command (smallcaps layout props str) (string?)
    "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
-   (interpret-markup paper props
+   (interpret-markup layout props
     (make-line-markup
      (map (lambda (s)
             (if (= (string-length s) 0)
@@ -423,33 +627,66 @@ The final result is as follows:
                         #:tiny (string-upcase (substring s 1)))))
           (string-split str #\Space)))))
 
-#(def-markup-command (character paper props name) (string?)
+#(def-markup-command (character layout props name) (string?)
    "Print the character name in small caps, translated to the left and
    top. Syntax: \\character #\"name\""
-   (interpret-markup paper props 
+   (interpret-markup layout props 
     (markup "" #:translate (cons -4 0) #:smallcaps name)))
 
-\score {
-    \notes { \fatText
+    { \fatText
         c''^\markup \character #"Cleopatra"
         e'^\markup \character #"Giulio Cesare"
     }
-}
 @end lilypond
 
+We have used the @code{caps} font shape, but suppose that our font
+that does not have a small-caps variant. In that case, we have to fake
+the small caps font, by setting a string in upcase, with the first
+letter a little larger:
+
+@example
+#(def-markup-command (smallcaps layout props str) (string?)
+   "Print the string argument in small caps."
+   (interpret-markup layout props
+    (make-line-markup
+     (map (lambda (s)
+            (if (= (string-length s) 0)
+                s
+                (markup #:large (string-upcase (substring s 0 1))
+                        #:translate (cons -0.6 0)
+                        #:tiny (string-upcase (substring s 1)))))
+          (string-split str #\Space)))))
+@end example
+
+The @code{smallcaps} command first splits its string argument into
+tokens separated by spaces (@code{(string-split str #\Space)}); for
+each token, a markup is built with the first letter made large and
+upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
+second markup built with the following letters made tiny and upcased
+(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond
+introduces a space between markups on a line, the second markup is
+translated to the left (@code{#:translate (cons -0.6 0) ...}). Then,
+the markups built for each token are put in a line by
+@code{(make-line-markup ...)}. Finally, the resulting markup is passed
+to the @code{interpret-markup} function, with the @code{layout} and
+@code{props} arguments.
+
 
 
 @node Contexts for programmers
-@appendixsec Contexts for programmers
+@section Contexts for programmers
 
 
 @menu
-* Context evaluation::         
-* Applyoutput::                        
+* Context evaluation::          
+* Running a function on all layout objects::  
 @end menu
 
 @node Context evaluation
-@appendixsubsec Context evaluation
+@subsection Context evaluation
+
+@cindex calling code during interpreting
+@cindex @code{\applycontext}
 
 Contexts can be modified during interpretation with Scheme code. The
 syntax for this is
@@ -470,8 +707,13 @@ current bar number on the standard output during the compile:
 
 
 
-@node Applyoutput
-@appendixsubsec Applyoutput
+@node Running a function on all layout objects
+@subsection Running a function on all layout objects
+
+
+@cindex calling code on layout objects
+@cindex @code{\applyoutput}
+
 
 The most versatile way of tuning an object is @code{\applyoutput}. Its
 syntax is
@@ -497,14 +739,15 @@ object property @code{cause}.  For example, for a note head, this is a
 @internalsref{NoteHead} event, and for a @internalsref{Stem} object,
 this is a @internalsref{NoteHead} object.
 
-Here is a simple example of @code{\applyoutput}; it blanks note-heads on the
-center-line:
+Here is a function to use for @code{\applyoutput}; it blanks
+note-heads on the center-line:
+
 @example
 (define (blanker grob grob-origin context)
   (if (and (memq (ly:grob-property grob 'interfaces)
                  note-head-interface)
            (eq? (ly:grob-property grob 'staff-position) 0))
 
-           (ly:grob-set-property! grob 'transparent #t)))
+           (set! (ly:grob-property grob 'transparent) #t)))
 @end example