]> git.donarmstrong.com Git - lilypond.git/blob - lily/global-context.cc
release commit
[lilypond.git] / lily / global-context.cc
1 /*
2   global-context.cc -- implement Global_context
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "global-context.hh"
10
11 #include <cstdio>
12 using namespace std;
13
14 #include "warn.hh"
15 #include "music.hh"
16 #include "music-iterator.hh"
17 #include "score-context.hh"
18 #include "context-def.hh"
19 #include "output-def.hh"
20 #include "lilypond-key.hh"
21
22 Global_context::Global_context (Output_def *o, Moment final, Object_key *key)
23   : Context (new Lilypond_context_key (key,
24                                        Moment (0),
25                                        "Global", "", 0))
26 {
27   output_def_ = o;
28   final_mom_ = final;
29   definition_ = find_context_def (o, ly_symbol2scm ("Global"));
30
31   Context_def *globaldef = unsmob_context_def (definition_);
32   if (!globaldef)
33     programming_error ("no `Global' context found");
34   else
35     globaldef->apply_default_property_operations (this);
36   accepts_list_ = scm_list_1 (ly_symbol2scm ("Score"));
37 }
38
39 Output_def *
40 Global_context::get_output_def () const
41 {
42   return output_def_;
43 }
44
45 void
46 Global_context::add_moment_to_process (Moment m)
47 {
48   if (m > final_mom_)
49     return;
50
51   if (m < now_mom_)
52     programming_error ("trying to freeze in time");
53
54   for (int i = 0; i < extra_mom_pq_.size (); i++)
55     if (extra_mom_pq_[i] == m)
56       return;
57   extra_mom_pq_.insert (m);
58 }
59
60 Moment
61 Global_context::sneaky_insert_extra_moment (Moment w)
62 {
63   while (extra_mom_pq_.size () && extra_mom_pq_.front () <= w)
64     w = extra_mom_pq_.get ();
65   return w;
66 }
67
68 int
69 Global_context::get_moments_left () const
70 {
71   return extra_mom_pq_.size ();
72 }
73
74 void
75 Global_context::prepare (Moment m)
76 {
77   prev_mom_ = now_mom_;
78   now_mom_ = m;
79
80   clear_key_disambiguations ();
81   if (get_score_context ())
82     get_score_context ()->prepare (m);
83 }
84
85 Moment
86 Global_context::now_mom () const
87 {
88   return now_mom_;
89 }
90
91 Score_context *
92 Global_context::get_score_context () const
93 {
94   return (scm_is_pair (context_list_))
95     ? dynamic_cast<Score_context *> (unsmob_context (scm_car (context_list_)))
96     : 0;
97 }
98
99 SCM
100 Global_context::get_output ()
101 {
102   return get_score_context ()->get_output ();
103 }
104
105 void
106 Global_context::one_time_step ()
107 {
108   get_score_context ()->one_time_step ();
109   apply_finalizations ();
110   check_removal ();
111 }
112
113 void
114 Global_context::finish ()
115 {
116   if (get_score_context ())
117     get_score_context ()->finish ();
118 }
119
120 void
121 Global_context::run_iterator_on_me (Music_iterator *iter)
122 {
123   if (iter->ok ())
124     prev_mom_ = now_mom_ = iter->pending_moment ();
125
126   bool first = true;
127   while (iter->ok () || get_moments_left ())
128     {
129       Moment w;
130       w.set_infinite (1);
131       if (iter->ok ())
132         w = iter->pending_moment ();
133
134       w = sneaky_insert_extra_moment (w);
135       if (w.main_part_.is_infinity ())
136         break;
137
138       if (first)
139         {
140           /*
141             Need this to get grace notes at start of a piece correct.
142           */
143           first = false;
144           set_property ("measurePosition", w.smobbed_copy ());
145         }
146
147       prepare (w);
148
149       if (iter->ok ())
150         iter->process (w);
151
152       if (!get_score_context ())
153         {
154           SCM sym = ly_symbol2scm ("Score");
155           Context_def *t = unsmob_context_def (find_context_def (get_output_def (),
156                                                                  sym));
157           if (!t)
158             error (_f ("can't find `%s' context", "Score"));
159
160           Object_key const *key = get_context_key ("Score", "");
161           Context *c = t->instantiate (SCM_EOL, key);
162           add_context (c);
163
164           Score_context *sc = dynamic_cast<Score_context *> (c);
165           sc->prepare (w);
166         }
167
168       one_time_step ();
169     }
170 }
171
172 void
173 Global_context::apply_finalizations ()
174 {
175   SCM lst = get_property ("finalizations");
176   set_property ("finalizations", SCM_EOL);
177   for (SCM s = lst; scm_is_pair (s); s = scm_cdr (s))
178
179     /* TODO: make safe.  */
180     scm_primitive_eval (scm_car (s));
181 }
182
183 /* Add a function to execute before stepping to the next time step.  */
184 void
185 Global_context::add_finalization (SCM x)
186 {
187   SCM lst = get_property ("finalizations");
188   lst = scm_cons (x, lst);
189   set_property ("finalizations", lst);
190 }
191
192 Moment
193 Global_context::previous_moment () const
194 {
195   return prev_mom_;
196 }
197
198 Context *
199 Global_context::get_default_interpreter ()
200 {
201   if (get_score_context ())
202     return get_score_context ()->get_default_interpreter ();
203   else
204     return Context::get_default_interpreter ();
205 }