]> git.donarmstrong.com Git - lilypond.git/commitdiff
lilypond-1.3.78
authorfred <fred>
Tue, 26 Mar 2002 23:54:51 +0000 (23:54 +0000)
committerfred <fred>
Tue, 26 Mar 2002 23:54:51 +0000 (23:54 +0000)
23 files changed:
input/test/dynamic-dir.ly [new file with mode: 0644]
input/test/non-empty-text.ly
input/test/part-combine.ly [new file with mode: 0644]
lily/a2-devnull-engraver.cc [new file with mode: 0644]
lily/a2-engraver.cc [new file with mode: 0644]
lily/axis-group-engraver.cc
lily/axis-group-interface.cc
lily/bar.cc
lily/hara-kiri-group-spanner.cc
lily/include/hara-kiri-group-spanner.hh
lily/include/part-combine-music-iterator.hh [new file with mode: 0644]
lily/include/part-combine-music.hh [new file with mode: 0644]
lily/include/score-element.hh
lily/music-iterator.cc
lily/my-lily-lexer.cc
lily/parser.yy
lily/part-combine-music-iterator.cc [new file with mode: 0644]
lily/part-combine-music.cc [new file with mode: 0644]
lily/property-engraver.cc
lily/score-element.cc
lily/span-bar.cc
lily/text-engraver.cc
ly/engraver.ly

diff --git a/input/test/dynamic-dir.ly b/input/test/dynamic-dir.ly
new file mode 100644 (file)
index 0000000..b7d353b
--- /dev/null
@@ -0,0 +1,12 @@
+%non of the dynamics properties work anymore
+
+\score { 
+  \context Voice \notes\relative c {
+%        \property Voice.verticalDirection = #-1
+
+        \property Voice.dynamicDirection = #1
+        \property Voice.dynamicPadding = #40
+        c \p c \<  \! c \ff\> c \!c-\p 
+
+  }
+}
index 6244598991616a5686c924bdf39e47376852a985..7054d872f6b7f4167eebaa9809e16f15cac2067b 100644 (file)
@@ -4,20 +4,10 @@
 %
 \score{
        \notes\relative c''{
-               %\property Staff.textEmptyDimension=1
-               a-"This text has no"
-               a
-               a
-               a-"width; the default"
-               \break
                \property Staff.textNonEmpty=##t
-               %\property Staff.textEmptyDimension=0
-               a-"This text"
-               a-"is fat: notes are spaced"
-               a-"far apart and text"
-               a-"does not collide"
+               c4_"longlonglonglonglonglong" c4_"text" 
                }
          \paper{
-             linewidth=80.\mm;
+             linewidth=-80.\mm;
          }
 }
