X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmusic-scheme.cc;h=de5442e9664d0fa71d3d387d8a42e70b49ebc373;hb=b872748c6aa8bb721ced458691b38ac2fac5dfc8;hp=1e08ba26ef0d42956f5a6975c83857d9df2f9794;hpb=e9a308e9c6002900fc336733950a0175bcbcc333;p=lilypond.git diff --git a/lily/music-scheme.cc b/lily/music-scheme.cc index 1e08ba26ef..de5442e966 100644 --- a/lily/music-scheme.cc +++ b/lily/music-scheme.cc @@ -1,120 +1,184 @@ /* - music-scheme.cc -- implement Music bindings + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2005--2015 Han-Wen Nienhuys - (c) 2005--2007 Han-Wen Nienhuys + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include "music.hh" #include "duration.hh" +#include "input.hh" +#include "lily-imports.hh" +#include "program-option.hh" #include "warn.hh" LY_DEFINE (ly_music_length, "ly:music-length", - 1, 0, 0, (SCM mus), - "Get the length of music expression @var{mus}, and return as a @code{Moment} object.") + 1, 0, 0, (SCM mus), + "Get the length of music expression @var{mus} and return" + " it as a @code{Moment} object.") { - LY_ASSERT_TYPE (unsmob_music, mus, 1); - Music *sc = unsmob_music (mus); + LY_ASSERT_SMOB (Music, mus, 1); + Music *sc = unsmob (mus); return sc->get_length ().smobbed_copy (); } -LY_DEFINE (ly_music_property, - "ly:music-property", 2, 1, 0, (SCM mus, SCM sym, SCM dfault), - "Get the property @var{sym} of music expression @var{mus}.\n" - "If @var{sym} is undefined, return @code{'()}.\n") +LY_DEFINE (ly_music_property, "ly:music-property", + 2, 1, 0, (SCM mus, SCM sym, SCM val), + "Return the value for property @var{sym} of music expression" + " @var{mus}. If no value is found, return @var{val} or" + " @code{'()} if @var{val} is not specified.") { - LY_ASSERT_TYPE (unsmob_music, mus, 1); - return ly_prob_property (mus,sym,dfault); + LY_ASSERT_SMOB (Music, mus, 1); + return ly_prob_property (mus, sym, val); } LY_DEFINE (ly_music_set_property_x, "ly:music-set-property!", - 3, 0, 0, (SCM mus, SCM sym, SCM val), - "Set property @var{sym} in music expression @var{mus} to @var{val}.") + 3, 0, 0, (SCM mus, SCM sym, SCM val), + "Set property @var{sym} in music expression @var{mus} to" + " @var{val}.") { - LY_ASSERT_TYPE (unsmob_music, mus, 1); + LY_ASSERT_SMOB (Music, mus, 1); return ly_prob_set_property_x (mus, sym, val); } - /* todo: property args */ LY_DEFINE (ly_make_music, "ly:make-music", - 1, 0, 0, (SCM props), - "Make a C++ Music object, initialize with\n" - "@var{props}. \n\n" - "" - "This function is for internal use, and is only called by " - "@code{make-music}, which is the preferred interface " - "for creating music objects. ") + 1, 0, 0, (SCM props), + "Make a C++ @code{Music} object and initialize it with" + " @var{props}.\n" + "\n" + "This function is for internal use and is only called by" + " @code{make-music}, which is the preferred interface" + " for creating music objects.") { Music *ms = new Music (props); return ms->unprotect (); } LY_DEFINE (ly_music_p, "ly:music?", - 1, 0, 0, (SCM obj), - "Type predicate") + 1, 0, 0, (SCM obj), + "Is @var{obj} a music object?") { - return scm_from_bool (unsmob_music (obj)); + return ly_bool2scm (unsmob (obj)); +} + +LY_DEFINE (ly_event_p, "ly:event?", + 1, 0, 0, (SCM obj), + "Is @var{obj} a proper (non-rhythmic) event object?") +{ + if (Music *m = unsmob (obj)) + { + return scm_from_bool (m->is_mus_type ("post-event")); + } + return SCM_BOOL_F; } /* todo: property args */ LY_DEFINE (ly_music_mutable_properties, "ly:music-mutable-properties", - 1, 0, 0, (SCM mus), - "Return an alist containing the mutable properties of @var{mus}.\n" - "The immutable properties are not available, since " - "they are constant and initialized by the " - "@code{make-music} function.\n") -{ - LY_ASSERT_TYPE (unsmob_music, mus, 1); - Music *m = unsmob_music (mus); + 1, 0, 0, (SCM mus), + "Return an alist containing the mutable properties of @var{mus}." + " The immutable properties are not available, since they are" + " constant and initialized by the @code{make-music} function.") +{ + LY_ASSERT_SMOB (Music, mus, 1); + Music *m = unsmob (mus); return m->get_property_alist (true); } LY_DEFINE (ly_music_list_p, "ly:music-list?", - 1, 0, 0, (SCM lst), - "Type predicate: return true if @var{lst} is a list " - "of music objects.") -{ - if (scm_list_p (lst) == SCM_BOOL_T) - while (scm_is_pair (lst)) - { - if (!unsmob_music (scm_car (lst))) - return SCM_BOOL_F; - lst = scm_cdr (lst); - } + 1, 0, 0, (SCM lst), + "Is @var{lst} a list of music objects?") +{ + if (!ly_is_list (lst)) + return SCM_BOOL_F; + + while (scm_is_pair (lst)) + { + if (!unsmob (scm_car (lst))) + return SCM_BOOL_F; + lst = scm_cdr (lst); + } return SCM_BOOL_T; } LY_DEFINE (ly_music_deep_copy, "ly:music-deep-copy", - 1, 0, 0, (SCM m), - "Copy @var{m} and all sub expressions of @var{m}") + 1, 1, 0, (SCM m, SCM origin), + "Copy @var{m} and all sub expressions of@tie{}@var{m}." + " @var{m} may be an arbitrary type; cons cells and music" + " are copied recursively. If @var{origin} is given," + " it is used as the origin for one level of music by calling" + " @code{ly:set-origin!} on the copy.") { - SCM copy = m; - if (unsmob_music (m)) - { - Music *mcopy = unsmob_music (m)->clone (); - copy = mcopy->unprotect (); - } - else if (scm_is_pair (m)) - copy = scm_cons (ly_music_deep_copy (scm_car (m)), - ly_music_deep_copy (scm_cdr (m))); - return copy; + m = music_deep_copy (m); + + if (SCM_UNBNDP (origin)) + return m; + + if (Music *mus = unsmob (origin)) + origin = mus->get_property ("origin"); + + if (scm_is_false (origin) || scm_is_null (origin)) + return m; + + LY_ASSERT_SMOB (Input, origin, 2); + + set_origin (m, origin); + return m; +} + +LY_DEFINE (ly_set_origin_x, "ly:set-origin!", + 1, 1, 0, (SCM m, SCM origin), + "This sets the origin given in @var{origin} to @var{m}. " + " @var{m} will typically be a music expression or a list" + " of music. List structures are searched recursively," + " but recursion stops at the changed music expressions" + " themselves. " + " @var{origin} is generally of type @code{ly:input-location?}," + " defaulting to @code{(*location*)}. Other valid values for" + " @code{origin} are a music expression which is then used as" + " the source of location information, or @code{#f}" + " or @code{'()} in which case no action is performed. " + " The return value is @var{m} itself.") +{ + if (SCM_UNBNDP (origin)) + origin = scm_fluid_ref (Lily::f_location); + else if (Music *mus = unsmob (origin)) + origin = mus->get_property ("origin"); + + if (scm_is_false (origin) || scm_is_null (origin)) + return m; + + LY_ASSERT_SMOB (Input, origin, 2); + + set_origin (m, origin); + return m; } LY_DEFINE (ly_music_transpose, "ly:music-transpose", - 2, 0, 0, (SCM m, SCM p), - "Transpose @var{m} such that central C is mapped to @var{p}. " - "Return @var{m}.") + 2, 0, 0, (SCM m, SCM p), + "Transpose @var{m} such that central@tie{}C is mapped" + " to@tie{}@var{p}. Return@tie{}@var{m}.") { - LY_ASSERT_TYPE (unsmob_music, m, 1); + LY_ASSERT_SMOB (Music, m, 1); LY_ASSERT_SMOB (Pitch, p, 2); - Music *sc = unsmob_music (m); - Pitch *sp = unsmob_pitch (p); + Music *sc = unsmob (m); + Pitch *sp = unsmob (p); sc->transpose (*sp); // SCM_UNDEFINED ? @@ -125,25 +189,41 @@ LY_DEFINE (ly_music_transpose, "ly:music-transpose", TODO: should take moment factor? */ LY_DEFINE (ly_music_compress, "ly:music-compress", - 2, 0, 0, (SCM m, SCM factor), - "Compress music object @var{m} by moment @var{factor}.") + 2, 0, 0, (SCM m, SCM factor), + "Compress music object@tie{}@var{m} by moment @var{factor}.") { - LY_ASSERT_TYPE (unsmob_music, m, 1); - LY_ASSERT_TYPE(unsmob_moment,factor, 2); + LY_ASSERT_SMOB (Music, m, 1); + LY_ASSERT_SMOB (Moment, factor, 2); - Music *sc = unsmob_music (m); - sc->compress (*unsmob_moment (factor)); + Music *sc = unsmob (m); + sc->compress (*unsmob (factor)); return sc->self_scm (); } +LY_DEFINE (ly_make_music_relative_x, "ly:make-music-relative!", + 2, 0, 0, (SCM music, SCM pitch), + "Make @var{music} relative to @var{pitch}," + " return final pitch.") +{ + LY_ASSERT_SMOB (Music, music, 1); + LY_ASSERT_SMOB (Pitch, pitch, 2); + + Pitch start = *unsmob (pitch); + Music *m = unsmob (music); + Pitch last = m->to_relative_octave (start); + + return last.smobbed_copy (); +} + LY_DEFINE (ly_music_duration_length, "ly:music-duration-length", 1, 0, 0, - (SCM mus), - "Extract the duration field from @var{mus}, and return the length.") + (SCM mus), + "Extract the duration field from @var{mus} and return the" + " length.") { - LY_ASSERT_TYPE (unsmob_music, mus, 1); - Music *m = unsmob_music (mus); + LY_ASSERT_SMOB (Music, mus, 1); + Music *m = unsmob (mus); - Duration *d = unsmob_duration (m->get_property ("duration")); + Duration *d = unsmob (m->get_property ("duration")); Moment len; if (d) @@ -154,16 +234,17 @@ LY_DEFINE (ly_music_duration_length, "ly:music-duration-length", 1, 0, 0, } LY_DEFINE (ly_music_duration_compress, "ly:music-duration-compress", 2, 0, 0, - (SCM mus, SCM fact), - "Compress @var{mus} by factor @var{fact}, which is a @code{Moment}.") + (SCM mus, SCM fact), + "Compress @var{mus} by factor @var{fact}, which is a" + " @code{Moment}.") { - LY_ASSERT_TYPE (unsmob_music, mus, 1); + LY_ASSERT_SMOB (Music, mus, 1); LY_ASSERT_SMOB (Moment, fact, 2); - - Music *m = unsmob_music (mus); - Moment *f = unsmob_moment (fact); - Duration *d = unsmob_duration (m->get_property ("duration")); + Music *m = unsmob (mus); + Moment *f = unsmob (fact); + + Duration *d = unsmob (m->get_property ("duration")); if (d) m->set_property ("duration", d->compressed (f->main_part_).smobbed_copy ()); return SCM_UNSPECIFIED; @@ -177,40 +258,40 @@ LY_DEFINE (ly_music_duration_compress, "ly:music-duration-compress", 2, 0, 0, TODO: this should use ly:pitch. */ LY_DEFINE (ly_transpose_key_alist, "ly:transpose-key-alist", - 2, 0, 0, (SCM l, SCM pit), - "Make a new key alist of @var{l} transposed by pitch @var{pit}") + 2, 0, 0, (SCM l, SCM pit), + "Make a new key alist of@tie{}@var{l} transposed by" + " pitch @var{pit}.") { SCM newlist = SCM_EOL; - Pitch *p = unsmob_pitch (pit); + Pitch *p = unsmob (pit); for (SCM s = l; scm_is_pair (s); s = scm_cdr (s)) { SCM key = scm_caar (s); SCM alter = scm_cdar (s); if (scm_is_pair (key)) - { - Pitch orig (scm_to_int (scm_car (key)), - scm_to_int (scm_cdr (key)), - ly_scm2rational (alter)); + { + Pitch orig (scm_to_int (scm_car (key)), + scm_to_int (scm_cdr (key)), + ly_scm2rational (alter)); - orig = orig.transposed (*p); + orig = orig.transposed (*p); - SCM key = scm_cons (scm_from_int (orig.get_octave ()), - scm_from_int (orig.get_notename ())); + SCM key = scm_cons (scm_from_int (orig.get_octave ()), + scm_from_int (orig.get_notename ())); - newlist = scm_cons (scm_cons (key, ly_rational2scm (orig.get_alteration ())), - newlist); - } + newlist = scm_cons (scm_cons (key, ly_rational2scm (orig.get_alteration ())), + newlist); + } else if (scm_is_number (key)) - { - Pitch orig (0, scm_to_int (key), ly_scm2rational (alter)); - orig = orig.transposed (*p); - - key = scm_from_int (orig.get_notename ()); - alter = ly_rational2scm (orig.get_alteration ()); - newlist = scm_cons (scm_cons (key, alter), newlist); - } + { + Pitch orig (0, scm_to_int (key), ly_scm2rational (alter)); + orig = orig.transposed (*p); + + key = scm_from_int (orig.get_notename ()); + alter = ly_rational2scm (orig.get_alteration ()); + newlist = scm_cons (scm_cons (key, alter), newlist); + } } return scm_reverse_x (newlist, SCM_EOL); } -