]> git.donarmstrong.com Git - lilypond.git/blob - lily/global-context.cc
Revert "Issue 4550 (2/2) Avoid "using namespace std;" in included files"
[lilypond.git] / lily / global-context.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "global-context.hh"
21
22 #include <cstdio>
23 using namespace std;
24
25 #include "context-def.hh"
26 #include "dispatcher.hh"
27 #include "international.hh"
28 #include "music-iterator.hh"
29 #include "music.hh"
30 #include "output-def.hh"
31 #include "warn.hh"
32
33 using std::string;
34
35 Global_context::Global_context (Output_def *o)
36   : Context ()
37 {
38   output_def_ = o;
39   definition_ = find_context_def (o, ly_symbol2scm ("Global"));
40
41   now_mom_.set_infinite (-1);
42   prev_mom_.set_infinite (-1);
43
44   /* We only need the most basic stuff to bootstrap the context tree */
45   event_source ()->add_listener (GET_LISTENER (Context, create_context_from_event),
46                                  ly_symbol2scm ("CreateContext"));
47   event_source ()->add_listener (GET_LISTENER (Global_context, prepare),
48                                  ly_symbol2scm ("Prepare"));
49   events_below ()->register_as_listener (event_source_);
50
51   Context_def *globaldef = unsmob<Context_def> (definition_);
52   if (!globaldef)
53     programming_error ("no `Global' context found");
54   else
55     globaldef->apply_default_property_operations (this);
56
57   default_child_ = ly_symbol2scm ("Score");
58   accepts_list_ = scm_list_1 (default_child_);
59 }
60
61 Output_def *
62 Global_context::get_output_def () const
63 {
64   return output_def_;
65 }
66
67 void
68 Global_context::add_moment_to_process (Moment m)
69 {
70   if (m < now_mom_)
71     programming_error ("trying to freeze in time");
72
73   for (vsize i = 0; i < extra_mom_pq_.size (); i++)
74     if (extra_mom_pq_[i] == m)
75       return;
76   extra_mom_pq_.insert (m);
77 }
78
79 Moment
80 Global_context::sneaky_insert_extra_moment (Moment w)
81 {
82   while (extra_mom_pq_.size () && extra_mom_pq_.front () <= w)
83     w = extra_mom_pq_.get ();
84   return w;
85 }
86
87 int
88 Global_context::get_moments_left () const
89 {
90   return extra_mom_pq_.size ();
91 }
92
93 void
94 Global_context::prepare (SCM sev)
95 {
96   Stream_event *ev = unsmob<Stream_event> (sev);
97   Moment *mom = unsmob<Moment> (ev->get_property ("moment"));
98
99   assert (mom);
100
101   if (prev_mom_.main_part_.is_infinity () && prev_mom_ < 0)
102     prev_mom_ = *mom;
103   else
104     prev_mom_ = now_mom_;
105   now_mom_ = *mom;
106 }
107
108 Moment
109 Global_context::now_mom () const
110 {
111   return now_mom_;
112 }
113
114 Context *
115 Global_context::get_score_context () const
116 {
117   return (scm_is_pair (context_list_))
118          ? unsmob<Context> (scm_car (context_list_))
119          : 0;
120 }
121
122 SCM
123 Global_context::get_output ()
124 {
125   Context *c = get_score_context ();
126   if (c)
127     return c->get_property ("output");
128   else
129     return SCM_EOL;
130 }
131
132 void
133 Global_context::run_iterator_on_me (Music_iterator *iter)
134 {
135   prev_mom_.set_infinite (-1);
136   now_mom_.set_infinite (-1);
137   Moment final_mom = iter->get_music ()->get_length ();
138
139   bool first = true;
140   while (iter->ok () || get_moments_left ())
141     {
142       Moment w;
143       w.set_infinite (1);
144       if (iter->ok ())
145         w = iter->pending_moment ();
146
147       w = sneaky_insert_extra_moment (w);
148       if (w.main_part_.is_infinity () || w > final_mom)
149         break;
150
151       if (w == prev_mom_)
152         {
153           programming_error ("Moment is not increasing."
154                              "  Aborting interpretation.");
155           break;
156         }
157
158       if (first)
159         {
160           /*
161             Need this to get grace notes at start of a piece correct.
162           */
163           first = false;
164           set_property ("measurePosition", w.smobbed_copy ());
165         }
166
167       send_stream_event (this, "Prepare", 0,
168                          ly_symbol2scm ("moment"), w.smobbed_copy ());
169
170       if (iter->ok ())
171         iter->process (w);
172
173       send_stream_event (this, "OneTimeStep", 0, 0);
174       apply_finalizations ();
175       check_removal ();
176     }
177 }
178
179 void
180 Global_context::apply_finalizations ()
181 {
182   SCM lst = get_property ("finalizations");
183   set_property ("finalizations", SCM_EOL);
184   for (SCM s = lst; scm_is_pair (s); s = scm_cdr (s))
185     scm_apply_0 (scm_caar (s), scm_cdar (s));
186 }
187
188 /* Add a function to execute before stepping to the next time step.  */
189 void
190 Global_context::add_finalization (SCM x)
191 {
192   SCM lst = get_property ("finalizations");
193   lst = scm_cons (x, lst);
194   set_property ("finalizations", lst);
195 }
196
197 Moment
198 Global_context::previous_moment () const
199 {
200   return prev_mom_;
201 }
202
203 Context *
204 Global_context::get_default_interpreter (const string &/* context_id */)
205 {
206   if (get_score_context ())
207     return get_score_context ()->get_default_interpreter ();
208   else
209     return Context::get_default_interpreter ();
210 }