2 /* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 by Arkkra Enterprises */
3 /* All rights reserved */
5 /* functions called at parse time to deal with beaming. */
13 static void subbeam
P((struct SSV
*ssv_p
, RATIONAL outer_time
, int obi
,
14 struct GRPSYL
*begin_gs_p
, struct GRPSYL
*end_gs_p
));
15 static struct GRPSYL
*verify_crossbeam
P((struct GRPSYL
*gs_p
,
16 struct GRPSYL
*other_gs_p
, RATIONAL start_time
, RATIONAL
*end_time_p
,
17 int staffno
, int size
));
19 slopelencheck
P((struct GRPSYL
*first_p
, struct GRPSYL
*last_p
, char *bmtype
));
22 /* this function will get called whenever a group is not the start or end
23 * of a custom beam group. This will fill in the beamloc based on past
24 * history. If we were most recently in a custom beam group, we still are.
25 * If we weren't before, we aren't now either. The non-custom beaming
26 * gets done later after we have collected a whole bar in do_beaming()
27 * which is called via do_bar(). */
30 setbeamloc(curr_grp_p
, last_grp_p
)
32 struct GRPSYL
*curr_grp_p
; /* the group we're working on */
33 struct GRPSYL
*last_grp_p
; /* the last group we did */
36 if (curr_grp_p
->grpvalue
== GV_ZERO
) {
37 /* grace notes don't get handled here */
38 curr_grp_p
->beamloc
= NOITEM
;
42 /* if the previous group is a grace group, that doesn't count. Back
43 * up in the list to the first non-grace or beginning of list */
44 for ( ; last_grp_p
!= (struct GRPSYL
*) 0
45 && last_grp_p
->grpvalue
== GV_ZERO
;
46 last_grp_p
= last_grp_p
->prev
) {
50 if (last_grp_p
!= (struct GRPSYL
*) 0) {
52 switch (last_grp_p
->beamloc
) {
56 curr_grp_p
->beamto
= last_grp_p
->beamto
;
57 /* Make sure notes are 8th or shorter. Spaces (which
58 * are allowed in cross-staff beams) can be longer. */
59 if (curr_grp_p
->basictime
< 8) {
60 /* At this point, spaces are still
61 * pseudo-pitches, so have to figure out
62 * if this group is really notes */
63 int letter
; /* pitch */
64 int n
; /* index through notelist */
65 for (n
= 0; n
< curr_grp_p
->nnotes
; n
++) {
66 letter
= curr_grp_p
->notelist
[n
].letter
;
67 if ((letter
>= 'a' && letter
<= 'g') ||
68 letter
== PP_NO_PITCH
) {
69 yyerror("beamed notes must be 8th or shorter");
75 /* if previous began beaming, we must be inside now */
76 /* if in beam before, we still are */
77 curr_grp_p
->beamloc
= INITEM
;
83 /* if previous was ending beaming, or
84 * we weren't inside a beam, must be no beam now */
85 curr_grp_p
->beamloc
= NOITEM
;
90 /* nothing specified before, so no beam */
91 curr_grp_p
->beamloc
= NOITEM
;
96 /* take a quick jaunt through a GRPSYL list, seeing if custom
97 * beaming was already done. If so, return YES, otherwise NO.
98 * If there are any non-grace groups with beaming info, there must
99 * have been custom beaming. Also, verify that user didn't attempt to
100 * custom beam a mixture of normal and cue size notes,
101 * or try to put illegal rests or spaces inside a beam.
102 * Spaces are only allowed in cross-staff beams, unless user explicitly
103 * says to beam across spaces. Rests are also only allowed in beams if
104 * the user explicitly states they should be. Rests and spaces cannot be on
105 * the ends, and must be eighth note or shorter.
106 * We allow beaming together chords that are stemmed to another staff
107 * only if all such instances are to the same staff--not some to staff above
108 * and others to staff below--because beaming involving 3 staffs at once is
109 * just too hard to deal with.
110 * Also check that any esbm has at least 2 notes before and after it.
114 has_cust_beaming(grpsyl_p
)
116 struct GRPSYL
*grpsyl_p
; /* list of GRPSYLs to check */
120 int size
= GS_NORMAL
;
121 int numnotes
= 0; /* how many notes groups, for esbm check */
122 short stemto
= CS_SAME
; /* to check for mixed CS_ABOVE/CS_BELOW */
123 struct GRPSYL
*start_p
= 0; /* first beamed group */
125 for ( ; grpsyl_p
!= (struct GRPSYL
*) NULL
;
126 grpsyl_p
= grpsyl_p
->next
) {
128 if ((grpsyl_p
->grpvalue
!= GV_ZERO
)
129 && (grpsyl_p
->beamloc
!= NOITEM
)) {
130 /* have non-grace with beam info set */
133 /* check for size or cross-staff stem mixtures */
134 if (grpsyl_p
->beamloc
== STARTITEM
) {
135 size
= grpsyl_p
->grpsize
;
139 /* check for size mixture. But only do non-cross-staff
140 * beams here, because it's a lot easier to do the
141 * cross-staff beam check in chk_crossbeams() */
142 else if (grpsyl_p
->grpsize
!= size
143 && grpsyl_p
->beamto
== CS_SAME
) {
144 l_yyerror(grpsyl_p
->inputfile
,
145 grpsyl_p
->inputlineno
,
146 "can't beam normal and cue notes together");
149 if (grpsyl_p
->grpcont
!= GC_NOTES
) {
150 if (grpsyl_p
->grpcont
== GC_REST
) {
151 if (grpsyl_p
->basictime
< 8) {
152 l_yyerror(grpsyl_p
->inputfile
,
153 grpsyl_p
->inputlineno
,
154 "rests inside a beam must be less than quarter note duration");
156 if (grpsyl_p
->beamloc
!= INITEM
) {
157 l_yyerror(grpsyl_p
->inputfile
,
158 grpsyl_p
->inputlineno
,
159 "beam cannot %s with a rest",
160 grpsyl_p
->beamloc
== STARTITEM ?
164 else if (grpsyl_p
->beamto
== CS_SAME
) {
165 if (grpsyl_p
->beamloc
!= INITEM
) {
166 l_yyerror(grpsyl_p
->inputfile
,
167 grpsyl_p
->inputlineno
,
168 "beam cannot begin or end with a space");
170 if (grpsyl_p
->basictime
< 8) {
171 l_yyerror(grpsyl_p
->inputfile
,
172 grpsyl_p
->inputlineno
,
173 "spaces inside a beam must be less than quarter note duration");
177 else if (grpsyl_p
->grpvalue
!= GV_ZERO
) {
181 if (grpsyl_p
->stemto
!= CS_SAME
) {
182 if (stemto
!= CS_SAME
&& grpsyl_p
->stemto
184 l_yyerror(grpsyl_p
->inputfile
,
185 grpsyl_p
->inputlineno
,
186 "beam cannot include chords with stems to both above and below staffs");
188 stemto
= grpsyl_p
->stemto
;
191 if (grpsyl_p
->beamloc
== INITEM
&&
192 IS_STEMLEN_KNOWN(grpsyl_p
->stemlen
)) {
193 l_yyerror(grpsyl_p
->inputfile
,
194 grpsyl_p
->inputlineno
,
195 "stem len specification not allowed inside a beam");
198 if (grpsyl_p
->beamloc
== STARTITEM
) {
201 else if (grpsyl_p
->beamloc
== ENDITEM
) {
203 slopelencheck(start_p
, grpsyl_p
, "beam");
208 if (grpsyl_p
->breakbeam
== YES
209 && grpsyl_p
->beamto
== CS_SAME
) {
211 l_warning(grpsyl_p
->inputfile
,
212 grpsyl_p
->inputlineno
,
213 "esbm must be preceeded by at least 2 beamed notes");
214 grpsyl_p
->breakbeam
= NO
;
219 /* Check that there are
220 * at least 2 following beamed notes */
222 for (g_p
= grpsyl_p
->next
; g_p
!= 0;
224 if (g_p
->grpcont
== GC_NOTES
&&
225 g_p
->grpvalue
!= GV_ZERO
) {
228 if (g_p
->breakbeam
== YES
) {
231 if (g_p
->beamloc
== ENDITEM
) {
236 l_warning(grpsyl_p
->inputfile
,
237 grpsyl_p
->inputlineno
,
238 "esbm must be followed by at least 2 beamed notes");
239 grpsyl_p
->breakbeam
= NO
;
241 else if (grpsyl_p
->grpcont
!= GC_NOTES
) {
242 /* User really should have put
243 * the esbm on the preceeding
244 * NOTES group. We'll be nice
245 * and move it for them.
247 grpsyl_p
->breakbeam
= NO
;
248 for (g_p
= grpsyl_p
->prev
;
249 g_p
->grpcont
!= GC_NOTES
;
253 g_p
->breakbeam
= YES
;
265 /* beam notes together according to user-specified default beaming style */
268 do_beaming(gs_p
, grpsize
, staffno
, vno
)
270 struct GRPSYL
*gs_p
; /* list of GRPSYLs to do beaming on */
271 int grpsize
; /* GS_NORMAL or GS_SMALL
272 * (grace are handled separately) */
274 int vno
; /* voice number */
277 struct SSV
*ssv_beaminfo_p
; /* ssv having relevent beam info */
278 register int n
; /* index into beamstyle list */
279 RATIONAL styletime
; /* accumulated time to beam together */
280 RATIONAL tot_time
; /* cumulative grpsyl time */
281 struct GRPSYL
*first_p
; /* first in beam group */
282 struct GRPSYL
*last_p
; /* last in beam group */
283 int stop
; /* YES if need to stop beaming */
284 int beamrests
; /* if to include rests inside beams */
285 int beamspaces
; /* if to include spaces inside beams */
286 short stemto
= CS_SAME
; /* check for mixed CS_ABOVE/CS_BELOW */
287 short restart
= NO
; /* YES if could start another beam
288 * with current group, even though
289 * it can go with previous */
293 debug(4, "do_beaming file=%s line=%d grpsize=%d staff=%d voice=%d",
294 gs_p
->inputfile
, gs_p
->inputlineno
, grpsize
, staffno
, vno
);
296 /* if no default beaming scheme for this voice, then nothing to do--
297 * any custom beaming would have already been done */
298 ssv_beaminfo_p
= vvpath(staffno
, vno
, BEAMSTLIST
);
299 if (ssv_beaminfo_p
->nbeam
== 0) {
303 /* ok. We may need to do some beaming. Go through the beamstlist and
304 * see if there are any groups to beam together */
307 /* point to first non-grace group */
308 for ( ; gs_p
!= (struct GRPSYL
*) 0 && gs_p
->grpcont
== GC_NOTES
309 && gs_p
->grpvalue
== GV_ZERO
; gs_p
= gs_p
->next
) {
313 /* if no groups, nothing to do */
314 if (gs_p
== (struct GRPSYL
*) 0) {
318 beamrests
= vvpath(staffno
, vno
, BEAMSTLIST
)->beamrests
;
319 beamspaces
= vvpath(staffno
, vno
, BEAMSTLIST
)->beamspaces
;
320 styletime
= tot_time
= Zero
;
321 for (n
= 0; n
< ssv_beaminfo_p
->nbeam
; n
++) {
322 styletime
= radd(styletime
, ssv_beaminfo_p
->beamstlist
[n
]);
324 if (GE(tot_time
, styletime
)) {
325 /* we're already past this beamstyle segment */
329 for (first_p
= last_p
= 0, stop
= NO
;
330 LT(tot_time
, styletime
); gs_p
= gs_p
->next
) {
333 /* Must be too few groups in measure.
334 * This error will already have been
335 * reported elsewhere.
341 while (gs_p
->grpvalue
== GV_ZERO
) {
344 /* Must have tried to end a measure
345 * with grace. Already reported. */
350 tot_time
= radd(tot_time
, gs_p
->fulltime
);
351 if (GE(tot_time
, styletime
)) {
352 /* This group puts us at or past
353 * the current beamstyle segment */
357 /* only 8th and shorter get beamed */
358 if (gs_p
->basictime
< 8 || (gs_p
->grpcont
== GC_SPACE
&&
359 beamspaces
== NO
) ) {
362 else if (gs_p
->grpcont
== GC_REST
&& beamrests
== NO
) {
365 else if (gs_p
->grpsize
!= grpsize
) {
366 /* Wrong size to beam on this call */
369 else if (gs_p
->stemto
!= CS_SAME
&& stemto
!= CS_SAME
370 && gs_p
->stemto
!= stemto
) {
371 /* We don't allow beaming across three staffs,
372 * so have to stop current beam, but could
373 * possibly beam this group with following
374 * groups, as long as they don't have a
375 * conflicting stemto */
379 else if (gs_p
->grpcont
== GC_NOTES
&&
380 LE(tot_time
, styletime
)) {
381 /* found something beam-able */
387 if (gs_p
->stemto
!= CS_SAME
) {
388 stemto
= gs_p
->stemto
;
392 if (first_p
!= 0 && last_p
!= 0
393 && first_p
!= last_p
) {
394 /* Disallow illegal combinations of
395 * slope and stem length */
396 slopelencheck(first_p
, last_p
, "beam");
398 /* If there are subbeam groupings,
400 subbeam(ssv_beaminfo_p
,
401 rsub(styletime
, ssv_beaminfo_p
->beamstlist
[n
]),
404 /* mark beginning of beam group */
405 first_p
->beamloc
= STARTITEM
;
407 /* mark all intermediate groups,
409 for (first_p
= first_p
->next
;
411 first_p
= first_p
->next
) {
413 if (first_p
->grpvalue
418 first_p
->beamloc
= INITEM
;
420 if (IS_STEMLEN_KNOWN(first_p
->stemlen
)) {
421 l_yyerror(first_p
->inputfile
, first_p
->inputlineno
,
422 "stem len specification not allowed inside a beam");
426 /* mark the end of the beam group */
427 last_p
->beamloc
= ENDITEM
;
430 /* Re-init for any more bunches to beam */
431 first_p
= last_p
= 0;
434 if (restart
== YES
) {
435 if (gs_p
->grpcont
== GC_NOTES
) {
446 /* Once a STARTITEM and ENDITEM groups of the regular beamstyle
447 * have been identified, go through them to see if there should
448 * be subgroups. If so, mark breakbeam = YES on the last group of
453 subbeam(ssv_p
, outer_time
, obi
, begin_gs_p
, end_gs_p
)
455 struct SSV
*ssv_p
; /* to get beamstlist and subbeamstlist */
456 RATIONAL outer_time
; /* Time in measure when outer beam begins */
457 int obi
; /* outer beam index, subscript into ssv_p->beamstlist */
458 struct GRPSYL
*begin_gs_p
;
459 struct GRPSYL
*end_gs_p
;
462 int sbi
; /* sub beam index, subscript of ssv_p->subbeamstlist */
463 RATIONAL subgroup_time
; /* duration of items in subbeamstlist */
464 RATIONAL tot_time
; /* sum of note groups in subbeaming */
465 struct GRPSYL
*gs_p
; /* walk through groups */
466 struct GRPSYL
*last_notegroup_p
;/* Most recent GC_NOTES GRPSYL */
469 /* Check if more than one beam subgroup
470 * makes up the outer beam grouping. */
471 if (ssv_p
->nbeam
== ssv_p
->nsubbeam
) {
472 /* There are no sub-beam groupings anywhere in the measure */
476 /* Find the subbeamlist entry that matches with the outer beam entry */
477 subgroup_time
= Zero
;
478 for (sbi
= 0; LT(subgroup_time
, outer_time
); sbi
++) {
479 subgroup_time
= radd(subgroup_time
, ssv_p
->subbeamstlist
[sbi
]);
482 if ( EQ(ssv_p
->beamstlist
[obi
], ssv_p
->subbeamstlist
[sbi
]) ) {
483 /* Outer and subbeam have the same time duration,
484 * so there aren't any subgroups in this outer beam grouping. */
488 /* There are subgroups inside the outer beam grouping,
489 * so we may need to set one or more breakbeams. */
490 subgroup_time
= ssv_p
->subbeamstlist
[sbi
];
492 /* If beam starts later than the outer beamstyle item begins,
493 * (e.g., if there was a rest at the beginning of the beam time),
494 * we have to count that time as already taken up from the subbeam.
496 for (tot_time
= Zero
, gs_p
= begin_gs_p
->prev
; gs_p
!= 0;
498 tot_time
= radd(tot_time
, gs_p
->fulltime
);
500 tot_time
= rsub(tot_time
, outer_time
);
501 last_notegroup_p
= 0;
502 for (gs_p
= begin_gs_p
; gs_p
!= end_gs_p
; gs_p
= gs_p
->next
) {
504 /* Grace notes are irrelevant */
505 if (gs_p
->grpvalue
== GV_ZERO
) {
509 /* Remember where last note group is, in case we
510 * need to set breakbeam on it. */
511 if (gs_p
->grpcont
== GC_NOTES
) {
512 last_notegroup_p
= gs_p
;
515 /* Add up group time values until the total equals
516 * or exceeds that of the subgroup. */
517 tot_time
= radd(tot_time
, gs_p
->fulltime
);
518 if (LT(tot_time
, subgroup_time
)) {
519 /* not far enough yet */
523 /* If the value exceeds, there is a note spanning the
524 * subgroup boundary, so just ignore the subgrouping. */
525 if (GT(tot_time
, subgroup_time
)) {
526 tot_time
= rsub(tot_time
, subgroup_time
);
527 subgroup_time
= ssv_p
->subbeamstlist
[++sbi
];
528 if (gs_p
->grpcont
!= GC_NOTES
) {
529 last_notegroup_p
= 0;
534 /* A group ends right at the subbeam boundary.
535 * Set breakbeam on last group, if there was one.
537 if (last_notegroup_p
!= 0) {
538 last_notegroup_p
->breakbeam
= YES
;
541 /* The current subbeam is finished.
542 * Move on to the next subbeam, if there is one. */
543 if (++sbi
< ssv_p
->nsubbeam
) {
544 subgroup_time
= ssv_p
->subbeamstlist
[sbi
];
545 /* Since we know the subbeam we just
546 * finished ended exactly
547 * at the subbeam boundary,
548 * we set to time taken up so far
549 * by the new subbeam to zero.
552 last_notegroup_p
= 0;
559 /* alt groups must always have beamloc set, so fix them */
564 struct GRPSYL
*gs_p
; /* a measure's worth of GRPSYLs for a voice */
567 struct GRPSYL
*other_gs_p
; /* group on other end of alt pair */
570 debug(4, "set_alt_beams file=%s line=%d",
571 gs_p
->inputfile
, gs_p
->inputlineno
);
573 /* walk through the list, fixing any alt groups */
574 for ( ; gs_p
!= (struct GRPSYL
*) 0; gs_p
= gs_p
->next
) {
576 /* check if is an alt pair */
577 if (gs_p
->slash_alt
< 0) {
579 if (gs_p
->next
== (struct GRPSYL
*) 0) {
580 /* no second group in alt, will be flagged
585 /* set the pair as a beam group */
586 gs_p
->beamloc
= STARTITEM
;
587 gs_p
->next
->beamloc
= ENDITEM
;
589 slopelencheck(gs_p
, gs_p
->next
, "alt");
591 /* middle phase wants to have both notes in an alt group
592 * have their alt field set, so do that */
593 gs_p
->next
->slash_alt
= gs_p
->slash_alt
;
595 /* adjust preceeding and following groups if necessary.
596 * If was already in a beam group, split off the other
597 * parts into their own groups or put flags on the
598 * extras if they are down to one group */
600 /* find previous normal group if any and adjust */
601 for (other_gs_p
= gs_p
->prev
;
602 other_gs_p
!= (struct GRPSYL
*) 0;
603 other_gs_p
= other_gs_p
->prev
) {
605 if (other_gs_p
->grpvalue
!= GV_ZERO
) {
606 if (other_gs_p
->grpcont
== GC_REST
) {
607 other_gs_p
->beamloc
= NOITEM
;
615 if (other_gs_p
!= (struct GRPSYL
*) 0) {
617 switch (other_gs_p
->beamloc
) {
620 other_gs_p
->beamloc
= ENDITEM
;
624 other_gs_p
->beamloc
= NOITEM
;
632 /* now do the same for the following group */
633 for (other_gs_p
= gs_p
->next
->next
;
634 other_gs_p
!= (struct GRPSYL
*) 0;
635 other_gs_p
= other_gs_p
->next
) {
637 if (other_gs_p
->grpvalue
!= GV_ZERO
) {
638 if (other_gs_p
->grpcont
== GC_REST
) {
639 other_gs_p
->beamloc
= NOITEM
;
647 if (other_gs_p
!= (struct GRPSYL
*) 0) {
649 switch (other_gs_p
->beamloc
) {
652 other_gs_p
->beamloc
= STARTITEM
;
656 other_gs_p
->beamloc
= NOITEM
;
664 /* skip over the second in the pair */
671 /* Given a list of GRPSYLs on a visible voice
672 * having "bm with staff below" do all the error checking.
673 * This list of groups has to be for the bottom visible voice
674 * for the duration of the beam.
675 * There has to be a set of groups on the top non-space visible
676 * voice of the first visible staff below,
677 * which starts a "bm with staff above" at exactly
678 * the same time value. The ebm values also have to match. At every
679 * point inside the beam, one voice must have notes and the other voice
682 * Have to be careful in this function,
683 * because the gs_p->staffno and gs_p->vno may not be filled in yet,
684 * so have to use the staffno from the STAFF struct, and get vno from the
685 * first gs_p, which the caller is supposed to have filled in correctly.
687 * Returns the staff number of the staff containing the matching
688 * "bm with staff above" or -1 if no such staff was found.
692 chk_crossbeam(gs_p
, mll_p
)
694 struct GRPSYL
*gs_p
; /* first group in above voice of cross staff beam */
695 struct MAINLL
*mll_p
; /* gs_p hangs off of here */
698 struct GRPSYL
*g_p
; /* for walking through group list */
699 struct GRPSYL
*other_p
; /* group on other staff */
700 struct MAINLL
*assoc_mll_p
; /* other staff hangs off of here */
701 struct GRPSYL
*assoc_grps_p
; /* the measure-worth of groups in
702 * the voice being beamed to */
703 RATIONAL start_time
, end_time
; /* of the above voice */
704 RATIONAL other_start
, other_end
;/* time of groups on below staff */
705 int user_specified_stem_len
; /* YES or NO */
706 int size
= GS_NORMAL
;
707 int assoc_vno
; /* voice number on below staff */
708 struct STAFF
*staff_p
;
713 /* only the first gs_p is guaranteed to have the right vno at this
714 * point, so save that. */
716 staff_p
= mll_p
->u
.staff_p
;
717 staffno
= staff_p
->staffno
;
719 /* find where in the measure the beam begins, by adding up the
720 * time values of all the groups prior to the first beamed group */
721 for (start_time
= Zero
, g_p
= gs_p
->prev
; g_p
!= (struct GRPSYL
*) 0;
723 start_time
= radd(start_time
, g_p
->fulltime
);
726 /* find how long the beam lasts. Also see if there are any small
728 for (end_time
= start_time
, g_p
= gs_p
; g_p
!= (struct GRPSYL
*) 0;
730 /* accumulate the time */
731 end_time
= radd(end_time
, g_p
->fulltime
);
733 /* check for small groups */
734 if (g_p
->grpcont
== GC_NOTES
&& g_p
->grpsize
== GS_SMALL
735 && g_p
->grpvalue
!= GV_ZERO
) {
739 /* end of the beam? */
740 if (g_p
->beamloc
== ENDITEM
&& g_p
->grpvalue
!= GV_ZERO
) {
744 if (g_p
== (struct GRPSYL
*) 0) {
745 /* maybe this should be silent, since another error message
746 * should already be printed, but this will point out that
747 * the problem was on a cross-staff beam */
748 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
749 "can't find end of cross-staff beam");
753 /* Make sure this is the bottom voice of the above staff.
754 * If it's voice 2 (subscript 1) then it is for sure.
755 * Otherwise, have to make sure the second and third voices, if any,
756 * have all spaces for the duration of the cross-staff beam */
758 /* If voice 2 is visible and not all spaces,
759 * or if we are working on voice 1 while voice 3 is
760 * visible and not all space, there is a problem. */
761 if (vvpath(staffno
, 2, VISIBLE
)->visible
== YES
&&
762 hasspace(staff_p
->groups_p
[1], start_time
,
763 end_time
) == NO
|| (vno
== 0 &&
764 vvpath(staffno
, 3, VISIBLE
)->visible
== YES
&&
765 hasspace(mll_p
->u
.staff_p
->groups_p
[2],
766 start_time
, end_time
) == NO
)) {
767 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
768 "cross-staff beam must be from bottom voice of staff %d",
769 mll_p
->u
.staff_p
->staffno
);
774 /* Find the associated voice, and the associated bm group
775 * in that voice. First find the next visible staff */
776 for (assoc_mll_p
= mll_p
->next
; ; assoc_mll_p
= assoc_mll_p
->next
) {
777 if (assoc_mll_p
== (struct MAINLL
*) 0 ||
778 assoc_mll_p
->str
!= S_STAFF
) {
779 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
780 "no visible staff below to beam with");
784 if (svpath(assoc_mll_p
->u
.staff_p
->staffno
, VISIBLE
)->visible
786 /* found the right staff */
791 /* Associated voice is probably voice 1 of the below staff.
792 * But there is a slight possibility it is voice 2, or even voice 3.
793 * Skip over voices that are all spaces for the duration of the beam.
794 * Since voice 3 is the "middle" voice, we check 1, then 3, then 2.
796 if (vvpath(staffno
, 1, VISIBLE
)->visible
== YES
&&
797 hasspace(assoc_mll_p
->u
.staff_p
->groups_p
[0],
798 start_time
, end_time
) == NO
) {
799 assoc_grps_p
= assoc_mll_p
->u
.staff_p
->groups_p
[0];
802 else if (vvpath(staffno
, 3, VISIBLE
)->visible
== YES
&&
803 hasspace(assoc_mll_p
->u
.staff_p
->groups_p
[2],
804 start_time
, end_time
) == NO
) {
805 assoc_grps_p
= assoc_mll_p
->u
.staff_p
->groups_p
[2];
808 else if (vvpath(staffno
, 2, VISIBLE
)->visible
== YES
&&
809 hasspace(assoc_mll_p
->u
.staff_p
->groups_p
[1],
810 start_time
, end_time
) == NO
) {
811 assoc_grps_p
= assoc_mll_p
->u
.staff_p
->groups_p
[1];
815 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
816 "cross-staff beam has no notes on staff %d",
817 assoc_mll_p
->u
.staff_p
->staffno
);
821 /* Tab staffs can't be involved in cross-staff beaming */
822 if (is_tab_staff(mll_p
->u
.staff_p
->staffno
) ||
823 is_tab_staff(assoc_mll_p
->u
.staff_p
->staffno
)) {
824 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
825 "cross-staff beaming not allowed on tab staff");
829 /* We don't allow the different staffs to have different staffscale
830 * values: it doesn't really make much sense to allow it, and avoids
831 * all the issues like how wide to make the beams.
833 if (svpath(mll_p
->u
.staff_p
->staffno
, STAFFSCALE
)->staffscale
!=
834 svpath(assoc_mll_p
->u
.staff_p
->staffno
,
835 STAFFSCALE
)->staffscale
) {
836 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
837 "staffs involved with cross-staff beams must have identical staffscale values");
838 /* We did find which to associate with, even though
839 * its staffscale was wrong. */
840 return(assoc_mll_p
->u
.staff_p
->staffno
);
843 /* find the group that ought to be the "bm with staff above" group, by
844 * going that far time-wise into the measure on the associated voice */
845 for (other_start
= Zero
, other_p
= assoc_grps_p
;
846 other_p
!= (struct GRPSYL
*) 0;
847 other_p
= other_p
->next
) {
849 if (GT(other_start
, start_time
)) {
850 /* too far. pretend to be at end of list so we
851 * and fall out of loop to print the error message
853 other_p
= (struct GRPSYL
*) 0;
857 if (EQ(other_start
, start_time
)) {
862 if (other_p
->grpvalue
== GV_ZERO
) {
866 /* have to keep going. Keep track of how far we are in time */
867 other_start
= radd(other_start
, other_p
->fulltime
);
870 /* skip past any grace groups */
871 while (other_p
!= 0 && other_p
->grpvalue
== GV_ZERO
) {
872 other_p
= other_p
->next
;
875 /* If we didn't find a voice below, or that voice's group
876 * isn't the start of a beam with above, there is a problem.
877 * In the second case, maybe user really meant to beam with some
878 * lower voice, but that would collide, which we don't allow.
880 if (other_p
== (struct GRPSYL
*) 0 || other_p
->beamloc
!= STARTITEM
881 || other_p
->beamto
!= CS_ABOVE
) {
882 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
883 "'bm with staff below' has no matching 'bm with staff above' (may be missing, invisible, or on wrong voice)");
884 return(assoc_mll_p
->u
.staff_p
->staffno
);
887 /* check if user specified a stem length on the first group */
888 if (IS_STEMLEN_KNOWN(gs_p
->stemlen
)
889 || IS_STEMLEN_KNOWN(other_p
->stemlen
)) {
890 user_specified_stem_len
= YES
;
893 user_specified_stem_len
= NO
;
896 /* go through the two voices. For each note group, verify that
897 * the other voice has space during that time period. Do the "other"
898 * staff first, because in a previous version of this function it
899 * had to be done in that order to avoid possible null pointer
900 * dereference. Now things have changed, so that doesn't matter
901 * any more, but I don't want to change the order, to make sure I
902 * don't break something.
904 other_p
= verify_crossbeam(other_p
,
905 mll_p
->u
.staff_p
->groups_p
[vno
], start_time
,
906 &other_end
, assoc_mll_p
->u
.staff_p
->staffno
, size
);
907 gs_p
= verify_crossbeam(gs_p
, assoc_grps_p
, start_time
, &end_time
,
908 mll_p
->u
.staff_p
->staffno
, size
);
910 /* we should be pointing to the ebm group for each staff,
911 * unless of course, something went wrong, like user didn't
913 if (gs_p
== (struct GRPSYL
*) 0 || other_p
== (struct GRPSYL
*) 0) {
914 /* maybe this should be silent, since another error message
915 * should already be printed, but this will point out that
916 * the problem was on a cross-staff beam */
917 l_yyerror(assoc_grps_p
->inputfile
, assoc_grps_p
->inputlineno
,
918 "failed to find ebm for cross-staff beam");
919 return(assoc_mll_p
->u
.staff_p
->staffno
);
922 if (NE(end_time
, other_end
)) {
923 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
924 "ebm not at same time in measure for both voices of cross-staff beam");
927 /* Disallow illegal combinations of slope and stem length */
928 slopelencheck(gs_p
, other_p
, "beam");
930 return(assoc_mll_p
->u
.staff_p
->staffno
);
934 /* Given the first group of a cross-staff beam, and the beginning of the
935 * list of GRPSYLs in the associated voice (the voice beamed to), and the
936 * time into the measure where the beam starts, check each group. Verify
937 * that each GC_NOTES group has GC_SPACE in the other voice and vice-versa.
938 * Also check that all note groups are the same size, and mark the spaces
939 * as the correct size so that everything in the beam has the same size.
940 * Return a pointer to the last group in the beam (null if something goes
941 * wrong). Also, return the time into the measure of the end of the beam,
942 * via the end_time_p pointer.
945 static struct GRPSYL
*
946 verify_crossbeam(gs_p
, other_gs_p
, start_time
, end_time_p
, staffno
, size
)
948 struct GRPSYL
*gs_p
; /* first group in list to be checked */
949 struct GRPSYL
*other_gs_p
; /* the groups_p of the associated voice */
950 RATIONAL start_time
; /* when the beam begins */
951 RATIONAL
*end_time_p
; /* time through end of beam will be returned here */
953 int size
; /* GS_NORMAL or GS_SMALL */
957 int has_at_least_1_note_group
= NO
;
960 /* go through each group in the beam */
961 for ( ; gs_p
!= (struct GRPSYL
*) 0; gs_p
= gs_p
->next
) {
963 /* skip over any grace groups */
964 if (gs_p
->grpvalue
== GV_ZERO
) {
968 /* find the end time of the group, for passing to hasspace() */
969 end_time
= radd(start_time
, gs_p
->fulltime
);
971 /* if notes, other voice must have space */
972 if (gs_p
->grpcont
== GC_NOTES
) {
973 if (hasspace(other_gs_p
, start_time
, end_time
) == NO
) {
974 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
975 "cross-staff beam must always have notes in one voice and space in the other voice");
976 return (struct GRPSYL
*) 0;
978 has_at_least_1_note_group
= YES
;
979 if (gs_p
->grpsize
!= size
) {
980 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
981 "can't mix normal and cue size chords in cross-staff beam");
985 /* conversely, if space, other voice must not have space */
986 else if (gs_p
->grpcont
== GC_SPACE
) {
989 int oldcont
= GC_SPACE
;
991 /* This is somewhat like hasspace() except that checks
992 * that the entire duration is space. Here we need
993 * to check if there is space at least somewhere during
994 * the time period. If so, user error.
996 for (g_p
= other_gs_p
, t
= Zero
; LT(t
, start_time
);
998 if (g_p
->grpvalue
== GV_ZERO
) {
1001 t
= radd(t
, g_p
->fulltime
);
1002 oldcont
= g_p
->grpcont
;
1004 if (GT(t
, start_time
) && oldcont
== GC_SPACE
) {
1005 /* group spilling into this time is space */
1006 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
1007 "cross-staff beam must always have notes in one voice and space in the other voice");
1008 return (struct GRPSYL
*) 0;
1010 for ( ; g_p
!= 0 && LT(t
, end_time
); g_p
= g_p
->next
) {
1011 if (g_p
->grpvalue
== GV_ZERO
) {
1014 if (g_p
->grpcont
== GC_SPACE
) {
1015 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
1016 "cross-staff beam must always have notes in one voice and space in the other voice");
1017 return (struct GRPSYL
*) 0;
1019 t
= radd(t
, g_p
->fulltime
);
1022 /* mark size of spaces. Normally space can't be cue * size, but in this case, it makes it easier for later
1023 * code (in print phrase at least) if everything in the
1024 * beam--even spaces--is marked as cue size */
1025 gs_p
->grpsize
= size
;
1028 /* esbm is not currently allowed on cross-staff beams.
1029 * It would much more complicated than normal beams,
1030 * because the "primary" beam might perhaps best be the top,
1031 * the bottom, or the middle, depending on where the notes are.
1032 * Placement and print phase would have to know about that,
1033 * so that stems could be adjusted properly,
1034 * and beams drawn in the right places.
1036 if (gs_p
->breakbeam
== YES
) {
1037 l_warning(gs_p
->inputfile
, gs_p
->inputlineno
,
1038 "esbm is not supported on cross-staff beams; being ignored");
1039 gs_p
->breakbeam
= NO
;
1042 /* see if we reached the end of the beam */
1043 if (gs_p
->beamloc
== ENDITEM
) {
1044 *end_time_p
= end_time
;
1045 if (has_at_least_1_note_group
== NO
) {
1046 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
1047 "cross-staff beam has no notes on staff %d",
1054 /* arrange for next time through the loop, by moving the
1055 * start_time to the next group */
1056 start_time
= end_time
;
1059 /* failed to find an ebm */
1060 return (struct GRPSYL
*) 0;
1064 /* User is not allowed to specify length on both ends of a beam along with
1065 * a slope, because they could becontradictory. */
1068 slopelencheck(first_p
, last_p
, bmtype
)
1070 struct GRPSYL
*first_p
; /* first beamed group */
1071 struct GRPSYL
*last_p
; /* last beamed group */
1072 char *bmtype
; /* "beam" or "alt" */
1075 if (IS_STEMLEN_KNOWN(first_p
->stemlen
) == YES
&&
1076 IS_STEMLEN_KNOWN(last_p
->stemlen
) == YES
&&
1077 fabs(first_p
->beamslope
- NOBEAMANGLE
) > 0.001) {
1078 l_yyerror(last_p
->inputfile
, last_p
->inputlineno
,
1079 "can't specify both end stem lengths and slope for %s",