Hi,

I've finished 2 more patches for music streams. One of them is considerably 
larger than the other, but the two should be independent.

Pathc 1:
 - lyric-combine-music.cc, partcombine-iterator.cc: updated to use stream 
events for busy testing.
 - chord-tremolo: massively cleaned up (iterator either generates ChordEvent, 
which is handled like :, or generates span start/stop events. Engraver is 
shrinked)
 - Translator_group::try_music is now invoked through listeners. 

Patch 2:
 - output-property-*: prepare for bottomification of try_music
 - exported some more rules to scheme:
  - \once is converted to music function (we might later want to make it a 
music macro)
  - context-specification -> ly-syntax rule
  - ly-syntax rule for music functions.


Two generic utility functions have been introduced, chordify-event and 
music-is-of-type?

Todo:
- create contexts through music streams (add new event for context creation 
announcements)
- make try_music auto-descend to bottom context. Some of the current places 
where stream-events are sent should then be replaced with try_music calls.
- Make other commands (SetProperty, ChangeContext, Prepare, OneTimeStep) use 
stream events.

Questions:
- It seems that the OutputPropertySetMusic music type is unused. Should I 
remove it?
- I have not yet done anything about old-lyric-combine-music-iterator. Should 
I spend time on making it work, or can we junk oldaddlyrics for the next 
release? (there's no regression test for oldaddlyrics, btw)
- What's the Right Way to pass warnings and errors from Scheme code? I want 
some warning messages to make use of Input objects.

-- 
Erik
? .sconf_temp
? build-stamp
? context-unique.diff
? def-rel-music-funciton.diff
? delay-music-functions.diff
? exjobb.diff3
? fonts
? lib
? lilypond.kdevelop
? lilypond.kdevelop.pcs
? lilypond.kdevses
? optimized
? os
? ref1.diff
? ref2.diff
? repeat.diff
? scons.cache
? Documentation/out
? Documentation/out-www
? Documentation/bibliography/out
? Documentation/misc/out
? Documentation/pictures/out
? Documentation/topdocs/out
? Documentation/user/out
? Documentation/user/out-www
? buildscripts/out
? buildscripts/out-www
? cygwin/out
? cygwin/out-www
? debian/out
? elisp/out
? elisp/out-www
? flower/out
? flower/out-scons
? flower/out-www
? flower/include/.sconsign
? flower/include/out
? flower/include/out-www
? input/Diagram1.dia.autosave
? input/les-nereides.pdf
? input/les-nereides.ps
? input/out
? input/out-www
? input/mutopia/out
? input/mutopia/out-www
? input/mutopia/E.Satie/out
? input/mutopia/E.Satie/out-www
? input/mutopia/F.Schubert/out
? input/mutopia/F.Schubert/out-www
? input/mutopia/J.S.Bach/out
? input/mutopia/J.S.Bach/out-www
? input/mutopia/R.Schumann/out
? input/mutopia/R.Schumann/out-www
? input/mutopia/W.A.Mozart/out
? input/mutopia/W.A.Mozart/out-www
? input/no-notation/out
? input/no-notation/out-www
? input/no-notation/to-xml.pdf
? input/no-notation/to-xml.ps
? input/regression/chord-tremolo.pdf
? input/regression/chord-tremolo.ps
? input/regression/out
? input/regression/out-www
? input/template/out
? input/test/out
? input/test/out-www
? input/tutorial/out
? input/tutorial/out-www
? kpath-guile/out
? kpath-guile/out-scons
? lily/On
? lily/busy-playing-listener.cc
? lily/foo.pdf
? lily/foo.ps
? lily/lilypond
? lily/lilypond.gdt
? lily/lilypond.gpr
? lily/out
? lily/out-scons
? lily/out-www
? lily/include/.sconsign
? lily/include/busy-playing-listener.hh
? lily/include/out
? lily/include/out-www
? ly/out
? ly/out-www
? make/out
? make/out-www
? mf/feta-alphabet11.600pk
? mf/feta-alphabet13.600pk
? mf/feta-alphabet14.600pk
? mf/feta-alphabet16.600pk
? mf/feta-alphabet18.600pk
? mf/feta-alphabet20.600pk
? mf/feta-alphabet23.600pk
? mf/feta-alphabet26.600pk
? mf/feta-braces-a.600pk
? mf/feta-braces-b.600pk
? mf/feta-braces-c.600pk
? mf/feta-braces-d.600pk
? mf/feta-braces-e.600pk
? mf/feta-braces-f.600pk
? mf/feta-braces-g.600pk
? mf/feta-braces-h.600pk
? mf/feta-braces-i.600pk
? mf/feta11.600pk
? mf/feta13.600pk
? mf/feta14.600pk
? mf/feta16.600pk
? mf/feta18.600pk
? mf/feta20.600pk
? mf/feta23.600pk
? mf/feta26.600pk
? mf/out
? mf/out-scons
? mf/out-www
? mf/parmesan11.600pk
? mf/parmesan13.600pk
? mf/parmesan14.600pk
? mf/parmesan16.600pk
? mf/parmesan18.600pk
? mf/parmesan20.600pk
? mf/parmesan23.600pk
? mf/parmesan26.600pk
? po/out
? po/out-www
? ps/out
? ps/out-www
? python/convertrules.pyc
? python/fontextract.pyc
? python/lilylib.pyc
? python/out
? python/out-www
? scm/out
? scm/out-www
? scripts/lilypond-book-36.py
? scripts/lilypond-book.py.new
? scripts/out
? scripts/out-www
? scripts/stat
? stepmake/out
? stepmake/out-www
? stepmake/bin/out
? stepmake/bin/out-www
? stepmake/bin/packagepython.pyc
? stepmake/stepmake/out
? stepmake/stepmake/out-www
? tex/out
? tex/out-www
? ttftool/out
? ttftool/out-scons
? ttftool/include/.sconsign
? ttftool/include/out
? vim/out
? vim/out-www
Index: ChangeLog
===================================================================
RCS file: /sources/lilypond/lilypond/ChangeLog,v
retrieving revision 1.4988
diff -u -r1.4988 ChangeLog
--- ChangeLog	21 May 2006 23:56:13 -0000	1.4988
+++ ChangeLog	22 May 2006 05:45:00 -0000
@@ -140,6 +140,9 @@
 	* lily/time-scaled-music-iterator.cc, lily/tuplet-engraver.cc:
 	rework tuplets: send start/stop events to engraver
 
+	* lily/context.cc, lily/music.cc, lily/context-scheme.cc: Add
+	dispatchers event-source and events-below to Context
+	
 2006-05-15  Graham Percival  <[EMAIL PROTECTED]>
 
 	* Documentation/user/README.txt: update info for doc writers.
Index: lily/chord-tremolo-engraver.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/chord-tremolo-engraver.cc,v
retrieving revision 1.99
diff -u -r1.99 chord-tremolo-engraver.cc
--- lily/chord-tremolo-engraver.cc	7 May 2006 19:51:11 -0000	1.99
+++ lily/chord-tremolo-engraver.cc	22 May 2006 05:45:00 -0000
@@ -4,12 +4,12 @@
   source file of the GNU LilyPond music typesetter
 
   (c) 2000--2006 Han-Wen Nienhuys <[EMAIL PROTECTED]>
+  		 Erik Sandberg <[EMAIL PROTECTED]>
 */
 
 #include "math.h" // ceil
 
 #include "beam.hh"
-#include "chord-tremolo-iterator.hh"
 #include "engraver-group.hh"
 #include "international.hh"
 #include "item.hh"
@@ -39,92 +39,72 @@
 */
 class Chord_tremolo_engraver : public Engraver
 {
-  void typeset_beam ();
   TRANSLATOR_DECLARATIONS (Chord_tremolo_engraver);
 protected:
   Music *repeat_;
 
-  /// moment (global time) where beam started.
-  Moment start_mom_;
-  Moment stop_mom_;
   int flags_;
-  int total_duration_flags_;
+  // number of beams for short tremolos
+  int expected_beaming_;
+  // current direction of beam (first RIGHT, then LEFT)
+  Direction dir_;
 
-  /// location  within measure where beam started.
-  Moment beam_start_location_;
-
-  bool body_is_sequential_;
   Spanner *beam_;
-  Spanner *finished_beam_;
-  Item *stem_tremolo_;
 protected:
   virtual void finalize ();
   virtual bool try_music (Music *);
-  void stop_translation_timestep ();
-  void start_translation_timestep ();
   void process_music ();
   DECLARE_ACKNOWLEDGER (stem);
 };
 
 Chord_tremolo_engraver::Chord_tremolo_engraver ()
 {
-  beam_ = finished_beam_ = 0;
+  beam_ = 0;
   repeat_ = 0;
   flags_ = 0;
-  stem_tremolo_ = 0;
-  body_is_sequential_ = false;
+  expected_beaming_ = 0;
+  dir_ = CENTER;
 }
 
 bool
 Chord_tremolo_engraver::try_music (Music *m)
 {
-  if (m->is_mus_type ("repeated-music")
-      && m->get_property ("iterator-ctor") == Chord_tremolo_iterator::constructor_proc
-      && !repeat_)
+  if (m->is_mus_type ("tremolo-span-event"))
     {
-      Moment l = m->get_length ();
-      repeat_ = m;
-      start_mom_ = now_mom ();
-      stop_mom_ = start_mom_ + l;
-
-      Music *body = Repeated_music::body (m);
-      body_is_sequential_ = body->is_mus_type ("sequential-music");
-
-      int elt_count = body_is_sequential_ ? scm_ilength (body->get_property ("elements")) : 1;
-
-      if (body_is_sequential_ && elt_count != 2)
-	m->origin ()->warning (_f ("expect 2 elements for chord tremolo, found %d", elt_count));
-
-      if (elt_count <= 0)
-	elt_count = 1;
-
-      Rational total_dur = l.main_part_;
-      Rational note_dur = total_dur / Rational (elt_count * Repeated_music::repeat_count (repeat_));
-
-      total_duration_flags_ = max (0, (intlog2 (total_dur.den ()) - 2));
-
-      flags_ = intlog2 (note_dur.den ()) -2;
-
+      Direction dir = to_dir (m->get_property ("span-direction"));
+      if (dir == START)
+	{
+	  repeat_ = m;
+	  int type = scm_to_int (m->get_property ("tremolo-type"));
+	  /* e.g. 1 for type 8, 2 for type 16 */
+	  flags_ = intlog2 (type) - 2;
+	  expected_beaming_ = scm_to_int (m->get_property ("expected-beaming"));
+	  dir_ = RIGHT;
+	}
+      if (dir == STOP)
+	{
+	  repeat_ = 0;
+          beam_ = 0;
+          expected_beaming_ = 0;
+          dir_ = CENTER;
+	}
       return true;
     }
-
   return false;
 }
 
 void
 Chord_tremolo_engraver::process_music ()
 {
-  if (repeat_ && body_is_sequential_ && !beam_)
+  if (repeat_ && !beam_)
     {
       beam_ = make_spanner ("Beam", repeat_->self_scm ());
-      beam_start_location_ = robust_scm2moment (get_property ("measurePosition"), Moment (0));
     }
 }
 
 void
 Chord_tremolo_engraver::finalize ()
 {
-  typeset_beam ();
   if (beam_)
     {
       repeat_->origin ()->warning (_ ("unterminated chord tremolo"));
@@ -133,25 +113,19 @@
 }
 
 void
-Chord_tremolo_engraver::typeset_beam ()
-{
-  finished_beam_ = 0;
-}
-
-void
 Chord_tremolo_engraver::acknowledge_stem (Grob_info info)
 {
   if (beam_)
     {
       Grob *s = info.grob ();
 
-      if (start_mom_ == now_mom ())
-	Stem::set_beaming (s, flags_, RIGHT);
-      else
-	Stem::set_beaming (s, flags_, LEFT);
+      Stem::set_beaming (s, flags_, dir_);
 
       if (Stem::duration_log (s) != 1)
-	beam_->set_property ("gap-count", scm_from_int (flags_ - total_duration_flags_));
+	beam_->set_property ("gap-count", scm_from_int (flags_ - expected_beaming_));
+
+      if (dir_ == RIGHT)
+        dir_ = LEFT;
 
       if (info.ultimate_music_cause ()->is_mus_type ("rhythmic-event"))
 	Beam::add_stem (beam_, s);
@@ -164,49 +138,12 @@
 	    ::warning (s);
 	}
     }
-  else if (repeat_
-	   && flags_
-	   && !body_is_sequential_)
-    {
-      stem_tremolo_ = make_item ("StemTremolo", repeat_->self_scm ());
-      stem_tremolo_->set_property ("flag-count",
-				   scm_from_int (flags_));
-      stem_tremolo_->set_object ("stem",
-				 info.grob ()->self_scm ());
-      stem_tremolo_->set_parent (info.grob (), X_AXIS);
-      info.grob ()->set_object ("tremolo-flag", stem_tremolo_->self_scm ());
-    }
-}
-
-void
-Chord_tremolo_engraver::start_translation_timestep ()
-{
-  if (beam_ && stop_mom_ == now_mom ())
-    {
-      finished_beam_ = beam_;
-      repeat_ = 0;
-      beam_ = 0;
-    }
-}
-
-void
-Chord_tremolo_engraver::stop_translation_timestep ()
-{
-  if (stem_tremolo_)
-    {
-      repeat_ = 0;
-      if (beam_)
-	programming_error ("beam and stem tremolo?");
-      stem_tremolo_ = 0;
-    }
-
-  typeset_beam ();
 }
 
 ADD_ACKNOWLEDGER (Chord_tremolo_engraver, stem);
 ADD_TRANSLATOR (Chord_tremolo_engraver,
-		/* doc */ "Generates beams for  tremolo repeats.",
+		/* doc */ "Generates beams for tremolo repeats.",
 		/* create */ "Beam",
-		/* accept */ "repeated-music",
+		/* accept */ "tremolo-span-event",
 		/* read */ "",
 		/* write */ "");
Index: lily/chord-tremolo-iterator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/chord-tremolo-iterator.cc,v
retrieving revision 1.35
diff -u -r1.35 chord-tremolo-iterator.cc
--- lily/chord-tremolo-iterator.cc	26 Jan 2006 11:17:08 -0000	1.35
+++ lily/chord-tremolo-iterator.cc	22 May 2006 05:45:00 -0000
@@ -4,82 +4,86 @@
   source file of the GNU LilyPond music typesetter
 
   (c) 2000--2006 Han-Wen Nienhuys <[EMAIL PROTECTED]>
+  		 Erik Sandberg <[EMAIL PROTECTED]>
 */
 
 #include "chord-tremolo-iterator.hh"
 
 #include "input.hh"
 #include "international.hh"
+#include "misc.hh"
 #include "repeated-music.hh"
 
-void
-Chord_tremolo_iterator::construct_children ()
-{
-  Music *m = get_music ();
-
-  factor_ = Moment (Rational (1, 1));
-  child_iter_ = unsmob_iterator (get_iterator (Repeated_music::body (m)));
-}
-
 Chord_tremolo_iterator::Chord_tremolo_iterator ()
 {
-  factor_ = 1;
-  child_iter_ = 0;
+  child_list_ = SCM_EOL;
 }
 
 void
-Chord_tremolo_iterator::do_quit ()
-{
-  if (child_iter_)
-    child_iter_->quit ();
-}
-
-void
-Chord_tremolo_iterator::derived_mark () const
+Chord_tremolo_iterator::construct_children ()
 {
-  if (child_iter_)
-    scm_gc_mark (child_iter_->self_scm ());
-}
+  Music *mus = get_music ();
+  Input *origin = mus->origin ();
+  Moment l = mus->get_length ();
+  Music *body = Repeated_music::body (mus);
+  bool body_is_sequential_ = body->is_mus_type ("sequential-music");
+
+  int elt_count = body_is_sequential_ ? scm_ilength (body->get_property ("elements")) : 1;
+
+  if (body_is_sequential_ && elt_count != 2)
+    mus->origin ()->warning (_f ("expect 2 elements for chord tremolo, found %d", elt_count));
+
+  if (elt_count <= 0)
+    elt_count = 1;
+      
+  Rational total_dur = l.main_part_;
+  Rational note_dur = total_dur / Rational (elt_count * Repeated_music::repeat_count (mus));
 
-void
-Chord_tremolo_iterator::derived_substitute (Context *f, Context *t)
-{
-  if (child_iter_)
-    child_iter_->substitute_outlet (f, t);
-}
+  SCM tremolo_type = scm_int2num (note_dur.den ());
+  int expected_beaming_ = max (0, (intlog2 (total_dur.den ()) - 2));
 
-void
-Chord_tremolo_iterator::process (Moment m)
-{
-  if (!m.to_bool ())
+  if (elt_count == 1)
     {
-      Music_iterator *yeah = try_music (get_music ());
-      if (yeah)
-	set_context (yeah->get_outlet ());
-      else
-	get_music ()->origin ()->warning (_ ("no one to print a tremolos"));
+      Music *ev = make_music_by_name (ly_symbol2scm ("TremoloEvent"));
+      ev->set_spot (*origin);
+      ev->set_property ("tremolo-type", tremolo_type);
+      SCM sev = scm_call_1 (ly_lily_module_constant ("chordify-event"), ev->unprotect ());
+      child_list_ = scm_list_2 (sev, body->self_scm ());
     }
-
-  child_iter_->process (factor_ * m);
-}
-
-Moment
-Chord_tremolo_iterator::pending_moment () const
-{
-  return child_iter_->pending_moment () / factor_;
+  else
+    { 
+      SCM tremolo_symbol = ly_symbol2scm ("TremoloSpanEvent");
+      SCM start_event_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tremolo_symbol, scm_from_int (START));
+      unsmob_music (start_event_scm)->set_spot (*origin);
+      SCM stop_event_scm = scm_call_2 (ly_lily_module_constant ("make-span-event"), tremolo_symbol, scm_from_int (STOP));
+
+      Music *start_event = unsmob_music (start_event_scm);
+      Music *stop_event = unsmob_music (stop_event_scm);
+      start_event->set_spot (*origin);
+      stop_event->set_spot (*origin);
+      start_event->set_property ("tremolo-type", tremolo_type);
+      start_event->set_property ("expected-beaming", scm_int2num (expected_beaming_));
+
+      SCM start_chord = scm_call_1 (ly_lily_module_constant ("chordify-event"), start_event_scm);
+      SCM stop_chord = scm_call_1 (ly_lily_module_constant ("chordify-event"), stop_event_scm);
+      
+      child_list_ = scm_list_3 (start_chord, body->self_scm (), stop_chord);
+    }
+  
+  Sequential_iterator::construct_children ();
 }
 
