]> git.donarmstrong.com Git - lilypond.git/blob - lily/new-part-combine-iterator.cc
* lily/include/music-iterator.hh (class Music_iterator): add
[lilypond.git] / lily / new-part-combine-iterator.cc
1 /*   
2   part-combine-music-iterator.cc -- implement  New_pc_iterator
3
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000--2003 Jan Nieuwenhuizen <janneke@gnu.org>
7  */
8
9 #include "part-combine-music-iterator.hh"
10 #include "translator-group.hh"
11 #include "event.hh"
12 #include "music-sequence.hh"
13 #include "lily-guile.hh"
14 #include "warn.hh"
15 #include "music-iterator.hh"
16 #include "interpretation-context-handle.hh"
17
18 class New_pc_iterator : public Music_iterator
19 {
20 public:
21   VIRTUAL_COPY_CONS (Music_iterator);
22   New_pc_iterator ();
23
24   DECLARE_SCHEME_CALLBACK(constructor, ()); 
25 protected:
26   virtual void derived_substitute (Translator_group*f, Translator_group*t) ;
27   virtual void derived_mark () const;
28   New_pc_iterator (New_pc_iterator const &);
29
30   virtual void construct_children ();
31   virtual Moment pending_moment () const;
32   virtual void do_quit(); 
33   virtual void process (Moment);
34
35   virtual SCM get_pending_events (Moment)const;
36   virtual Music_iterator *try_music_in_children (Music *) const;
37
38   virtual bool ok () const;
39
40 private:
41   Music_iterator * first_iter_;
42   Music_iterator * second_iter_;
43   bool is_shared_ ;
44   SCM split_list_;
45
46   Interpretation_context_handle one_;
47   Interpretation_context_handle two_;
48   Interpretation_context_handle shared_;
49
50   void together ();
51   void apart ();
52 };
53
54
55 New_pc_iterator::New_pc_iterator ()
56 {
57   is_shared_  =false;
58   first_iter_ = 0;
59   second_iter_ = 0;
60   split_list_ = SCM_EOL;
61 }
62
63 void
64 New_pc_iterator::derived_mark () const
65 {
66   if (first_iter_)
67     scm_gc_mark (first_iter_->self_scm());
68   if (second_iter_)
69     scm_gc_mark(second_iter_->self_scm());
70 }
71
72 void
73 New_pc_iterator::derived_substitute (Translator_group*f,
74                                                  Translator_group*t)
75 {
76   if (first_iter_)
77     first_iter_->substitute_outlet (f,t);
78   if (second_iter_)
79     second_iter_->substitute_outlet (f,t);
80 }
81
82 void
83 New_pc_iterator::do_quit ()
84 {
85   if (first_iter_)
86     first_iter_->quit();
87   if (second_iter_)
88     second_iter_->quit();
89
90   one_ .set_translator (0);
91   two_.set_translator (0);
92   shared_.set_translator (0);
93 }
94
95 New_pc_iterator::New_pc_iterator (New_pc_iterator const &src)
96   : Music_iterator (src)
97 {
98   first_iter_ = 0;
99   second_iter_ = 0;
100
101   if(src.first_iter_)
102     first_iter_ = src.first_iter_->clone ();
103   if (src.second_iter_)
104     second_iter_ = src.second_iter_->clone ();
105
106   split_list_ = src.split_list_;
107   
108   if (first_iter_)
109     scm_gc_unprotect_object (first_iter_->self_scm());
110   if (second_iter_)
111     scm_gc_unprotect_object (second_iter_->self_scm());
112 }
113
114 Moment
115 New_pc_iterator::pending_moment () const
116 {
117   Moment p;
118   p.set_infinite (1);
119   if (first_iter_->ok ())
120     p = p <? first_iter_->pending_moment ();
121
122   if (second_iter_->ok ())
123     p = p <? second_iter_->pending_moment ();
124   return p;
125 }
126
127 bool
128 New_pc_iterator::ok () const
129 {
130   return first_iter_->ok () || second_iter_->ok ();
131 }
132
133 void
134 New_pc_iterator::together ()
135 {
136   first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
137   second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
138 }
139
140 void
141 New_pc_iterator::apart ()
142 {
143   first_iter_->substitute_outlet (shared_.report_to (),one_.report_to ());
144   second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ());
145 }
146
147
148 void
149 New_pc_iterator::construct_children ()
150 {
151   split_list_ =  get_music ()->get_mus_property ("split-list");
152   SCM lst =  get_music ()->get_mus_property ("elements");
153
154   Translator_group *tr
155     =  report_to ()->find_create_translator (ly_symbol2scm ("Voice"),
156                                              "shared", SCM_EOL);
157
158   tr->execute_pushpop_property (ly_symbol2scm ("NoteHead"),
159                                 ly_symbol2scm ("font-size"), gh_int2scm (3));
160
161   
162   shared_ .set_translator (tr); 
163   set_translator (tr);
164
165   Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
166                                                       "one", SCM_EOL);
167
168   one_.set_translator (one);
169   one->execute_pushpop_property (ly_symbol2scm ("Stem"),
170                                  ly_symbol2scm ("direction"), gh_int2scm (1));
171
172   set_translator (one);
173   first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst))));
174
175
176   Translator_group *two = tr->find_create_translator (ly_symbol2scm ("Voice"),
177                                                       "two", SCM_EOL);
178   two_.set_translator (two);
179   two_.report_to ()->execute_pushpop_property (ly_symbol2scm ("Stem"),
180                                   ly_symbol2scm ("direction"), gh_int2scm (-1));
181   set_translator (two);
182   second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst))));
183
184
185   set_translator (tr);
186 }
187
188 void
189 New_pc_iterator::process (Moment m)
190 {
191   Moment now = report_to ()->now_mom ();
192   Moment *splitm = 0;
193   
194   for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_))
195     {
196       splitm = unsmob_moment (gh_caar (split_list_));
197       if (*splitm > now)
198         break ;
199
200       if (gh_cdar (split_list_) == ly_symbol2scm ("together"))
201         together ();
202       else if (gh_cdar (split_list_) == ly_symbol2scm ("apart"))
203         apart ();
204       else
205         programming_error ("Unknown split directive.");
206     }
207   
208   if (first_iter_->ok ())
209     first_iter_->process (m);
210   
211   if (second_iter_->ok ())
212     second_iter_->process (m);
213 }
214
215 Music_iterator*
216 New_pc_iterator::try_music_in_children (Music *m) const
217 {
218   Music_iterator * i =  first_iter_->try_music (m);
219   if (i)
220     return i;
221   else
222     return second_iter_->try_music (m);
223 }
224
225
226 SCM
227 New_pc_iterator::get_pending_events (Moment m)const
228 {
229   SCM s = SCM_EOL;
230   if (first_iter_)
231     s = gh_append2 (s,first_iter_->get_pending_events (m));
232   if (second_iter_)
233     s = gh_append2 (second_iter_->get_pending_events (m),s);
234   return s;
235 }
236
237 IMPLEMENT_CTOR_CALLBACK (New_pc_iterator);