diff --git a/input/test/part-combine.ly b/input/test/part-combine.ly
new file mode 100644 (file)
index 0000000..0744984
--- /dev/null
@@ -0,0 +1,22 @@
+\score{
+       \context Staff = first <
+               \context Voice=first { \skip 1; }
+               \context Voice=second { \skip 1; }
+
+               \context Voice=first \partcombine Voice
+                       \context Thread=first \notes\relative c''
+                               {
+                                       c4 d e f
+                                       b,4 d c d
+                                       r2 e4 f
+                                       c4 d e f
+                               }
+                       \context Thread=second \notes\relative c''
+                               {
+                                       a b c d
+                                       r2 c4 d
+                                       a c c d
+                                       a4. b8 c4 d
+                               }
+               >
+}
diff --git a/lily/a2-devnull-engraver.cc b/lily/a2-devnull-engraver.cc
new file mode 100644 (file)
index 0000000..680dedb
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+  a2-devnull-engraver.cc -- implement A2_devnull_engraver
+
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include "engraver.hh"
+#include "item.hh"
+#include "musical-request.hh"
+#include "translator-group.hh"
+
+class A2_devnull_engraver : public Engraver
+{
+public:
+  VIRTUAL_COPY_CONS (Translator);
+  
+protected:
+  virtual bool do_try_music (Music*);
+};
+
+ADD_THIS_TRANSLATOR (A2_devnull_engraver);
+
+bool
+A2_devnull_engraver::do_try_music (Music *m) 
+{
+  if (Note_req * n = dynamic_cast <Note_req *> (m))
+    {
+      SCM a2 = get_property ("a2");
+      // should be able to read id_str_, no?
+      SCM second = get_property ("second");
+
+      if (a2 == SCM_BOOL_T && second == SCM_BOOL_T)
+       {
+         return true;
+       }
+    }
+  return false;
+}
+      
diff --git a/lily/a2-engraver.cc b/lily/a2-engraver.cc
new file mode 100644 (file)
index 0000000..65a239e
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+  a2-engraver.cc -- implement A2_engraver
+
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include "engraver.hh"
+#include "item.hh"
+#include "note-head.hh"
+#include "stem.hh"
+#include "translator-group.hh"
+#include "side-position-interface.hh"
+#include "directional-element-interface.hh"
+
+class A2_engraver : public Engraver
+{
+public:
+  A2_engraver ();
+  VIRTUAL_COPY_CONS (Translator);
+  
+protected:
+  virtual void do_process_music ();
+  virtual void acknowledge_element (Score_element_info);
+  //virtual void process_acknowledged ();
+
+  virtual void do_pre_move_processing ();
+
+private:
+  Item* text_p_;
+};
+
+ADD_THIS_TRANSLATOR (A2_engraver);
+
+A2_engraver::A2_engraver ()
+{
+  text_p_ = 0;
+}
+
+void
+A2_engraver::do_process_music ()
+{
+  if (!text_p_)
+    {
+      SCM a2 = get_property ("a2");
+      SCM solo = get_property ("solo");
+      SCM solo2 = get_property ("solo2");
+
+      if (solo == SCM_BOOL_T || a2 == SCM_BOOL_T || solo2 == SCM_BOOL_T)
+       {
+         text_p_ = new Item (get_property ("basicTextScriptProperties"));
+         Side_position::set_axis (text_p_, Y_AXIS);
+         announce_element (text_p_, 0);
+      
+         /*
+           Urg, read prop
+         */
+         SCM text;
+         Direction dir = UP;
+         if (solo == SCM_BOOL_T)
+           {
+             text = ly_str02scm ("Solo");
+           }
+         else if (solo2 == SCM_BOOL_T)
+           {
+             text = ly_str02scm ("Solo II");
+             dir = DOWN;
+           }
+         else if (a2 == SCM_BOOL_T)
+           {
+             text = ly_str02scm ("\\`a 2");
+           }
+
+         Side_position::set_direction (text_p_, dir);
+         text_p_->set_elt_property ("text", text);
+
+       }
+    }
+}
+
+void
+A2_engraver::acknowledge_element (Score_element_info i)
+{
+  if (text_p_)
+    {
+      if (Note_head::has_interface (i.elem_l_))
+       {
+         Score_element*t = text_p_;
+         Side_position::add_support (t, i.elem_l_);
+         if (Side_position::get_axis (t) == X_AXIS
+             && !t->parent_l (Y_AXIS))
+           t->set_parent (i.elem_l_, Y_AXIS);
+       }
+      if (Stem::has_interface (i.elem_l_))
+       {
+         Side_position::add_support (text_p_, i.elem_l_);
+         
+         SCM a2 = get_property ("a2");
+         SCM solo = get_property ("solo");
+         SCM solo2 = get_property ("solo2");
+
+         SCM first = get_property ("first");
+         SCM second = get_property ("second");
+
+         if (solo != SCM_BOOL_T
+             && solo2 != SCM_BOOL_T
+             && a2 != SCM_BOOL_T)
+           {
+             if (first == SCM_BOOL_T)
+               {
+                 Directional_element_interface (i.elem_l_).set (UP);
+               }
+             else if (second == SCM_BOOL_T)
+               {
+                 Directional_element_interface (i.elem_l_).set (DOWN);
+               }
+           }
+       }
+    }
+}
+
+void 
+A2_engraver::do_pre_move_processing ()
+{
+  if (text_p_)
+    {
+      Side_position::add_staff_support (text_p_);
+      typeset_element (text_p_);
+      text_p_ = 0;
+    }
+  // burp: reset properties
+  daddy_trans_l_->set_property ("a2", SCM_BOOL_F);
+  daddy_trans_l_->set_property ("solo", SCM_BOOL_F);
+  daddy_trans_l_->set_property ("solo2", SCM_BOOL_F);
+}
+
index ca6f5fb359fe8c6544102647ce32c4705d97edb8..606c93ef8b910d5e97855d5cafe015653e3dfb90 100644 (file)
@@ -26,7 +26,9 @@ protected:
   virtual void acknowledge_element (Score_element_info);
   virtual void process_acknowledged ();
   virtual Spanner* get_spanner_p () const;
+  virtual void add_element (Score_element*) ;
 public:
+  
   VIRTUAL_COPY_CONS(Translator);
   Axis_group_engraver ();
 };
@@ -106,11 +108,16 @@ Axis_group_engraver::process_acknowledged ()
 
       if ((!par || !Axis_group_interface::has_interface (par))
          && ! elts_[i]->empty_b (Y_AXIS))