-bool
-Chord_tremolo_iterator::ok () const
+SCM
+Chord_tremolo_iterator::get_music_list () const
 {
-  return child_iter_ && child_iter_->ok ();
+  return child_list_;
 }
 
-Music_iterator *
-Chord_tremolo_iterator::try_music_in_children (Music *m) const
+void
+Chord_tremolo_iterator::derived_mark () const
 {
-  return child_iter_->try_music (m);
+  scm_gc_mark (child_list_);
+  Sequential_iterator::derived_mark ();
 }
 
 IMPLEMENT_CTOR_CALLBACK (Chord_tremolo_iterator);
-
Index: lily/context-def.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/context-def.cc,v
retrieving revision 1.61
diff -u -r1.61 context-def.cc
--- lily/context-def.cc	16 May 2006 11:30:54 -0000	1.61
+++ lily/context-def.cc	22 May 2006 05:45:00 -0000
@@ -344,9 +344,8 @@
   else if (dynamic_cast<Performer_group *> (g))
     g->simple_trans_list_ = filter_engravers (g->simple_trans_list_);
 
-  g->context_ = context;
   context->aliases_ = context_aliases_;
-
+  g->connect_to_context (context);
   g->unprotect ();
 
   context->accepts_list_ = get_accepted (ops);
Index: lily/lyric-combine-music-iterator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/lyric-combine-music-iterator.cc,v
retrieving revision 1.53
diff -u -r1.53 lyric-combine-music-iterator.cc
--- lily/lyric-combine-music-iterator.cc	2 Mar 2006 00:39:54 -0000	1.53
+++ lily/lyric-combine-music-iterator.cc	22 May 2006 05:45:00 -0000
@@ -7,9 +7,11 @@
 */
 
 #include "context.hh"
