]> git.donarmstrong.com Git - lilypond.git/blob - lily/global-context.cc
40fe3a61cdb7a0b657398fc459bde7a7e6a87ed7
[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   return get_score_context ()->get_property ("output");
118 }
119
120 void
121 Global_context::run_iterator_on_me (Music_iterator *iter)
122 {
123   prev_mom_.set_infinite (-1);
124   now_mom_.set_infinite (-1);
125   Moment final_mom = iter->get_music ()->get_length ();
126
127   bool first = true;
128   while (iter->ok () || get_moments_left ())
129     {
130       Moment w;
131       w.set_infinite (1);
132       if (iter->ok ())
133         w = iter->pending_moment ();
134
135       w = sneaky_insert_extra_moment (w);
136       if (w.main_part_.is_infinity () || w > final_mom)
137         break;
138
139       if (first)
140         {
141           /*
142             Need this to get grace notes at start of a piece correct.
143           */
144           first = false;
145           set_property ("measurePosition", w.smobbed_copy ());
146         }
147
148       send_stream_event (this, "Prepare", 0,
149                          ly_symbol2scm ("moment"), w.smobbed_copy ());
150
151       if (iter->ok ())
152         iter->process (w);
153
154       send_stream_event (this, "OneTimeStep", 0, 0);
155       apply_finalizations ();
156       check_removal ();
157     }
158 }
159
160 void
161 Global_context::apply_finalizations ()
162 {
163   SCM lst = get_property ("finalizations");
164   set_property ("finalizations", SCM_EOL);
165   for (SCM s = lst; scm_is_pair (s); s = scm_cdr (s))
166
167     /* TODO: make safe.  */
168     scm_primitive_eval (scm_car (s));
169 }
170
171 /* Add a function to execute before stepping to the next time step.  */
172 void
173 Global_context::add_finalization (SCM x)
174 {
175   SCM lst = get_property ("finalizations");
176   lst = scm_cons (x, lst);
177   set_property ("finalizations", lst);
178 }
179
180 Moment
181 Global_context::previous_moment () const
182 {
183   return prev_mom_;
184 }
185
186 Context *
187 Global_context::get_default_interpreter ()
188 {
189   if (get_score_context ())
190     return get_score_context ()->get_default_interpreter ();
191   else
192     return Context::get_default_interpreter ();
193 }