lilypond-devel
[Top][All Lists]
Advanced

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

Re: [patch] \label, page references


From: Nicolas Sceaux
Subject: Re: [patch] \label, page references
Date: Sun, 27 May 2007 22:04:09 +0200
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin)

Han-wen,

Here is a new patch:

 - the \label command can be used at top-level or inside music;

 - for labels inside music: the paper_column_engraver handles
   label-events and fills the labels property of the paper column;

 - for top-level labels: Paper_book::get_system_specs() fill the labels
   property of the previous prob or of the first column of the previous
   paper_score;

 - when systems are built, the labels of their columns are collected to
   set the system labels property;

 - in Page_breaking::make_pages(), a label->page-number table is built,
   and stored in the labels_ slot of the paper-book object;

 - the \page-ref markup command accesses the paper-book object by its
   props argument, and then the label/page-number table using a
   ly:paper-book-labels accessor. This evaluation of the stencil is
   postponed to the layout output phase. A user-supplied gauge is used
   in the mean time to estimate the stencil dimensions.

A MARKUP_HEAD_SCM0_MARKUP1_MARKUP2 token has been added to the parser
for this new markup command.

The regression test illustrates how this can be used for a table of
contents.

However, an major issue is remaining: only top-level markups can access
the paper-book instance, and thus the labels table. (With little effort,
page headers and footers could also do it). This means that \page-ref
won't work in a TextScript. I can't find a way to make that possible,
other than by modifying the paper instance. (Grobs can't access the
paper-book, do they?).

>> +      else if (Prob * markup = unsmob_prob (scm_car (l)))
>> +        labels = markup->get_property ("labels");
>> +
>
> This looks fishy; the type checking should be stricter, music is a prob too.

I haven't addressed this. Whatever the actual type of the prob that is
found here (this is in Page_breaking::make_pages), we would like to
collect the labels anyway, no? I've renamed the variable prob.

nicolas

