]> git.donarmstrong.com Git - lilypond.git/blob - lily/quote-iterator.cc
* lily/sequential-iterator.cc (process): only process if moment >= 0.
[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   DECLARE_SCHEME_CALLBACK(constructor, ()); 
31
32 protected:
33   virtual void construct_children ();
34   virtual Moment pending_moment () const;
35   virtual void process (Moment);
36   virtual bool ok () const;
37 };
38
39 Quote_iterator::Quote_iterator ()
40 {
41   event_vector_ = SCM_EOL;
42   event_idx_ = 0;
43   end_idx_ = 0;
44 }
45
46 bool
47 moment_less (SCM a, SCM b)
48 {
49   return  *unsmob_moment (a) < *unsmob_moment (b);
50 }
51
52
53 int
54 binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b))
55 {
56   int lo;
57   int hi;
58   lo = 0;
59   hi = SCM_VECTOR_LENGTH (vec);
60
61   /* binary search */
62   do
63   {
64     int cmp = (lo + hi) / 2;
65
66       SCM when = gh_car (SCM_VECTOR_REF(vec, cmp));
67       bool result =  (*is_less) (key, when);
68       if (result)
69           hi = cmp;
70       else
71           lo = cmp;
72     }
73   while (hi - lo > 1);
74
75   return lo;
76 }
77
78
79 void
80 Quote_iterator::construct_children ()
81 {
82   SCM tab = get_outlet()->get_property ("quotes");
83   if (scm_hash_table_p (tab) != SCM_BOOL_T)
84     {
85       get_music ()->origin ()->warning ("Context property `quotes' unset; cannot process quote.");
86       return ;
87     }
88
89   SCM name = get_music ()->get_mus_property ("quoted-name");
90   SCM dur = get_music ()->get_mus_property ("duration");
91
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   
102   event_vector_ = scm_hash_ref (tab, name, SCM_BOOL_F);
103
104   if (scm_vector_p (event_vector_) == SCM_BOOL_T)
105     {
106       event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
107       end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
108     }
109   else
110     get_music ()->origin ()->warning ("Can't find requested source");
111 }
112
113
114 bool
115 Quote_iterator::ok () const
116 {
117   return (event_idx_ <  end_idx_);
118 }
119
120
121 Moment
122 Quote_iterator::pending_moment () const
123 {
124   SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
125   return *unsmob_moment (gh_car (entry)) - start_moment_;
126 }
127
128
129 void
130 Quote_iterator::process (Moment m)
131 {
132   SCM entry = SCM_EOL;
133
134   m += start_moment_;
135   while (event_idx_ < end_idx_)
136     {
137       entry = SCM_VECTOR_REF (event_vector_, event_idx_);
138
139       Moment em = *unsmob_moment (gh_car (entry));
140
141       if (em > m)
142         return ;
143
144       if (em == m)
145         break ;
146
147       event_idx_++;
148     }
149
150   if (!gh_pair_p (entry))
151     return;
152   
153   for (SCM s = gh_cdr (entry); gh_pair_p (s); s = gh_cdr (s))
154     {
155       SCM ev_acc = gh_car (s);
156
157
158       Music * mus = unsmob_music (gh_car (ev_acc));
159       if (mus)
160         {
161           bool b = get_outlet ()->try_music (mus);
162       
163           if (!b)
164             mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name()));
165         }
166       else
167         programming_error ("need music in quote.");
168     }
169
170   event_idx_ ++; 
171 }
172
173 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);