1use crate::defaults::FloatType;
11use crate::display::Drawn;
12use crate::notation::Placement;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17#[non_exhaustive]
18pub enum SpannerKind {
19 Slur,
21 Crescendo,
23 Diminuendo,
25 Ottava,
27 Line,
30 PedalMark,
32 TrillExtension,
35 ArpeggioMark,
38 Glissando,
41 TremoloSpanner,
43 Neume,
46 MultiMeasureRest,
49}
50
51impl SpannerKind {
52 pub fn class_name(self) -> &'static str {
54 match self {
55 Self::Slur => "Slur",
56 Self::Crescendo => "Crescendo",
57 Self::Diminuendo => "Diminuendo",
58 Self::Ottava => "Ottava",
59 Self::Line => "Line",
60 Self::PedalMark => "PedalMark",
61 Self::ArpeggioMark => "ArpeggioMarkSpanner",
62 Self::TrillExtension => "TrillExtension",
63 Self::Glissando => "Glissando",
64 Self::TremoloSpanner => "TremoloSpanner",
65 Self::Neume => "Neume",
66 Self::MultiMeasureRest => "MultiMeasureRest",
67 }
68 }
69
70 pub fn numbering_class(self) -> &'static str {
74 match self {
75 Self::Crescendo | Self::Diminuendo => "DynamicWedge",
76 other => other.class_name(),
77 }
78 }
79
80 pub fn is_wedge(self) -> bool {
82 matches!(self, Self::Crescendo | Self::Diminuendo)
83 }
84}
85
86#[derive(Clone, Debug, PartialEq, Eq)]
88#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89#[must_use]
90pub struct Spanner {
91 kind: SpannerKind,
92 spanned: Vec<Option<usize>>,
95 #[cfg_attr(feature = "serde", serde(default))]
96 placement: Drawn<Option<Placement>>,
97 #[cfg_attr(feature = "serde", serde(default))]
98 line_type: Drawn<Option<String>>,
99 #[cfg_attr(feature = "serde", serde(default))]
100 spread: Drawn<Option<FloatType>>,
101 #[cfg_attr(feature = "serde", serde(default))]
102 shift: Option<OctaveShift>,
103 #[cfg_attr(feature = "serde", serde(default))]
104 ends: Drawn<LineEnds>,
105 #[cfg_attr(feature = "serde", serde(default))]
106 pedal: Option<Pedal>,
107 #[cfg_attr(feature = "serde", serde(default))]
108 arpeggio: crate::expressions::ArpeggioType,
109 #[cfg_attr(feature = "serde", serde(default))]
110 glissando: Option<Glissando>,
111 #[cfg_attr(feature = "serde", serde(default))]
112 marks: Option<u8>,
113 #[cfg_attr(feature = "serde", serde(default))]
114 offset: Drawn<FloatType>,
115 #[cfg_attr(feature = "serde", serde(default))]
116 multi_rest: Option<MultiRest>,
117 #[cfg_attr(feature = "serde", serde(default))]
120 id_local: Drawn<Option<String>>,
121 #[cfg_attr(feature = "serde", serde(default))]
124 complete: Drawn<bool>,
125 #[cfg_attr(feature = "serde", serde(default))]
128 in_score: Drawn<bool>,
129 #[cfg_attr(feature = "serde", serde(default))]
133 unplaced: Drawn<Vec<(usize, crate::stream::StreamElement)>>,
134}
135
136#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
139#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
140pub struct MultiRest {
141 pub use_symbols: bool,
144 pub max_symbols: u32,
146 pub count: Option<usize>,
149}
150
151impl Default for MultiRest {
152 fn default() -> Self {
154 Self {
155 use_symbols: true,
156 max_symbols: 11,
157 count: None,
158 }
159 }
160}
161
162#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
164#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
165pub enum SlideType {
166 #[default]
168 Chromatic,
169 Continuous,
171 Diatonic,
173 White,
175 Black,
177}
178
179impl SlideType {
180 pub fn as_str(self) -> &'static str {
183 match self {
184 Self::Chromatic => "chromatic",
185 Self::Continuous => "continuous",
186 Self::Diatonic => "diatonic",
187 Self::White => "white",
188 Self::Black => "black",
189 }
190 }
191
192 pub fn from_name(name: &str) -> crate::error::Result<Self> {
198 let lower = name.to_lowercase();
199 [
200 Self::Chromatic,
201 Self::Continuous,
202 Self::Diatonic,
203 Self::White,
204 Self::Black,
205 ]
206 .into_iter()
207 .find(|kind| kind.as_str() == lower)
208 .ok_or_else(|| crate::error::Error::Value(format!("not a valid value: {name}")))
209 }
210}
211
212#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216pub struct Glissando {
217 pub slide_type: SlideType,
219 pub label: Option<String>,
221}
222
223#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
225#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
226pub enum PedalObjectKind {
227 Bounce,
230 GapStart,
233 GapEnd,
235}
236
237impl PedalObjectKind {
238 pub fn class_name(self) -> &'static str {
240 match self {
241 Self::Bounce => "PedalBounce",
242 Self::GapStart => "PedalGapStart",
243 Self::GapEnd => "PedalGapEnd",
244 }
245 }
246
247 pub fn from_class_name(name: &str) -> Option<Self> {
249 [Self::Bounce, Self::GapStart, Self::GapEnd]
250 .into_iter()
251 .find(|kind| kind.class_name() == name)
252 }
253}
254
255#[derive(Clone, Debug, PartialEq, Eq, Hash)]
259#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
260#[must_use]
261pub struct PedalObject {
262 kind: PedalObjectKind,
263 #[cfg_attr(feature = "serde", serde(default))]
264 placement: Drawn<Option<Placement>>,
265}
266
267impl PedalObject {
268 pub fn new(kind: PedalObjectKind) -> Self {
270 Self {
271 kind,
272 placement: Drawn(None),
273 }
274 }
275
276 pub fn kind(&self) -> PedalObjectKind {
278 self.kind
279 }
280
281 pub fn placement(&self) -> Option<Placement> {
283 self.placement.0
284 }
285
286 pub fn set_placement(&mut self, placement: Option<Placement>) {
288 self.placement.0 = placement;
289 }
290}
291
292#[derive(Clone, Copy, Debug, PartialEq, Default)]
295#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
296pub struct LineEnds {
297 pub start: LineEnd,
299 pub end: LineEnd,
301 pub start_height: Option<FloatType>,
303 pub end_height: Option<FloatType>,
305}
306
307#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
309#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
310pub enum LineEnd {
311 Up,
313 #[default]
315 Down,
316 Arrow,
318 Both,
320 None,
322}
323
324impl LineEnd {
325 pub fn as_str(self) -> &'static str {
328 match self {
329 Self::Up => "up",
330 Self::Down => "down",
331 Self::Arrow => "arrow",
332 Self::Both => "both",
333 Self::None => "none",
334 }
335 }
336
337 pub fn from_name(name: &str) -> crate::error::Result<Self> {
339 Ok(match name.to_lowercase().as_str() {
340 "up" => Self::Up,
341 "down" => Self::Down,
342 "arrow" => Self::Arrow,
343 "both" => Self::Both,
344 "none" => Self::None,
345 other => {
346 return Err(crate::error::Error::Value(format!(
347 "not a valid value: {other}"
348 )));
349 }
350 })
351 }
352}
353
354#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
356#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
357pub enum PedalType {
358 Sustain,
360 Sostenuto,
362 Soft,
364 Silent,
366}
367
368#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
370#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
371pub enum PedalForm {
372 Line,
374 Symbol,
376 SymbolAlt,
378 SymbolLine,
380}
381
382#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
386#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
387pub struct Pedal {
388 pub pedal_type: Option<PedalType>,
390 pub form: Option<PedalForm>,
392 pub abbreviated: bool,
394}
395
396impl PedalType {
397 pub fn as_str(self) -> &'static str {
399 match self {
400 Self::Sustain => "sustain",
401 Self::Sostenuto => "sostenuto",
402 Self::Soft => "soft",
403 Self::Silent => "silent",
404 }
405 }
406
407 pub fn from_name(name: &str) -> Option<Self> {
409 [Self::Sustain, Self::Sostenuto, Self::Soft, Self::Silent]
410 .into_iter()
411 .find(|kind| kind.as_str() == name)
412 }
413}
414
415impl PedalForm {
416 pub fn as_str(self) -> &'static str {
419 match self {
420 Self::Line => "line",
421 Self::Symbol => "symbol",
422 Self::SymbolAlt => "symbolalt",
423 Self::SymbolLine => "symbolline",
424 }
425 }
426
427 pub fn from_name(name: &str) -> Option<Self> {
429 [Self::Line, Self::Symbol, Self::SymbolAlt, Self::SymbolLine]
430 .into_iter()
431 .find(|form| form.as_str() == name)
432 }
433
434 pub fn has_line(self) -> bool {
436 matches!(self, Self::Line | Self::SymbolLine)
437 }
438}
439
440#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
443#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
444pub struct OctaveShift {
445 size: u8,
446 up: bool,
447 transposing: bool,
448}
449
450impl OctaveShift {
451 pub fn from_name(name: &str, transposing: bool) -> crate::error::Result<Self> {
455 let (size, up) = match name.to_lowercase().as_str() {
456 "8va" => (8, true),
457 "8vb" => (8, false),
458 "15ma" => (15, true),
459 "15mb" => (15, false),
460 "22da" => (22, true),
461 "22db" => (22, false),
462 other => {
463 return Err(crate::error::Error::Value(format!(
464 "cannot create Ottava of type: {other}"
465 )));
466 }
467 };
468 Ok(Self {
469 size,
470 up,
471 transposing,
472 })
473 }
474
475 pub fn name(&self) -> &'static str {
477 match (self.size, self.up) {
478 (8, true) => "8va",
479 (8, false) => "8vb",
480 (15, true) => "15ma",
481 (15, false) => "15mb",
482 (_, true) => "22da",
483 (_, false) => "22db",
484 }
485 }
486
487 pub fn magnitude(&self) -> u8 {
489 self.size
490 }
491
492 pub fn up(&self) -> bool {
494 self.up
495 }
496
497 pub fn transposing(&self) -> bool {
500 self.transposing
501 }
502
503 pub fn set_transposing(&mut self, transposing: bool) {
507 self.transposing = transposing;
508 }
509
510 pub fn interval(&self) -> crate::interval::Interval {
513 let name = if self.up {
514 format!("P{}", self.size)
515 } else {
516 format!("P-{}", self.size)
517 };
518 crate::interval::Interval::from_name(&name)
519 .expect("a perfect octave, fifteenth or twenty-second is an interval")
520 }
521}
522
523impl Spanner {
524 pub fn new(kind: SpannerKind, spanned: Vec<usize>) -> Self {
534 Self::with_unplaced(kind, spanned.into_iter().map(Some).collect())
535 }
536
537 pub fn with_unplaced(kind: SpannerKind, spanned: Vec<Option<usize>>) -> Self {
542 Self {
543 kind,
544 spanned,
545 placement: Drawn(None),
546 line_type: Drawn(None),
547 spread: Drawn(None),
548 shift: None,
549 ends: Drawn(LineEnds::default()),
550 pedal: None,
551 arpeggio: crate::expressions::ArpeggioType::Normal,
552 glissando: None,
553 marks: None,
554 offset: Drawn(0.0),
555 multi_rest: None,
556 id_local: Drawn(None),
557 complete: Drawn(false),
558 in_score: Drawn(false),
559 unplaced: Drawn(Vec::new()),
560 }
561 }
562
563 pub fn multi_measure_rest(spanned: Vec<usize>) -> Self {
566 let mut rest = Self::new(SpannerKind::MultiMeasureRest, spanned);
567 rest.multi_rest = Some(MultiRest::default());
568 rest
569 }
570
571 pub fn multi_rest(&self) -> Option<MultiRest> {
573 self.multi_rest
574 }
575
576 pub fn set_multi_rest(&mut self, multi_rest: Option<MultiRest>) {
578 self.multi_rest = multi_rest;
579 }
580
581 pub fn num_rests(&self) -> usize {
584 self.multi_rest
585 .and_then(|rest| rest.count)
586 .unwrap_or(self.spanned.len())
587 }
588
589 pub fn glissando(spanned: Vec<usize>) -> Self {
592 let mut glissando = Self::new(SpannerKind::Glissando, spanned);
593 glissando.line_type = Drawn(Some("wavy".to_string()));
594 glissando.glissando = Some(Glissando::default());
595 glissando
596 }
597
598 pub fn glissando_details(&self) -> Option<&Glissando> {
600 self.glissando.as_ref()
601 }
602
603 pub fn set_glissando_details(&mut self, glissando: Option<Glissando>) {
605 self.glissando = glissando;
606 }
607
608 pub fn tremolo(marks: u8, spanned: Vec<usize>) -> crate::error::Result<Self> {
615 let mut tremolo = Self::new(SpannerKind::TremoloSpanner, spanned);
616 tremolo.set_number_of_marks(Some(marks))?;
617 Ok(tremolo)
618 }
619
620 pub fn number_of_marks(&self) -> Option<u8> {
623 self.marks
624 }
625
626 pub fn set_number_of_marks(&mut self, marks: Option<u8>) -> crate::error::Result<()> {
632 if marks.is_some_and(|marks| marks > 8) {
633 return Err(crate::error::Error::Value(
634 "Number of marks must be a number from 0 to 8".to_string(),
635 ));
636 }
637 self.marks = marks;
638 Ok(())
639 }
640
641 pub fn offset(&self) -> FloatType {
645 self.offset.0
646 }
647
648 pub fn set_offset(&mut self, offset: FloatType) {
650 self.offset.0 = offset;
651 }
652
653 pub fn arpeggio_mark(arpeggio: crate::expressions::ArpeggioType, spanned: Vec<usize>) -> Self {
655 let mut mark = Self::new(SpannerKind::ArpeggioMark, spanned);
656 mark.arpeggio = arpeggio;
657 mark
658 }
659
660 pub fn arpeggio(&self) -> crate::expressions::ArpeggioType {
662 self.arpeggio
663 }
664
665 pub fn set_arpeggio(&mut self, arpeggio: crate::expressions::ArpeggioType) {
667 self.arpeggio = arpeggio;
668 }
669
670 pub fn line(spanned: Vec<usize>) -> Self {
673 let mut line = Self::new(SpannerKind::Line, spanned);
674 line.line_type = Drawn(Some("solid".to_string()));
675 line
676 }
677
678 pub fn ends(&self) -> LineEnds {
680 self.ends.0
681 }
682
683 pub fn set_ends(&mut self, ends: LineEnds) {
685 self.ends.0 = ends;
686 }
687
688 pub fn pedal_mark(pedal: Pedal, spanned: Vec<usize>) -> Self {
690 let mut mark = Self::new(SpannerKind::PedalMark, spanned);
691 mark.pedal = Some(pedal);
692 mark
693 }
694
695 pub fn pedal(&self) -> Option<Pedal> {
697 self.pedal
698 }
699
700 pub fn set_pedal(&mut self, pedal: Option<Pedal>) {
702 self.pedal = pedal;
703 }
704
705 pub fn ottava(shift: OctaveShift, spanned: Vec<usize>) -> Self {
718 let mut ottava = Self::new(SpannerKind::Ottava, spanned);
719 ottava.placement = Drawn(Some(Placement::Above));
720 ottava.shift = Some(shift);
721 ottava
722 }
723
724 pub fn shift(&self) -> Option<OctaveShift> {
726 self.shift
727 }
728
729 pub fn set_shift(&mut self, shift: Option<OctaveShift>) {
731 self.shift = shift;
732 }
733
734 pub fn slur(spanned: Vec<usize>) -> Self {
751 Self::new(SpannerKind::Slur, spanned)
752 }
753
754 pub fn wedge(kind: SpannerKind, spanned: Vec<usize>) -> Self {
765 let mut wedge = Self::new(kind, spanned);
766 wedge.placement = Drawn(Some(Placement::Below));
767 wedge.spread = Drawn(Some(15.0));
768 wedge
769 }
770
771 pub fn spread(&self) -> Option<FloatType> {
774 self.spread.0
775 }
776
777 pub fn set_spread(&mut self, spread: Option<FloatType>) {
779 self.spread.0 = spread;
780 }
781
782 pub fn kind(&self) -> SpannerKind {
784 self.kind
785 }
786
787 pub fn spanned(&self) -> &[Option<usize>] {
797 &self.spanned
798 }
799
800 pub(crate) fn spanned_mut(&mut self) -> &mut Vec<Option<usize>> {
803 &mut self.spanned
804 }
805
806 pub(crate) fn move_places(&mut self, moved: &[Option<usize>]) {
809 for place in &mut self.spanned {
810 *place = place.and_then(|old| moved.get(old).copied().flatten());
811 }
812 }
813
814 pub(crate) fn drop_repeated_places(&mut self) {
817 let mut seen: Vec<usize> = Vec::new();
818 self.spanned.retain(|place| match place {
819 Some(place) if seen.contains(place) => false,
820 Some(place) => {
821 seen.push(*place);
822 true
823 }
824 None => true,
825 });
826 }
827
828 pub fn len(&self) -> usize {
830 self.spanned.len()
831 }
832
833 pub fn is_empty(&self) -> bool {
835 self.spanned.is_empty()
836 }
837
838 pub fn is_first(&self, position: usize) -> bool {
841 self.spanned.first() == Some(&Some(position))
842 }
843
844 pub fn is_last(&self, position: usize) -> bool {
847 self.spanned.last() == Some(&Some(position))
848 }
849
850 pub fn has_spanned_element(&self, position: usize) -> bool {
853 self.spanned.contains(&Some(position))
854 }
855
856 pub fn add_spanned_elements(&mut self, positions: impl IntoIterator<Item = usize>) {
868 for position in positions {
869 if !self.has_spanned_element(position) {
870 self.spanned.push(Some(position));
871 }
872 }
873 }
874
875 pub fn insert_first_spanned_element(&mut self, position: usize) {
879 if !self.has_spanned_element(position) {
880 self.spanned.insert(0, Some(position));
881 }
882 }
883
884 pub fn replace_spanned_element(&mut self, old: usize, new: usize) {
897 if self.has_spanned_element(new) {
898 self.spanned.retain(|place| *place != Some(old));
899 return;
900 }
901 for place in &mut self.spanned {
902 if *place == Some(old) {
903 *place = Some(new);
904 }
905 }
906 }
907
908 pub fn placement(&self) -> Option<Placement> {
910 self.placement.0
911 }
912
913 pub fn set_placement(&mut self, placement: Option<Placement>) {
915 self.placement.0 = placement;
916 }
917
918 pub fn id_local(&self) -> Option<&str> {
921 self.id_local.0.as_deref()
922 }
923
924 pub fn set_id_local(&mut self, id_local: Option<String>) {
926 self.id_local.0 = id_local;
927 }
928
929 pub fn unplaced_elements(&self) -> &[(usize, crate::stream::StreamElement)] {
932 &self.unplaced.0
933 }
934
935 pub fn set_unplaced_element(&mut self, place: usize, element: crate::stream::StreamElement) {
937 self.unplaced.0.retain(|(held, _)| *held != place);
938 self.unplaced.0.push((place, element));
939 self.unplaced.0.sort_by_key(|(held, _)| *held);
940 }
941
942 pub fn stands_in_score(&self) -> bool {
946 self.in_score.0
947 }
948
949 pub fn set_stands_in_score(&mut self, in_score: bool) {
951 self.in_score.0 = in_score;
952 }
953
954 pub fn complete(&self) -> bool {
957 self.complete.0
958 }
959
960 pub fn set_complete(&mut self, complete: bool) {
962 self.complete.0 = complete;
963 }
964
965 pub fn line_type(&self) -> Option<&str> {
968 self.line_type.0.as_deref()
969 }
970
971 pub fn set_line_type(&mut self, line_type: Option<String>) {
973 self.line_type.0 = line_type;
974 }
975}
976
977#[cfg(test)]
978mod tests {
979 use super::*;
980
981 #[test]
982 fn a_spanner_knows_its_ends() {
983 let slur = Spanner::slur(vec![3, 4, 5]);
984 assert!(slur.is_first(3));
985 assert!(slur.is_last(5));
986 assert!(!slur.is_first(4) && !slur.is_last(4));
987 assert_eq!(slur.kind().class_name(), "Slur");
988 }
989
990 #[test]
991 fn an_element_is_joined_once_in_the_order_added() {
992 let mut line = Spanner::new(SpannerKind::Line, vec![]);
994 line.add_spanned_elements([1]);
995 line.add_spanned_elements([2, 3]);
996 line.add_spanned_elements([4, 5, 2]);
997 assert_eq!(
998 line.spanned(),
999 [Some(1), Some(2), Some(3), Some(4), Some(5)]
1000 );
1001 assert!(line.has_spanned_element(4));
1002 assert!(!line.has_spanned_element(6));
1003 }
1004
1005 #[test]
1006 fn an_element_inserted_first_goes_before_the_rest() {
1007 let mut line = Spanner::new(SpannerKind::Line, vec![2, 3, 4, 5]);
1008 line.insert_first_spanned_element(1);
1009 assert_eq!(
1010 line.spanned(),
1011 [Some(1), Some(2), Some(3), Some(4), Some(5)]
1012 );
1013 line.insert_first_spanned_element(4);
1015 assert_eq!(
1016 line.spanned(),
1017 [Some(1), Some(2), Some(3), Some(4), Some(5)]
1018 );
1019
1020 let mut empty = Spanner::new(SpannerKind::Line, vec![]);
1021 empty.insert_first_spanned_element(7);
1022 assert_eq!(empty.spanned(), [Some(7)]);
1023 }
1024
1025 #[test]
1026 fn a_replaced_element_keeps_its_place() {
1027 let mut slur = Spanner::slur(vec![1, 2, 3]);
1028 slur.replace_spanned_element(1, 9);
1029 assert_eq!(slur.spanned(), [Some(9), Some(2), Some(3)]);
1030 slur.replace_spanned_element(6, 7);
1032 assert_eq!(slur.spanned(), [Some(9), Some(2), Some(3)]);
1033 slur.replace_spanned_element(2, 3);
1035 assert_eq!(slur.spanned(), [Some(9), Some(3)]);
1036 }
1037
1038 #[test]
1039 fn a_multi_measure_rest_counts_its_rests() {
1040 let mut rest = Spanner::multi_measure_rest(vec![1, 2, 3]);
1041 assert_eq!(rest.num_rests(), 3);
1042 assert!(rest.multi_rest().is_some_and(|said| said.use_symbols));
1043
1044 rest.set_multi_rest(Some(MultiRest {
1045 count: Some(10),
1046 ..MultiRest::default()
1047 }));
1048 assert_eq!(rest.num_rests(), 10);
1049 }
1050}