]> git.donarmstrong.com Git - lilypond.git/commitdiff
* scm/define-music-types.scm (music-descriptions): add
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 2 Feb 2004 15:31:08 +0000 (15:31 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 2 Feb 2004 15:31:08 +0000 (15:31 +0000)
Solo{One,Two}Event and UnisonoEvent

* lily/new-part-combine-iterator.cc (unisono): add state_
variable, signal changes with part-combine-event.

* input/regression/new-part-combine-text.ly: new file.

* lily/part-combine-engraver.cc: new file.

ChangeLog
input/regression/new-part-combine-text.ly [new file with mode: 0644]
input/regression/new-part-combine.ly
lily/new-part-combine-iterator.cc
lily/part-combine-engraver.cc [new file with mode: 0644]
ly/engraver-init.ly
scm/define-grobs.scm
scm/define-music-properties.scm
scm/define-music-types.scm
scm/music-functions.scm

index 9091adb42eb1abdc7600b1528cd9a93d9a3310ea..610e235f3cdabca11d34740dc6e4aba4816defef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,24 @@
+2004-02-02  Han-Wen Nienhuys   <hanwen@xs4all.nl>
+
+       * scm/define-music-types.scm (music-descriptions): add
+       Solo{One,Two}Event and UnisonoEvent
+
+       * lily/new-part-combine-iterator.cc (unisono): add state_
+       variable, signal changes with part-combine-event.
+
+       * input/regression/new-part-combine-text.ly: new file.
+
+       * lily/part-combine-engraver.cc: new file.
+
 2004-02-02  Jan Nieuwenhuizen  <janneke@gnu.org>
 
        * scripts/filter-lilypond-book.py: Handle snippet options.
 
 2004-02-02  Han-Wen Nienhuys   <hanwen@xs4all.nl>
 
+       * scm/music-functions.scm (determine-split-list): detect solo1/2
+       and unisono.
+
        * lily/new-lyric-combine-music-iterator.cc (construct_children):
        revert fix, document why.
 
diff --git a/input/regression/new-part-combine-text.ly b/input/regression/new-part-combine-text.ly
new file mode 100644 (file)
index 0000000..89a6530
--- /dev/null
@@ -0,0 +1,18 @@
+
+\header {
+    texidoc ="The new part combiner:
+
+Detect a2, solo1, solo2  and print texts accordingly.
+"
+
+    
+    }
+
+
+vone = \notes \relative a' { R1 a4 r4 r r a a a a }
+vtwo = \notes \relative a' { R1 f4 f4 f4 f f f a a  }
+
+\score {
+   \newpartcombine \vone \vtwo
+}
index e83d6bdde30ff59ccd7b10231bd6f957ab48d41f..dfc3cb5d873238639a4d444ffd4bfb45a2caa5f2 100644 (file)
@@ -10,10 +10,6 @@ Apart for:
 "
     }
 
-theMusic = \context Staff \notes { c4 d8-. }
-
-
-
 vone = \notes \relative a' { g2 g    g  g4 g f' c c( c) c c  c ~ c
                             c2. c4   c
                         }
index ecb4534c17445cdd1306391171c195e9707f7c9b..c98761aa9d7f49fe34a64359219f30ff4d893acd 100644 (file)
@@ -43,6 +43,12 @@ private:
   bool is_shared_ ;
   SCM split_list_;
 
+  enum  {
+    APART, TOGETHER,
+    SOLO1, SOLO2,
+    UNISONO,
+  } state_;
+
   Interpretation_context_handle one_;
   Interpretation_context_handle two_;
   Interpretation_context_handle null_;
@@ -62,6 +68,7 @@ New_pc_iterator::New_pc_iterator ()
   first_iter_ = 0;
   second_iter_ = 0;
   split_list_ = SCM_EOL;
+  state_ = APART;
 }
 
 void
