1 /* Copyright (c) 2003 by Arkkra Enterprises. */
2 /* All rights reserved. */
4 /* This file contains parse-time functions related to TIMEDSSVs.
5 * These are used to specify mid-measure parameter changes,
13 /* Mid-measure SSV's eventually get attached to the BAR, but we need
14 * to point to the list temporarily while the BAR doesn't exist yet. */
15 static struct TIMEDSSV
*Timedssv_p
;
17 /* When there is more than one TIMEDSSV at the same moment in time,
18 * we use user input order, so we add items to the end of the list.
19 * This keeps track of where to put the next one.
21 static struct TIMEDSSV
**Timed_tail_p_p
= &Timedssv_p
;
23 static struct TIMEDSSV
*tssv_new
P((int context
));
26 /* Allocate and initalize a TIMEDSSV for each staff/voice being defined,
27 * and return pointer to the first one.
36 struct SVRANGELIST
*svr_p
; /* list of staffs/voices being entered */
37 struct RANGELIST
*srange_p
; /* list of staffs being entered */
38 struct RANGELIST
*vrange_p
; /* list of voices being entered */
39 struct TIMEDSSV
*new_p
;
40 struct TIMEDSSV
*first_p
= 0; /* first one created */
41 int s
; /* staff number */
42 int v
; /* voice number */
44 /* Create as many new TIMEDSSVs as needed, based on the current list
45 * of staffs/voices being defined,
46 * link them onto the temporary list for the current measure.
51 first_p
= new_p
= tssv_new(context
);
55 for (svr_p
= Svrangelist_p
; svr_p
!= 0; svr_p
= svr_p
->next
) {
56 for (srange_p
= svr_p
->stafflist_p
; srange_p
!= 0;
57 srange_p
= srange_p
->next
) {
58 for (s
= srange_p
->begin
; s
<= srange_p
->end
; s
++) {
59 if (context
== C_STAFF
) {
60 new_p
= tssv_new(context
);
64 new_p
->ssv
.staffno
= s
;
67 for (vrange_p
= svr_p
->vnolist_p
;
69 vrange_p
= vrange_p
->next
) {
70 for (v
= vrange_p
->begin
;
73 new_p
= tssv_new(context
);
77 new_p
->ssv
.staffno
= s
;
78 new_p
->ssv
.voiceno
= v
;
87 pfatal("invalid context %d when creating TIMEDSSV", context
);
95 /* Create a single TIMEDSSV and link it onto the list */
97 static struct TIMEDSSV
*
103 struct TIMEDSSV
*curr_tssv_p
;
105 CALLOC(TIMEDSSV
, curr_tssv_p
, 1);
106 zapssv( & (curr_tssv_p
->ssv
) );
107 curr_tssv_p
->ssv
.context
= context
;
108 curr_tssv_p
->grpsyl_p
= 0;
109 curr_tssv_p
->time_off
.n
= -1;
110 curr_tssv_p
->time_off
.d
= 1;
112 curr_tssv_p
->next
= 0;
113 *Timed_tail_p_p
= curr_tssv_p
;
114 Timed_tail_p_p
= &(curr_tssv_p
->next
);
120 /* Save a parameter setting in the given TIMEDSSV. We only support a very
121 * limited list of parameters that can be changed mid-measure,
122 * so this checks for valid ones.
126 tssv_update(timedssv_p
, param
, value
)
128 struct TIMEDSSV
*timedssv_p
;
133 /* Could be multiple staffs/voices, so do them all */
134 for ( ; timedssv_p
!= 0; timedssv_p
= timedssv_p
->next
) {
137 timedssv_p
->ssv
.clef
= value
;
140 if (rangecheck(value
, MINRELEASE
, MAXRELEASE
,
141 "mid-measure release change") == YES
) {
142 timedssv_p
->ssv
.release
= value
;
146 if (rangecheck(value
, MINOCTAVE
, MAXOCTAVE
,
147 "mid-measure defoct change") == YES
) {
148 timedssv_p
->ssv
.defoct
= value
;
153 yyerror("only clef, defoct, and release parameters can be changed mid-measure");
156 if (timedssv_p
->ssv
.used
[param
] == YES
) {
157 warning("multiple changes of the same parameter; last used");
159 timedssv_p
->ssv
.used
[param
] = YES
;
164 /* Associate grpsyl with TIMEDSSV. This should be called at the end of
165 * parsing of a grpsyl, in case it has at least one timed ssv. */
173 struct TIMEDSSV
*tssv_p
;
175 /* User could input multiple << >> things, and each gets their
176 * own TIMEDSSV, so we need to associate this grpsyl with
177 * all that don't yet have one. */
178 for (tssv_p
= Timedssv_p
; tssv_p
!= 0; tssv_p
= tssv_p
->next
) {
179 if (tssv_p
->grpsyl_p
== 0) {
180 tssv_p
->grpsyl_p
= gs_p
;
182 /* Do some error checks */
183 if (tssv_p
->ssv
.used
[CLEF
] == YES
) {
184 if (tssv_p
->ssv
.context
== C_STAFF
185 && is_tab_staff(tssv_p
->ssv
.staffno
)) {
186 yyerror("can't change clef of tab staff");
188 if (tssv_p
->ssv
.context
== C_VOICE
) {
189 yyerror("can't change clef in voice context");
198 /* Do processing on one input line worth of TIMEDSSVs.
204 struct TIMEDSSV
*ts_p
;
207 /* First we have to find the time offsets of each TIMEDSSV.
208 * We can't necessarily calculate them at the time
209 * they were added to the list, since for tuplets
210 * we don't know fulltimes till we reach the end
211 * of the tuplet, and know how to adjust.
212 * So we just save the GRPSYL* at that point,
213 * and now we go through and find all the actual times.
215 for (ts_p
= Timedssv_p
; ts_p
!= 0; ts_p
= ts_p
->next
) {
216 if (GE(ts_p
->time_off
, Zero
)) {
217 /* already set from some previous line */
221 if (ts_p
->grpsyl_p
== 0) {
222 /* This could happen if there was a user input
223 * error, because we could have set up the TIMEDSSV
224 * and then not been able to parse the GRPSYL that
225 * was intended to go with it. Set time offset to
226 * a safe value, and skip the rest of the loop,
227 * so we don't try to dereference the null ptr. */
228 ts_p
->time_off
= Zero
;
232 /* Count up the time before the group where the timed
233 * SSV was specified. */
234 for (ts_p
->time_off
= Zero
, gs_p
= ts_p
->grpsyl_p
->prev
;
235 gs_p
!= 0; gs_p
= gs_p
->prev
) {
236 /* Alt groups have not yet had their time adjusted,
237 * so we have to compensate for that. */
238 if (gs_p
->slash_alt
< 0 || (gs_p
->prev
!= 0
239 && gs_p
->prev
->slash_alt
< 0) ) {
240 ts_p
->time_off
= radd(ts_p
->time_off
,
241 rdiv(gs_p
->fulltime
, Two
));
243 else if (gs_p
->grpvalue
!= GV_ZERO
) {
244 ts_p
->time_off
= radd(ts_p
->time_off
,
252 /* Sort the current TIMEDSSV list by time and return pointer to the head
253 * of the sorted list. The sorting is done by time. When there is a tie
254 * things are put in user input order. Also re-inits for the next measure.
261 struct TIMEDSSV
*ret
; /* return value is pointer to sorted list */
262 short moved
; /* YES if something was moved during sort */
264 /* Most of the time, the list will be empty. */
265 if (Timedssv_p
== 0) {
269 /* Sort in time order.
270 * The list is almost certain to be very short,
271 * so sort needn't be very efficient. So we check pairs
272 * and swap ones that are backwards. */
274 struct TIMEDSSV
**ts_p_p
;
275 struct TIMEDSSV
*tmp_ts_p
;
278 for (ts_p_p
= &Timedssv_p
; (*ts_p_p
)->next
!= 0;
279 ts_p_p
= &((*ts_p_p
)->next
) ) {
280 if ( GT( (*ts_p_p
)->time_off
, (*ts_p_p
)->next
->time_off
) ) {
281 /* Wrong order. Swap them */
282 tmp_ts_p
= (*ts_p_p
)->next
;
283 (*ts_p_p
)->next
= (*ts_p_p
)->next
->next
;
284 tmp_ts_p
->next
= *ts_p_p
;
290 } while (moved
== YES
);
293 /* re-init for next measure */
295 Timed_tail_p_p
= &(Timedssv_p
);