+#include "dispatcher.hh"
 #include "grob.hh"
 #include "input.hh"
 #include "international.hh"
+#include "listener.hh"
 #include "music-iterator.hh"
 #include "music.hh"
 
@@ -29,9 +31,14 @@
   virtual bool ok () const;
   virtual void derived_mark () const;
   virtual void derived_substitute (Context *, Context *);
+  void set_music_context (Context *to);
 private:
   bool start_new_syllable ();
   void find_voice ();
+  DECLARE_LISTENER (set_busy);
+  DECLARE_LISTENER (check_new_context);
+  /* true when check_new_context is listening */
+  bool listening_;
 
   bool pending_grace_lyric_;
   bool music_found_;
@@ -40,16 +47,10 @@
   Context *music_context_;
   SCM lyricsto_voice_name_;
 
+  bool busy_;
   Music_iterator *lyric_iter_;
 };
 
-/*
-  Ugh; this is a hack, let's not export this hack, so static.
-*/
-static Music *busy_ev;
-static Music *start_ev;
-static Music *melisma_playing_ev;
-
 Lyric_combine_music_iterator::Lyric_combine_music_iterator ()
 {
   music_found_ = false;
@@ -58,35 +59,46 @@
   lyric_iter_ = 0;
   music_context_ = 0;
   lyrics_context_ = 0;
+  listening_ = false;
+}
 