diff --git a/input/regression/page-label.ly b/input/regression/page-label.ly
new file mode 100644
index 0000000..7adf975
--- /dev/null
+++ b/input/regression/page-label.ly
@@ -0,0 +1,32 @@
+\version "2.11.24"
+
+\header {
+  texidoc = "Page labels may be placed inside music or at top-level,
+and refered to in markups."
+}
+
+#(set-default-paper-size "a6")
+
+#(define-markup-command (toc-line layout props label text) (symbol? markup?)
+  (interpret-markup layout props
+   (markup #:fill-line (text #:page-ref label "8" "?"))))
+
+\score {
+  { c'1 c'1 \pageBreak
+    \mark "A" \label #'markA d'
+    \mark "B" \label #'markB d'2 
+    \once \override Score . RehearsalMark #'break-visibility = 
#begin-of-line-invisible
+    \mark "C" \label #'markC
+  }
+  \header { piece = "First score" }
+} \label #'firstScore
+\pageBreak
+\markup \column {
+  \large \fill-line { \null "Table of contents" \null }
+  \toc-line #'firstScore "First Score"
+  \toc-line #'markA "Mark A"
+  \toc-line #'markB "Mark B"
+  \toc-line #'markC "Mark C"
+  \toc-line #'unknown "Unknown label"
+  \toc-line #'toc "Table of contents"
+} \label #'toc
diff --git a/lily/include/page-marker.hh b/lily/include/page-marker.hh
index a925a6c..69962e6 100644
--- a/lily/include/page-marker.hh
+++ b/lily/include/page-marker.hh
@@ -17,12 +17,17 @@ class Page_marker
 
   SCM symbol_; /* either 'page-turn-permission or 'page-break-permission */
   SCM permission_;  /* 'force, 'allow, or '() */
+  SCM label_; /* bookmarking label (a symbol) */
 
 public:
-  Page_marker (SCM symbol, SCM permission);
+  Page_marker ();
   
+  void set_permission (SCM symbol, SCM permission);
+  void set_label (SCM label);
+
   SCM permission_symbol ();
   SCM permission_value ();
+  SCM label ();
 };
 
 DECLARE_UNSMOB (Page_marker, page_marker)
diff --git a/lily/include/paper-book.hh b/lily/include/paper-book.hh
index 4ea1927..25a4d6f 100644
--- a/lily/include/paper-book.hh
+++ b/lily/include/paper-book.hh
@@ -32,6 +32,7 @@ public:
   SCM header_0_;
   SCM scores_;
   Output_def *paper_;
+  SCM labels_;
 
   Paper_book ();
 
diff --git a/lily/include/paper-column-engraver.hh 
b/lily/include/paper-column-engraver.hh
index 793d085..fbe51a5 100644
--- a/lily/include/paper-column-engraver.hh
+++ b/lily/include/paper-column-engraver.hh
@@ -31,6 +31,7 @@ protected:
   virtual void finalize ();
 
   DECLARE_TRANSLATOR_LISTENER (break);
+  DECLARE_TRANSLATOR_LISTENER (label);
 
   DECLARE_ACKNOWLEDGER (item);
   DECLARE_ACKNOWLEDGER (note_spacing);
@@ -38,6 +39,7 @@ protected:
 
   System *system_;
   vector<Stream_event*> break_events_;
+  vector<Stream_event*> label_events_;
   int breaks_;                 // used for stat printing
   Paper_column *command_column_;
   Paper_column *musical_column_;
diff --git a/lily/lexer.ll b/lily/lexer.ll
index 66457f4..ec17fb3 100644
--- a/lily/lexer.ll
+++ b/lily/lexer.ll
@@ -536,6 +536,8 @@ BOM_UTF8    \357\273\277
                                return MARKUP_HEAD_SCM0_MARKUP1;
                        else if (tag == ly_symbol2scm 
("scheme0-scheme1-markup2"))
                                return MARKUP_HEAD_SCM0_SCM1_MARKUP2;
+                       else if (tag == ly_symbol2scm 
("scheme0-markup1-markup2"))
+                               return MARKUP_HEAD_SCM0_MARKUP1_MARKUP2;
                        else if (tag == ly_symbol2scm 
("scheme0-scheme1-scheme2"))
                                return MARKUP_HEAD_SCM0_SCM1_SCM2;
                        else {
diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc
index 46a1eed..87aefc7 100644
--- a/lily/page-breaking.cc
+++ b/lily/page-breaking.cc
@@ -235,6 +235,7 @@ Page_breaking::make_pages (vector<vsize>
   SCM book = book_->self_scm ();
   int first_page_number = robust_scm2int (book_->paper_->c_variable 
("first-page-number"), 1);
   SCM ret = SCM_EOL;
+  SCM label_page_table = SCM_EOL;
 
   for (vsize i = 0; i < lines_per_page.size (); i++)
     {
@@ -246,10 +247,28 @@ Page_breaking::make_pages (vector<vsize>
       SCM page = scm_apply_0 (make_page,
                              scm_list_n (book, lines, page_num, rag, last, 
SCM_UNDEFINED));
 
+      /* collect labels */
+      for (SCM l = lines ; scm_is_pair (l)  ; l = scm_cdr (l))
+       {
+         SCM labels = SCM_EOL;
+         if (Grob * line = unsmob_grob (scm_car (l)))
+           {
+             System *system = dynamic_cast<System*> (line);
+             labels = system->get_property ("labels");
+           }
+         else if (Prob *prob = unsmob_prob (scm_car (l)))
+           labels = prob->get_property ("labels");
+
+         for (SCM lbls = labels ; scm_is_pair (lbls) ; lbls = scm_cdr (lbls))
+           label_page_table = scm_cons (scm_cons (scm_car (lbls), page_num),
+                                        label_page_table);
+       }
+
       scm_apply_1 (page_stencil, page, SCM_EOL);
       ret = scm_cons (page, ret);
       systems = scm_list_tail (systems, line_count);
     }
+  book_->labels_ = label_page_table;
   ret = scm_reverse (ret);
   return ret;
 }
diff --git a/lily/page-marker-scheme.cc b/lily/page-marker-scheme.cc
index 3278a7b..f2450be 100644
--- a/lily/page-marker-scheme.cc
+++ b/lily/page-marker-scheme.cc
@@ -8,12 +8,24 @@
 
 #include "page-marker.hh"
 
-LY_DEFINE (ly_make_page_marker, "ly:make-page-marker",
+LY_DEFINE (ly_make_page_permission_marker, "ly:make-page-permission-marker",
           2, 0, 0,
           (SCM symbol, SCM permission),
           "Return page marker with page breaking and turning permissions.")
 {
   LY_ASSERT_TYPE (ly_is_symbol, symbol, 1);
-  Page_marker *page_marker = new Page_marker (symbol, permission);
+  Page_marker *page_marker = new Page_marker ();
+  page_marker->set_permission (symbol, permission);
+  return page_marker->unprotect ();
+}
+
+LY_DEFINE (ly_make_page_label_marker, "ly:make-page-label-marker",
+          1, 0, 0,
+          (SCM label),
+          "Return page marker with label.")
+{
+  LY_ASSERT_TYPE (ly_is_symbol, label, 1);
+  Page_marker *page_marker = new Page_marker ();
+  page_marker->set_label (label);
   return page_marker->unprotect ();
 }
diff --git a/lily/page-marker.cc b/lily/page-marker.cc
index dd43c35..11b1999 100644
--- a/lily/page-marker.cc
+++ b/lily/page-marker.cc
@@ -9,10 +9,11 @@
 #include "page-marker.hh"
 #include "ly-smobs.icc"
 
-Page_marker::Page_marker (SCM symbol, SCM permission)
+Page_marker::Page_marker ()
 {
-  symbol_ = symbol;
-  permission_ = permission;
+  symbol_ = SCM_EOL;
+  permission_ = SCM_EOL;
+  label_ = SCM_EOL;
   smobify_self ();
 }
 
@@ -30,6 +31,7 @@ Page_marker::mark_smob (SCM smob)
   Page_marker *pm = (Page_marker *) SCM_CELL_WORD_1 (smob);
   scm_gc_mark (pm->symbol_);
   scm_gc_mark (pm->permission_);
+  scm_gc_mark (pm->label_);
   return SCM_EOL;
 }
 
@@ -53,3 +55,24 @@ Page_marker::permission_value ()
 {
   return permission_;
 }
+
+SCM
+Page_marker::label ()
+{
+  return label_;
+}
+
+void
+Page_marker::set_permission (SCM symbol, SCM permission)
+{
+  symbol_ = symbol;
+  permission_ = permission;
+}
+
+void
+Page_marker::set_label (SCM label)
+{
+  label_ = label;
+}
+
+
diff --git a/lily/paper-book-scheme.cc b/lily/paper-book-scheme.cc
index 94bb17f..f366d88 100644
--- a/lily/paper-book-scheme.cc
+++ b/lily/paper-book-scheme.cc
@@ -56,3 +56,11 @@ LY_DEFINE (ly_paper_book_paper, "ly:pape
   Paper_book *pbook = unsmob_paper_book (pb);
   return pbook->paper_->self_scm ();
 }
+
+LY_DEFINE (ly_paper_book_labels, "ly:paper-book-labels",
+          1, 0, 0, (SCM pb),
+          "Return the labels - page numbers table of book PB.")
+{
+  LY_ASSERT_SMOB (Paper_book, pb, 1);
+  return unsmob_paper_book (pb)->labels_;
+}
diff --git a/lily/paper-book.cc b/lily/paper-book.cc
index 95be368..df51cf0 100644
--- a/lily/paper-book.cc
+++ b/lily/paper-book.cc
@@ -29,6 +29,7 @@ Paper_book::Paper_book ()
   scores_ = SCM_EOL;
   performances_ = SCM_EOL;
   systems_ = SCM_BOOL_F;
+  labels_ = SCM_EOL;
 
   paper_ = 0;
   smobify_self ();
@@ -53,6 +54,7 @@ Paper_book::mark_smob (SCM smob)
   scm_gc_mark (b->pages_);
   scm_gc_mark (b->performances_);
   scm_gc_mark (b->scores_);
+  scm_gc_mark (b->labels_);
   return b->systems_;
 }
 
@@ -270,6 +272,24 @@ set_system_penalty (SCM sys, SCM header)
     }
 }
 