@@ -137,59 +144,102 @@ New_pc_iterator::ok () const
 void
 New_pc_iterator::chords_together ()
 {
-  first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
-  first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
-  second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
-  second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+  if (state_ == TOGETHER)
+    return;
+  else
+    {
+      state_ = TOGETHER;
+      first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
+      first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+      second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
+      second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+    }
 }
 
 
 void
 New_pc_iterator::solo1 ()
 {
-  first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
-  first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
+  if (state_ == SOLO1)
+    return;
+  else
+    {
+      state_ = SOLO1;
+      first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+      first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
 
-  second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
-  second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
-}
+      second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
+      second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
+
+      static Music* event;
+      if (!event)
+       event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
 
+    first_iter_-> try_music_in_children (event);
+    }
+}
 void
 New_pc_iterator::unisono ()
 {
-  /*
-    like solo1, but should set a2 string.
-   */
-  first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
-  first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
-
-  second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
-  second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
-}
+  if (state_ == UNISONO)
+    return;
+  else
+    {
+      state_ = UNISONO;
+
+      first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+      first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
+
+      second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
+      second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
 
 
+      static Music* event;
+      if (!event)
+       event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
+
+      first_iter_-> try_music_in_children (event);      
+    }
+}
+
 void
 New_pc_iterator::solo2 ()
 {
-  second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
-  second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
+  if (state_ == SOLO2)
+    return;
+  else
+    {
+      state_ = SOLO2;
+      second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+      second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
 
-  first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
-  first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
-}
+      first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
+      first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
 
+      static Music* event;
+      if (!event)
+       event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
+
+      second_iter_-> try_music_in_children (event);
+    }
+}
 
 void
 New_pc_iterator::apart ()
 {
-  first_iter_->substitute_outlet (null_.report_to (), one_.report_to ());
-  first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ());
+  if (state_ == APART)
+    return;
+  else
+    {
+      state_ = APART;
+  
+      first_iter_->substitute_outlet (null_.report_to (), one_.report_to ());
+      first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ());
   
-  second_iter_->substitute_outlet (null_.report_to (), two_.report_to ());
-  second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ());
+      second_iter_->substitute_outlet (null_.report_to (), two_.report_to ());
+      second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ());    }
 }
 
-
 void
 New_pc_iterator::construct_children ()
 {
diff --git a/lily/part-combine-engraver.cc b/lily/part-combine-engraver.cc
new file mode 100644 (file)
index 0000000..1952395
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+  part-combine-engraver.cc -- implement PC-engraver
+
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2000--2003 Jan Nieuwenhuizen <janneke@gnu.org>
+
+  Han-Wen Nienhuys <hanwen@xs4all.nl>
+  
+*/
+
+#include "engraver.hh"
+#include "item.hh"
+#include "text-item.hh"
+#include "note-head.hh"
+#include "stem.hh"
+#include "side-position-interface.hh"
+#include "multi-measure-rest.hh"
+
+class Part_combine_engraver : public Engraver
+{
+  TRANSLATOR_DECLARATIONS(Part_combine_engraver);
+
+protected:
+  virtual void acknowledge_grob (Grob_info);
+  virtual void process_music ();
+  virtual void stop_translation_timestep ();
+  virtual bool try_music (Music *);
+private:
+  Item *text_;
+  Music *event_;
+};
+
+bool
+Part_combine_engraver::try_music (Music*m)
+{
+  event_ = m;
+  return true;
+}
+
+Part_combine_engraver::Part_combine_engraver ()
+{
+  text_ = 0;
+  event_  =0;
+}
+
+void
+Part_combine_engraver::process_music ()
+{
+  if (event_
+      && to_boolean (get_property ("soloADue")))
+    {
+      SCM what = event_->get_mus_property ("part-combine-status");
+      SCM text = SCM_EOL;
+      if (what == ly_symbol2scm ("solo1"))
+       text = get_property ("soloText");
+      else if (what== ly_symbol2scm ("solo2"))
+       text = get_property ("soloIIText");
+      else if (what == ly_symbol2scm ("unisono"))
+       text = get_property ("aDueText");
+
+      if (Text_item::markup_p (text))
+       {
+         text_ =  make_item ("CombineTextScript");
+         text_->set_grob_property ("text", text);
+         announce_grob (text_, event_->self_scm ());
+       }
+    }
+}
+
+void
+Part_combine_engraver::acknowledge_grob (Grob_info i)
+{
+  if (text_)
+    {
+      if (Note_head::has_interface (i.grob_))
+       {
+         Grob*t = text_;
+         Side_position_interface::add_support (t, i.grob_);
+         if (Side_position_interface::get_axis (t) == X_AXIS
+             && !t->get_parent (Y_AXIS))
+           t->set_parent (i.grob_, Y_AXIS);
+       }
+      if (Stem::has_interface (i.grob_))
+       {
+         Side_position_interface::add_support (text_, i.grob_);
+       }
+    }
+}
+
+void 
+Part_combine_engraver::stop_translation_timestep ()
+{
+  if (text_)
+    {
+      typeset_grob (text_);
+      text_ = 0;
+    }
+  event_ = 0;
+}
+
+ENTER_DESCRIPTION(Part_combine_engraver,
+/* descr */       "Part combine engraver for orchestral scores:                "
+                 "Print markings a2, Solo, Solo II, and unisono ",
+/* creats*/       "CombineTextScript",
+/* accepts */     "part-combine-event",
+/* acks  */       "multi-measure-rest-interface "
+"slur-interface stem-interface note-head-interface"
+,/* reads */       "soloADue",
+/* write */       "");
index 193dd3ea47665f58f3cadb6fe6bae6c2837d1f1d..b664bd8578e4abb3fde587ba208b24111cca9d31 100644 (file)
        \consists "Percent_repeat_engraver"
        \consists "Slash_repeat_engraver"
        \consists "Melisma_engraver"
+       \consists "Part_combine_engraver"
 
 %{
  Must come before text_engraver, but after note_column engraver.
index a3da4407dc3b585eeaf5a187291a68e11bff0dce..435adc0378d8306810dea1d88095522ddb22b198 100644 (file)
        (font-family . roman)
        (meta . ((interfaces . (text-script-interface text-interface side-position-interface font-interface item-interface ))))
        ))