-  /*
-    Ugh. out of place here.
-  */
-  if (!busy_ev)
-    {
-      busy_ev
-	= make_music_by_name (ly_symbol2scm ("BusyPlayingEvent"));
-      start_ev
-	= make_music_by_name (ly_symbol2scm ("StartPlayingEvent"));
-      melisma_playing_ev
-	= make_music_by_name (ly_symbol2scm ("MelismaPlayingEvent"));
-    }
+IMPLEMENT_LISTENER (Lyric_combine_music_iterator, set_busy)
+void
+Lyric_combine_music_iterator::set_busy (SCM se)
+{
+  Stream_event *e = unsmob_stream_event (se);
+  SCM mus = e->get_property ("music");
+  Music *m = unsmob_music (mus);
+  assert (m);
+
+  if (m->is_mus_type ("note-event") || m->is_mus_type ("cluster-note-event"))
+    busy_ = true;
+}
+
+void
+Lyric_combine_music_iterator::set_music_context (Context *to)
+{
+  if (music_context_)
+    music_context_->event_source()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent"));
+  music_context_ = to;
+  if (to)
+    to->event_source()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent"));
 }
 
 bool
 Lyric_combine_music_iterator::start_new_syllable ()
 {
-  bool b = music_context_->try_music (busy_ev);
-
-  if (!b)
+  if (!busy_)
     return false;
 
+  busy_ = false;
+
   if (!lyrics_context_)
     return false;
 
   if (!to_boolean (lyrics_context_->get_property ("ignoreMelismata")))
     {
-      bool m = music_context_->try_music (melisma_playing_ev);
+      bool m = melisma_busy (music_context_);
       if (m)
 	return false;
     }
@@ -135,7 +147,7 @@
   if (lyrics_context_ && lyrics_context_ == f)
     lyrics_context_ = t;
   if (music_context_ && music_context_ == f)
-    music_context_ = t;
+    set_music_context (t);
 }
 
 void
@@ -159,6 +171,21 @@
   */
 }
 
+IMPLEMENT_LISTENER (Lyric_combine_music_iterator, check_new_context)
+void
+Lyric_combine_music_iterator::check_new_context (SCM sev)
+{
+  // TODO: Check first if type=Voice and if id matches
+  (void)sev;
+
+  find_voice ();
+}
+
+/*
+This method looks for the voice to align lyrics to.
+If none is found, a listener is registered which retries whenever new contexts are created.
+from_listener is true when called from this listener.
+*/
 void
 Lyric_combine_music_iterator::find_voice ()
 {
@@ -189,7 +216,21 @@
       Context *voice = find_context_below (t, ly_symbol2scm ("Voice"), name);
 
       if (voice)
-	music_context_ = voice;
+        {
+	  set_music_context (voice);
+      	  if (listening_)
+            {
+	      // we're pleased now.
+	      t->events_below ()->remove_listener (GET_LISTENER (check_new_context), ly_symbol2scm ("CreateContext"));
+	      listening_ = false;
+            }
+        }
+      else if (!listening_)
+        {
+          // Wait for a Create_context event, to catch implicitly created voices before it's too late.
+          t->events_below ()->add_listener (GET_LISTENER (check_new_context), ly_symbol2scm ("CreateContext"));
+          listening_ = true;
+        }
     }
 
   if (lyrics_context_ && music_context_)
@@ -204,9 +245,8 @@
 }
 
 void
-Lyric_combine_music_iterator::process (Moment mom)
+Lyric_combine_music_iterator::process (Moment)
 {
-  (void) mom;
   find_voice ();
   if (!music_context_)
     return;
@@ -220,7 +260,7 @@
       if (lyrics_context_)
 	lyrics_context_->unset_property (ly_symbol2scm ("associatedVoiceContext"));
       lyric_iter_ = 0;
-      music_context_ = 0;
+      set_music_context (0);
     }
 
   if (music_context_
Index: lily/music-iterator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/music-iterator.cc,v
retrieving revision 1.108
diff -u -r1.108 music-iterator.cc
--- lily/music-iterator.cc	16 May 2006 11:30:54 -0000	1.108
+++ lily/music-iterator.cc	22 May 2006 05:45:00 -0000
@@ -153,6 +153,7 @@
 Music_iterator *
 Music_iterator::try_music (Music *m) const
 {
+#if 0
   bool b = get_outlet ()->try_music ((Music *)m); // ugh
   Music_iterator *it = b ? (Music_iterator *) this : 0;	// ugh
   if (!it)
@@ -164,6 +165,9 @@
      The function should also be renamed, and it should not return a value. */
     m->send_to_context (get_outlet ());
   return it;
+#endif
+  m->send_to_context (get_outlet ());
+  return (Music_iterator *)this;
 }
 
 Music_iterator *
Index: lily/output-property-engraver.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/output-property-engraver.cc,v
retrieving revision 1.53
diff -u -r1.53 output-property-engraver.cc
--- lily/output-property-engraver.cc	11 Feb 2006 11:35:17 -0000	1.53
+++ lily/output-property-engraver.cc	22 May 2006 05:45:00 -0000
@@ -31,8 +31,13 @@
 {
   if (m->is_mus_type ("layout-instruction"))
     {
-      props_.push_back (m);
-      return true;
+      // UGH. Only swallow the output property event in the context
+      // it was intended for. This is inelegant but not inefficient.
+      if (context ()->context_name_symbol () == m->get_property ("context-type"))
+        {
+          props_.push_back (m);
+          return true;
+        }
     }
   return false;
 }
Index: lily/output-property-music-iterator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/output-property-music-iterator.cc,v
retrieving revision 1.22
diff -u -r1.22 output-property-music-iterator.cc
--- lily/output-property-music-iterator.cc	26 Jan 2006 11:16:52 -0000	1.22
+++ lily/output-property-music-iterator.cc	22 May 2006 05:45:00 -0000
@@ -8,6 +8,8 @@
 
 #include "simple-music-iterator.hh"
 
+#include "context.hh"
+#include "dispatcher.hh"
 #include "input.hh"
 #include "international.hh"
 #include "music.hh"
@@ -26,10 +28,11 @@
 {
   if (last_processed_mom_ < Moment (0))
     {
-      bool accepted = try_music (get_music ());
-      if (!accepted)
-	get_music ()->origin ()->warning (_f ("junking event: `%s'",
-					      get_music ()->class_name ()));
+      // Send the event to a bottom context. The context-type property
+      // will later be used to apply the event in this context
+      get_music ()->set_property ("context-type",
+				  get_outlet ()->context_name_symbol ());
+      get_music ()->send_to_context (get_outlet ());
     }
   Simple_music_iterator::process (m);
 }
Index: lily/part-combine-iterator.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/part-combine-iterator.cc,v
retrieving revision 1.30
diff -u -r1.30 part-combine-iterator.cc
--- lily/part-combine-iterator.cc	11 Feb 2006 11:35:17 -0000	1.30
+++ lily/part-combine-iterator.cc	22 May 2006 05:45:00 -0000
@@ -7,11 +7,13 @@
 */
 
 #include "context.hh"
+#include "dispatcher.hh"
+#include "lily-guile.hh"
+#include "listener.hh"
 #include "music.hh"
+#include "music-iterator.hh"
 #include "music-sequence.hh"
-#include "lily-guile.hh"
 #include "warn.hh"
-#include "music-iterator.hh"
 
 class Part_combine_iterator : public Music_iterator
 {
@@ -34,6 +36,12 @@
   virtual bool ok () const;
 
 private:
+  /* used by try_process */
+  DECLARE_LISTENER (set_busy);
+  bool busy_;
+  
+  bool try_process (Music_iterator *i, Moment m);
+  
   Music_iterator *first_iter_;
   Music_iterator *second_iter_;
   Moment start_moment_;
@@ -77,8 +85,6 @@
   void unisono (bool silent);
 };
 
-static Music *busy_playing_event;
-
 void
 Part_combine_iterator::do_quit ()
 {
@@ -101,12 +107,6 @@
   split_list_ = SCM_EOL;
   state_ = APART;
   playing_state_ = APART;
-
-  if (!busy_playing_event)
-    {
-      busy_playing_event
-	= make_music_by_name (ly_symbol2scm ("BusyPlayingEvent"));
-    }
 }
 
 void
@@ -169,7 +169,7 @@
       mmrest->set_property ("duration", SCM_EOL);
     }
 
