]> git.donarmstrong.com Git - lilypond.git/blob - lily/music-sequence.cc
Release: bump Welcome versions.
[lilypond.git] / lily / music-sequence.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1998--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 "music-sequence.hh"
21
22 #include "warn.hh"
23 #include "program-option.hh"
24 #include "duration.hh"
25 #include "moment.hh"
26 #include "music.hh"
27 #include "input.hh"
28
29 void
30 transpose_music_list (SCM lst, Pitch rq)
31 {
32   for (SCM s = lst; scm_is_pair (s); s = scm_cdr (s))
33     if (Prob *p = unsmob<Prob> (scm_car (s)))
34       p->transpose (rq);
35 }
36
37 Moment
38 Music_sequence::cumulative_length (SCM l)
39 {
40   Moment cumulative;
41   Moment last_len;
42
43   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
44     {
45       Moment l = unsmob<Music> (scm_car (s))->get_length ();
46       if (last_len.grace_part_ && l.main_part_)
47         last_len.grace_part_ = Rational (0);
48       cumulative += last_len;
49       last_len = l;
50     }
51
52   last_len.grace_part_ = Rational (0);
53   cumulative += last_len;
54
55   return cumulative;
56 }
57
58 Moment
59 Music_sequence::maximum_length (SCM l)
60 {
61   Moment dur = 0;
62   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
63     {
64       Music *m = unsmob<Music> (scm_car (s));
65       if (!m)
66         programming_error ("Music sequence should have music elements");
67       else
68         {
69           Moment l = m->get_length ();
70           dur = max (dur, l);
71         }
72     }
73
74   return dur;
75 }
76
77 MAKE_SCHEME_CALLBACK (Music_sequence, maximum_length_callback, 1);
78 SCM
79 Music_sequence::maximum_length_callback (SCM m)
80 {
81   Music *me = unsmob<Music> (m);
82   return maximum_length (me->get_property ("elements")).smobbed_copy ();
83 }
84
85 MAKE_SCHEME_CALLBACK (Music_sequence, event_chord_length_callback, 1);
86 SCM
87 Music_sequence::event_chord_length_callback (SCM m)
88 {
89   Music *me = unsmob<Music> (m);
90   Duration *d = unsmob<Duration> (me->get_property ("duration"));
91   // Preset duration is used in chord repetitions.
92   if (d)
93     {
94       Moment mom = d->get_length ();
95       return mom.smobbed_copy ();
96     }
97   return maximum_length (me->get_property ("elements")).smobbed_copy ();
98 }
99
100 MAKE_SCHEME_CALLBACK (Music_sequence, cumulative_length_callback, 1);
101 SCM
102 Music_sequence::cumulative_length_callback (SCM m)
103 {
104   Music *me = unsmob<Music> (m);
105   return cumulative_length (me->get_property ("elements")).smobbed_copy ();
106 }
107
108 MAKE_SCHEME_CALLBACK (Music_sequence, minimum_start_callback, 1);
109 SCM
110 Music_sequence::minimum_start_callback (SCM m)
111 {
112   Music *me = unsmob<Music> (m);
113   return minimum_start (me->get_property ("elements")).smobbed_copy ();
114 }
115
116 MAKE_SCHEME_CALLBACK (Music_sequence, first_start_callback, 1);
117 SCM
118 Music_sequence::first_start_callback (SCM m)
119 {
120   Music *me = unsmob<Music> (m);
121   return first_start (me->get_property ("elements")).smobbed_copy ();
122 }
123
124 Pitch
125 music_list_to_relative (SCM l, Pitch p, bool ret_first)
126 {
127   Pitch first = p;
128   int count = 0;
129
130   Pitch last = p;
131   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
132     {
133       if (Music *m = unsmob<Music> (scm_car (s)))
134         {
135           last = m->to_relative_octave (last);
136           if (!count++)
137             first = last;
138         }
139     }
140
141   return (ret_first) ? first : last;
142 }
143
144 void
145 compress_music_list (SCM l, Moment m)
146 {
147   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
148     unsmob<Music> (scm_car (s))->compress (m);
149 }
150
151 Moment
152 Music_sequence::minimum_start (SCM l)
153 {
154   Moment m;
155
156   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
157     m = min (m, unsmob<Music> (scm_car (s))->start_mom ());
158   return m;
159 }
160
161 Moment
162 Music_sequence::first_start (SCM l)
163 {
164
165   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
166     {
167       Music *mus = unsmob<Music> (scm_car (s));
168       Moment start = mus->start_mom ();
169       if (mus->get_length ().to_bool () || start.to_bool ())
170         return start;
171     }
172   return Moment ();
173 }
174
175 MAKE_SCHEME_CALLBACK (Music_sequence, simultaneous_relative_callback, 2);
176 SCM
177 Music_sequence::simultaneous_relative_callback (SCM music, SCM pitch)
178 {
179   Music *me = unsmob<Music> (music);
180   Pitch p = *unsmob<Pitch> (pitch);
181   return music_list_to_relative (me->get_property ("elements"),
182                                  p, false).smobbed_copy ();
183 }
184
185 MAKE_SCHEME_CALLBACK (Music_sequence, event_chord_relative_callback, 2);
186 SCM
187 Music_sequence::event_chord_relative_callback (SCM music, SCM pitch)
188 {
189   Music *me = unsmob<Music> (music);
190   Pitch p = *unsmob<Pitch> (pitch);
191   return music_list_to_relative (me->get_property ("elements"),
192                                  p, true).smobbed_copy ();
193 }