-       Axis_group_interface::add_element (staffline_p_, elts_[i]);
+       add_element (elts_[i]);
     }
   elts_.clear ();
 }
 
+void
+Axis_group_engraver::add_element (Score_element*e)
+{
+  Axis_group_interface::add_element (staffline_p_, e);
+}
 
 ////////////////////////////////////////////////////////
 
@@ -124,10 +131,18 @@ class Hara_kiri_engraver : public Axis_group_engraver
 protected:
   virtual Spanner*get_spanner_p ()const;
   virtual void acknowledge_element (Score_element_info);
+  virtual void add_element (Score_element *e);
 public:
   VIRTUAL_COPY_CONS(Translator);
 };
 
+void
+Hara_kiri_engraver::add_element (Score_element*e)
+{
+  Hara_kiri_group_spanner::add_element (staffline_p_, e);
+}
+
+
 Spanner*
 Hara_kiri_engraver::get_spanner_p () const
 {
index 943c74a7ba2583cbc9238b2bf0a851183318d268..a156379adbdcddf7477d79072af93dbbc4f3d392 100644 (file)
@@ -6,7 +6,7 @@
   (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
   
  */
-
+#include "hara-kiri-group-spanner.hh"
 #include "axis-group-interface.hh"
 #include "score-element.hh"
 
@@ -28,7 +28,13 @@ Axis_group_interface::add_element (Score_element*me,Score_element *e)
 bool
 Axis_group_interface::axis_b (Score_element*me,Axis a )
 {
-  return me->has_extent_callback_b (group_extent_callback, a);
+  /*
+    urg. FIXME, check for Hara_kiri_group_spanner shouldn't be necessary?
+
+    
+   */
+  return me->has_extent_callback_b (group_extent_callback, a) ||
+    (me->has_extent_callback_b (Hara_kiri_group_spanner::y_extent, a));
 }
 
 Interval
@@ -88,8 +94,11 @@ Axis_group_interface::set_axes (Score_element*me,Axis a1, Axis a2)
   if (a1 != Y_AXIS && a2 != Y_AXIS)
     me->set_extent_callback (0, Y_AXIS);
   
-  me->set_extent_callback (Axis_group_interface::group_extent_callback,a1);
-  me->set_extent_callback (Axis_group_interface::group_extent_callback,a2);
+  //  if (!me->has_extent_callback_b (a1))
+  if (me->has_extent_callback_b (Score_element::molecule_extent, a1))
+    me->set_extent_callback (Axis_group_interface::group_extent_callback,a1);
+  if (me->has_extent_callback_b (Score_element::molecule_extent, a2))
+    me->set_extent_callback (Axis_group_interface::group_extent_callback,a2);
 }
 
 Link_array<Score_element> 
index cb956edf231d2ae475200eb4598db5f27bfd527f..7eaa478b7dc6bd93aa464a9126425835e5c73b41 100644 (file)
@@ -33,7 +33,11 @@ Bar::brew_molecule (SCM smob)
     {
       String str  =ly_scm2string (s);
       SCM siz = gh_call1 (barsiz_proc, me->self_scm ());
-      return compound_barline (me, str, gh_scm2double (siz)).create_scheme ();
+      Real sz =  gh_scm2double (siz);
+      if (sz < 0)
+       return SCM_EOL;
+      
+      return compound_barline (me, str, sz).create_scheme ();
     }
   return SCM_EOL;
 }
index cd16fab04f8026b68e36ba69a30cb896f3076879..25680db3ef26eca41d0d08886515c6dfb4bf1530 100644 (file)
@@ -19,8 +19,18 @@ Hara_kiri_group_spanner::set_interface (Score_element*me)
   me->set_elt_property ("items-worth-living", SCM_EOL);
   me->add_offset_callback (force_hara_kiri_callback, Y_AXIS);
   me->set_interface (ly_symbol2scm ("hara-kiri-spanner-interface"));
+  me->set_extent_callback (Hara_kiri_group_spanner::y_extent, Y_AXIS);
 }
 
+Interval
+Hara_kiri_group_spanner::y_extent(Score_element*me, Axis a)
+{
+  assert (a == Y_AXIS);
+  consider_suicide (me);
+  return  Axis_group_interface::group_extent_callback (me, a);
+}
+
+
 bool
 Hara_kiri_group_spanner::has_interface (Score_element*me)
 {
@@ -66,3 +76,18 @@ Hara_kiri_group_spanner::force_hara_kiri_callback (Score_element *elt, Axis a)
   return 0.0;
 }
 