-  tg->try_music (mmrest);
+  mmrest->send_to_context (tg);
 }
 
 void
@@ -192,7 +192,7 @@
 	  if (!event)
 	    event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
 
-	  first_iter_->try_music_in_children (event);
+	  event->send_to_context (first_iter_->get_outlet ());
 	}
       playing_state_ = SOLO1;
     }
@@ -255,8 +255,9 @@
 	  if (!event)
 	    event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
 
-	  (last_playing_ == SOLO2 ? second_iter_ : first_iter_)
-	    ->try_music_in_children (event);
+	  Context *out = (last_playing_ == SOLO2 ? second_iter_ : first_iter_)
+	    ->get_outlet ();
+	  event->send_to_context (out);
 	  playing_state_ = UNISONO;
 	}
       state_ = newstate;
@@ -280,7 +281,7 @@
 	  if (!event)
 	    event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
 
-	  second_iter_->try_music_in_children (event);
+	  event->send_to_context (second_iter_->get_outlet ());
 	  playing_state_ = SOLO2;
 	}
     }
@@ -380,12 +381,45 @@
     }
 }
 
+IMPLEMENT_LISTENER (Part_combine_iterator, set_busy);
+void
+Part_combine_iterator::set_busy (SCM se)
+{
+  Stream_event *e = unsmob_stream_event (se);
+  SCM mus = e->get_property ("music");
+  Music *m = unsmob_music (mus);
+  assert (m);
+
+  if (m->is_mus_type ("note-event") || m->is_mus_type ("cluster-note-event"))
+    busy_ = true;
+}
+
+/*
+* Processes a moment in an iterator, and returns whether any new music was reported.
+*/
+bool
+Part_combine_iterator::try_process (Music_iterator *i, Moment m)
+{
+  Dispatcher *disp = i->get_outlet ()->event_source ();
+  
+  disp->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent"));
+  busy_ = false;
+  
+  i->process (m);
+  
+  disp->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("MusicEvent"));
+  return busy_;
+}
+
 void
 Part_combine_iterator::process (Moment m)
 {
   Moment now = get_outlet ()->now_mom ();
   Moment *splitm = 0;
 
+  if (start_moment_.main_part_.is_infinity () && start_moment_ < 0)
+    start_moment_ = now;
+
   for (; scm_is_pair (split_list_); split_list_ = scm_cdr (split_list_))
     {
       splitm = unsmob_moment (scm_caar (split_list_));
@@ -418,15 +452,13 @@
 
   if (first_iter_->ok ())
     {
-      first_iter_->process (m);
-      if (first_iter_->try_music_in_children (busy_playing_event))
-	last_playing_ = SOLO1;
+      if (try_process (first_iter_, m))
+        last_playing_ = SOLO1;
     }
 
   if (second_iter_->ok ())
     {
-      second_iter_->process (m);
-      if (second_iter_->try_music_in_children (busy_playing_event))
+      if (try_process (second_iter_, m))
 	last_playing_ = SOLO2;
     }
 }
Index: lily/translator-group.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/translator-group.cc,v
retrieving revision 1.152
diff -u -r1.152 translator-group.cc
--- lily/translator-group.cc	11 Feb 2006 11:35:17 -0000	1.152
+++ lily/translator-group.cc	22 May 2006 05:45:00 -0000
@@ -3,18 +3,21 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 1997--2006 Han-Wen Nienhuys <[EMAIL PROTECTED]>
+  (c) 1997--2006 Han-Wen Nienhuys <[EMAIL PROTECTED]>,
+                 Erik Sandberg <[EMAIL PROTECTED]>
 */
 
 #include "translator-group.hh"
 
-#include "output-def.hh"
-#include "warn.hh"
-#include "scm-hash.hh"
 #include "context-def.hh"
 #include "context.hh"
+#include "dispatcher.hh"
 #include "main.hh"
 #include "music.hh"
+#include "output-def.hh"
+#include "scm-hash.hh"
+#include "stream-event.hh"
+#include "warn.hh"
 
 Translator_group *
 Translator_group::get_daddy_translator () const
@@ -36,6 +39,16 @@
 }
 
 void
+Translator_group::connect_to_context (Context *c)
+{
+  if (context_)
+    programming_error ("already connected to a context");
+  context_ = c;
+  c->event_source ()->add_listener (GET_LISTENER (eat_event), ly_symbol2scm ("MusicEvent"));
+//   c->event_source ()->add_listener (GET_LISTENER (create_child), ly_symbol2scm ("CreateContext"));
+}
+
+void
 Translator_group::finalize ()
 {
 }
@@ -67,6 +80,20 @@
   return l;
 }
 
+IMPLEMENT_LISTENER (Translator_group, eat_event);
+void
+Translator_group::eat_event (SCM sev)
+{
+  Stream_event *ev = unsmob_stream_event (sev);
+  SCM sm = ev->get_property ("music");
+  Music *m = unsmob_music (sm);
+/*
+  if (!try_music (m))
+    // TODO: this is for testing and will be removed
+    m->origin ()->warning ("Music not swallowed by engraver");
+*/
+}
+
 bool
 Translator_group::try_music (Music *m)
 {
Index: lily/include/chord-tremolo-iterator.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/chord-tremolo-iterator.hh,v
retrieving revision 1.20
diff -u -r1.20 chord-tremolo-iterator.hh
--- lily/include/chord-tremolo-iterator.hh	6 Jan 2006 09:13:24 -0000	1.20
+++ lily/include/chord-tremolo-iterator.hh	22 May 2006 05:45:00 -0000
@@ -9,8 +9,24 @@
 #ifndef CHORD_TREMOLO_ITERATOR_HH
 #define CHORD_TREMOLO_ITERATOR_HH
 
-#include "music-iterator.hh"
+#include "sequential-iterator.hh"
 
+class Chord_tremolo_iterator : public Sequential_iterator
+{
+public:
+  DECLARE_SCHEME_CALLBACK (constructor, ());
+  /* construction */
+  DECLARE_CLASSNAME(Chord_tremolo_iterator);
+  Chord_tremolo_iterator ();
+protected:
+  virtual SCM get_music_list () const;
+  virtual void derived_mark () const;
+  virtual void construct_children ();
+private:
+  SCM child_list_;
+};
+
+#if 0
 class Chord_tremolo_iterator : public Music_iterator
 {
 public:
@@ -32,6 +48,7 @@
   Moment factor_;
   Music_iterator *child_iter_;
 };
+#endif
 
 #endif /* CHORD_TREMOLO_ITERATOR_HH */
 
Index: lily/include/translator-group.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/translator-group.hh,v
retrieving revision 1.81
diff -u -r1.81 translator-group.hh
--- lily/include/translator-group.hh	11 Feb 2006 11:35:16 -0000	1.81
+++ lily/include/translator-group.hh	22 May 2006 05:45:00 -0000
@@ -9,6 +9,7 @@
 #ifndef TRANSLATOR_GROUP_HH
 #define TRANSLATOR_GROUP_HH
 
+#include "listener.hh"
 #include "translator.hh"
 #include "std-vector.hh"
 
@@ -46,11 +47,14 @@
   Translator_group_void_method
   precomputed_self_method_bindings_[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
 
+  DECLARE_LISTENER (eat_event);
+
 public:
   VIRTUAL_COPY_CONSTRUCTOR (Translator_group, Translator_group);
   DECLARE_SMOBS (Translator_group, dummy);
 
 public:
+  void connect_to_context (Context *c);
   virtual Translator_group *get_daddy_translator ()const;
   virtual SCM get_simple_trans_list ();
   virtual bool try_music (Music *req);
Index: ly/music-functions-init.ly
===================================================================
RCS file: /sources/lilypond/lilypond/ly/music-functions-init.ly,v
retrieving revision 1.58
diff -u -r1.58 music-functions-init.ly
--- ly/music-functions-init.ly	17 May 2006 15:21:49 -0000	1.58
+++ ly/music-functions-init.ly	22 May 2006 05:45:00 -0000
@@ -140,8 +140,7 @@
 		    (if (equal?
 			 (cdr (assoc 'name (ly:grob-property grob 'meta)))
 			 grob-name)
-			(set! (ly:grob-property grob property) value)
-			)))
+			(set! (ly:grob-property grob property) value))))
 
       context-name)))
 
