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