+
+Real
+Hara_kiri_group_spanner::force_hara_kiri_in_parent_callback (Score_element*daughter, Axis a)
+{
+  assert (a == Y_AXIS);
+  force_hara_kiri_callback (daughter->parent_l (a), Y_AXIS);
+  return 0.0;
+}
+
+void
+Hara_kiri_group_spanner::add_element (Score_element * me, Score_element *e)
+{
+  //  e->add_offset_callback (force_hara_kiri_in_parent_callback, Y_AXIS);
+  Axis_group_interface::add_element (me, e);
+}
index b2ddc79a08f00615705ccf7cde659c9ed6e7393e..9f4287910728732a94a1a0b486f18130214bc536 100644 (file)
   items-worth-living -- list of interesting items. If empty in a particular system,
     clear this line
 
+
+    todo: naming
 */
 class Hara_kiri_group_spanner 
 {
 public:
   static Real force_hara_kiri_callback (Score_element * , Axis);
+  static Interval y_extent (Score_element * , Axis);
+  static Real force_hara_kiri_in_parent_callback (Score_element * , Axis);
+  static void add_element (Score_element *me, Score_element *e);
   static void set_interface (Score_element*me);
   static bool has_interface (Score_element*);
   static void consider_suicide (Score_element*me);
diff --git a/lily/include/part-combine-music-iterator.hh b/lily/include/part-combine-music-iterator.hh
new file mode 100644 (file)
index 0000000..60cbebc
--- /dev/null
@@ -0,0 +1,40 @@
+/*   
+  part-combine-music-iterator.hh -- declare Part_combine_music_iterator
+  
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+  
+ */
+
+#ifndef PART_COMBINE_MUSIC_ITERATOR_HH
+#define PART_COMBINE_MUSIC_ITERATOR_HH
+
+#include "music-iterator.hh"
+
+class Part_combine_music_iterator : public Music_iterator
+{
+public:
+  Part_combine_music_iterator ();
+
+protected:
+  virtual void construct_children ();
+  virtual Moment next_moment () const;
+  virtual void do_process_and_next (Moment);
+  virtual Music_iterator *try_music_in_children (Music *) const;
+
+  virtual bool ok () const;
+  virtual void do_print () const;
+  virtual ~Part_combine_music_iterator ();
+
+private:
+  void change_to (Music_iterator*, String, String);
+
+  Music_iterator * first_iter_p_;
+  Music_iterator * second_iter_p_;
+
+  bool combined_b_;
+};
+
+#endif /* PART_COMBINE_MUSIC_ITERATOR_HH */
+
diff --git a/lily/include/part-combine-music.hh b/lily/include/part-combine-music.hh
new file mode 100644 (file)
index 0000000..102de3a
--- /dev/null
@@ -0,0 +1,35 @@
+/*   
+  part-combine-music.hh -- declare Part_combine_music
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+  
+ */
+
+#ifndef PART_COMBINE_MUSIC_HH
+#define PART_COMBINE_MUSIC_HH
+
+#include "music.hh"
+
+
+class Part_combine_music : public Music
+{
+public:
+  VIRTUAL_COPY_CONS (Music);
+  Part_combine_music (String, Music*, Music*);
+
+  Music * first_l () const;
+  Music * second_l () const;
+  
+  virtual void transpose (Musical_pitch);
+  virtual void do_print () const;
+  virtual Moment length_mom () const;
+  virtual Musical_pitch to_relative_octave (Musical_pitch);
+  virtual void compress (Moment);
+
+  String what_str_;
+};
+
+#endif /* PART_COMBINE_MUSIC_HH */
+
index 85ff5e8774a90fd61edf77169657bfab7ed06d80..f1a86dee28288426efaac213634820b00f5a60e6 100644 (file)
@@ -187,9 +187,11 @@ public:
   Score_element*common_refpoint (Score_element const* s, Axis a) const;
   Score_element*common_refpoint (SCM elt_list, Axis a) const;
 
+  // duh. slim down interface here. (todo)
   bool has_offset_callback_b (Offset_callback, Axis)const;
   void add_offset_callback (Offset_callback, Axis);
   bool has_extent_callback_b (Extent_callback, Axis)const;  
+  bool has_extent_callback_b (Axis) const;
   void set_extent_callback (Extent_callback , Axis);
 
   /**
index d3a92834e74dc7ef23d39849747f97f67978765b..9e88aeb12b1a7c6e0bc7f94a08233fc1f1752733 100644 (file)
@@ -34,6 +34,8 @@
 #include "lyric-combine-music-iterator.hh"
 #include "auto-change-music.hh"
 #include "auto-change-iterator.hh"
+#include "part-combine-music.hh"
+#include "part-combine-music-iterator.hh"
 #include "request.hh"
 #include "request-iterator.hh"
 #include "output-property.hh"
@@ -146,6 +148,8 @@ Music_iterator::static_get_iterator_p (Music  *m)
     p = new Grace_iterator;
   else if (dynamic_cast<Auto_change_music *> (m))
     p = new Auto_change_iterator;
+  else if (dynamic_cast<Part_combine_music *> (m))
+    p = new Part_combine_music_iterator;
   else if (dynamic_cast<Music_wrapper   *> (m))
     p = new Music_wrapper_iterator;
   else if (Repeated_music  * n = dynamic_cast<Repeated_music  *> (m))
index 9020ae16590f1e81ce5b710369df54faa8fa71ec..4bd5a30495bba5541a84a8a88864bba29a61b117 100644 (file)
@@ -66,6 +66,7 @@ static Keyword_ent the_key_tab[]={
   {"remove", REMOVE},
   {"repeat", REPEAT},
   {"addlyrics", ADDLYRICS},
+  {"partcombine", PARTCOMBINE},
   {"score", SCORE},
   {"script", SCRIPT},
   {"skip", SKIP},
index 5c4632ac7227f192e5c9415944f9072a60792b34..215dd6939480a49b58213f9ffc20f84a196108c4 100644 (file)
@@ -41,6 +41,7 @@
 #include "mudela-version.hh"
 #include "grace-music.hh"
 #include "auto-change-music.hh"
+#include "part-combine-music.hh"
 #include "output-property.hh"
 
 bool
@@ -168,6 +169,7 @@ yylex (YYSTYPE *s,  void * v_l)
 %token REMOVE
 %token REPEAT
 %token ADDLYRICS
+%token PARTCOMBINE
 %token SCM_T
 %token SCORE
 %token SCRIPT
@@ -237,7 +239,7 @@ yylex (YYSTYPE *s,  void * v_l)
 
 %type <scm>  embedded_scm scalar
 %type <music>  Music Sequential_music Simultaneous_music Music_sequence
-%type <music>  relative_music re_rhythmed_music
+%type <music>  relative_music re_rhythmed_music part_combined_music
 %type <music>  property_def translator_change
 %type <scm> Music_list
 %type <outputdef>  music_output_def_body
@@ -757,6 +759,7 @@ Composite_music:
        }
        | relative_music        { $$ = $1; }
        | re_rhythmed_music     { $$ = $1; } 
+       | part_combined_music   { $$ = $1; } 
        ;
 
 relative_music:
@@ -773,6 +776,13 @@ re_rhythmed_music:
        }
        ;
 
+part_combined_music:
+       PARTCOMBINE STRING Music Music {
+               Part_combine_music * p = new Part_combine_music (ly_scm2string ($2), $3, $4);
+               $$ = p;
+       }
+       ;
+
 translator_change:
        TRANSLATOR STRING '=' STRING  {
                Change_translator * t = new Change_translator;
diff --git a/lily/part-combine-music-iterator.cc b/lily/part-combine-music-iterator.cc
new file mode 100644 (file)
index 0000000..86f0354
--- /dev/null
@@ -0,0 +1,249 @@
+/*   
+  part-combine-music-iterator.cc -- implement  Part_combine_music_iterator
+
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+ */
+
+#include "part-combine-music.hh"
+#include "part-combine-music-iterator.hh"
+#include "translator-group.hh"
+#include "musical-request.hh"
+#include "warn.hh"
+
+Part_combine_music_iterator::Part_combine_music_iterator ()
+{
+  combined_b_ = false;
+
+  first_iter_p_ = 0;
+  second_iter_p_ = 0;
+}
+
+Part_combine_music_iterator::~Part_combine_music_iterator ()
+{
+  delete second_iter_p_;
+  delete first_iter_p_;
+}
+
+Moment
+Part_combine_music_iterator::next_moment () const
+{
+  Moment first_next = first_iter_p_->next_moment ();
+  Moment second_next = second_iter_p_->next_moment ();
+  return first_next <? second_next;
+}
+
+bool
+Part_combine_music_iterator::ok () const
+{
+  //hmm
+  return first_iter_p_->ok ();
+}
+
+void
+Part_combine_music_iterator::do_print () const
+{
+  first_iter_p_->print ();
+  second_iter_p_->print ();
+}
+
+void
+Part_combine_music_iterator::construct_children ()
+{
+  Part_combine_music const * m = dynamic_cast<Part_combine_music const*> (music_l_);
+  
+  first_iter_p_ = get_iterator_p (m->first_l ());
+  second_iter_p_ = get_iterator_p (m->second_l ());
+}
+
+void
+Part_combine_music_iterator::change_to (Music_iterator *it, String to_type,
+                                       String to_id)
+{
+  Translator_group * current = it->report_to_l ();
+  Translator_group * last = 0;
+
+  /*
+    Cut & Paste from from Auto_change_iterator from Change_iterator (ugh).
+
+    TODO: abstract this function 
+   */
+  
+  /* find the type  of translator that we're changing.
+     
+     If \translator Staff = bass, then look for Staff = *
+   */
+  while  (current && current->type_str_ != to_type)
+    {
+      last = current;
+      current = current->daddy_trans_l_;
+    }
+
+  if (current && current->id_str_ == to_id)
+    {
+      String msg;
+      msg += _ ("Can't switch translators, I'm there already");
+    }
+  
+  if (current) 
+    if (last)
+      {
+       Translator_group * dest = 
+         it->report_to_l ()->find_create_translator_l (to_type, to_id);
+       current->remove_translator_p (last);
+       dest->add_translator (last);
+      }
+    else
+      {
+       /*
+         We could change the current translator's id, but that would make 
+         errors hard to catch
+         
+          last->translator_id_str_  = change_l ()->change_to_id_str_;
+       */
+       error (_f ("I'm one myself: `%s'", to_type.ch_C ()));
+      }
+  else
+    error (_f ("none of these in my family: `%s'", to_id.ch_C ()));
+}
+
+Pitch_interrogate_req* first_spanish_inquisition; // nobody expects it
+Pitch_interrogate_req* second_spanish_inquisition; // won't strike twice
+
+void
+Part_combine_music_iterator::do_process_and_next (Moment m)
+{
+  Moment first_next = first_iter_p_->next_moment ();
+  Moment second_next = second_iter_p_->next_moment ();
+
+  bool changed_b = false;
+  Part_combine_music const * p = dynamic_cast<Part_combine_music const* > (music_l_);
+
+  String to_id =  combined_b_ ? "first" : "second";
+  /*
+    different rhythm for combined voices: separate 
+    same rhythm for separated voices: combine
+  */
+  if ((first_next != second_next && combined_b_)
+      || (first_next == second_next && !combined_b_))
+    {
+      combined_b_ = !combined_b_;
+      to_id =  combined_b_ ? "first" : "second";
+      change_to (second_iter_p_, p->what_str_, to_id);
+      changed_b = true;
+    }
+
+  Translator_group * fd = 
+    first_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_,
+                                                            "first");
+  Translator_group * sd = 
+    second_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_,
+                                                             to_id);
+
+  fd->set_property ("first", SCM_BOOL_T);
+  sd->set_property ("second", SCM_BOOL_T);
+
+  if (first_next <= m)
+    first_iter_p_->process_and_next (m);
+
+  if (second_next <= m)
+    second_iter_p_->process_and_next (m);
+
+  Music_iterator::do_process_and_next (m);
+
+  /*
+    TODO:
+    
+    * "a2" string is fine, but "Soli" strings are one request late,
+      second a2 requests are junked one requst late...
+    
+      The problem seems to be: we need to do_try_music for the
+      spanish_inquisition to work; but the properties that we set
+      need to be set *before* we do_try_music?
+      
+    * setting of stem directions by a2-engraver don't work
+      
+    * move much as possible code (changed?) to engravers: just notify
+      them of status: unison/solo.  Engravers should be able to find
+      out whether something changed and if so, what to do.
+
+    * who should reset the properties, it's a mess now?
+
+
+    Later (because currently,we only handle thread swiching, really):
+
+    Maybe different modes exist?
+
+    * Wind instruments (Flute I/II)
+    * Hymnals:  
+
+
+      Rules for Hymnals/SATB (John Henckel <henckel@iname.com>):
+
+      1. if S and A differ by less than a third, the stems should be up/down.
+      2. else if S and A have different values, the stems should be up/down.
+      3. else if A sings "la" or higher, both S and A stems should be down.
+      4. else both stems should be up
+
+    * This may get really tricky: combining voices/staffs: string instruments
+
+   */
+  
+  if (!first_spanish_inquisition)
+    first_spanish_inquisition = new Pitch_interrogate_req;
+  Music_iterator* fit = first_iter_p_->try_music (first_spanish_inquisition);
+
+  if (!second_spanish_inquisition)
+    second_spanish_inquisition = new Pitch_interrogate_req;
+  Music_iterator* sit = second_iter_p_->try_music (second_spanish_inquisition);
+
+
+  // URG, moveme: just set properties
+  if (//changed_b
+      //&&
+      (first_next == second_next)
+      && first_spanish_inquisition->pitch_arr_.size ()
+      && (first_spanish_inquisition->pitch_arr_.size ()
+         == second_spanish_inquisition->pitch_arr_.size ())
+      && (first_spanish_inquisition->pitch_arr_[0] ==
+         second_spanish_inquisition->pitch_arr_[0]))
+    {
+      if (changed_b)
+       {
+         fd->set_property ("a2", SCM_BOOL_T);
+         sd->set_property ("a2", SCM_BOOL_T);
+       }
+      second_iter_p_->report_to_l ()->set_property ("a2", SCM_BOOL_T);
+    }
+  else
+    second_iter_p_->report_to_l ()->set_property ("a2", SCM_BOOL_F);
+  
+  if (changed_b
+      && first_spanish_inquisition->pitch_arr_.size ()
+      && !second_spanish_inquisition->pitch_arr_.size ())
+    {
+      fd->set_property ("solo", SCM_BOOL_T);
+    }
+
+  if (changed_b
+      && !first_spanish_inquisition->pitch_arr_.size ()
+      && second_spanish_inquisition->pitch_arr_.size ())
+    {
+      sd->set_property ("solo2", SCM_BOOL_T);
+    }
+
+  first_spanish_inquisition->pitch_arr_.clear ();
+  second_spanish_inquisition->pitch_arr_.clear ();
+}
+
+Music_iterator*
+Part_combine_music_iterator::try_music_in_children (Music *m) const
+{
+  Music_iterator * i =  first_iter_p_->try_music (m);
+  if (i)
+    return i;
+  else
+    return second_iter_p_->try_music (m);
+}
+
diff --git a/lily/part-combine-music.cc b/lily/part-combine-music.cc
new file mode 100644 (file)
index 0000000..41127ac
--- /dev/null
@@ -0,0 +1,65 @@
+/*   
+  part-combine-music.cc --  implement Part_combine_music
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+  
+ */
+
+#include "part-combine-music.hh"
+#include "musical-pitch.hh"
+
+Part_combine_music::Part_combine_music (String what, Music * f, Music * s)
+{
+  what_str_ = what;
+  set_mus_property ("first", f->self_scm ());
+  set_mus_property ("second", s->self_scm ());  
+}
+
+
+void
+Part_combine_music::transpose (Musical_pitch p)
+{
+  first_l ()->transpose (p);
+  second_l () ->transpose (p);
+}
+
+void
+Part_combine_music::do_print () const  
+{
+  first_l ()->print();
+  second_l () ->print ();
+}
+
+Moment
+Part_combine_music::length_mom () const
+{
+  return first_l ()->length_mom ();
+}
+
+Musical_pitch
+Part_combine_music::to_relative_octave (Musical_pitch p)
+{
+  p = first_l ()->to_relative_octave (p);
+  return second_l ()->to_relative_octave (p);
+}
+
+void
+Part_combine_music::compress (Moment m)
+{
+  first_l ()->compress (m);
+  second_l ()->compress (m);
+}
+
+Music*
+Part_combine_music::first_l () const
+{
+  return unsmob_music (get_mus_property ("first"));
+}
+
+Music*
+Part_combine_music::second_l () const
+{
+  return unsmob_music (get_mus_property ("second"));
+}
index c6e54302637fb1b2523d54014a2cddef262cd8e5..e7baf2ec253d21434c3669b373fc1c21c0d39fb4 100644 (file)
@@ -85,7 +85,7 @@ Property_engraver::acknowledge_element (Score_element_info i)
 
 void
 Property_engraver::apply_properties (SCM p, Score_element *e)