Index: scm/define-music-properties.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/define-music-properties.scm,v
retrieving revision 1.52
diff -u -r1.52 define-music-properties.scm
--- scm/define-music-properties.scm	17 May 2006 15:21:49 -0000	1.52
+++ scm/define-music-properties.scm	22 May 2006 05:45:00 -0000
@@ -50,6 +50,7 @@
      (error-found ,boolean? "If true, a parsing error was found in this expression")
      (element ,ly:music? "The single child of a Music_wrapper music object, or the body of a repeat.")
      (elements ,ly:music-list? "A list of elements for sequential of simultaneous music, or the alternatives of repeated music. ")
+     (expected-beaming ,integer? "Expected number of non-tremolo beams in a tremolo repeat")
      (force-accidental ,boolean? "If set, a cautionary accidental should always be printed on this note")
      (grob-property ,symbol? "The symbol of the grob property to set. ")
      (grob-property-path ,list? "A list of symbols, locating a nested grob property, e.g. (beamed-lengths details). ")
@@ -100,7 +101,7 @@
      (text ,markup? "markup expression to be printed")
      (tempo-unit ,ly:duration? "The unit for the metronome count.")
      (tonic ,ly:pitch? "Base of the scale")
-     (tremolo-type ,integer? "")
+     (tremolo-type ,integer? "speed of tremolo, e.g. 16 for c4:16")
      (trill-pitch ,ly:pitch? "Pitch of other note of the trill.")
      (type ,symbol? "The type of this music object. Determines iteration in some cases.")
      (types ,list? "The types of this music object; determines by what
Index: scm/define-music-types.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/define-music-types.scm,v
retrieving revision 1.79
diff -u -r1.79 define-music-types.scm
--- scm/define-music-types.scm	16 May 2006 11:19:50 -0000	1.79
+++ scm/define-music-types.scm	22 May 2006 05:45:00 -0000
@@ -37,7 +37,7 @@
 
 ")
 	(iterator-ctor . ,ly:output-property-music-iterator::constructor)
-	(types . (general-music layout-instruction))
+	(types . (general-music event layout-instruction))
 	))
     (ArpeggioEvent 
      . (
@@ -340,7 +340,7 @@
 = @var{val}}.")
 
 	(iterator-ctor . ,ly:output-property-music-iterator::constructor)
-	(types . (general-music layout-instruction))
+	(types . (general-music event layout-instruction))
 	))
     
     (OverrideProperty
@@ -674,6 +674,12 @@
 	(types . (general-music event tremolo-event))
 	))
     
