]> git.donarmstrong.com Git - lilypond.git/blob - lily/quote-iterator.cc
(LY_DEFINE): use Scheme style naming for
[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 dur = get_music ()->get_property ("duration");
83   if (!unsmob_duration (dur))
84     return ;
85
86   set_translator (get_outlet ()->get_default_interpreter ());
87   
88   Moment now = get_outlet ()->now_mom ();
89   Moment stop = now + unsmob_duration (dur)->get_length ();
90
91   start_moment_ = now;
92   event_vector_ = get_music ()->get_property ("quoted-events");
93
94   if (scm_vector_p (event_vector_) == SCM_BOOL_T)
95     {
96       event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less);
97       end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less);
98     }
99 }
100
101
102 bool
103 Quote_iterator::ok () const
104 {
105   return (event_idx_ <= end_idx_);
106 }
107
108
109 Moment
110 Quote_iterator::pending_moment () const
111 {
112   SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_);
113   return *unsmob_moment (gh_car (entry)) - start_moment_;
114 }
115
116
117 void
118 Quote_iterator::process (Moment m)
119 {
120   SCM entry = SCM_EOL;
121
122   m += start_moment_;
123   while (event_idx_ < end_idx_)
124     {
125       entry = SCM_VECTOR_REF (event_vector_, event_idx_);
126
127       Moment em = *unsmob_moment (gh_car (entry));
128
129       if (em > m)
130         return ;
131
132       if (em == m)
133         break ;
134
135       event_idx_++;
136     }
137
138   if (gh_pair_p (entry))
139     {
140       for (SCM s = gh_cdr (entry); gh_pair_p (s); s = gh_cdr (s))
141         {
142           SCM ev_acc = gh_car (s);
143
144
145           Music * mus = unsmob_music (gh_car (ev_acc));
146           if (mus)
147             {
148               bool b = get_outlet ()->try_music (mus);
149       
150               if (!b)
151                 mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name()));
152             }
153           else
154             programming_error ("need music in quote.");
155         }
156     }
157   event_idx_ ++; 
158 }
159
160 IMPLEMENT_CTOR_CALLBACK (Quote_iterator);