]> git.donarmstrong.com Git - lilypond.git/commitdiff
Allows for automatic renumbering of measure numbers at volta repeats.
authorMike Solomon <mike@apollinemike.com>
Mon, 5 Dec 2011 06:56:37 +0000 (07:56 +0100)
committerMike Solomon <mike@apollinemike.com>
Mon, 5 Dec 2011 06:56:37 +0000 (07:56 +0100)
Does this via the use of an AlternativeEvent, which tells the current
number to either memorize its current position or to go back to the
memorized position.

lily/bar-number-engraver.cc
lily/volta-repeat-iterator.cc
ly/engraver-init.ly
scm/define-context-properties.scm
scm/define-event-classes.scm
scm/define-music-callbacks.scm
scm/define-music-display-methods.scm
scm/define-music-properties.scm
scm/define-music-types.scm

index 269ed126207960893f042c5b0038175eaf1173b0..83ff7fed5148f8a39034973a031266b7552d8b25 100644 (file)
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <algorithm> // for reverse
+
 #include "paper-column.hh"
 #include "output-def.hh"
 #include "side-position-interface.hh"
 #include "engraver.hh"
 #include "context.hh"
 #include "grob-array.hh"
+#include "stream-event.hh"
 
 #include "translator.icc"
 
@@ -35,14 +38,62 @@ class Bar_number_engraver : public Engraver
 {
 protected:
   Item *text_;
+  int alternative_starting_bar_number_;
+  int alternative_number_;
+  int alternative_number_increment_;
+  Stream_event *alternative_event_;
+
 protected:
   void stop_translation_timestep ();
+  DECLARE_TRANSLATOR_LISTENER (alternative);
   DECLARE_ACKNOWLEDGER (break_alignment);
   void process_music ();
   void create_items ();
   TRANSLATOR_DECLARATIONS (Bar_number_engraver);
 };
 
+IMPLEMENT_TRANSLATOR_LISTENER (Bar_number_engraver, alternative);
+void
+Bar_number_engraver::listen_alternative (Stream_event *ev)
+{
+  if (alternative_event_)
+    return;
+
+  alternative_event_ = ev;
+  int current_barnumber = robust_scm2int (get_property ("currentBarNumber"), 0);
+  Direction alternative_dir = robust_scm2dir (ev->get_property ("alternative-dir"), CENTER);
+  bool make_alternative = get_property ("alternativeNumberingStyle") == ly_symbol2scm ("numbers")
+                          || get_property ("alternativeNumberingStyle") == ly_symbol2scm ("numbers-with-letters");
+  if (make_alternative)
+    {
+      /*
+        if we're starting the first alternative, we set the starting
+        bar number to the current bar number
+      */
+      if (alternative_dir == LEFT)
+        alternative_starting_bar_number_ = current_barnumber;
+
+      /*
+        if the alternative is not the last one, we send the
+        current bar number back to the alternative bar number.
+      */
+      if (alternative_dir < RIGHT)
+        current_barnumber = alternative_starting_bar_number_;
+
+      context ()->set_property ("currentBarNumber", scm_from_int (current_barnumber));
+    }
+}
+
+int
+int_pow (int n, int i)
+{
+  if (i == 1)
+    return n;
+  if (i <= 0)
+    return 1;
+  return int_pow (n * n, i - 1);
+}
+
 void
 Bar_number_engraver::process_music ()
 {
@@ -59,9 +110,51 @@ Bar_number_engraver::process_music ()
               && to_boolean (scm_call_1 (proc, bn)))
             {
               create_items ();
+              SCM alternative_style = get_property ("alternativeNumberingStyle");
+              string text_tag = "";
+              if (alternative_style == ly_symbol2scm ("numbers-with-letters"))
+                {
+                  if (alternative_event_)
+                    {
+                      Direction alternative_dir = robust_scm2dir (alternative_event_->get_property ("alternative-dir"), RIGHT);
+                      switch (alternative_dir)
+                        {
+                        case LEFT:
+                          alternative_number_ = 0;
+                          break;
+                        case CENTER:
+                          break;
+                        case RIGHT:
+                          alternative_number_ = INT_MIN;
+                          break;
+                        default:
+                          assert (false);
+                        }
+                      alternative_number_ += alternative_number_increment_;
+
+                      alternative_number_increment_ = robust_scm2int (alternative_event_->get_property ("alternative-increment"), 1);
+                    }
+                  if (alternative_number_ >= 0)
+                    {
+                      string alphabet = "abcdefghijklmnopqrstuvwxyz";
+                      int power = 0;
+                      int running_sum = 0;
+                      int scratch = alternative_number_;
+                      while (running_sum <= alternative_number_)
+                        {
+                          power++;
+                          running_sum += int_pow (26, power);
+                        }
+                      scratch += int_pow (26, power) - running_sum;
+                      for (int i = power; i--;)
+                        text_tag += alphabet.at ((scratch / int_pow (26, i)) % 26);
+                    }
+                }
               // guh.
               text_->set_property
-              ("text", scm_number_to_string (bn, scm_from_int (10)));
+                ("text",
+                  scm_string_concatenate (scm_list_2 (scm_number_to_string (bn, scm_from_int (10)),
+                                                      ly_string2scm (text_tag))));
             }
         }
     }