+    (TremoloSpanEvent
+     . (
+	(description . "Tremolo over two stems")
+	(types . (general-music event span-event tremolo-span-event))
+	))
+
     (VoiceSeparator
      . (
 	(description .	"Separate polyphonic voices in simultaneous music. 
Index: scm/music-functions.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/music-functions.scm,v
retrieving revision 1.169
diff -u -r1.169 music-functions.scm
--- scm/music-functions.scm	16 May 2006 11:19:50 -0000	1.169
+++ scm/music-functions.scm	22 May 2006 05:45:00 -0000
@@ -374,6 +374,12 @@
   (make-music 'EventChord
 	      'elements elts))
 
+(define-safe-public (chordify-event . ev)
+  "Wraps music events inside an EventChord"
+  (make-music 'EventChord
+  	      'elements ev
+  	      'origin (ly:music-property (car ev) 'origin)))
+
 (define-public (make-skip-music dur)
   (make-music 'SkipMusic
 	      'duration dur))
? build-stamp
? context-unique.diff
? def-rel-music-funciton.diff
? delay-music-functions.diff
? exjobb.diff3
? fonts
? lib
? lilypond.kdevelop
? lilypond.kdevelop.pcs
? lilypond.kdevses
? optimized
? os
? re
? ref1.diff
? ref2.diff
? repeat.diff
? scons.cache
? string
? sys
? Documentation/out
? Documentation/out-www
? Documentation/bibliography/out
? Documentation/bibliography/out-www
? Documentation/misc/out
? Documentation/misc/out-www
? Documentation/pictures/out
? Documentation/pictures/out-www
? Documentation/topdocs/out
? Documentation/topdocs/out-www
? Documentation/user/out
? Documentation/user/out-www
? buildscripts/out
? buildscripts/out-www
? cygwin/out
? cygwin/out-www
? debian/out
? elisp/out
? elisp/out-www
? flower/out
? flower/out-scons
? flower/out-www
? flower/include/.sconsign
? flower/include/out
? flower/include/out-www
? input/Diagram1.dia.autosave
? input/les-nereides.pdf
? input/les-nereides.ps
? input/out
? input/out-www
? input/mutopia/out
? input/mutopia/out-www
? input/mutopia/E.Satie/out
? input/mutopia/E.Satie/out-www
? input/mutopia/F.Schubert/out
? input/mutopia/F.Schubert/out-www
? input/mutopia/J.S.Bach/out
? input/mutopia/J.S.Bach/out-www
? input/mutopia/R.Schumann/out
? input/mutopia/R.Schumann/out-www
? input/mutopia/W.A.Mozart/out
? input/mutopia/W.A.Mozart/out-www
? input/no-notation/out
? input/no-notation/out-www
? input/no-notation/parse-expressions.facit
? input/no-notation/parse-expressions.ly
? input/no-notation/parse-expressions.pdf
? input/no-notation/parse-expressions.ps
? input/no-notation/to-xml.pdf
? input/no-notation/to-xml.ps
? input/regression/chord-tremolo.pdf
? input/regression/chord-tremolo.ps
? input/regression/lyric-melisma-manual.pdf
? input/regression/lyric-melisma-manual.ps
? input/regression/lyrics-melisma-beam.pdf
? input/regression/lyrics-melisma-beam.ps
? input/regression/out
? input/regression/out-www
? input/regression/tuplet-nest.pdf
? input/regression/tuplet-nest.ps
? input/template/out
? input/test/out
? input/test/out-www
? input/tutorial/out
? input/tutorial/out-www
? kpath-guile/out
? kpath-guile/out-scons
? lily/On
? lily/foo.pdf
? lily/foo.ps
? lily/lilypond
? lily/lilypond.gdt
? lily/lilypond.gpr
? lily/out
? lily/out-scons
? lily/out-www
? lily/parser.yy.ok
? lily/include/.sconsign
? lily/include/out
? lily/include/out-www
? ly/out
? ly/out-www
? make/out
? make/out-www
? mf/feta-alphabet11.600pk
? mf/feta-alphabet13.600pk
? mf/feta-alphabet14.600pk
? mf/feta-alphabet16.600pk
? mf/feta-alphabet18.600pk
? mf/feta-alphabet20.600pk
? mf/feta-alphabet23.600pk
? mf/feta-alphabet26.600pk
? mf/feta-braces-a.600pk
? mf/feta-braces-b.600pk
? mf/feta-braces-c.600pk
? mf/feta-braces-d.600pk
? mf/feta-braces-e.600pk
? mf/feta-braces-f.600pk
? mf/feta-braces-g.600pk
? mf/feta-braces-h.600pk
? mf/feta-braces-i.600pk
? mf/feta11.600pk
? mf/feta13.600pk
? mf/feta14.600pk
? mf/feta16.600pk
? mf/feta18.600pk
? mf/feta20.600pk
? mf/feta23.600pk
? mf/feta26.600pk
? mf/out
? mf/out-scons
? mf/out-www
? mf/parmesan11.600pk
? mf/parmesan13.600pk
? mf/parmesan14.600pk
? mf/parmesan16.600pk
? mf/parmesan18.600pk
? mf/parmesan20.600pk
? mf/parmesan23.600pk
? mf/parmesan26.600pk
? po/out
? po/out-www
? ps/out
? ps/out-www
? python/convertrules.pyc
? python/fontextract.pyc
? python/lilylib.pyc
? python/out
? python/out-www
? scm/out
? scm/out-www
? scripts/lilypond-book-36.py
? scripts/lilypond-book.py.new
? scripts/out
? scripts/out-www
? stepmake/out
? stepmake/out-www
? stepmake/bin/out
? stepmake/bin/out-www
? stepmake/bin/packagepython.pyc
? stepmake/stepmake/out
? stepmake/stepmake/out-www
? tex/out
? tex/out-www
? ttftool/out
? ttftool/out-scons
? ttftool/include/.sconsign
? ttftool/include/out
? vim/out
? vim/out-www
Index: lily/lily-lexer.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/lily-lexer.cc,v
retrieving revision 1.46
diff -u -r1.46 lily-lexer.cc
--- lily/lily-lexer.cc	11 Feb 2006 11:35:17 -0000	1.46
+++ lily/lily-lexer.cc	22 May 2006 05:45:09 -0000
@@ -56,7 +56,6 @@
   {"new", NEWCONTEXT},
   {"notemode", NOTEMODE},
   {"objectid", OBJECTID},
-  {"once", ONCE},
   {"override", OVERRIDE},
   {"paper", PAPER},
   {"partial", PARTIAL},
Index: lily/parser.yy
===================================================================
RCS file: /sources/lilypond/lilypond/lily/parser.yy,v
retrieving revision 1.515
diff -u -r1.515 parser.yy
--- lily/parser.yy	19 May 2006 06:43:36 -0000	1.515
+++ lily/parser.yy	22 May 2006 05:45:09 -0000
@@ -115,8 +115,11 @@
 - Don't use lily module, create a new module instead.
 - delay application of the function
 */
+#define LOWLEVEL_MAKE_SYNTAX(proc, args)	\
+  scm_apply_0 (proc, args)
+/* Syntactic Sugar. */
 #define MAKE_SYNTAX(name, location, ...)	\
-  scm_apply_0 (ly_lily_module_constant (name), scm_list_n (make_input (location), __VA_ARGS__, SCM_UNDEFINED));
+  LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant (name), scm_list_n (make_input (location), __VA_ARGS__, SCM_UNDEFINED));
 
 Music *property_op_to_music (SCM op);
 SCM context_spec_music (SCM type, SCM id, SCM m, SCM ops, bool create_new);
@@ -135,7 +138,7 @@
 
 SCM make_lyric_combine_music (SCM name, SCM music);
 SCM make_music_relative (Pitch start, SCM music);
-Music *run_music_function (Lily_parser *, SCM expr);
+SCM run_music_function (Lily_parser *, SCM expr);
 Music *set_property_music (SCM sym, SCM value);
 SCM get_first_context_id (SCM type, Music *m);
 SCM make_chord (SCM pitch, SCM dur, SCM modification_list);
@@ -191,7 +194,6 @@
 %token NOTEMODE "\\notemode"
 %token OBJECTID "\\objectid"	
 %token OCTAVE "\\octave"
-%token ONCE "\\once"
 %token OVERRIDE "\\override"
 %token PAPER "\\paper"
 %token PARTIAL "\\partial"
@@ -989,13 +991,13 @@
 
 Prefix_composite_music:
 	Generic_prefix_music_scm {
-		$$ = run_music_function (THIS, $1)->unprotect ();
+		$$ = run_music_function (THIS, $1);
 	}
 	| CONTEXT    simple_string optional_id optional_context_mod Music {
-		$$ = context_spec_music ($2, $3, $5, $4, false);
+		$$ = MAKE_SYNTAX ("context-specification", @$, $2, $3, $5, $4, SCM_BOOL_F);
 	}
 	| NEWCONTEXT simple_string optional_id optional_context_mod Music {
-		$$ = context_spec_music ($2, $3, $5, $4, true);
+		$$ = MAKE_SYNTAX ("context-specification", @$, $2, $3, $5, $4, SCM_BOOL_T);
 	}
 
 	| TIMES fraction Music 	
@@ -1037,7 +1039,7 @@
 		THIS->lexer_->pop_state ();
 	}
 	| mode_changing_head_with_context optional_context_mod Grouped_music_list {
-		$$ = context_spec_music ($1, SCM_UNDEFINED, $3, $2, true);
+		$$ = MAKE_SYNTAX ("context-specification", @$, $1, SCM_EOL, $3, $2, SCM_BOOL_T);
 		if ($1 == ly_symbol2scm ("ChordNames"))
 		{
 		  Music *chm = MY_MAKE_MUSIC ("UnrelativableMusic");
@@ -1247,18 +1249,19 @@
 
 music_property_def:
 	OVERRIDE context_prop_spec embedded_scm '=' scalar {
+		/* TODO: do this properly */
 		Music *m = property_op_to_music (scm_list_4 (
 			ly_symbol2scm ("push"),
 			scm_cadr ($2),
 			$5, $3));
-		$$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, m->unprotect (), SCM_EOL, false);
+		$$ = MAKE_SYNTAX ("context-specification", @$, scm_car ($2), SCM_EOL, m->unprotect (), SCM_EOL, SCM_BOOL_F);
 	}
 	| OVERRIDE context_prop_spec embedded_scm  embedded_scm '=' scalar {
 		Music *m = property_op_to_music (scm_list_5 (
 			ly_symbol2scm ("push"),
 			scm_cadr ($2),
 			$6, $4, $3));
-		$$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, m->unprotect (), SCM_EOL, false);
+		$$ = MAKE_SYNTAX ("context-specification", @$, scm_car ($2), SCM_EOL, m->unprotect (), SCM_EOL, SCM_BOOL_F);
 	}
 	| REVERT context_prop_spec embedded_scm {
 		Music *m = property_op_to_music (scm_list_3 (
@@ -1266,26 +1269,20 @@
 			scm_cadr ($2),
 			$3));
 
-		$$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, m->unprotect (), SCM_EOL, false);
+		$$ = MAKE_SYNTAX ("context-specification", @$, scm_car ($2), SCM_EOL, m->unprotect (), SCM_EOL, SCM_BOOL_F);
 	}
 	| SET context_prop_spec '=' scalar {
 		Music *m = property_op_to_music (scm_list_3 (
 			ly_symbol2scm ("assign"),
 			scm_cadr ($2),
 			$4));
-		$$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, m->unprotect (), SCM_EOL, false);
+		$$ = MAKE_SYNTAX ("context-specification", @$, scm_car ($2), SCM_EOL, m->unprotect (), SCM_EOL, SCM_BOOL_F);
 	}
 	| UNSET context_prop_spec {
 		Music *m = property_op_to_music (scm_list_2 (
 			ly_symbol2scm ("unset"),
 			scm_cadr ($2)));
-		$$ = context_spec_music (scm_car ($2), SCM_UNDEFINED, m->unprotect (), SCM_EOL, false);
-	}
-	| ONCE music_property_def {
-		Music *m = unsmob_music ($2);
-		SCM e = m->get_property ("element");
-                unsmob_music (e)->set_property ("once", SCM_BOOL_T);
-		$$ = $2;
+		$$ = MAKE_SYNTAX ("context-specification", @$, scm_car ($2), SCM_EOL, m->unprotect (), SCM_EOL, SCM_BOOL_F);
 	}
 	;
 
@@ -1465,9 +1462,7 @@
 		$$ = n->unprotect ();
 	}
 	| music_function_chord_body { 
-		Music *m = run_music_function (THIS, $1);
-		m->set_spot (@$);
-		$$ = m->unprotect ();
+		$$ = run_music_function (THIS, $1);
 	}
 	;
 
