]> git.donarmstrong.com Git - lilypond.git/blob - lily/music-sequence.cc
Merge branch 'lilypond/translation' of ssh://git.sv.gnu.org/srv/git/lilypond into...
[lilypond.git] / lily / music-sequence.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1998--2010 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 "music.hh"
25 #include "input.hh"
26
27 void
28 transpose_music_list (SCM lst, Pitch rq)
29 {
30   for (SCM s = lst; scm_is_pair (s); s = scm_cdr (s))
31     unsmob_music (scm_car (s))->transpose (rq);
32 }
33
34 Moment
35 Music_sequence::cumulative_length (SCM l)
36 {
37   Moment cumulative;
38   Moment last_len;
39
40   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
41     {
42       Moment l = unsmob_music (scm_car (s))->get_length ();
43       if (last_len.grace_part_ && l.main_part_)
44         last_len.grace_part_ = Rational (0);
45       cumulative += last_len;
46       last_len = l;
47     }
48
49   last_len.grace_part_ = Rational (0);
50   cumulative += last_len;
51
52   return cumulative;
53 }
54
55 Moment
56 Music_sequence::maximum_length (SCM l)
57 {
58   Moment dur = 0;
59   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
60     {
61       Music *m = unsmob_music (scm_car (s));
62       if (!m)
63         programming_error ("Music sequence should have music elements");
64       else
65         {
66           Moment l = m->get_length ();
67           dur = max (dur, l);
68         }
69     }
70
71   return dur;
72 }
73
74 MAKE_SCHEME_CALLBACK (Music_sequence, maximum_length_callback, 1);
75 SCM
76 Music_sequence::maximum_length_callback (SCM m)
77 {
78   Music *me = unsmob_music (m);
79   return maximum_length (me->get_property ("elements")).smobbed_copy ();
80 }
81
82 MAKE_SCHEME_CALLBACK (Music_sequence, cumulative_length_callback, 1);
83 SCM
84 Music_sequence::cumulative_length_callback (SCM m)
85 {
86   Music *me = unsmob_music (m);
87   return cumulative_length (me->get_property ("elements")).smobbed_copy ();
88 }
89
90 MAKE_SCHEME_CALLBACK (Music_sequence, minimum_start_callback, 1);
91 SCM
92 Music_sequence::minimum_start_callback (SCM m)
93 {
94   Music *me = unsmob_music (m);
95   return minimum_start (me->get_property ("elements")).smobbed_copy ();
96 }
97
98 MAKE_SCHEME_CALLBACK (Music_sequence, first_start_callback, 1);
99 SCM
100 Music_sequence::first_start_callback (SCM m)
101 {
102   Music *me = unsmob_music (m);
103   return first_start (me->get_property ("elements")).smobbed_copy ();
104 }
105
106 Pitch
107 music_list_to_relative (SCM l, Pitch p, bool ret_first)
108 {
109   Pitch first = p;
110   int count = 0;
111
112   Pitch last = p;
113   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
114     {
115       if (Music *m = unsmob_music (scm_car (s)))
116         {
117           last = m->to_relative_octave (last);
118           if (!count++)
119             first = last;
120         }
121     }
122
123   return (ret_first) ? first : last;
124 }
125
126 void
127 compress_music_list (SCM l, Moment m)
128 {
129   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
130     unsmob_music (scm_car (s))->compress (m);
131 }
132
133 Moment
134 Music_sequence::minimum_start (SCM l)
135 {
136   Moment m;
137
138   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
139     m = min (m, unsmob_music (scm_car (s))->start_mom ());
140   return m;
141 }
142
143 Moment
144 Music_sequence::first_start (SCM l)
145 {
146   Moment m;
147
148   for (SCM s = l; scm_is_pair (s); s = scm_cdr (s))
149     {
150       Music *mus = unsmob_music (scm_car (s));
151       Moment l = mus->get_length ();
152       Moment s = mus->start_mom ();
153       if (l.to_bool () || s.to_bool ())
154         return s;
155     }
156   return m;
157 }
158
159 MAKE_SCHEME_CALLBACK (Music_sequence, simultaneous_relative_callback, 2);
160 SCM
161 Music_sequence::simultaneous_relative_callback (SCM music, SCM pitch)
162 {
163   Music *me = unsmob_music (music);
164   Pitch p = *unsmob_pitch (pitch);
165
166   SCM elts = me->get_property ("elements");
167   SCM copied = SCM_EOL;
168   if (lily_1_8_relative)
169     copied = ly_music_deep_copy (elts);
170
171   Pitch retval = music_list_to_relative (elts, p, false);
172
173   if (lily_1_8_relative)
174     {
175
176       Pitch retval_1_8 = music_list_to_relative (copied, p, true);
177       if (retval_1_8 != retval)
178         lily_1_8_compatibility_used = true;
179
180       retval = retval_1_8;
181     }
182
183   return retval.smobbed_copy ();
184 }
185
186 MAKE_SCHEME_CALLBACK (Music_sequence, event_chord_relative_callback, 2);
187 SCM
188 Music_sequence::event_chord_relative_callback (SCM music, SCM pitch)
189 {
190   Music *me = unsmob_music (music);
191   Pitch p = *unsmob_pitch (pitch);
192   return music_list_to_relative (me->get_property ("elements"),
193                                  p, true).smobbed_copy ();
194 }
195
196 MAKE_SCHEME_CALLBACK (Music_sequence, repeated_chord_relative_callback, 2);
197 SCM
198 Music_sequence::repeated_chord_relative_callback (SCM music, SCM pitch)
199 {
200   Music *me = unsmob_music (music);
201   Music *repeated_chord = unsmob_music (me->get_property ("element"));
202   Music *original_chord = unsmob_music (me->get_property ("original-chord"));
203
204   /* A repeated chord octave is not computed from the previous pitch,
205    * (this function `pitch' argument), but from the original chord, so
206    * that repeated chords have the same octave have the original chord,
207    * even though other simple notes have been entered meanwhile.
208    */
209   assert (repeated_chord);
210   Pitch *p = 0;
211   /* Get the original chord first pitch */
212   if (original_chord)
213     {
214       for (SCM s = original_chord->get_property ("elements"); scm_is_pair (s); s = scm_cdr (s))
215         {
216           if (Music *m = unsmob_music (scm_car (s)))
217             {
218               p = unsmob_pitch (m->get_property ("pitch"));
219               if (p)
220                 break;
221             }
222         }
223     }
224   /* Use the `pitch' argument if no pitch found in original chord. */
225   if (! p)
226     p = unsmob_pitch (pitch);
227
228   /* Change the first note pitch to -1, to avoid octaviation.  Indeed,
229    * the first pitch should be the same as the original chord first
230    * pitch. */
231   for (SCM s = repeated_chord->get_property ("elements"); scm_is_pair (s); s = scm_cdr (s))
232     {
233       if (Music *m = unsmob_music (scm_car (s)))
234         {
235           Pitch *first_pitch = unsmob_pitch (m->get_property ("pitch"));
236           if (first_pitch)
237             {
238               Pitch new_pitch = Pitch (-1,
239                                        first_pitch->get_notename (),
240                                        first_pitch->get_alteration ());
241               m->set_property ("pitch", new_pitch.smobbed_copy ());
242               break;
243             }
244         }
245     }
246   music_list_to_relative (repeated_chord->get_property ("elements"), *p, true).smobbed_copy ();
247   /* Return `pitch' instead of the repeated chord first pitch,
248    * because `pitch' is the last explicitly entered pitch */
249   return pitch;
250 }