2 music.cc -- implement Music
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "input-smob.hh"
12 #include "music-list.hh"
15 #include "ly-smobs.icc"
18 ly_deep_mus_copy (SCM m)
22 SCM ss = unsmob_music (m)->clone ()->self_scm ();
23 scm_gc_unprotect_object (ss);
26 else if (gh_pair_p (m))
28 return gh_cons (ly_deep_mus_copy (ly_car (m)), ly_deep_mus_copy (ly_cdr (m)));
38 Music::add_music_type (SCM sym)
40 assert (gh_symbol_p (sym));
42 SCM types= get_mus_property ("types");
43 types = scm_cons (sym, types);
44 set_mus_property ("types", types);
48 Music::is_music_type (SCM k)const
50 SCM ifs = get_mus_property ("types");
52 return scm_memq (k, ifs) != SCM_BOOL_F;
55 Music::Music (Music const &m)
57 immutable_property_alist_ = m.immutable_property_alist_;
58 mutable_property_alist_ = SCM_EOL;
62 First we smobify_self, then we copy over the stuff. If we don't,
63 stack vars that hold the copy might be optimized away, meaning
64 that they won't be protected from GC.
67 mutable_property_alist_ = ly_deep_mus_copy (m.mutable_property_alist_);
68 set_spot (*m.origin ());
70 add_music_type (ly_symbol2scm ("general-music"));
78 immutable_property_alist_ = SCM_EOL;
79 mutable_property_alist_ = SCM_EOL;
85 Music::mark_smob (SCM m)
87 Music * mus = (Music *)SCM_CELL_WORD_1 (m);
88 scm_gc_mark (mus->immutable_property_alist_);
89 scm_gc_mark (mus->mutable_property_alist_);
94 Music::compress (Moment)
101 Music::length_mom () const
103 SCM l = get_mus_property ("length");
104 if (unsmob_moment (l))
105 return *unsmob_moment (l);
106 else if (gh_procedure_p (l))
108 SCM res = gh_call1 (l, self_scm ());
109 return *unsmob_moment (res);
116 Music::start_mom () const
118 SCM l = get_mus_property ("start-moment-function");
119 if (gh_procedure_p (l))
121 SCM res = gh_call1 (l, self_scm ());
122 return *unsmob_moment (res);
130 print_alist (SCM a, SCM port)
133 SCM_EOL -> catch malformed lists.
135 for (SCM s = a; gh_pair_p (s); s = ly_cdr (s))
137 scm_display (ly_caar (s), port);
138 scm_puts (" = ", port);
139 scm_write (ly_cdar (s), port);
140 scm_puts ("\n", port);
145 Music::print_smob (SCM s, SCM p, scm_print_state*)
147 scm_puts ("#<Music ", p);
148 Music* m = unsmob_music (s);
149 scm_puts (classname (m),p);
151 print_alist (m->mutable_property_alist_, p);
152 print_alist (m->immutable_property_alist_, p);
159 Music::to_relative_octave (Pitch m)
166 Music::transpose (Pitch delta)
168 Pitch *p = unsmob_pitch (get_mus_property ("pitch"));
173 np.transpose (delta);
175 if (abs (np.alteration_) > 2)
177 warning (_f ("Transposition by %s makes accidental larger than two",
181 set_mus_property ("pitch", np.smobbed_copy ());
184 IMPLEMENT_TYPE_P (Music, "music?");
186 IMPLEMENT_SMOBS (Music);
187 IMPLEMENT_DEFAULT_EQUAL_P (Music);
189 /****************************/
192 Music::internal_get_mus_property (SCM sym) const
194 SCM s = scm_sloppy_assq (sym, mutable_property_alist_);
198 s = scm_sloppy_assq (sym, immutable_property_alist_);
199 return (s == SCM_BOOL_F) ? SCM_EOL : ly_cdr (s);
203 Music::internal_set_mus_property (SCM s, SCM v)
205 if (internal_type_checking_global_b)
206 if (!type_check_assignment (s, v, ly_symbol2scm ("music-type?")))
209 mutable_property_alist_ = scm_assq_set_x (mutable_property_alist_, s, v);
217 Music::set_spot (Input ip)
219 set_mus_property ("origin", make_input (ip));
223 Music::origin () const
225 Input *ip = unsmob_input (get_mus_property ("origin"));
226 return ip ? ip : & dummy_input_global;
235 LY_DEFINE(ly_get_mus_property,
236 "ly-get-mus-property", 2, 0, 0, (SCM mus, SCM sym),
237 "Get the property @var{sym} of music expression @var{mus}.")
239 Music * sc = unsmob_music (mus);
240 SCM_ASSERT_TYPE(sc, mus, SCM_ARG1, __FUNCTION__, "music");
241 SCM_ASSERT_TYPE(gh_symbol_p (sym), sym, SCM_ARG2, __FUNCTION__, "symbol");
243 return sc->internal_get_mus_property (sym);
246 LY_DEFINE(ly_set_mus_property,
247 "ly-set-mus-property!", 3, 0, 0,
248 (SCM mus, SCM sym, SCM val),
249 "Set property @var{sym} in music expression @var{mus} to @var{val}.")
251 Music * sc = unsmob_music (mus);
252 SCM_ASSERT_TYPE(sc, mus, SCM_ARG1, __FUNCTION__, "music");
253 SCM_ASSERT_TYPE(gh_symbol_p (sym), sym, SCM_ARG2, __FUNCTION__, "symbol");
255 bool ok = type_check_assignment (sym, val, ly_symbol2scm ("music-type?"));
258 sc->internal_set_mus_property (sym, val);
261 return SCM_UNSPECIFIED;
265 LY_DEFINE(ly_music_name, "ly-music-name", 1, 0, 0,
267 "Return the name of @var{music}.")
269 Music * m = unsmob_music (mus);
270 SCM_ASSERT_TYPE(m, mus, SCM_ARG1, __FUNCTION__ ,"music");
272 const char * nm = classname (m);
273 return scm_makfrom0str (nm);
278 // to do property args
279 LY_DEFINE(ly_extended_make_music,
280 "ly-make-bare-music", 2, 0, 0, (SCM type, SCM props),
282 Make a music object/expression of type @var{type}, init with
283 @var{props}. Warning: this interface will likely change in the near
286 Music is the data type that music expressions are stored in. The data
287 type does not yet offer many manipulations.
289 WARNING: deprecated; use make-music-by-name.
292 SCM_ASSERT_TYPE(gh_string_p (type), type, SCM_ARG1, __FUNCTION__, "string");
294 SCM s = make_music (ly_scm2string (type))->self_scm ();
295 unsmob_music (s)->immutable_property_alist_ = props;
296 scm_gc_unprotect_object (s);
300 LY_DEFINE(ly_music_list_p,"music-list?", 1, 0, 0,
301 (SCM l),"Type predicate: return true if @var{l} is a list of music objects.")
303 if (scm_list_p (l) != SCM_BOOL_T)
306 while (gh_pair_p (l))
308 if (!unsmob_music (gh_car (l)))
321 make_music_by_name (SCM sym)
323 if (!make_music_proc)
324 make_music_proc = scm_primitive_eval (ly_symbol2scm ("make-music-by-name"));
326 SCM rv = scm_call_1 (make_music_proc, sym);
331 scm_gc_protect_object (rv);
332 return unsmob_music (rv);