@@ -1641,9 +1636,7 @@
 		$$ = $1;
 	}
 	| '-' music_function_event {
-		Music *mus = run_music_function (THIS, $2);
-		mus->set_spot (@1);
-		$$ = mus->unprotect ();
+		$$ = run_music_function (THIS, $2);
 	}
 	| HYPHEN {
 		if (!THIS->lexer_->is_lyric_state ())
@@ -2587,6 +2580,7 @@
 	return m;
 }
 
+/* TODO: Remove this function? */
 SCM
 context_spec_music (SCM type, SCM id, SCM m, SCM ops, bool create_new)
 {
@@ -2622,7 +2616,7 @@
 }
 
 
-Music *
+SCM
 run_music_function (Lily_parser *parser, SCM expr)
 {
 	SCM func = scm_car (expr);
@@ -2631,34 +2625,14 @@
 	SCM sig = scm_object_property (func, ly_symbol2scm ("music-function-signature"));
 
 	SCM type_check_proc = ly_lily_module_constant ("type-check-list");
-	bool ok  = true;
 
 	if (!to_boolean (scm_call_3  (type_check_proc, scm_cadr (expr), sig, args)))
 	{
 		parser->error_level_ = 1;
-		ok = false;
+		return MAKE_SYNTAX ("void-music", *loc, SCM_UNDEFINED);
 	}
 
-	SCM m = SCM_EOL;
-	if (ok)
-		m = scm_apply_0 (func, scm_cons (parser->self_scm(),
-						 scm_cdr (expr)));
-
-
-	Music* retval = 0;
-	if (unsmob_music (m))
-		{
-		retval = unsmob_music (m);
-		retval->protect ();
-		}
-	else
-		{
-		if (ok)
-			loc->error (_ ("music head function must return Music object")); 
-		retval = MY_MAKE_MUSIC ("Music");
-		}
-	retval->set_spot (*loc);
-	return retval;
+	return MAKE_SYNTAX ("music-function", *loc, func, parser->self_scm(), args);
 }
 
 bool
Index: ly/music-functions-init.ly
===================================================================
RCS file: /sources/lilypond/lilypond/ly/music-functions-init.ly,v
retrieving revision 1.58
diff -u -r1.58 music-functions-init.ly
--- ly/music-functions-init.ly	17 May 2006 15:21:49 -0000	1.58
+++ ly/music-functions-init.ly	22 May 2006 05:45:09 -0000
@@ -112,6 +112,16 @@
                   'origin location
                   'procedure proc))
 
+% TODO: Should this be a music macro?
+once =
+#(define-music-function (parser location csm) (ly:music?)
+   (let ((set-expr (ly:music-property csm 'element)))
+     (if (or (not (music-is-of-type? csm 'context-specification))
+	     (not (music-is-of-type? set-expr 'layout-instruction)))
+	 (ly:warning (_ "\\once only makes sense on \\set, \\unset, \\override or \\revert expressions")))
+     (set! (ly:music-property set-expr 'once) #t)
+     csm))
+
 overrideProperty =
 #(define-music-function (parser location name property value)
    (string? symbol? scheme?)
Index: scm/ly-syntax-constructors.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/ly-syntax-constructors.scm,v
retrieving revision 1.1
diff -u -r1.1 ly-syntax-constructors.scm
--- scm/ly-syntax-constructors.scm	19 May 2006 11:07:35 -0000	1.1
+++ scm/ly-syntax-constructors.scm	22 May 2006 05:45:10 -0000
@@ -7,14 +7,29 @@
 ;; TODO: use separate module for parser.
 (define define-ly-syntax define-public)
 
-;; This shorthand adds a location parameter, and uses it to set the
-;; origin. It can be used for most music functions.
+;; Syntactic sugar which adds a location parameter, and uses it to set
+;; the origin. It can be used for most music functions.
 (defmacro define-ly-syntax-loc (args . body)
   (primitive-eval `(define-ly-syntax ,(cons* (car args) 'location (cdr args))
 		     (let ((m ((lambda ,(cdr args) . ,body) . ,(cdr args))))
 		       (set! (ly:music-property m 'origin) location)
 		       m))))
 
+;; Music function: Apply function and check return value.
+(define-ly-syntax (music-function loc fun parser args)
+  (let ((m (apply fun (cons* parser loc args))))
+    (if (ly:music? m)
+	(begin
+	  (set! (ly:music-property m 'origin) loc)
+	  m)
+	(begin
+	  (ly:error _ ("Music head function must return Music object"))
+	  (make-music "Music"
+		      'origin loc)))))
+
+(define-ly-syntax-loc (void-music)
+  (make-music 'Music))
+
 (define-ly-syntax-loc (sequential-music mlist)
   (make-sequential-music mlist))
 
@@ -23,3 +38,10 @@
 
 (define-ly-syntax-loc (repeat type num body alts)
   (make-repeat type num body alts))
+
+(define-ly-syntax-loc (context-specification type id mus ops create-new?)
+  (let* ((type-sym (if (symbol? type) type (string->symbol type)))
+	 (csm (context-spec-music mus type-sym id)))
+    (set! (ly:music-property csm 'property-operations) ops)
+    (if create-new? set! (ly:music-property csm 'create-new #t))
+    csm))
Index: scm/music-functions.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/music-functions.scm,v
retrieving revision 1.169
diff -u -r1.169 music-functions.scm
--- scm/music-functions.scm	16 May 2006 11:19:50 -0000	1.169
+++ scm/music-functions.scm	22 May 2006 05:45:10 -0000
@@ -16,6 +16,9 @@
   (make-procedure-with-setter ly:music-property
 			      ly:music-set-property!))
 
+(define-safe-public (music-is-of-type? mus type)
+  "Does @code{mus} belong to the music class @code{type}?"
+  (memq type (ly:music-property mus 'types)))
 
 ;; TODO move this
 (define-public ly:grob-property
@@ -196,8 +199,6 @@
 	  (set! (ly:music-property music 'duration) nd)))
     music))
 
-
-
 (define-public (shift-duration-log music shift dot)
   (music-map (lambda (x) (shift-one-duration-log x shift dot))
 	     music))
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to