-{  
+{
   for (; gh_pair_p (p); p = gh_cdr (p))
     {
       /*
index c39624b53b3ff422e43625e387c567a487f3e6f2..6a294a43019696c4cddfb85f48714e4ef9d020d1 100644 (file)
@@ -45,6 +45,9 @@ remove dynamic_cast<Spanner,Item> and put this code into respective
 
 Score_element::Score_element(SCM basicprops)
 {
+  /*
+    fixme: default should be no callback.
+   */
   set_extent_callback (molecule_extent, X_AXIS);
   set_extent_callback (molecule_extent, Y_AXIS);    
 
@@ -520,8 +523,8 @@ Score_element::get_offset (Axis a) const
       Real r =  (*c) (me,a );
       if (isinf (r) || isnan (r))
        {
-         r = 0.0;
          programming_error (INFINITY_MSG);
+         r = 0.0;
        }
       me->dim_cache_[a].offset_ +=r;
     }
@@ -641,6 +644,13 @@ Score_element::has_extent_callback_b (Extent_callback cb, Axis a)const
   return cb == dim_cache_[a].extent_callback_l_;
 }
 
+
+bool
+Score_element::has_extent_callback_b (Axis a) const
+{
+  return dim_cache_[a].extent_callback_l_;
+}
+
 bool
 Score_element::has_offset_callback_b (Offset_callback cb, Axis a)const
 {
index e4e790da14d36e626e8fdb89c5713caf89c5fbe8..722dd45d77db41ddeb248d9bad560bb503347cbf 100644 (file)
@@ -66,7 +66,13 @@ Span_bar::center_on_spanned_callback (Score_element * me, Axis a)
 
 void
 Span_bar::evaluate_empty (Score_element*me)
-{ 
+{
+  /*
+    TODO: filter all hara-kiried out of ELEMENS list, and then
+    optionally do suicide. Call this cleanage function from
+    center_on_spanned_callback() as well.
+    
+   */
   if (!gh_pair_p (me->get_elt_property ("elements")))
     {
       me->suicide ();
@@ -113,8 +119,11 @@ Span_bar::get_bar_size (SCM smob)
   Interval iv (get_spanned_interval (me));
   if (iv.empty_b ())
     {
-      programming_error("Huh? My children deflated (FIXME)");
-      iv = Interval (0,0);
+      /*
+       This happens if the bars are hara-kiried from under us.
+       */
+      me->suicide ();
+      return gh_double2scm (-1);
     }
   return gh_double2scm (iv.length ());
 }
index 0fa41ca7cd98b2fdec077db2d7967671d23745dc..b634bf70e6a9809afb4a04e2c964c738fb320d09 100644 (file)
@@ -98,25 +98,19 @@ Text_engraver::do_process_music ()
        text->set_elt_property ("style", ly_str02scm (r->style_str_.ch_C()));
       
       /*
-       huh?, this said:
-
-        SCM empty = get_property ("textNonEmpty");
-        if (to_boolean (empty))
-           no-spacing-rods
-
        Text is empty by default, which means that the only condition
        for not setting 'no-spacing-rods' should be: boolean && true.
 
        Anyway, non-empty text has been broken for some time now.
        */
       SCM nonempty = get_property ("textNonEmpty");
-      if (to_boolean (nonempty))
-        ;
-      else
-       {
-         text->set_elt_property ("no-spacing-rods" , SCM_BOOL_F);
-         text->set_extent_callback (0, X_AXIS);
-       }
+      if (!to_boolean (nonempty))
+       /*
+         empty text: signal that no rods should be applied.  
+        */
+       text->set_elt_property ("no-spacing-rods" , SCM_BOOL_T);
+
+               
       announce_element (text, r);
       texts_.push (text);
     }
index 790704c229d6741f3b875a5cbc6f57720c430694..60399daa1bf62c93d5e8b1c0d0958e080751e1e7 100644 (file)
@@ -145,6 +145,7 @@ VoiceContext = \translator {
        \consists "Melisma_engraver";
        textScriptPadding = #3.0
        \consists "Text_engraver";
+       \consists "A2_engraver";
 
 
        startSustain = #"Ped."
@@ -204,7 +205,8 @@ GraceContext=\translator {
 
 ThreadContext = \translator{
        \type Engraver_group_engraver;
-       \consists "Note_heads_engraver" ;
+       \consists "A2_devnull_engraver";
+       \consists "Note_heads_engraver";
        \consists "Output_property_engraver";   
        Generic_property_list = #generic-thread-properties
        \consists "Property_engraver";
@@ -472,6 +474,7 @@ ScoreContext = \translator {
        basicChordNameProperties = #`(
                (molecule-callback . ,Chord_name::brew_molecule)
                (interfaces . (chord-name-interface))
+               (after-line-breaking-callback . ,Chord_name::after_line_breaking) 
        )
        basicCollisionProperties = #`(
                (axes 0 1)
@@ -491,12 +494,12 @@ ScoreContext = \translator {
                (interfaces . (dot-interface))
        )
        basicDynamicLineSpannerProperties = #`(
-               (interfaces (dynamic-interface axis-group-interface))
+               (interfaces (dynamic-interface axis-group-interface))
                (axes . ( 1))
        )
        basicDynamicTextProperties       = # `(
                (style . "dynamic")
-               (interface (dynamic-interface))
+               (interfaces . (dynamic-interface))
                (molecule-callback . ,Text_item::brew_molecule)
                (script-priority . 100)
                (self-alignment-Y . 0)
@@ -683,7 +686,9 @@ ScoreContext = \translator {
        )
        basicTextScriptProperties = #`(
                (molecule-callback . ,Text_item::brew_molecule)
-               (no-spacing-rods . #t)
+
+: -- don't set, because property-engraver will not override it.  
+;              (no-spacing-rods . #t)
                (interfaces . (text-script-interface text-item-interface))
        )
        basicTieProperties = #`(