(staff_eligible): new function.
[lilypond.git] / lily / music.cc
blob7e6fe2b14fec55a2e17421c447b61111727d6eed
1 /*
2 music.cc -- implement Music
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
9 #include "main.hh"
10 #include "input-smob.hh"
11 #include "music.hh"
12 #include "music-list.hh"
13 #include "warn.hh"
14 #include "pitch.hh"
15 #include "ly-smobs.icc"
18 SCM ly_deep_mus_copy (SCM);
20 bool
21 Music::internal_is_music_type (SCM k)const
23 SCM ifs = get_mus_property ("types");
25 return scm_memq (k, ifs) != SCM_BOOL_F;
28 String
29 Music::name () const
31 SCM nm = get_mus_property ("name");
32 if (gh_symbol_p (nm))
34 return ly_symbol2string (nm);
36 else
38 return classname (this);
44 Music::Music (Music const &m)
46 immutable_property_alist_ = m.immutable_property_alist_;
47 mutable_property_alist_ = SCM_EOL;
48 self_scm_ = SCM_EOL;
51 First we smobify_self, then we copy over the stuff. If we don't,
52 stack vars that hold the copy might be optimized away, meaning
53 that they won't be protected from GC.
55 smobify_self ();
56 mutable_property_alist_ = ly_deep_mus_copy (m.mutable_property_alist_);
57 set_spot (*m.origin ());
60 Music::Music ()
62 self_scm_ = SCM_EOL;
63 immutable_property_alist_ = SCM_EOL;
64 mutable_property_alist_ = SCM_EOL;
65 smobify_self ();
68 SCM
69 Music::get_property_alist (bool m) const
71 return (m) ? mutable_property_alist_ : immutable_property_alist_;
74 SCM
75 Music::mark_smob (SCM m)
77 Music * mus = (Music *)SCM_CELL_WORD_1 (m);
78 scm_gc_mark (mus->immutable_property_alist_);
79 scm_gc_mark (mus->mutable_property_alist_);
80 return SCM_EOL;
83 Moment
84 Music::get_length () const
86 SCM l = get_mus_property ("length");
87 if (unsmob_moment (l))
88 return *unsmob_moment (l);
89 else if (gh_procedure_p (l))
91 SCM res = gh_call1 (l, self_scm ());
92 return *unsmob_moment (res);
95 return 0;
98 Moment
99 Music::start_mom () const
101 SCM l = get_mus_property ("start-moment-function");
102 if (gh_procedure_p (l))
104 SCM res = gh_call1 (l, self_scm ());
105 return *unsmob_moment (res);
108 Moment m ;
109 return m;
112 void
113 print_alist (SCM a, SCM port)
116 SCM_EOL -> catch malformed lists.
118 for (SCM s = a; gh_pair_p (s); s = ly_cdr (s))
120 scm_display (ly_caar (s), port);
121 scm_puts (" = ", port);
122 scm_write (ly_cdar (s), port);
123 scm_puts ("\n", port);
128 Music::print_smob (SCM s, SCM p, scm_print_state*)
130 scm_puts ("#<Music ", p);
131 Music* m = unsmob_music (s);
133 SCM nm = m->get_mus_property ("name");
134 if (gh_symbol_p (nm) || gh_string_p (nm))
136 scm_display (nm, p);
138 else
140 scm_puts (classname (m),p);
144 Printing properties takes a lot of time, especially during backtraces.
145 For inspecting, it is better to explicitly use an inspection
146 function.
149 scm_puts (">",p);
150 return 1;
153 Pitch
154 Music::to_relative_octave (Pitch p)
156 SCM elt = get_mus_property ("element");
158 if (Music* m = unsmob_music (elt))
159 p = m->to_relative_octave (p);
161 p = music_list_to_relative (get_mus_property ("elements"),
162 p, false);
163 return p;
166 void
167 Music::compress (Moment factor)
169 SCM elt = get_mus_property ("element");
171 if (Music* m = unsmob_music (elt))
172 m->compress (factor);
174 compress_music_list (get_mus_property ("elements"), factor);
178 void
179 Music::transpose (Pitch delta)
181 SCM elt = get_mus_property ("element");
183 if (Music* m = unsmob_music (elt))
184 m->transpose (delta);
186 transpose_music_list (get_mus_property ("elements"), delta);
190 IMPLEMENT_TYPE_P (Music, "ly:music?");
192 IMPLEMENT_SMOBS (Music);
193 IMPLEMENT_DEFAULT_EQUAL_P (Music);
195 /****************************/
198 Music::internal_get_mus_property (SCM sym) const
200 SCM s = scm_sloppy_assq (sym, mutable_property_alist_);
201 if (s != SCM_BOOL_F)
202 return ly_cdr (s);
204 s = scm_sloppy_assq (sym, immutable_property_alist_);
205 return (s == SCM_BOOL_F) ? SCM_EOL : ly_cdr (s);
208 void
209 Music::internal_set_mus_property (SCM s, SCM v)
211 if (internal_type_checking_global_b)
212 if (!type_check_assignment (s, v, ly_symbol2scm ("music-type?")))
213 abort ();
215 mutable_property_alist_ = scm_assq_set_x (mutable_property_alist_, s, v);
220 #include "main.hh"
222 void
223 Music::set_spot (Input ip)
225 set_mus_property ("origin", make_input (ip));
228 Input*
229 Music::origin () const
231 Input *ip = unsmob_input (get_mus_property ("origin"));
232 return ip ? ip : & dummy_input_global;
236 Music::~Music ()
241 LY_DEFINE(ly_get_music_length,
242 "ly:get-music-length", 1, 0, 0, (SCM mus),
243 "Get the length (in musical time) of music expression @var{mus}.")
245 Music * sc = unsmob_music (mus);
246 SCM_ASSERT_TYPE(sc, mus, SCM_ARG1, __FUNCTION__, "music");
247 return sc->get_length().smobbed_copy();
250 LY_DEFINE(ly_get_mus_property,
251 "ly:get-mus-property", 2, 0, 0, (SCM mus, SCM sym),
252 "Get the property @var{sym} of music expression @var{mus}.\n"
253 "If @var{sym} is undefined, return @code{'()}.\n"
256 Music * sc = unsmob_music (mus);
257 SCM_ASSERT_TYPE(sc, mus, SCM_ARG1, __FUNCTION__, "music");
258 SCM_ASSERT_TYPE(gh_symbol_p (sym), sym, SCM_ARG2, __FUNCTION__, "symbol");
260 return sc->internal_get_mus_property (sym);
263 LY_DEFINE(ly_set_mus_property,
264 "ly:set-mus-property!", 3, 0, 0,
265 (SCM mus, SCM sym, SCM val),
266 "Set property @var{sym} in music expression @var{mus} to @var{val}.")
268 Music * sc = unsmob_music (mus);
269 SCM_ASSERT_TYPE(sc, mus, SCM_ARG1, __FUNCTION__, "music");
270 SCM_ASSERT_TYPE(gh_symbol_p (sym), sym, SCM_ARG2, __FUNCTION__, "symbol");
272 bool ok = type_check_assignment (sym, val, ly_symbol2scm ("music-type?"));
273 if (ok)
275 sc->internal_set_mus_property (sym, val);
278 return SCM_UNSPECIFIED;
282 LY_DEFINE(ly_music_name, "ly:music-name", 1, 0, 0,
283 (SCM mus),
284 "Return the name of @var{music}.")
286 Music * m = unsmob_music (mus);
287 SCM_ASSERT_TYPE(m, mus, SCM_ARG1, __FUNCTION__ ,"music");
289 const char * nm = classname (m);
290 return scm_makfrom0str (nm);
295 // to do property args
296 LY_DEFINE(ly_extended_make_music,
297 "ly:make-bare-music", 2, 0, 0, (SCM type, SCM props),
298 "Make a music object/expression of type @var{type}, init with\n"
299 "@var{props}. Warning: this interface will likely change in the near\n"
300 "future.\n"
301 "\n"
302 "Music is the data type that music expressions are stored in. The data\n"
303 "type does not yet offer many manipulations.\n"
304 "\n"
305 "WARNING: only for internal use. Please use make-music-by-name. \n"
308 SCM_ASSERT_TYPE(gh_string_p (type), type, SCM_ARG1, __FUNCTION__, "string");
310 SCM s = make_music (ly_scm2string (type))->self_scm ();
311 unsmob_music (s)->immutable_property_alist_ = props;
312 scm_gc_unprotect_object (s);
313 return s;
316 // to do property args
317 LY_DEFINE(ly_get_mutable_properties,
318 "ly:get-mutable-properties", 1, 0, 0, (SCM mus),
319 "Return an alist signifying the mutable properties of @var{mus}.\n"
320 "The immutable properties are not available; they should be initialized\n"
321 "by the functions make-music-by-name function.\n"
324 Music *m = unsmob_music (mus);
325 SCM_ASSERT_TYPE(m, mus, SCM_ARG1, __FUNCTION__, "music");
327 return m->get_property_alist (true);
330 LY_DEFINE(ly_music_list_p,"music-list?", 1, 0, 0,
331 (SCM l),"Type predicate: return true if @var{l} is a list of music objects.")
333 if (scm_list_p (l) != SCM_BOOL_T)
334 return SCM_BOOL_F;
336 while (gh_pair_p (l))
338 if (!unsmob_music (gh_car (l)))
339 return SCM_BOOL_F;
340 l =gh_cdr (l);
342 return SCM_BOOL_T;
344 ADD_MUSIC(Music);
348 LY_DEFINE(ly_deep_mus_copy,
349 "ly:music-deep-copy", 1,0,0, (SCM m),
350 "Copy @var{m} and all sub expressions of @var{m}")
352 if (unsmob_music (m))
354 SCM ss = unsmob_music (m)->clone ()->self_scm ();
355 scm_gc_unprotect_object (ss);
356 return ss;
358 else if (gh_pair_p (m))
360 return gh_cons (ly_deep_mus_copy (ly_car (m)), ly_deep_mus_copy (ly_cdr (m)));
362 else
363 return m;
366 LY_DEFINE(ly_music_transpose,
367 "ly:music-transpose", 2,0,0, (SCM m, SCM p),
368 "Transpose @var{m} such that central C is mapped to @var{p}. "
369 "Return @var{m}.")
371 Music * sc = unsmob_music (m);
372 Pitch * sp = unsmob_pitch (p);
373 SCM_ASSERT_TYPE(sc, m, SCM_ARG1, __FUNCTION__, "music");
374 SCM_ASSERT_TYPE(sp, p, SCM_ARG2, __FUNCTION__, "pitch");
376 sc->transpose (*sp);
377 return sc->self_scm(); // SCM_UNDEFINED ?
381 SCM make_music_proc;
384 Music*
385 make_music_by_name (SCM sym)
387 if (!make_music_proc)
388 make_music_proc = scm_primitive_eval (ly_symbol2scm ("make-music-by-name"));
390 SCM rv = scm_call_1 (make_music_proc, sym);
393 UGH.
395 scm_gc_protect_object (rv);
396 return unsmob_music (rv);