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