+void
+set_label (SCM sys, SCM label)
+{
+  if (Paper_score *ps = dynamic_cast<Paper_score*> (unsmob_music_output (sys)))
+    {
+      vector<Grob*> cols = ps->get_columns ();
+      if (cols.size ())
+       {
+         Paper_column *col = dynamic_cast<Paper_column*> (cols[0]);
+         col->set_property ("labels", scm_cons (label, col->get_property 
("labels")));
+         Paper_column *col_right = col->find_prebroken_piece (RIGHT);
+         col_right->set_property ("labels", scm_cons (label, 
col_right->get_property ("labels")));
+       }
+    }
+  else if (Prob *pb = unsmob_prob (sys))
+    pb->set_property ("labels", scm_cons (label, pb->get_property ("labels")));
+}
+
 SCM
 Paper_book::get_score_title (SCM header)
 {
@@ -310,8 +330,9 @@ Paper_book::get_system_specs ()
     }
 
   SCM page_properties
-    = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
-                 paper_->self_scm ());
+    = scm_cons (scm_list_1 (scm_cons (ly_symbol2scm ("paper-book"), self_scm 
())),
+               scm_call_1 (ly_lily_module_constant 
("layout-extract-page-properties"),
+                           paper_->self_scm ()));
 
   SCM header = SCM_EOL;
   for (SCM s = scm_reverse (scores_); scm_is_pair (s); s = scm_cdr (s))
