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