@@ -70,6 +163,10 @@ Bar_number_engraver::process_music ()
 Bar_number_engraver::Bar_number_engraver ()
 {
   text_ = 0;
+  alternative_starting_bar_number_ = 0;
+  alternative_number_increment_ = 0;
+  alternative_number_ = INT_MIN;
+  alternative_event_ = 0;
 }
 
 void
@@ -86,6 +183,7 @@ Bar_number_engraver::acknowledge_break_alignment (Grob_info inf)
 void
 Bar_number_engraver::stop_translation_timestep ()
 {
+  alternative_event_ = 0;
   if (text_)
     {
       text_->set_object ("side-support-elements",
@@ -121,8 +219,9 @@ ADD_TRANSLATOR (Bar_number_engraver,
                 "currentBarNumber "
                 "whichBar "
                 "stavesFound "
-                "barNumberVisibility ",
+                "barNumberVisibility "
+                "alternativeNumberingStyle ",
 
                 /* write */
-                ""
+                "currentBarNumber "
                );
index 91bf94e42a0323a4e8d7049f4f2b3fb1a8019b47..dddbbc20958e95943a9e4fd7bf746517c580f61f 100644 (file)
@@ -50,7 +50,7 @@ SCM
 Volta_repeat_iterator::get_music_list ()const
 {
   return scm_cons (get_music ()->get_property ("element"),
-                   get_music ()->get_property ("elements"));
+                   Sequential_iterator::get_music_list ());
 }
 
 void
index 46b0f72b05c723b5057a335741e71ac575f95f80..2e0a90d0e68e081d7d63552dd1947e81f7f44f79 100644 (file)
@@ -523,6 +523,7 @@ automatically when an output definition (a @code{\score} or
 
   %% move the alias along with the engraver.
 
+  % timing translator must come BEFORE bar number engraver
   \consists "Timing_translator"
   \consists "Default_bar_line_engraver"
   \consists "Output_property_engraver"
index 6c79bbdb95b22091c03807a9529bbc605571b843..a0cf0ae8328fa38e94495c697f3a0674b6e9fe23 100644 (file)
@@ -53,6 +53,10 @@ vertical alignment.")
 are aligned in bass figure context.")
      (alignBelowContext ,string? "Where to insert newly created context in
 vertical alignment.")
+     (alternativeNumberingStyle ,symbol? "The style of an alternative's bar
+numbers.  Can be @code{numbers} for going back to the same number or
+@code{numbers-with-letters} for going back to the same number with letter
+suffixes.  No setting will not go back in measure-number time.")
      (associatedVoice ,string? "Name of the @code{Voice} that has the
 melody for this @code{Lyrics} line.")
      (autoAccidentals ,list? "List of different ways to typeset an
index 65dbd38e4f94748c762026a436506293eb9ad6b0..19444111afde5debd1bc844d8b8aec3edc48b363 100644 (file)
@@ -35,7 +35,8 @@
       harmonic-event hyphen-event laissez-vibrer-event mark-event
       multi-measure-text-event note-grouping-event
       pes-or-flexa-event repeat-tie-event spacing-section-event
-      layout-instruction-event completize-extender-event break-span-event))
+      layout-instruction-event completize-extender-event break-span-event
+      alternative-event))
 
     (layout-instruction-event . (apply-output-event))
     (script-event . (articulation-event text-script-event))
index 0cbd96b862658c504841edda2af8fb35cb870ecf..06d616f8b014e3cfbb4e57da6811315af3020f07 100644 (file)
@@ -34,6 +34,34 @@ to be used by the sequential-iterator"
          (make-music 'BarCheck
                      'origin location))))
 
+(define (make-volta-set music)
+  (let* ((alts (ly:music-property music 'elements))
+         (lalts (length alts))
+         (times (ly:music-property music 'repeat-count)))
+    (map (lambda (x y)
+           (make-music
+             'SequentialMusic
+             'elements
+               ;; set properties for proper bar numbering
+               (append
+                 (list (make-music 'AlternativeEvent
+                                   'alternative-dir (if (= y 0)
+                                                        -1
+                                                        0)
+                                   'alternative-increment
+                                     (if (= 0 y)
+                                         (1+ (- times
+                                                lalts))
+                                             1)))
+                       (list x)
+                       (if (= y (1- lalts))
+                           (list (make-music 'AlternativeEvent
+                                             'alternative-dir 1
+                                             'alternative-increment 0))
+                           '()))))
+         alts
+         (iota lalts))))
+
 (define (make-ottava-set music)
   "Set context properties for an ottava bracket."
   (let ((octavation (ly:music-property music 'ottava-number)))
index d0926d5f85389b0730d41b86d2988afcaae3bb73..85ae00d906af2288615f5f52755999afa636f8f3 100644 (file)
@@ -697,6 +697,8 @@ Otherwise, return #f."
 ;;; Repeats
 ;;;
 
+(define-display-method AlternativeEvent (alternative parser) "")
+
 (define (repeat->lily-string expr repeat-type parser)
   (format #f "\\repeat ~a ~a ~a ~a"
          repeat-type
index 8911239473dd3cbf7977843d5bf87d4a6cf726df..673c66a8e59141cf93882ef516ad480c0294d609 100644 (file)
      (absolute-octave ,integer?
                      "The absolute octave for a octave check note.")
      (alteration ,number? "Alteration for figured bass.")
+     (alternative-dir ,ly:dir? "Indicates if an AlternativeMusic is the
+First (-1), Middle (0), or Last (1) of group of alternate endings.")
+     (alternative-increment ,integer? "The number of times an alternative's
+lettering should be incremented.")
      (articulation-type ,string? "Key for script definitions alist.
 
 TODO: Consider making type into symbol.")
@@ -210,6 +214,8 @@ engraver this music expression is processed.")
      (value ,scheme? "Assignment value for a translation property.")
      (void ,boolean? "If this property is @code{#t}, then the
 music expression is to be discarded by the toplevel music handler.")
+     (volta-repeats ,list? "A list that is transformed into a volta
+repeat element list.")
 
      (what ,symbol? "What to change for auto-change.
 
index 015a628c535dc6ef4562adc5665435cc9e72f978..8dbc6decc04276d15e18220d396aafecc6e00408 100644 (file)
@@ -32,6 +32,11 @@ Syntax: @var{note}@code{\\x}, where @code{\\x} is a dynamic mark like
        (types . (general-music event dynamic-event absolute-dynamic-event))
        ))
 
+    (AlternativeEvent
+     . ((description . "Create a alternative event.")
+        (types . (general-music event alternative-event))
+       ))
+
     (AnnotateOutputEvent
      . ((description . "Print an annotation of an output element.")
        (types . (general-music event annotate-output-event))
@@ -712,6 +717,7 @@ Syntax: @code{\\\\}")
     (VoltaRepeatedMusic
      . ((description . "Repeats with alternatives placed sequentially.")
        (iterator-ctor . ,ly:volta-repeat-iterator::constructor)
+       (elements-callback . ,make-volta-set)
        (start-callback .  ,ly:repeated-music::first-start)
        (length-callback . ,ly:repeated-music::volta-music-length)
        (types . (general-music repeated-music volta-repeated-music))