@@ -324,11 +345,22 @@ Paper_book::get_system_specs ()
        }
       else if (Page_marker *page_marker = unsmob_page_marker (scm_car (s)))
        {
-         /* a page marker: set previous element page break or turn permission 
*/
-         if (scm_is_pair (system_specs))
-           set_page_permission (scm_car (system_specs),
-                                page_marker->permission_symbol (),
-                                page_marker->permission_value ());
+         /* page markers are used to set page breaking/turning permission,
+            or to place bookmarking labels */ 
+         if (scm_is_symbol (page_marker->permission_symbol ()))
+           {
+             /* set previous element page break or turn permission */
+             if (scm_is_pair (system_specs))
+               set_page_permission (scm_car (system_specs),
+                                    page_marker->permission_symbol (),
+                                    page_marker->permission_value ());
+           }
+         if (scm_is_symbol (page_marker->label ()))
+           {
+             /* set previous element label */
+             if (scm_is_pair (system_specs))
+               set_label (scm_car (system_specs), page_marker->label ());
+           }
        }
       else if (Music_output *mop = unsmob_music_output (scm_car (s)))
        {
diff --git a/lily/paper-column-engraver.cc b/lily/paper-column-engraver.cc
index d583bc5..6dbafb5 100644
--- a/lily/paper-column-engraver.cc
+++ b/lily/paper-column-engraver.cc
@@ -116,6 +116,13 @@ Paper_column_engraver::listen_break (Str
   break_events_.push_back (ev);
 }
 
+IMPLEMENT_TRANSLATOR_LISTENER (Paper_column_engraver, label);
+void
+Paper_column_engraver::listen_label (Stream_event *ev)
+{
+  label_events_.push_back (ev);
+}
+
 void
 Paper_column_engraver::process_music ()
 {
@@ -150,6 +157,13 @@ Paper_column_engraver::process_music ()
        command_column_->set_property (perm_str.c_str (), perm);
     }
 
+  for (vsize i = 0 ; i < label_events_.size () ; i ++)
+    {
+      SCM label = label_events_[i]->get_property ("label");
+      SCM labels = command_column_->get_property ("labels");
+      command_column_->set_property ("labels", scm_cons (label, labels));
+    }
+
   bool start_of_measure = (last_moment_.main_part_ != now_mom ().main_part_
                           && !measure_position (context ()).main_part_);
 
diff --git a/lily/parser.yy b/lily/parser.yy
index f901a6d..18668de 100644
--- a/lily/parser.yy
+++ b/lily/parser.yy
@@ -279,6 +279,7 @@ If we give names, Bison complains.
 %token <scm> MARKUP_HEAD_SCM0_MARKUP1
 %token <scm> MARKUP_HEAD_SCM0_SCM1
 %token <scm> MARKUP_HEAD_SCM0_SCM1_MARKUP2
+%token <scm> MARKUP_HEAD_SCM0_MARKUP1_MARKUP2
 %token <scm> MARKUP_HEAD_SCM0_SCM1_SCM2
 %token <scm> MARKUP_IDENTIFIER
 %token <scm> MUSIC_FUNCTION
@@ -2293,6 +2294,9 @@ simple_markup:
        | MARKUP_HEAD_SCM0_SCM1 embedded_scm embedded_scm {
                $$ = scm_list_3 ($1, $2, $3);
        }
+       | MARKUP_HEAD_SCM0_MARKUP1_MARKUP2 embedded_scm markup markup {
+               $$ = scm_list_4 ($1, $2, $3, $4);
+       }
        | MARKUP_HEAD_EMPTY {
                $$ = scm_list_1 ($1);
        }
diff --git a/lily/stencil-interpret.cc b/lily/stencil-interpret.cc
index f6deee0..8afc330 100644
--- a/lily/stencil-interpret.cc
+++ b/lily/stencil-interpret.cc
@@ -21,6 +21,11 @@ interpret_stencil_expression (SCM expr,
 
       SCM head = scm_car (expr);
 
+      if (head == ly_symbol2scm ("delay-stencil-evaluation"))
+       {
+         interpret_stencil_expression (scm_force (scm_cadr (expr)), func, 
func_arg, o);
+         return;
+       }
       if (head == ly_symbol2scm ("translate-stencil"))
        {
          o += ly_scm2offset (scm_cadr (expr));
diff --git a/lily/system.cc b/lily/system.cc
index e700615..ef0e067 100644
--- a/lily/system.cc
+++ b/lily/system.cc
@@ -227,11 +227,17 @@ System::break_into_pieces (vector<Column
 
       system->set_bound (LEFT, c[0]);
       system->set_bound (RIGHT, c.back ());
+      SCM system_labels = SCM_EOL;
       for (vsize j = 0; j < c.size (); j++)
        {
          c[j]->translate_axis (breaking[i].config_[j], X_AXIS);
          dynamic_cast<Paper_column *> (c[j])->system_ = system;
+         /* collect the column labels */
+         SCM col_labels = c[j]->get_property ("labels");
+         if (scm_is_pair (col_labels))
+           system_labels = scm_append (scm_list_2 (col_labels, system_labels));
        }
+      system->set_property ("labels", system_labels);
       
       set_loose_columns (system, &breaking[i]);
       broken_intos_.push_back (system);
diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly
index 8360dcb..ea28ba4 100644
--- a/ly/music-functions-init.ly
+++ b/ly/music-functions-init.ly
@@ -298,7 +298,15 @@ killCues =
       (if (string? (ly:music-property mus 'quoted-music-name))
          (ly:music-property mus 'element)
          mus)) music))
-   
+
+label = 
+#(define-music-function (parser location label) (symbol?)
+   (_i "Place a bookmarking label, either at top-level or inside music.")
+   (make-music 'EventChord
+              'page-marker #t
+              'label label
+              'elements (list (make-music 'LabelEvent
+                                          'label label)))) 
 
 makeClusters =
 #(define-music-function
diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm
index 2bda1a2..f5d7b79 100644
--- a/scm/define-event-classes.scm
+++ b/scm/define-event-classes.scm
@@ -16,7 +16,7 @@
                                OneTimeStep Finish)) 
     (music-event . (annotate-output-event
                    arpeggio-event breathing-event extender-event span-event
-      rhythmic-event dynamic-event break-event percent-event
+      rhythmic-event dynamic-event break-event label-event percent-event
       key-change-event string-number-event stroke-finger-event tie-event 
part-combine-event
       beam-forbid-event script-event
       tremolo-event bend-after-event fingering-event glissando-event
@@ -86,7 +86,7 @@
 ;; All leaf event classes that no translator listens to
 ;; directly. Avoids printing a warning.
 (define unlistened-music-event-classes
-  '(harmonic-event line-break-event page-break-event page-turn-event
+  '(harmonic-event line-break-event page-break-event page-turn-event 
label-event
                   solo-one-event solo-two-event skip-event unisono-event))
 
 ;; produce neater representation of music event tree.
diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm
index 8a0853e..8198cbc 100644
--- a/scm/define-markup-commands.scm
+++ b/scm/define-markup-commands.scm
@@ -1463,8 +1463,31 @@ that."
         (m (interpret-markup layout props arg)))
     (bracketify-stencil m Y th (* 2.5 th) th)))
 
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; size indications arrow
+;; Delayed markup evaluation
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+(define-builtin-markup-command (page-ref layout props label gauge default)
+  (symbol? markup? markup?)
+  "Reference to a page number. @var{label} is the label set on the referenced
+page (using the @code{\\label} command), @var{gauge} a markup used to estimate
+the maximum width of the page number, and @var{default} the value to display
+when @var{label} is not found."
+  (let* ((gauge-stencil (interpret-markup layout props gauge))
+        (x-ext (ly:stencil-extent gauge-stencil X))
+        (y-ext (ly:stencil-extent gauge-stencil Y)))
+    (ly:make-stencil
+     `(delay-stencil-evaluation
+       ,(delay (ly:stencil-expr
+               (let* ((paper-book (chain-assoc-get 'paper-book props #f))
+                      (table (and paper-book (ly:paper-book-labels 
paper-book)))
+                      (label-page (and (list? table) (assoc label table)))
+                      (page-number (and label-page (cdr label-page)))
+                      (page-markup (if page-number (format "~a" page-number) 
default))
+                      (page-stencil (interpret-markup layout props 
page-markup))
+                      (gap (- (interval-length x-ext)
+                              (interval-length (ly:stencil-extent page-stencil 
X)))))
+                 (interpret-markup layout props
+                                   (markup #:concat (#:hspace gap 
page-markup)))))))
+     x-ext
+     y-ext)))
diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm
index 03ac6f8..c6a83c4 100644
--- a/scm/define-music-types.scm
+++ b/scm/define-music-types.scm
@@ -238,6 +238,9 @@ Syntax: @code{\\key } @var{name} @var{sc
        (to-relative-callback . ,(lambda (x p) p))
        (types . (general-music key-change-event event))
        ))
+    (LabelEvent
+     . ((description . "Place a bookmarking label")
+       (types . (general-music label-event event))))
     (LaissezVibrerEvent
      . ((description . "Don't damp this chord.
 
diff --git a/scm/define-stencil-commands.scm b/scm/define-stencil-commands.scm
index 9b0b942..6a027b6 100644
--- a/scm/define-stencil-commands.scm
+++ b/scm/define-stencil-commands.scm
@@ -37,6 +37,8 @@
        no-origin
        placebox
        unknown
+
+       delay-stencil-evaluation
        ))
 
 ;; TODO:
diff --git a/scm/lily-library.scm b/scm/lily-library.scm
index 7a1141d..5435533 100644
--- a/scm/lily-library.scm
+++ b/scm/lily-library.scm
@@ -70,17 +70,21 @@
          value
          #f)))
   (cond ((music-property 'page-marker)
-        ;; a page marker: set page break/turn permissions
-        (for-each (lambda (symbol)
-                    (let ((permission (music-property symbol)))
-                      (if (symbol? permission)
-                          (score-handler
-                           (ly:make-page-marker symbol
-                                                (if (eqv? 'forbid permission)
-                                                    '()
-                                                    permission))))))
-                  (list 'line-break-permission 'page-break-permission
-                        'page-turn-permission)))
+        ;; a page marker: set page break/turn permissions or label
+        (begin
+          (let ((label (music-property 'label)))
+            (if (symbol? label)
+                (score-handler (ly:make-page-label-marker label))))
+          (for-each (lambda (symbol)
+                      (let ((permission (music-property symbol)))
+                        (if (symbol? permission)
+                            (score-handler
+                             (ly:make-page-permission-marker symbol
+                                                             (if (eqv? 'forbid 
permission)
+                                                                 '()
+                                                                 
permission))))))
+                    (list 'line-break-permission 'page-break-permission
+                          'page-turn-permission))))
        ((not (music-property 'void))
         ;; a regular music expression: make a score with this music
         ;; void music is discarded

reply via email to

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