-
+    (CombineTextScript
+     . (
+       (molecule-callback . ,Text_item::brew_molecule)
+       (no-spacing-rods . #t)
+       (Y-offset-callbacks . (,Side_position_interface::aligned_side))
+       (X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+       (direction . 1)
+       (padding . 0.5)
+       (staff-padding . 0.5)
+       (script-priority . 200)
+       ;; todo: add X self alignment?
+       (baseline-skip . 2)
+       (font-family . roman)
+       (font-series . bold)
+       (meta . ((interfaces . (text-script-interface text-interface  side-position-interface font-interface item-interface ))))
+       ))
     (TextSpanner
      . (
        (molecule-callback . ,Text_spanner::brew_molecule)
index 6731047090cb1a64ca84ceb4955933b9c8d46cf0..a118419f74fc0ad3e52d5b22981cbce030a0c7db 100644 (file)
@@ -79,7 +79,10 @@ For chord inversions, this is negative.")
                            "Do these operations for instantiating the context.")
 (music-property-description 'predicate procedure? "the predicate of a \\outputproperty")
 (music-property-description 'type symbol? "The type of this music object. Determines iteration in some cases.")
-(music-property-description 'types list? "The types of this music object. Determines iteration in some cases.")
+(music-property-description 'types list? "The types of this music
+object; determines by what engraver this music expression is
+processed.")
+
 (music-property-description 'repeat-count  integer? "do a @code{\repeat} how ofen?")
 (music-property-description 'span-direction ly:dir? "Does this start or stop a spanner?")
 (music-property-description 'split-list list? "splitting moments for part combiner.")
@@ -94,6 +97,9 @@ starting grace notes.")
 (music-property-description 'value scheme? "Assignment value for a
 translation property")
 (music-property-description 'what symbol? "What to change for auto-change. FIXME, naming")
+(music-property-description 'part-combine-status symbol?
+                           "Change to what kind of state? Options are
+solo1, solo2 and unisono")
 
 (music-property-description 'figure string? "a `figure' (which may be
 a string) for figured bass")
index 58ff4e01217fc700acee7782783f64941bf324f0..c845f602cb7f157466c09ca5e1c2407f64fc605c 100644 (file)
@@ -139,7 +139,7 @@ c8-[ c c-] c8")
     
     (CrescendoEvent
      . (
-   (description .  "Begins or ends a crescendo.  Syntax: @var{note}\\cr
+       (description .  "Begins or ends a crescendo.  Syntax: @var{note}\\cr
 ... @var{note}\\rc (you can also use \\<, \\!, \\cresc, and
 \\endcresc.  See the user manual for details.).")
 
@@ -405,6 +405,26 @@ to group start-mmrest, skip, stop-mmrest sequence. Syntax @code{R2.*5} for 5 mea
        (iterator-ctor . ,Sequential_music_iterator::constructor)
        (types . (general-music sequential-music))
        ))
+
+    (SoloOneEvent
+     . (
+       (description . "Print Solo.1")
+       (internal-class-name . "Event")
+       (part-combine-status . solo1)
+       (types . (general-music event part-combine-event))
+       ))
+    (SoloTwoEvent
+     . (
+       (description . "Print Solo.2")
+       (internal-class-name . "Event")
+       (part-combine-status . solo2)
+       (types . (general-music event part-combine-event))
+       ))
+    (UnisonoEvent
+     . ((description . "Print a2")
+       (internal-class-name .  "Event")
+       (part-combine-status . unisono)
+       (types . (general-music event part-combine-event))))
     
     (SimultaneousMusic
      . (
index 081163c8af0ec0a6088c8512e3c872b32f359b67..9100c8907ec538732e2dff7494cdfc02759fc295 100644 (file)
@@ -844,6 +844,10 @@ Rest can contain a list of beat groupings
     (cdr (vector-ref v i)))
 
   (define chord-threshold 8)
+  (define (get-note-evs v i)
+    (define (f? x)
+      (equal? (ly:get-mus-property  x 'name) 'NoteEvent))
+    (filter f? (map car (what v i))))
   
   (define result
     (list->vector
@@ -907,11 +911,7 @@ Rest can contain a list of beat groupings
                       (helper analyse-tie-end active evs) evs) evs)
        active<?))
     
-    (define (get-note-evs v i)
-      (define (f? x)
-       (equal? (ly:get-mus-property  x 'name) 'NoteEvent))
-      (filter f? (map car (what v i))))
-    
+
     (define (put x . index)
       "Put the result to X, starting from INDEX backwards."
       (let
@@ -981,6 +981,8 @@ Rest can contain a list of beat groupings
                (cond
                 ((> (length notes1) 1) (put 'apart))
                 ((> (length notes2) 1) (put 'apart))
+                ((not (= (length notes1) (length notes2)))
+                 (put 'apart))
                 ((and
                   (= (length durs1) 1)
                   (= (length durs2) 1)
@@ -988,36 +990,81 @@ Rest can contain a list of beat groupings
 
                  (put 'apart))
                 (else
-                 (if
-                  (and (= (length pitches1) 1) (= (length pitches2) 1) 
-                   (< chord-threshold (ly:pitch-steps
-                                       (ly:pitch-diff (car pitches1) (car pitches2)))))
-                       (put 'apart)
-
-
-                       ;; copy previous split state from spanner state
-                       (begin
-                         (map (lambda (key-idx)
-                                (let*
-                                    ((idx (cdr key-idx))
-                                     (prev (what result  idx))
-                                     )
-                                  (if (symbol? prev)
-                                      (put prev))
-                                  )) (append active1 active2))
-                         (if (and (null? new-active1) (null? new-active2))
-                             (put 'chords ri)))
-                   
-                   ))) )
+                 (if (and (= (length pitches1) (length pitches2)))
+                     (if
+                      (and (pair?  pitches1) (pair? pitches2)
+                      (< chord-threshold (ly:pitch-steps
+                                          (ly:pitch-diff (car pitches1) (car pitches2)))))
+                      (put 'apart)
+
+
+                      ;; copy previous split state from spanner state
+                      (begin
+                        (map (lambda (key-idx)
+                               (let*
+                                   ((idx (cdr key-idx))
+                                    (prev (what result  idx))
+                                    )
+                                 (if (symbol? prev)
+                                     (put prev))
+                                 )) (append active1 active2))
+                        (if (and (null? new-active1) (null? new-active2))
+                            (put 'chords ri))))
+                 
+                 ))))
+             
              ;; active states different: 
-             (put 'apart) )
-         (analyse-time-step (1+ i1) (1+ i2) (1+ ri) new-active1 new-active2))
-        )))))
+             (put 'apart))
+         (analyse-time-step (1+ i1) (1+ i2) (1+ ri) new-active1 new-active2)))
+        ))))
 
 ;; 
-  
-  
+   (define (analyse-solo12 i1 i2 ri)
+     (cond
+      ((= ri (vector-length result)) '())
+      ((= i1 (vector-length ev1)) '())
+      ((= i2 (vector-length ev2)) '())
+      (else
+       (let*
+         (
+          (m1 (when ev1 i1))
+          (m2 (when ev2 i2))
+          (notes1 (get-note-evs ev1 i1))
+          (durs1 (sort (map (lambda (x) (ly:get-mus-property x 'duration)) notes1) ly:duration<?))
+          (pitches1 (sort
+                     (map (lambda (x) (ly:get-mus-property x 'pitch)) notes1) ly:pitch<?))
+          (notes2 (get-note-evs ev2 i2))
+          (durs2 (sort (map (lambda (x) (ly:get-mus-property x 'duration)) notes2) ly:duration<?))
+          (pitches2 (sort
+                     (map (lambda (x) (ly:get-mus-property x 'pitch)) notes2) ly:pitch<?))
+          )
+
+        (if (equal? (what result ri) 'apart)
+            (cond
+             ((and (= 0 (length notes1))
+                  (< 0 (length notes2)))
+              (set-cdr! (vector-ref result ri) 'solo2))
+             ((and (< 0 (length notes1))
+                   (= 0 (length notes2)))
+              (set-cdr! (vector-ref result ri) 'solo1))
+             ))
+
+        (if (and
+             (equal? (what result ri) 'chords)
+             (pair? pitches1)
+             (equal? pitches1 pitches2))
+            (set-cdr! (vector-ref result ri) 'unisono) )
+        
+        (cond
+         ((ly:moment<? m1 m2)
+          (analyse-solo12 (1+ i1) i2 (1+ ri) ))
+         ((ly:moment<? m2 m1)
+          (analyse-solo12 i1 (1+ i2) (1+ ri) ))
+         (else
+          (analyse-solo12 (1+ i1) (1+ i2) (1+ ri)))
+         )))))
 
    (analyse-time-step 0 0  0 '() '())
-;   (display result)
+   (analyse-solo12 0 0 0)
+   (display result)
    (vector->list result))