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