]> git.donarmstrong.com Git - lilypond.git/blob - lily/quote-iterator.cc
* lily/include/lily-guile.hh: many new ly_ functions. Thanks to
[lilypond.git] / lily / quote-iterator.cc
1 /*   
2   quote-iterator.cc --  implement Quote_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
8 */
9
10 #include "context.hh"
11 #include "event.hh"
12 #include "music-sequence.hh"
13 #include "lily-guile.hh"
14 #include "music-iterator.hh"
15 #include "music.hh"
16 #include "input.hh"
17 #include "warn.hh"
18
19
20 class Quote_iterator : public Music_iterator
21 {
22 public:
23   Quote_iterator ();
24   
25   Moment start_moment_;
26   SCM event_vector_;
27   int event_idx_;
28   int end_idx_ ;
29
30   SCM transposed_musics_;
31   
32   DECLARE_SCHEME_CALLBACK (constructor, ()); 
33
34 protected:
35   virtual void derived_mark ();
36   virtual void construct_children ();
37   virtual Moment pending_moment () const;
38   virtual void process (Moment);
39   virtual bool ok () const;
40 };
41
42 void
43 Quote_iterator::derived_mark ()
44 {
45   scm_gc_mark (transposed_musics_ );
46 }
47
48 Quote_iterator::Quote_iterator ()
49 {
50   event_vector_ = SCM_EOL;
51   event_idx_ = 0;
52   end_idx_ = 0;
53 }
54
55 bool
56 moment_less (SCM a, SCM b)
57 {
58   return  *unsmob_moment (a) < *unsmob_moment (b);
59 }
60
61
62 int
63 binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
64 {
65   int lo;
66   int hi;
67   lo = 0;
68   hi = SCM_VECTOR_LENGTH (vec);
69
70   /* binary search */
71   do
72   {
73     int cmp = (lo + hi) / 2;
74
75       SCM when = ly_caar (SCM_VECTOR_REF (vec, cmp));
76       bool result =  (*is_less) (key, when);
77       if (result)
78           hi = cmp;
79       else
80           lo = cmp;
81     }
82   while (hi - lo > 1);
83
84   return lo;
85 }
86
87
88 void
89 Quote_iterator::construct_children ()
90 {
91   SCM dur = get_music ()->get_property ("duration");
92   if (!unsmob_duration (dur))
93     return ;
94
95   set_translator (get_outlet ()->get_default_interpreter ());
96   
97   Moment now = get_outlet ()->now_mom ();
98   Moment stop = now + unsmob_duration (dur)->get_length ();
99
100   start_moment_ = now;
101   event_vector_ = get_music ()->get_property ("quoted-events");
102
103   if (ly_vector_p (event_vector_))
104     {
105       event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
106       end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
107     }
108 }
109
110
111 bool
112 Quote_iterator::ok () const
113 {
114   return (event_idx_ <= end_idx_);
115 }
116
117
118 Moment
119 Quote_iterator::pending_moment () const
120 {
121   SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
122   return *unsmob_moment (ly_caar (entry)) - start_moment_;
123 }
124
125
126 void
127 Quote_iterator::process (Moment m)
128 {
129   SCM entry = SCM_EOL;
130
131   m += start_moment_;
132   while (event_idx_ < end_idx_)
133     {
134       entry = SCM_VECTOR_REF (event_vector_, event_idx_);
135
136       Moment em = *unsmob_moment (ly_caar (entry));
137
138       if (em > m)
139         return ;
140
141       if (em == m)
142         break ;
143
144       event_idx_++;
145     }
146
147   if (ly_pair_p (entry))
148     {
149       Pitch * quote_pitch = unsmob_pitch (ly_cdar (entry));
150       Pitch * me_pitch = unsmob_pitch (get_outlet ()->get_property ("instrumentTransposition"));
151       
152       for (SCM s = ly_cdr (entry); ly_pair_p (s); s = ly_cdr (s))
153         {
154           SCM ev_acc = ly_car (s);
155
156
157           Music * mus = unsmob_music (ly_car (ev_acc));
158           if (mus)
159             {
160               if (quote_pitch || me_pitch)
161                 {
162                   Pitch qp, mp;
163                   if (quote_pitch)
164                     qp = *quote_pitch;
165                   if (me_pitch)
166                     mp = *me_pitch;
167
168                   Pitch diff = interval (mp, qp);
169
170                   SCM copy = ly_deep_mus_copy (mus->self_scm ());
171                   mus = unsmob_music (copy);
172                   transposed_musics_ = scm_cons (copy, transposed_musics_);
173                   
174                   mus->transpose (diff);
175                 }
176
177               
178               bool b = get_outlet ()->try_music (mus);
179       
180               if (!b)
181                 mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name ()));
182             }
183           else
184             programming_error ("need music in quote.");
185         }
186     }
187   event_idx_ ++; 
188 }
189
190 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);