1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Rosegarden
5     A sequencer and musical notation editor.
6     Copyright 2000-2021 the Rosegarden development team.
7     See the AUTHORS file for more details.
8 
9     This program is free software; you can redistribute it and/or
10     modify it under the terms of the GNU General Public License as
11     published by the Free Software Foundation; either version 2 of the
12     License, or (at your option) any later version.  See the file
13     COPYING included with this distribution for more information.
14 */
15 
16 #ifndef RG_NOTATION_TYPES_H
17 #define RG_NOTATION_TYPES_H
18 
19 #include <list>
20 #include <map>
21 
22 #include <rosegardenprivate_export.h>
23 
24 #include "Event.h"
25 
26 /*
27  * NotationTypes.h
28  *
29  * This file contains definitions of several classes to assist in
30  * creating and manipulating certain event types.  The classes are:
31  *
32  *   Accidental
33  *   Clef
34  *   Key
35  *   Indication
36  *   Pitch
37  *   Note
38  *   TimeSignature
39  *   AccidentalTable
40  *   Symbol
41  *   GeneratedRegion
42  *
43  * The classes in this file are _not_ actually used for storing
44  * events.  Events are always stored in Event objects (see Event.h).
45  *
46  * These classes are usually constructed on-the-fly when a particular
47  * operation specific to a single sort of event is required, and
48  * usually destroyed as soon as they go out of scope.  The most common
49  * usages are for creating events (create an instance of one of these
50  * classes with the data you require, then call getAsEvent on it), for
51  * doing notation-related calculations from existing events (such as
52  * the bar duration of a time signature), and for doing calculations
53  * that are independent of any particular instance of an event (such
54  * as the Note methods that calculate duration-related values without
55  * reference to any specific pitch or other note-event properties; or
56  * everything in Pitch).
57  *
58  * This file also defines the event types and standard property names
59  * for the basic events.
60  */
61 
62 namespace Rosegarden
63 {
64 
65 extern ROSEGARDENPRIVATE_EXPORT const int MIN_SUBORDERING;
66 
67 typedef std::list<int> DurationList;
68 
69 
70 /**
71  * Accidentals are stored in the event as string properties, purely
72  * for clarity.  (They aren't manipulated _all_ that often, so this
73  * probably isn't a great inefficiency.)  Originally we used an enum
74  * for the Accidental type with conversion functions to and from
75  * strings, but making Accidental a string seems simpler.
76  */
77 
78 typedef std::string Accidental;
79 
80 namespace Accidentals
81 {
82     extern ROSEGARDENPRIVATE_EXPORT const Accidental NoAccidental;
83     extern ROSEGARDENPRIVATE_EXPORT const Accidental Sharp;
84     extern ROSEGARDENPRIVATE_EXPORT const Accidental Flat;
85     extern ROSEGARDENPRIVATE_EXPORT const Accidental Natural;
86     extern ROSEGARDENPRIVATE_EXPORT const Accidental DoubleSharp;
87     extern ROSEGARDENPRIVATE_EXPORT const Accidental DoubleFlat;
88     extern ROSEGARDENPRIVATE_EXPORT const Accidental QuarterFlat;
89     extern ROSEGARDENPRIVATE_EXPORT const Accidental ThreeQuarterFlat;
90     extern ROSEGARDENPRIVATE_EXPORT const Accidental QuarterSharp;
91     extern ROSEGARDENPRIVATE_EXPORT const Accidental ThreeQuarterSharp;
92 
93     typedef std::vector<Accidental> AccidentalList;
94 
95 	/**
96 	 * When no accidental is specified for a pitch, there are several
97 	 * strategies to determine what accidental to display for an
98 	 * out-of-key pitch
99 	 */
100 	enum NoAccidentalStrategy {
101 		/** always use sharps */
102 		UseSharps,
103 		/** always use flats */
104 		UseFlats,
105 		/** always use sharps or always use flats depending on of what
106 		 * type of accidentals the current key is made up */
107 		UseKeySharpness,
108 		/** use the most likely accidental for this key */
109 		UseKey
110 	};
111 
112     /**
113      * Get the predefined accidentals (i.e. the ones listed above)
114      * in their defined order.
115      */
116     extern ROSEGARDENPRIVATE_EXPORT AccidentalList getStandardAccidentals();
117 
118     /**
119      * Get the change in pitch resulting from an accidental: -1 for
120      * flat, 2 for double-sharp, 0 for natural or NoAccidental etc.
121      * This is not as useful as it may seem, as in reality the
122      * effect of an accidental depends on the key as well -- see
123      * the Key and Pitch classes.
124      */
125     extern ROSEGARDENPRIVATE_EXPORT int getPitchOffset(const Accidental &accidental);
126 
127 
128     /**
129      * Get the Accidental corresponding to a change in pitch: flat
130      * for -1, double-sharp for 2, natural for 0 etc.
131      *
132      * Useful for tying to code that represents accidentals by
133      * their pitch change.
134      */
135     extern ROSEGARDENPRIVATE_EXPORT Accidental getAccidental(int pitchChange);
136 }
137 
138 
139 /**
140  * Marks, like Accidentals, are stored in the event as string properties.
141  */
142 
143 typedef std::string Mark;
144 
145 namespace Marks //!!! This would be better as a class, these days
146 {
147     extern ROSEGARDENPRIVATE_EXPORT const Mark NoMark;         // " "
148 
149     extern ROSEGARDENPRIVATE_EXPORT const Mark Accent;         // ">"
150     extern ROSEGARDENPRIVATE_EXPORT const Mark Tenuto;         // "-"  ("legato" in RG2.1)
151     extern ROSEGARDENPRIVATE_EXPORT const Mark Staccato;       // "."
152     extern ROSEGARDENPRIVATE_EXPORT const Mark Staccatissimo;  // "'"
153     extern ROSEGARDENPRIVATE_EXPORT const Mark Marcato;        // "^"
154     extern ROSEGARDENPRIVATE_EXPORT const Mark Open;           // "o"
155     extern ROSEGARDENPRIVATE_EXPORT const Mark Stopped;        // "+"
156     extern ROSEGARDENPRIVATE_EXPORT const Mark Harmonic;       // "°"
157 
158     extern ROSEGARDENPRIVATE_EXPORT const Mark Sforzando;      // "sf"
159     extern ROSEGARDENPRIVATE_EXPORT const Mark Rinforzando;    // "rf"
160 
161     extern ROSEGARDENPRIVATE_EXPORT const Mark Trill;          // "tr"
162     extern ROSEGARDENPRIVATE_EXPORT const Mark LongTrill;      // with wiggly line
163     extern ROSEGARDENPRIVATE_EXPORT const Mark TrillLine;      // line on its own
164     extern ROSEGARDENPRIVATE_EXPORT const Mark Turn;           // "~"
165 
166     extern ROSEGARDENPRIVATE_EXPORT const Mark Pause;          // aka "fermata"
167 
168     extern ROSEGARDENPRIVATE_EXPORT const Mark UpBow;          // "v"
169     extern ROSEGARDENPRIVATE_EXPORT const Mark DownBow;        // a square with the bottom side missing
170 
171     extern ROSEGARDENPRIVATE_EXPORT const Mark Mordent;
172     extern ROSEGARDENPRIVATE_EXPORT const Mark MordentInverted;
173     extern ROSEGARDENPRIVATE_EXPORT const Mark MordentLong;
174     extern ROSEGARDENPRIVATE_EXPORT const Mark MordentLongInverted;
175 
176     /**
177      * Given a string, return a mark that will be recognised as a
178      * text mark containing that string.  For example, the Sforzando
179      * mark is actually defined as getTextMark("sf").
180      */
181     extern ROSEGARDENPRIVATE_EXPORT Mark getTextMark(std::string text);
182 
183     /**
184      * Return true if the given mark is a text mark.
185      */
186     extern ROSEGARDENPRIVATE_EXPORT bool isTextMark(Mark mark);
187 
188     /**
189      * Extract the string from a text mark.
190      */
191     extern ROSEGARDENPRIVATE_EXPORT std::string getTextFromMark(Mark mark);
192 
193     /**
194      * Given a string, return a mark that will be recognised as a
195      * fingering mark containing that string.  (We use a string
196      * instead of a number to permit "fingering" marks containing
197      * labels like "+".)
198      */
199     extern ROSEGARDENPRIVATE_EXPORT Mark getFingeringMark(std::string fingering);
200 
201     /**
202      * Return true if the given mark is a fingering mark.
203      */
204     extern ROSEGARDENPRIVATE_EXPORT bool isFingeringMark(Mark mark);
205 
206     /**
207      * Extract the string from a fingering mark.
208      */
209     extern ROSEGARDENPRIVATE_EXPORT std::string getFingeringFromMark(Mark mark);
210 
211     /**
212      * Return true if the given mark makes sense when applied to a rest.
213      */
214     extern ROSEGARDENPRIVATE_EXPORT bool isApplicableToRests(Mark mark);
215 
216     /**
217      * Extract the number of marks from an event.
218      */
219     extern ROSEGARDENPRIVATE_EXPORT int getMarkCount(const Event &e);
220 
221     /**
222      * Extract the marks from an event.
223      */
224     extern ROSEGARDENPRIVATE_EXPORT std::vector<Mark> getMarks(const Event &e);
225 
226     /**
227      * Return the first fingering mark on an event (or NoMark, if none).
228      */
229     extern ROSEGARDENPRIVATE_EXPORT Mark getFingeringMark(const Event &e);
230 
231     /**
232      * Add a mark to an event.  If unique is true, add the mark only
233      * if the event does not already have it (otherwise permit
234      * multiple identical marks).
235      */
236     extern ROSEGARDENPRIVATE_EXPORT void addMark(Event &e, const Mark &mark, bool unique);
237 
238     /**
239      * Remove a mark from an event.  Returns true if the mark was
240      * there to remove.  If the mark was not unique, removes only
241      * the first instance of it.
242      */
243     extern ROSEGARDENPRIVATE_EXPORT bool removeMark(Event &e, const Mark &mark);
244 
245     /**
246      * Returns true if the event has the given mark.
247      */
248     extern ROSEGARDENPRIVATE_EXPORT bool hasMark(const Event &e, const Mark &mark);
249 
250     /**
251      * Get the predefined marks (i.e. the ones listed above) in their
252      * defined order.
253      */
254     extern ROSEGARDENPRIVATE_EXPORT std::vector<Mark> getStandardMarks();
255 }
256 
257 
258 /**
259  * Clefs are represented as one of a set of standard strings, stored
260  * within a clef Event.  The Clef class defines those standards and
261  * provides a few bits of information about the clefs.
262  */
263 
264 class ROSEGARDENPRIVATE_EXPORT Clef
265 {
266 public:
267     static const std::string EventType;
268     static const int EventSubOrdering;
269     static const PropertyName ClefPropertyName;
270     static const PropertyName OctaveOffsetPropertyName;
271     static const Clef DefaultClef;
272     static const Clef UndefinedClef;
273     typedef Exception BadClefName;
274 
275     static const std::string Treble;
276     static const std::string French;
277     static const std::string Soprano;
278     static const std::string Mezzosoprano;
279     static const std::string Alto;
280     static const std::string Tenor;
281     static const std::string Baritone;
282     static const std::string Varbaritone;
283     static const std::string Bass;
284     static const std::string Subbass;
285     static const std::string TwoBar;
286 
287     /**
288      * Construct the default clef (treble).
289      */
Clef()290     Clef() : m_clef(DefaultClef.m_clef), m_octaveOffset(0) { }
291 
292     /**
293      * Construct a Clef from the clef data in the given event.  If the
294      * event is not of clef type or contains insufficient data, this
295      * returns the default clef (with a warning).  You should normally
296      * test Clef::isValid() to catch that before construction.
297      */
298     Clef(const Event &e);
299 
300     /**
301      * Construct a Clef from the given data.  Throws a BadClefName
302      * exception if the given string does not match one of the above
303      * clef name constants.
304      */
305     Clef(const std::string &s, int octaveOffset = 0);
306 
Clef(const Clef & c)307     Clef(const Clef &c) : m_clef(c.m_clef), m_octaveOffset(c.m_octaveOffset) {
308     }
309 
310     Clef &operator=(const Clef &c);
311 
312     bool operator==(const Clef &c) const {
313         return c.m_clef == m_clef && c.m_octaveOffset == m_octaveOffset;
314     }
315 
316     bool operator!=(const Clef &c) const {
317         return !(c == *this);
318     }
319 
~Clef()320     ~Clef() { }
321 
322     /**
323      * Test whether the given event is a valid Clef event.
324      */
325     static bool isValid(const Event &e);
326 
327     /**
328      * Return the basic clef type (Treble, French, Soprano, Mezzosoprano, Alto, Tenor, Baritone, Varbaritone, Bass, Subbass)
329      */
getClefType()330     std::string getClefType() const { return m_clef; }
331 
332     /**
333      * Return any additional octave offset, that is, return 1 for
334      * a clef shifted an 8ve up, etc
335      */
getOctaveOffset()336     int getOctaveOffset() const { return m_octaveOffset; }
337 
338     /**
339      * Return the number of semitones a pitch in the treble clef would
340      * have to be lowered by in order to be drawn with the same height
341      * and accidental in this clef
342      */
343     int getTranspose() const;
344 
345     /**
346      * Return the octave component of getTranspose(), i.e. the number
347      * of octaves difference in pitch between this clef and the treble
348      */
349     int getOctave() const;
350 
351     /**
352      * Return the intra-octave component of getTranspose(), i.e. the
353      * number of semitones this clef is distinct in pitch from the treble
354      * besides the difference in octaves
355      */
356     int getPitchOffset() const;
357 
358     /**
359      * Return the height-on-staff (in Pitch terminology)
360      * of the clef's axis -- the line around which the clef is drawn.
361      */
362     int getAxisHeight() const;
363 
364     typedef std::vector<Clef> ClefList;
365 
366     /**
367      * Return all the clefs, in ascending order of pitch
368      */
369     static ClefList getClefs();
370 
371     /// Returned event is on heap; caller takes responsibility for ownership
372     Event *getAsEvent(timeT absoluteTime) const;
373 
374 private:
375     std::string m_clef;
376     int m_octaveOffset;
377 };
378 
379 /**
380  * All we store in a key Event is the name of the key.  A Key object
381  * can be constructed from such an Event or just from its name, and
382  * will return all the properties of the key.  The Key class also
383  * provides some useful mechanisms for getting information about and
384  * transposing between keys.
385  */
386 
387 class ROSEGARDENPRIVATE_EXPORT Key
388 {
389 public:
390     static const std::string EventType;
391     static const int EventSubOrdering;
392     static const PropertyName KeyPropertyName;
393     static const Key DefaultKey;
394     static const Key UndefinedKey;
395     typedef Exception BadKeyName;
396     typedef Exception BadKeySpec;
397 
398     /**
399      * Construct the default key (C major).
400      */
401     Key();
402 
403     /**
404      * Construct a Key from the key data in the given event.  If the
405      * event is not of key type or contains insufficient data, this
406      * returns the default key (with a warning).  You should normally
407      * test Key::isValid() to catch that before construction.
408      */
409     Key(const Event &e);
410 
411     /**
412      * Construct the named key.  Throws a BadKeyName exception if the
413      * given string does not match one of the known key names.
414      */
415     Key(const std::string &name);
416 
417     /**
418      * Construct a key from signature and mode.  May throw a
419      * BadKeySpec exception.
420      */
421     Key(int accidentalCount, bool isSharp, bool isMinor);
422 
423     /**
424      * Construct the key with the given tonic and mode. (Ambiguous.)
425      * May throw a BadKeySpec exception.
426      */
427     Key(int tonicPitch, bool isMinor);
428 
429     Key(const Key &kc);
430 
~Key()431     ~Key() {
432         delete m_accidentalHeights;
433     }
434 
435     Key &operator=(const Key &kc);
436 
437     bool operator==(const Key &k) const {
438         return k.m_name == m_name;
439     }
440 
441     bool operator!=(const Key &k) const {
442         return !(k == *this);
443     }
444 
445     // We only use this for map, which doesn't need an intelligent
446     // ordering.
447     bool operator<(const Key &b) const
448     { return this->getName() < b.getName(); }
449 
450     /**
451      * Test whether the given event is a valid Key event.
452      */
453     static bool isValid(const Event &e);
454 
455     /**
456      * Return true if this is a minor key.  Unlike in RG2.1,
457      * we distinguish between major and minor keys with the
458      * same signature.
459      */
isMinor()460     bool isMinor() const {
461         return m_keyDetailMap[m_name].m_minor;
462     }
463 
464     /**
465      * Return true if this key's signature is made up of
466      * sharps, false if flats.
467      */
isSharp()468     bool isSharp() const {
469         return m_keyDetailMap[m_name].m_sharps;
470     }
471 
472     /**
473      * Return the pitch of the tonic note in this key, as a
474      * MIDI (or RG4) pitch modulo 12 (i.e. in the range 0-11).
475      * This is the pitch of the note named in the key's name,
476      * e.g. 0 for the C in C major.
477      */
getTonicPitch()478     int getTonicPitch() const {
479         return m_keyDetailMap[m_name].m_tonicPitch;
480     }
481 
482     /**
483      * Return the number of sharps or flats in the key's signature.
484      */
getAccidentalCount()485     int getAccidentalCount() const {
486         return m_keyDetailMap[m_name].m_sharpCount;
487     }
488 
489     /**
490      * Return the key with the same signature but different
491      * major/minor mode.  For example if called on C major,
492      * returns A minor.
493      */
getEquivalent()494     Key getEquivalent() const {
495         return Key(m_keyDetailMap[m_name].m_equivalence);
496     }
497 
498     /**
499      * Return the name of the key, in a human-readable form
500      * also suitable for passing to the Key constructor.
501      */
getName()502     std::string getName() const {
503         return m_name;
504     }
505 
506     /**
507      * Return the name of the key, in the form used by X11 RG2.1.
508      */
getRosegarden2Name()509     std::string getRosegarden2Name() const {
510         return m_keyDetailMap[m_name].m_rg2name;
511     }
512 
513     /**
514      * Return the accidental at the given height-on-staff
515      * (in Pitch terminology) in the given clef.
516      */
517     Accidental getAccidentalAtHeight(int height, const Clef &clef) const;
518 
519     /**
520      * Return the accidental for the the given number of steps
521      * from the tonic. For example: for F major, step '3' is the
522      * Bb, so getAccidentalForStep(3) will yield a Flat.
523      */
524     Accidental getAccidentalForStep(int steps) const;
525 
526     /**
527      * Return the heights-on-staff (in Pitch
528      * terminology) of all accidentals in the key's signature,
529      * in the given clef.
530      */
531     std::vector<int> getAccidentalHeights(const Clef &clef) const;
532 
533     /**
534      * Return the result of applying this key to the given
535      * pitch, that is, modifying the pitch so that it has the
536      * same status in terms of accidentals as it had when
537      * found in the given previous key.
538      */
539     int convertFrom(int pitch, const Key &previousKey,
540                     const Accidental &explicitAccidental =
541                     Accidentals::NoAccidental) const;
542 
543     /**
544      * Return the result of transposing the given pitch into
545      * this key, that is, modifying the pitch by the difference
546      * between the tonic pitches of this and the given previous
547      * key.
548      */
549     int transposeFrom(int pitch, const Key &previousKey) const;
550 
551     /**
552      * Reduce a height-on-staff to a single octave, so that it
553      * can be compared against the accidental heights returned
554      * by the preceding method.
555      */
canonicalHeight(int height)556     static inline unsigned int canonicalHeight(int height) {
557         return (height > 0) ? (height % 7) : ((7 - (-height % 7)) % 7);
558     }
559 
560     typedef std::vector<Key> KeyList;
561 
562     /**
563      * Return all the keys in the given major/minor mode, in
564      * no particular order.
565      */
566     static KeyList getKeys(bool minor = false);
567 
568 
569     /// Returned event is on heap; caller takes responsibility for ownership
570     Event *getAsEvent(timeT absoluteTime) const;
571 
572     /**
573      * Transpose this key by the specified interval given in pitch and steps
574      *
575      * For example: transposing F major by a major triad (4,2) yields
576      *  A major.
577      */
578     Key transpose(int pitchDelta, int heightDelta);
579 
580 private:
581     std::string m_name;
582     mutable std::vector<int> *m_accidentalHeights;
583 
584     struct KeyDetails {
585         bool   m_sharps;
586         bool   m_minor;
587         int    m_sharpCount;
588         std::string m_equivalence;
589         std::string m_rg2name;
590         int    m_tonicPitch;
591 
592         KeyDetails(); // ctor needed in order to live in a map
593 
594         KeyDetails(bool sharps, bool minor, int sharpCount,
595                    std::string equivalence, std::string rg2name,
596                                    int m_tonicPitch);
597 
598         KeyDetails(const KeyDetails &d);
599 
600         KeyDetails &operator=(const KeyDetails &d);
601     };
602 
603 
604     typedef std::map<std::string, KeyDetails> KeyDetailMap;
605     static KeyDetailMap m_keyDetailMap;
606     static void checkMap();
607     void checkAccidentalHeights() const;
608 
609 };
610 
611 
612 /**
613  * Indication is a collective name for graphical marks that span a
614  * series of events, such as slurs, dynamic marks etc.  These are
615  * stored in indication Events with a type and duration.  The
616  * Indication class gives a basic set of indication types.
617  */
618 
619 class Indication
620 {
621 public:
622     static const std::string EventType;
623     static const int EventSubOrdering;
624     static const PropertyName IndicationTypePropertyName;
625     typedef Exception BadIndicationName;
626 
627     static const std::string Slur;
628     static const std::string PhrasingSlur;
629     static const std::string Crescendo;
630     static const std::string Decrescendo;
631     static const std::string Glissando;
632 
633     static const std::string QuindicesimaUp;
634     static const std::string OttavaUp;
635     static const std::string OttavaDown;
636     static const std::string QuindicesimaDown;
637 
638     static const std::string TrillLine;
639 
640     static const std::string FigParameterChord;
641     static const std::string Figuration;
642 
643     Indication(const Event &e)
644         /* throw (Event::NoData, Event::BadType) */;
645     Indication(const std::string &s, timeT indicationDuration)
646         /* throw (BadIndicationName) */;
647 
Indication(const Indication & m)648     Indication(const Indication &m) : m_indicationType(m.m_indicationType),
649                                       m_duration(m.m_duration) { }
650 
651     Indication &operator=(const Indication &m);
652 
~Indication()653     ~Indication() { }
654 
getIndicationType()655     std::string getIndicationType() const { return m_indicationType; }
getIndicationDuration()656     timeT getIndicationDuration() const { return m_duration; }
657 
isOttavaType()658     bool isOttavaType() const {
659         return
660             m_indicationType == QuindicesimaUp ||
661             m_indicationType == OttavaUp ||
662             m_indicationType == OttavaDown ||
663             m_indicationType == QuindicesimaDown;
664     }
665 
getOttavaShift()666     int getOttavaShift() const {
667         return (m_indicationType == QuindicesimaUp ? 2 :
668                 m_indicationType == OttavaUp ? 1 :
669                 m_indicationType == OttavaDown ? -1 :
670                 m_indicationType == QuindicesimaDown ? -2 : 0);
671     }
672 
673     /// Returned event is on heap; caller takes responsibility for ownership
674     Event *getAsEvent(timeT absoluteTime) const;
675 
676 private:
677     bool isValid(const std::string &s) const;
678 
679     std::string m_indicationType;
680     timeT m_duration;
681 };
682 
683 /**
684  * Definitions for use in the Text event type
685  */
686 
687 class Text
688 {
689 public:
690     static const std::string EventType;
691     static const int EventSubOrdering;
692     static const PropertyName TextPropertyName;
693     static const PropertyName TextTypePropertyName;
694     static const PropertyName LyricVersePropertyName;
695 
696     /**
697      * Text styles
698      */
699     static const std::string UnspecifiedType;
700     static const std::string StaffName;
701     static const std::string ChordName;
702     static const std::string KeyName;
703     static const std::string Lyric;
704     static const std::string Chord;
705     static const std::string Dynamic;
706     static const std::string Direction;
707     static const std::string LocalDirection;
708     static const std::string Tempo;
709     static const std::string LocalTempo;
710     static const std::string Annotation;
711     static const std::string LilyPondDirective;
712 
713     /**
714      * Special LilyPond directives
715      */
716     static const std::string FakeSegno;   // print segno here
717     static const std::string FakeCoda;    // print coda sign here
718     static const std::string Alternate1;  // first alternative ending
719     static const std::string Alternate2;  // second alternative ending
720     static const std::string BarDouble;   // next barline is double
721     static const std::string BarEnd;      // next barline is final double
722     static const std::string BarDot;      // next barline is dotted
723     static const std::string Gliss;       // \glissando on this note (to next note)
724     static const std::string Arpeggio;    // \arpeggio on this chord
725 //    static const std::string ArpeggioUp;  // \ArpeggioUp on this chord
726 //    static const std::string ArpeggioDn;  // \ArpeggioDown on this chord
727     static const std::string Tiny;        // begin \tiny font section
728     static const std::string Small;       // begin \small font section
729     static const std::string NormalSize;  // begin \normalsize font section
730 
731     Text(const Event &e)
732         /* throw (Event::NoData, Event::BadType) */;
733     Text(const std::string &text,
734          const std::string &textType = UnspecifiedType);
735     Text(const Text &);
736     Text &operator=(const Text &);
737     ~Text();
738 
getText()739     std::string getText() const { return m_text; }
getTextType()740     std::string getTextType() const { return m_type; }
741 
742     // Relevant for lyrics, and borrowed for figuration IDs.
getVerse()743     int getVerse() const { return m_verse; }
setVerse(int verse)744     void setVerse(int verse) { m_verse = verse; }
745 
746     static bool isTextOfType(Event *, std::string type);
747 
748     /**
749      * Return those text types that the user should be allowed to
750      * specify directly and visually
751      */
752     static std::vector<std::string> getUserStyles();
753 
754     /**
755      * Return a list of available special LilyPond directives
756      */
757     static std::vector<std::string> getLilyPondDirectives();
758 
759     /// Returned event is on heap; caller takes responsibility for ownership
760     Event *getAsEvent(timeT absoluteTime) const;
761 
762 private:
763     std::string m_text;
764     std::string m_type;
765     long m_verse;
766 };
767 
768 
769 
770 /**
771  * Pitch stores a note's pitch and provides information about it in
772  * various different ways, notably in terms of the position of the
773  * note on the staff and its associated accidental.
774  *
775  * (See docs/discussion/units.txt for explanation of pitch units.)
776  *
777  * This completely replaces the older NotationDisplayPitch class.
778  */
779 
780 class ROSEGARDENPRIVATE_EXPORT Pitch
781 {
782 public:
783     /**
784      * Construct a Pitch object based on the given Event, which must
785      * have a BaseProperties::PITCH property.  If the property is
786      * absent, NoData is thrown.  The BaseProperties::ACCIDENTAL
787      * property will also be used if present.
788      */
789     Pitch(const Event &e)
790         /* throw Event::NoData */;
791 
792     /**
793      * Construct a Pitch object based on the given performance (MIDI) pitch.
794      */
795     Pitch(int performancePitch,
796           const Accidental &explicitAccidental = Accidentals::NoAccidental);
797 
798     /**
799      * Construct a Pitch based on octave and pitch in octave.  The
800      * lowest permissible octave number is octaveBase, and middle C is
801      * in octave octaveBase + 5.  pitchInOctave must be in the range
802      * 0-11 where 0 is C, 1 is C sharp, etc.
803      */
804     Pitch(int pitchInOctave, int octave,
805           const Accidental &explicitAccidental = Accidentals::NoAccidental,
806           int octaveBase = -2);
807 
808     /**
809      * Construct a Pitch based on octave and note in scale.  The
810      * lowest permissible octave number is octaveBase, and middle C is
811      * in octave octaveBase + 5.  The octave supplied should be that
812      * of the root note in the given key, which may be in a different
813      * MIDI octave from the resulting pitch (as MIDI octaves always
814      * begin at C).  noteInScale must be in the range 0-6 where 0 is
815      * the root of the key and so on.  The accidental is relative to
816      * noteInScale: if there is an accidental in the key for this note
817      * already, explicitAccidental will be "added" to it.
818      *
819      * For minor keys, the harmonic scale is used.
820      */
821     Pitch(int noteInScale, int octave, const Key &key,
822           const Accidental &explicitAccidental = Accidentals::NoAccidental,
823           int octaveBase = -2);
824 
825     /**
826      * Construct a Pitch based on (MIDI) octave, note in the C major scale and
827      * performance pitch. The accidental is calculated based on these
828      * properties.
829      */
830     Pitch(int noteInCMajor, int octave, int pitch,
831           int octaveBase = -2);
832 
833     /**
834      * Construct a Pitch based on octave and note name.  The lowest
835      * permissible octave number is octaveBase, and middle C is in
836      * octave octaveBase + 5.  noteName must be a character in the
837      * range [CDEFGAB] or lower-case equivalents.  The key is supplied
838      * so that we know how to interpret the NoAccidental case.
839      */
840     Pitch(char noteName, int octave, const Key &key,
841           const Accidental &explicitAccidental = Accidentals::NoAccidental,
842           int octaveBase = -2);
843 
844     /**
845      * Construct a Pitch corresponding a staff line or space on a
846      * classical 5-line staff.  The bottom staff line has height 0,
847      * the top has height 8, and both positive and negative values are
848      * permissible.
849      */
850     Pitch(int heightOnStaff, const Clef &clef, const Key &key,
851           const Accidental &explicitAccidental = Accidentals::NoAccidental);
852 
853     Pitch(const Pitch &);
854     Pitch &operator=(const Pitch &);
855 
856     /**
857      * Return the MIDI pitch for this Pitch object.
858      */
859     int getPerformancePitch() const;
860 
861     /**
862      * Return the accidental for this pitch using a bool to prefer sharps over
863      * flats if there is any doubt.  This is the accidental
864      * that would be used to display this pitch outside of the context
865      * of any key; that is, it may duplicate an accidental actually in
866      * the current key.  This should not be used if you need to get an
867      * explicit accidental returned for E#, Fb, B# or Cb.
868      *
869      * This version of the function exists to avoid breaking old code.
870      */
871     Accidental getAccidental(bool useSharps) const;
872 
873     /**
874      * Return the accidental for this pitch, using a key.  This should be used
875      * if you need an explicit accidental returned for E#, Fb, B# or Cb, which
876      * can't be resolved correctly without knowing that their key requires
877      * them to take an accidental.  The provided key will also be used to
878      * determine whether to prefer sharps over flats.
879      */
880     Accidental getAccidental(const Key &key) const;
881 
882     /**
883      * Return the accidental that should be used to display this pitch
884      * in a given key.  For example, if the pitch is F-sharp in a key
885      * in which F has a sharp, NoAccidental will be returned.  (This
886      * is in contrast to getAccidental, which would return Sharp.)
887      * This obviously can't take into account things like which
888      * accidentals have already been displayed in the bar, etc.
889      */
890     Accidental getDisplayAccidental(const Key &key) const;
891 
892     /**
893      * Return the accidental that should be used to display this pitch
894      * in a given key, using the given strategy to resolve pitches where
895      * an accidental is needed but not specified.
896      */
897     Accidental getDisplayAccidental(const Key &key, Accidentals::NoAccidentalStrategy) const;
898 
899     /**
900      * Return the position in the scale for this pitch, as a number in
901      * the range 0 to 6 where 0 is the root of the key.
902      */
903     int getNoteInScale(const Key &key) const;
904 
905     /**
906      * Return the note name for this pitch, as a single character in
907      * the range A to G.  (This is a reference value that should not
908      * normally be shown directly to the user, for i18n reasons.)
909      */
910     char getNoteName(const Key &key) const;
911 
912     /**
913      * Return the height at which this pitch should display on a
914      * conventional 5-line staff.  0 is the bottom line, 1 the first
915      * space, etc., so for example middle-C in the treble clef would
916      * return -2.
917      *
918      * Chooses the most likely accidental for this pitch in this key.
919      */
920     int getHeightOnStaff(const Clef &clef, const Key &key) const;
921 
922     /**
923      * Return the height at which this pitch should display on a
924      * conventional 5-line staff.  0 is the bottom line, 1 the first
925      * space, etc., so for example middle-C in the treble clef would
926      * return -2.
927      *
928      * Chooses the accidental specified by the 'useSharps' parameter
929      */
930     int getHeightOnStaff(const Clef &clef, bool useSharps) const;
931 
932     /**
933      * Return the octave containing this pitch.  The octaveBase argument
934      * specifies the octave containing MIDI pitch 0; middle-C is in octave
935      * octaveBase + 5.
936      */
937     int getOctave(int octaveBase = -2) const;
938 
939     /**
940      * Return the octave containing this pitch, including the accidentals.
941      * The octaveBase argument specifies the octave containing MIDI pitch 0;
942      * middle-C is in octave octaveBase + 5.
943      */
944     int getOctaveAccidental(int octaveBase = -2, Accidental acc = Accidentals::NoAccidental) const;
945 
946     /**
947      * Return the pitch within the octave, in the range 0 to 11.
948      */
949     int getPitchInOctave() const;
950 
951     /**
952      * Return whether this pitch is diatonic in the given key.
953      */
954     bool isDiatonicInKey(const Key &key) const;
955 
956     /**
957      * Return a reference name for this pitch.  (C 4, Bb 2, etc...)
958      * using the key of C major explicitly, which should allow the accidentals
959      * to take their natural forms of C# Eb F# G# Ab Bb from the key, rather
960      * than being forced sharp explicilty.
961      *
962      * This replaces an earlier version of this function that took a "use
963      * sharps" argument to return either sharps or flats, which broke after
964      * Arnout Engelen did some really nice accidental spelling improvements to
965      * make everything more human.
966      */
967     std::string getAsString(bool inclOctave = true,
968                             int octaveBase = -2) const;
969 
970     /**
971      * Return a number 0-6 corresponding to the given note name, which
972      * must be in the range [CDEFGAB] or lower-case equivalents.  The
973      * return value is in the range 0-6 with 0 for C, 1 for D etc.
974      */
975     static int getIndexForNote(char noteName);
976 
977     /**
978      * Return a note name corresponding to the given note index, which
979      * must be in the range 0-6 with 0 for C, 1 for D etc.
980      */
981     static char getNoteForIndex(int index);
982 
983     /**
984      * Calculate and return the performance (MIDI) pitch corresponding
985      * to the stored height and accidental, interpreting them as
986      * Rosegarden-2.1-style values (for backward compatibility use),
987      * in the given clef and key
988      */
989     static int getPerformancePitchFromRG21Pitch(int heightOnStaff,
990                                                 const Accidental &accidental,
991                                                 const Clef &clef,
992                                                 const Key &key);
993 
994     /**
995      * return the result of transposing the given pitch by the
996      * specified interval in the given key. The key is left unchanged,
997      * only the pitch is transposed.
998      */
999     Pitch transpose(const Key &key, int pitchDelta, int heightDelta);
1000 
1001     /**
1002       * checks whether the accidental specified for this pitch (if any)
1003       * is valid - for example, a Sharp for pitch 11 is invalid, as
1004       * it's between A# and B#.
1005       */
1006     bool validAccidental() const;
1007 
1008     /**
1009      * Returned event is on heap; caller takes responsibility for ownership
1010      */
1011     Event *getAsNoteEvent(timeT absoluteTime, timeT duration) const;
1012 
1013     /**
1014      * Get the major key that has this Pitch as the tonic
1015      */
1016     Key getAsKey() const;
1017 
1018     /**
1019      * Get the major or minor key that has this Pitch as the tonic
1020      */
1021     Key getAsKey(bool isMinor) const;
1022 
1023 private:
1024     int m_pitch;
1025     Accidental m_accidental;
1026 
1027     static void rawPitchToDisplayPitch
1028     (int, const Clef &, const Key &, int &, Accidental &,
1029     Accidentals::NoAccidentalStrategy);
1030 
1031     static void displayPitchToRawPitch
1032     (int, Accidental, const Clef &, const Key &,
1033      int &, bool ignoreOffset = false);
1034 };
1035 
1036 
1037 
1038 class TimeSignature;
1039 
1040 
1041 /**
1042  * The Note class represents note durations only, not pitch or
1043  * accidental; it's therefore just as relevant to rest events as to
1044  * note events.  You can construct one of these from either.
1045  */
1046 
1047 class ROSEGARDENPRIVATE_EXPORT Note
1048 {
1049 public:
1050     static const std::string EventType;
1051     static const std::string EventRestType;
1052     static const int EventRestSubOrdering;
1053 
1054     typedef int Type; // not an enum, too much arithmetic at stake
1055 
1056     // define both sorts of names; some people prefer the American
1057     // names, but I just can't remember which of them is which
1058 
1059     static const Type
1060 
1061         SixtyFourthNote     = 0,
1062         ThirtySecondNote    = 1,
1063         SixteenthNote       = 2,
1064         EighthNote          = 3,
1065         QuarterNote         = 4,
1066         HalfNote            = 5,
1067         WholeNote           = 6,
1068         DoubleWholeNote     = 7,
1069 
1070         Hemidemisemiquaver  = 0,
1071         Demisemiquaver      = 1,
1072         Semiquaver          = 2,
1073         Quaver              = 3,
1074         Crotchet            = 4,
1075         Minim               = 5,
1076         Semibreve           = 6,
1077         Breve               = 7,
1078 
1079         Shortest            = 0,
1080         Longest             = 7;
1081 
1082 
1083     /**
1084      * Create a Note object of the given type, representing a
1085      * particular sort of duration.  Note objects are strictly
1086      * durational; they don't represent pitch, and may be as
1087      * relevant to rests as actual notes.
1088      */
1089     Note(Type type, int dots = 0) :
1090         m_type(type < Shortest ? Shortest :
1091                type >  Longest ?  Longest :
1092                type),
1093         m_dots(dots) { }
1094 
Note(const Note & n)1095     Note(const Note &n) : m_type(n.m_type), m_dots(n.m_dots) { }
~Note()1096     ~Note() { }
1097 
1098     Note &operator=(const Note &n);
1099 
getNoteType()1100     Type getNoteType()  const { return m_type; }
getDots()1101     int  getDots()      const { return m_dots; }
1102 
1103     /**
1104      * Return the duration of this note type.
1105      */
getDuration()1106     timeT getDuration()  const {
1107         return m_dots ? getDurationAux() : (m_shortestTime * (1 << m_type));
1108     }
1109 
1110     /**
1111      * Return the Note whose duration is closest to (but shorter than or
1112      * equal to) the given duration, permitting at most maxDots dots.
1113      */
1114     static Note getNearestNote(timeT duration, int maxDots = 2);
1115 
1116     /// Returned event is on heap; caller takes responsibility for ownership
1117     Event *getAsNoteEvent(timeT absoluteTime, int pitch) const;
1118 
1119     /// Returned event is on heap; caller takes responsibility for ownership
1120     Event *getAsRestEvent(timeT absoluteTime) const;
1121 
1122 
1123 private:
1124     Type m_type;
1125     int m_dots;
1126 
1127     timeT getDurationAux()  const;
1128 
1129     // a time & effort saving device; if changing this, change
1130     // TimeSignature::m_crotchetTime etc too
1131     static const timeT m_shortestTime;
1132 };
1133 
1134 
1135 
1136 /**
1137  * TimeSignature contains arithmetic methods relevant to time
1138  * signatures and bar durations, including code for splitting long
1139  * rest intervals into bite-sized chunks.  Although there is a time
1140  * signature Event type, these Events don't appear in regular Segments
1141  * but only in the Composition's reference segment.
1142  */
1143 
1144 class ROSEGARDENPRIVATE_EXPORT TimeSignature
1145 {
1146 public:
1147     static const TimeSignature DefaultTimeSignature;
1148     typedef Exception BadTimeSignature;
1149 
TimeSignature()1150     TimeSignature() :
1151         m_numerator(DefaultTimeSignature.m_numerator),
1152         m_denominator(DefaultTimeSignature.m_denominator),
1153         m_common(false), m_hidden(false), m_hiddenBars(false) { }
1154 
1155     /**
1156      * Construct a TimeSignature object describing a time signature
1157      * with the given numerator and denominator.  If preferCommon is
1158      * true and the time signature is a common or cut-common time, the
1159      * constructed object will return true for isCommon; if hidden is
1160      * true, the time signature is intended not to be displayed and
1161      * isHidden will return true; if hiddenBars is true, the bar lines
1162      * between this time signature and the next will not be shown.
1163      */
1164     TimeSignature(int numerator, int denominator,
1165                   bool preferCommon = false,
1166                   bool hidden = false,
1167                   bool hiddenBars = false)
1168         /* throw (BadTimeSignature) */;
1169 
TimeSignature(const TimeSignature & ts)1170     TimeSignature(const TimeSignature &ts) :
1171         m_numerator(ts.m_numerator),
1172         m_denominator(ts.m_denominator),
1173         m_common(ts.m_common),
1174         m_hidden(ts.m_hidden),
1175         m_hiddenBars(ts.m_hiddenBars) { }
1176 
~TimeSignature()1177     ~TimeSignature() { }
1178 
1179     TimeSignature &operator=(const TimeSignature &ts);
1180 
1181     bool operator==(const TimeSignature &ts) const {
1182         return ts.m_numerator == m_numerator && ts.m_denominator == m_denominator;
1183     }
1184     bool operator!=(const TimeSignature &ts) const {
1185         return !operator==(ts);
1186     }
1187     bool operator<(const TimeSignature &ts) const {
1188         // We don't really need to ordered time signatures, but to be able to
1189         // create a map keyed with time signatures. We want to distinguish
1190         // 4/4 from 2/4 as well as 4/4 from 2/2.
1191         double ratio1 = (double) m_numerator / (double) m_denominator;
1192         double ratio2 = (double) ts.m_numerator / (double) ts.m_denominator;
1193         if (ratio1 == ratio2) return m_denominator > ts.m_denominator;
1194         else return ratio1 < ratio2;
1195     }
1196 
getNumerator()1197     int getNumerator()     const { return m_numerator; }
getDenominator()1198     int getDenominator()   const { return m_denominator; }
1199 
isCommon()1200     bool isCommon()        const { return m_common; }
isHidden()1201     bool isHidden()        const { return m_hidden; }
hasHiddenBars()1202     bool hasHiddenBars()   const { return m_hiddenBars; }
1203 
setHidden(bool hidden)1204     void setHidden(bool hidden) { m_hidden = hidden; }
1205 
1206     timeT getBarDuration() const;
1207 
1208     /**
1209      * Return the unit of the time signature.  This is the note
1210      * implied by the denominator.  For example, the unit of 4/4 time
1211      * is the crotchet, and that of 6/8 is the quaver.  (The numerator
1212      * of the time signature gives the number of units per bar.)
1213      */
1214     Note::Type getUnit()  const;
1215 
1216     /**
1217      * Return the duration of the unit of the time signature.
1218      * See also getUnit().  In most cases getBeatDuration() gives
1219      * a more meaningful value.
1220      */
1221     timeT getUnitDuration() const;
1222 
1223     /**
1224      * Return true if this time signature indicates dotted time.
1225      */
1226     bool isDotted() const;
1227 
1228     /**
1229      * Return the duration of the beat of the time signature.  For
1230      * example, the beat of 4/4 time is the crotchet, the same as its
1231      * unit, but that of 6/8 is the dotted crotchet (there are only
1232      * two beats in a 6/8 bar).  The beat therefore depends on whether
1233      * the signature indicates dotted or undotted time.
1234      */
1235     timeT getBeatDuration() const;
1236 
1237     /**
1238      * Return the number of beats in a complete bar.
1239      */
getBeatsPerBar()1240     int getBeatsPerBar()  const {
1241         return getBarDuration() / getBeatDuration();
1242     }
1243 
1244     /**
1245      * Get the "optimal" list of rest durations to make up a bar in
1246      * this time signature.
1247      */
1248     void getDurationListForBar(DurationList &dlist) const;
1249 
1250     /**
1251      * Get the "optimal" list of rest durations to make up a time
1252      * interval of the given total duration, starting at the given
1253      * offset after the start of a bar, assuming that the interval
1254      * is entirely in this time signature.
1255      */
1256     void getDurationListForInterval(DurationList &dlist,
1257                                     timeT intervalDuration,
1258                                     timeT startOffset = 0) const;
1259 
1260     /**
1261      * Get the level of emphasis for a position in a bar. 4 is lots
1262      * of emphasis, 0 is none.
1263      */
1264     int getEmphasisForTime(timeT offset);
1265 
1266     /**
1267      * Return a list of divisions, subdivisions, subsubdivisions
1268      * etc of a bar in this time, up to the given depth.  For example,
1269      * if the time signature is 6/8 and the depth is 3, return a list
1270      * containing 2, 3, and 2 (there are 2 beats to the bar, each of
1271      * which is best subdivided into 3 subdivisions, each of which
1272      * divides most neatly into 2).
1273      */
1274     void getDivisions(int depth, std::vector<int> &divisions) const;
1275 
1276 private:
1277     friend class Composition;
1278     friend class TimeTempoSelection;
1279 
1280     TimeSignature(const Event &e)
1281         /* throw (Event::NoData, Event::BadType, BadTimeSignature) */;
1282 
1283     static const std::string EventType;
1284     static const int EventSubOrdering;
1285     static const PropertyName NumeratorPropertyName;
1286     static const PropertyName DenominatorPropertyName;
1287     static const PropertyName ShowAsCommonTimePropertyName;
1288     static const PropertyName IsHiddenPropertyName;
1289     static const PropertyName HasHiddenBarsPropertyName;
1290 
1291     /// Returned event is on heap; caller takes responsibility for ownership
1292     Event *getAsEvent(timeT absoluteTime) const;
1293 
1294 private:
1295     int m_numerator;
1296     int m_denominator;
1297 
1298     bool m_common;
1299     bool m_hidden;
1300     bool m_hiddenBars;
1301 
1302     mutable int  m_barDuration;
1303     mutable int  m_beatDuration;
1304     mutable int  m_beatDivisionDuration;
1305     mutable bool m_dotted;
1306     void setInternalDurations() const;
1307 
1308     // a time & effort saving device
1309     static const timeT m_crotchetTime;
1310     static const timeT m_dottedCrotchetTime;
1311 };
1312 
1313 
1314 
1315 /**
1316  * AccidentalTable represents a set of accidentals in force at a
1317  * given time.
1318  *
1319  * Keep an AccidentalTable variable on-hand as you track through a
1320  * staff; then when reading a chord, call processDisplayAccidental
1321  * on the accidentals found in the chord to obtain the actual
1322  * displayed accidentals and to tell the AccidentalTable to
1323  * remember the accidentals that have been found in the chord.
1324  * Then when the chord ends, call update() on the AccidentalTable
1325  * so that that chord's accidentals are taken into account for the
1326  * next one.
1327  *
1328  * Create a new AccidentalTable whenever a new key is encountered,
1329  * and call newBar() or newClef() when a new bar happens or a new
1330  * clef is encountered.
1331  */
1332 class ROSEGARDENPRIVATE_EXPORT AccidentalTable
1333 {
1334 public:
1335     enum OctaveType {
1336         OctavesIndependent, // if c' and c'' sharp, mark them both sharp
1337         OctavesCautionary,  // if c' and c'' sharp, put the second one in brackets
1338         OctavesEquivalent   // if c' and c'' sharp, only mark the first one
1339     };
1340 
1341     enum BarResetType {
1342         BarResetNone,       // c# | c -> omit natural
1343         BarResetCautionary, // c# | c -> add natural to c in brackets
1344         BarResetExplicit    // c# | c -> add natural to c
1345     };
1346 
1347     AccidentalTable(const Key & = Key(), const Clef & = Clef(),
1348                     OctaveType = OctavesCautionary,
1349                     BarResetType = BarResetCautionary);
1350 
1351     AccidentalTable(const AccidentalTable &);
1352     AccidentalTable &operator=(const AccidentalTable &);
1353 
1354     Accidental processDisplayAccidental(const Accidental &displayAcc,
1355                                         int heightOnStaff,
1356                                         bool &cautionary);
1357 
1358     void update();
1359 
1360     void newBar();
1361     void newClef(const Clef &);
1362 
1363 private:
1364     Key m_key;
1365     Clef m_clef;
1366     OctaveType m_octaves;
1367     BarResetType m_barReset;
1368 
1369     struct AccidentalRec {
AccidentalRecAccidentalRec1370         AccidentalRec() : accidental(Accidentals::NoAccidental), previousBar(false) { }
AccidentalRecAccidentalRec1371         AccidentalRec(Accidental a, bool p) : accidental(a), previousBar(p) { }
1372         Accidental accidental;
1373         bool previousBar;
1374     };
1375 
1376     typedef std::map<int, AccidentalRec> AccidentalMap;
1377 
1378     AccidentalMap m_accidentals;
1379     AccidentalMap m_canonicalAccidentals;
1380 
1381     AccidentalMap m_newAccidentals;
1382     AccidentalMap m_newCanonicalAccidentals;
1383 };
1384 
1385 
1386 /** Definitions for use in the Symbol event type
1387  *
1388  * A Symbol has no duration, and the things it represents will probably always
1389  * be no-ops that are never interpreted by the sequencer or MIDI export engines
1390  *
1391  * \author D. Michael McIntyre
1392  */
1393 class ROSEGARDENPRIVATE_EXPORT Symbol
1394 {
1395 public:
1396     static const std::string EventType;
1397     static const int EventSubOrdering;
1398     static const PropertyName SymbolTypePropertyName;
1399 
1400     /**
1401      * Symbol types
1402      */
1403     static const std::string UnspecifiedType;
1404     static const std::string Segno;
1405     static const std::string Coda;
1406     static const std::string Breath;
1407 
1408     Symbol(const Event &e)
1409         /* throw (Event::NoData, Event::BadType) */;
1410     Symbol(const std::string &symbolType = UnspecifiedType);
1411     Symbol(const Symbol &);
1412     Symbol &operator=(const Symbol &);
1413     ~Symbol ();
1414 
getSymbolType()1415     std::string getSymbolType() const { return m_type; }
1416 
1417     static bool isSymbolOfType(Event *, std::string type);
1418 
1419     /// Returned event is on heap; caller takes responsibility for ownership
1420     Event *getAsEvent(timeT absoluteTime) const;
1421 
1422 private:
1423     std::string m_type;
1424 };
1425 
1426 }
1427 
1428 
1429 #endif
1430