1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 4 /* 5 Rosegarden 6 A sequencer and musical notation editor. 7 Copyright 2000-2021 the Rosegarden development team. 8 See the AUTHORS file for more details. 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License as 12 published by the Free Software Foundation; either version 2 of the 13 License, or (at your option) any later version. See the file 14 COPYING included with this distribution for more information. 15 */ 16 17 #ifndef RG_SEGMENT_H 18 #define RG_SEGMENT_H 19 20 #include <set> 21 #include <list> 22 #include <string> 23 #include <memory> 24 25 #include "Track.h" 26 #include "Event.h" 27 #include "base/NotationTypes.h" 28 #include "RefreshStatus.h" 29 #include "RealTime.h" 30 #include "MidiProgram.h" 31 #include "MidiTypes.h" // for Controller::EventType 32 33 #include <QColor> 34 #include <QSharedPointer> 35 36 namespace Rosegarden 37 { 38 39 /// A refresh flag with a time range. 40 class SegmentRefreshStatus : public RefreshStatus 41 { 42 public: SegmentRefreshStatus()43 SegmentRefreshStatus() : m_from(0), m_to(0) {} 44 45 void push(timeT from, timeT to); 46 from()47 timeT from() const { return m_from; } to()48 timeT to() const { return m_to; } 49 50 protected: 51 timeT m_from; 52 timeT m_to; 53 }; 54 55 class SegmentObserver; 56 class Quantizer; 57 class BasicQuantizer; 58 class Composition; 59 class SegmentLinker; 60 class BasicCommand; 61 62 /// Container of Event objects. 63 /** 64 * EventContainer is a precursor to Segment, used in code that needs 65 * to store events but doesn't need all the ancillary data and 66 * behaviors that Segment provides. 67 * 68 * ??? The STL container classes are not intended to be derived from. 69 * They provide no virtual dtor. EventContainer should instead 70 * have a std::multiset member object. 71 */ 72 class ROSEGARDENPRIVATE_EXPORT EventContainer : public std::multiset<Event*, Event::EventCmp> 73 { 74 public: 75 iterator findEventOfType(iterator i, const std::string &type); 76 }; 77 78 /// Container of Event objects. 79 /** 80 * Segment is the container for a set of Events that are all played on 81 * the same track. Each event has an absolute starting time, 82 * which is used as the index within the segment. Multiple events may 83 * have the same absolute time. 84 * 85 * (For example, chords are represented simply as a sequence of notes 86 * that share a starting time. The Segment can contain counterpoint -- 87 * notes that overlap, rather than starting and ending together -- but 88 * in practice it's probably too hard to display so we should make 89 * more than one Segment if we want to represent true counterpoint.) 90 * 91 * If you want to carry out notation-related editing operations on 92 * a Segment, take a look at SegmentNotationHelper. If you want to play a 93 * Segment, try SegmentPerformanceHelper for duration calculations. 94 * 95 * The Segment owns the Events its items are pointing at. 96 */ 97 class ROSEGARDENPRIVATE_EXPORT Segment : public QObject, public EventContainer 98 { 99 Q_OBJECT 100 101 public: 102 103 /// A Segment contains either Internal representation or Audio 104 typedef enum { 105 Internal, // ??? rename: MIDI 106 Audio 107 } SegmentType; 108 109 /** 110 * The manners in which a segment can participate in the 111 * composition. The ones other than `normal' are for various 112 * forms of dummies for display or editing. 113 */ 114 typedef enum { 115 normal, 116 editableClone, 117 readOnly, 118 justForShow, 119 } Participation; 120 121 /** 122 * Construct a Segment of a given type with a given formal starting time. 123 */ 124 Segment(SegmentType segmentType = Internal, 125 timeT startTime = 0); 126 127 /** 128 * Virtual copy constructor interface, in case this is actually a linked segment 129 * (or potentially any other type derived from Segment) 130 * @param deep true to return a deep copy, false to return just a segment 131 * containing a copy of the events of this 132 */ 133 Segment* clone(bool deep = true) const 134 { 135 if(deep) { return cloneImpl(); } 136 else { return new Segment(*this); } 137 } 138 139 protected: 140 /** 141 * Virtual copy constructor implementation 142 */ 143 virtual Segment* cloneImpl() const; 144 145 /** 146 * Copy constructor - protected to encourage use of the clone function 147 * when a copy is required 148 */ 149 Segment(const Segment&); 150 151 public: 152 ~Segment() override; 153 154 155 ////// 156 // 157 // BASIC SEGMENT ATTRIBUTES 158 159 /** 160 * Get the Segment type (Internal or Audio) 161 */ getType()162 SegmentType getType() const { return m_type; } isMIDI()163 bool isMIDI() const { return (m_type == Internal); } isAudio()164 bool isAudio() const { return (m_type == Audio); } 165 166 /** 167 * Get the element name this class will have when serialised 168 */ getXmlElementName()169 virtual QString getXmlElementName() const { return "segment"; } 170 171 /** 172 * Note that a Segment does not have to be in a Composition; 173 * if it isn't, this will return zero 174 */ getComposition()175 Composition *getComposition() const { 176 if (isTmp()) { 177 return getRealSegment()->getComposition(); 178 } else { 179 return m_composition; 180 } 181 } 182 183 // Get the track ID this Segment is associated with. 184 /** 185 * rename: getTrackId() 186 */ getTrack()187 TrackId getTrack() const { return m_trackId; } 188 189 /// Set the track ID this Segment is associated with. 190 /** 191 * rename: setTrackId() 192 */ 193 void setTrack(TrackId trackId); 194 195 /** 196 * Values other than `normal' make the segment act like it's not 197 * really in the composition. Eg, setTrack won't actually move it 198 * to track N. Actually attaching/detaching it from the 199 * Composition is not handled by this. 200 */ setParticipation(Participation participation)201 void setParticipation(Participation participation) 202 { m_participation = participation; } 203 getParticipation()204 Participation getParticipation() 205 { return m_participation; } 206 207 // label 208 // 209 void setLabel(const std::string &label); getLabel()210 std::string getLabel() const { return m_label; } 211 212 // Colour information 213 void setColourIndex(const unsigned int input); getColourIndex()214 unsigned int getColourIndex() const { return m_colourIndex; } 215 /// Get a high-contrast color to use for segment previews 216 QColor getPreviewColour() const; 217 218 /** 219 * Returns a numeric id of some sort 220 * The id is guaranteed to be unique within the segment, but not to 221 * have any other interesting properties 222 */ 223 int getNextId() const; 224 225 /** 226 * Returns a MIDI pitch representing the highest suggested playable note for 227 * notation contained in this segment, as a convenience reminder to composers. 228 * 229 * This property, and its corresponding lowest note counterpart, initialize by 230 * default such that no limitation is imposed. (lowest = 0, highest = 127) 231 */ getHighestPlayable()232 int getHighestPlayable() { return m_highestPlayable; } 233 234 /** 235 * Set the highest suggested playable note for this segment 236 */ setHighestPlayable(int pitch)237 void setHighestPlayable(int pitch) { m_highestPlayable = pitch; } 238 239 /** 240 * Returns a MIDI pitch representing the lowest suggested playable note for 241 * notation contained in this segment, as a convenience reminder to composers 242 */ getLowestPlayable()243 int getLowestPlayable() { return m_lowestPlayable; } 244 245 /** 246 * Set the highest suggested playable note for this segment 247 */ setLowestPlayable(int pitch)248 void setLowestPlayable(int pitch) { m_lowestPlayable = pitch; } 249 250 251 ////// 252 // 253 // TIME & DURATION VALUES 254 255 /** 256 * Return the start time of the Segment. For a non-audio 257 * Segment, this is the start time of the first event in it. 258 */ 259 timeT getStartTime() const; 260 261 /** 262 * Return the start time of the Segment, clipped so that if there is a 263 * Composition, this will not return a time earlier than the Composition 264 * start marker. (Used to constrain edit views non-destructively.) 265 */ 266 timeT getClippedStartTime() const; 267 268 /** 269 * Return the nominal end time of the Segment. This must 270 * be the same as or earlier than the getEndTime() value. 271 * The return value will not necessarily be that last set 272 * with setEndMarkerTime, as if there is a Composition its 273 * end marker will also be used for clipping. 274 * comp = true truncates endmarker time based on composition 275 * end. comp = false disregards composition end. 276 */ 277 timeT getEndMarkerTime(bool comp = true) const; 278 279 /** 280 * Return the time of the end of the last event stored in the 281 * Segment. This time may be outside the audible/editable 282 * range of the Segment, depending on the location of the end 283 * marker. 284 */ 285 timeT getEndTime() const; 286 287 /** 288 * Shift the start time of the Segment by moving the start 289 * times of all the events in the Segment. 290 */ 291 void setStartTime(timeT); 292 293 /** 294 * DO NOT USE THIS METHOD 295 * Simple accessor for the m_startTime member. Used by 296 * Composition#setSegmentStartTime 297 */ setStartTimeDataMember(timeT t)298 void setStartTimeDataMember(timeT t) { m_startTime = t; } 299 300 /** 301 * Set the end marker (nominal end time) of this Segment. 302 * 303 * If the given time is later than the current end of the 304 * Segment's storage, extend the Segment by filling it with 305 * rests; if earlier, simply move the end marker. The end 306 * marker time may not precede the start time. 307 */ 308 void setEndMarkerTime(timeT); 309 310 /** 311 * Set the end time of the Segment. 312 * 313 * If the given time is later than the current end of the 314 * Segment's storage, extend the Segment by filling it with 315 * rests; if earlier, shorten it by throwing away events as 316 * necessary (though do not truncate any events) and also move 317 * the end marker to the given time. The end time may not 318 * precede the start time. 319 * 320 * Note that simply inserting an event beyond the end of the 321 * Segment will also change the end time, although it does 322 * not fill with rests in the desirable way. 323 * 324 * Consider using setEndMarkerTime in preference to this. 325 */ 326 void setEndTime(timeT); 327 328 /** 329 * Return an iterator pointing to the nominal end of the 330 * Segment. This may be earlier than the end() iterator. 331 */ 332 iterator getEndMarker() const; 333 334 /** 335 * Return true if the given iterator points earlier in the 336 * Segment than the nominal end marker. You can use this 337 * as an extent test in code such as 338 * 339 * while (segment.isBeforeEndMarker(my_iterator)) { 340 * // ... 341 * ++my_iterator; 342 * } 343 * 344 * It is not generally safe to write 345 * 346 * while (my_iterator != segment.getEndMarker()) { 347 * // ... 348 * ++my_iterator; 349 * } 350 * 351 * as the loop will not terminate if my_iterator's initial 352 * value is already beyond the end marker. (Also takes the 353 * Composition's end marker into account.) 354 */ 355 bool isBeforeEndMarker(const_iterator) const; 356 357 /** 358 * Remove the end marker, thus making the Segment end 359 * at its storage end time (unless the Composition's 360 * end marker is earlier). 361 */ 362 void clearEndMarker(); 363 364 /** 365 * Return the end marker in raw form, that is, a pointer to 366 * its value or null if none is set. Does not take the 367 * composition's end marker into account. 368 */ 369 const timeT *getRawEndMarkerTime() const; 370 371 ////// 372 // 373 // QUANTIZATION 374 375 /** 376 * Switch quantization on or off. 377 */ 378 void setQuantization(bool quantize); 379 380 /** 381 * Find out whether quantization is on or off. 382 */ 383 bool hasQuantization() const; 384 385 /** 386 * Set the quantization level. 387 * (This does not switch quantization on, if it's currently off, 388 * it only changes the level that will be used when it's next 389 * switched on.) 390 */ 391 void setQuantizeLevel(timeT unit); 392 393 /** 394 * Get the quantizer currently in (or not in) use. 395 */ getQuantizer()396 QSharedPointer<const BasicQuantizer> getQuantizer() const 397 { return m_quantizer; } 398 399 400 401 ////// 402 // 403 // EVENT MANIPULATION 404 405 /// Insert a single Event 406 iterator insert(Event *e); 407 408 /// Erase a single Event 409 void erase(iterator pos); 410 411 /// Erase a set of Events 412 void erase(iterator from, iterator to); 413 414 /// Clear the segment. clear()415 void clear() { erase(begin(), end()); } 416 417 /** 418 * Looks up an Event and if it finds it, erases it. 419 * @return true if the event was found and erased, false otherwise. 420 */ 421 bool eraseSingle(Event*); 422 423 /** 424 * Returns an iterator pointing to that specific element, 425 * end() otherwise 426 */ 427 iterator findSingle(Event*); 428 findSingle(Event * e)429 const_iterator findSingle(Event *e) const { 430 return const_iterator(((Segment *)this)->findSingle(e)); 431 } 432 433 /** 434 * Returns an iterator pointing to the first element starting at 435 * or beyond the given absolute time 436 */ 437 iterator findTime(timeT time); 438 findTime(timeT time)439 const_iterator findTime(timeT time) const { 440 return const_iterator(((Segment *)this)->findTime(time)); 441 } 442 443 /** 444 * Returns an iterator pointing to the first element starting at 445 * or before the given absolute time (so returns end() if the 446 * time precedes the first event, not if it follows the last one) 447 */ 448 iterator findNearestTime(timeT time); 449 findNearestTime(timeT time)450 const_iterator findNearestTime(timeT time) const { 451 return const_iterator(((Segment *)this)->findNearestTime(time)); 452 } 453 454 455 ////// 456 // 457 // ADVANCED, ESOTERIC, or PLAIN STUPID MANIPULATION 458 459 /** 460 * Returns the range [start, end[ of events which are at absoluteTime 461 */ 462 void getTimeSlice(timeT absoluteTime, iterator &start, iterator &end); 463 464 /** 465 * Returns the range [start, end[ of events which are at absoluteTime 466 */ 467 void getTimeSlice(timeT absoluteTime, const_iterator &start, const_iterator &end) const; 468 469 /** 470 * Return the starting time of the bar that contains time t. This 471 * differs from Composition's bar methods in that it will truncate 472 * to the start and end times of this Segment, and is guaranteed 473 * to return the start time of a bar that is at least partially 474 * within this Segment. 475 * 476 * (See Composition for most of the generally useful bar methods.) 477 */ 478 timeT getBarStartForTime(timeT t) const; 479 480 /** 481 * Return the ending time of the bar that contains time t. This 482 * differs from Composition's bar methods in that it will truncate 483 * to the start and end times of this Segment, and is guaranteed 484 * to return the end time of a bar that is at least partially 485 * within this Segment. 486 * 487 * (See Composition for most of the generally useful bar methods.) 488 */ 489 timeT getBarEndForTime(timeT t) const; 490 491 /** 492 * Fill up the segment with rests, from the end of the last event 493 * currently on the segment to the endTime given. Actually, this 494 * does much the same as setEndTime does when it extends a segment. 495 */ 496 void fillWithRests(timeT endTime); 497 498 /** 499 * Fill up a section within a segment with rests, from the 500 * startTime given to the endTime given. This may be useful if 501 * you have a pathological segment that contains notes already but 502 * not rests, but it is is likely to be dangerous unless you're 503 * quite careful about making sure the given range doesn't overlap 504 * any notes. 505 */ 506 void fillWithRests(timeT startTime, timeT endTime); 507 508 /** 509 * For each series of contiguous rests found between the start and 510 * end time, replace the series of rests with another series of 511 * the same duration but composed of the theoretically "correct" 512 * rest durations to fill the gap, in the current time signature. 513 * The start and end time should be the raw absolute times of the 514 * events, not the notation-quantized versions, although the code 515 * will use the notation quantizations if it finds them. 516 */ 517 void normalizeRests(timeT startTime, timeT endTime); 518 519 /** 520 * Return the clef in effect at the given time. This is a 521 * reasonably quick call. 522 */ 523 Clef getClefAtTime(timeT time) const; 524 525 /** 526 * Return the clef in effect at the given time, and set ctime to 527 * the time of the clef change. This is a reasonably quick call. 528 */ 529 Clef getClefAtTime(timeT time, timeT &ctime) const; 530 531 /** 532 * If there is another clef change following the given time, 533 * return its time in nextTime and return true. If there is no 534 * further clef change after the given time, return false. This 535 * is a reasonably quick call. 536 */ 537 bool getNextClefTime(timeT time, timeT &nextTime) const; 538 539 /** 540 * Return the key signature in effect at the given time. This is 541 * a reasonably quick call. 542 */ 543 Key getKeyAtTime(timeT time) const; 544 545 /** 546 * Return the key signature in effect at the given time, and set 547 * ktime to the time of the key change. This is a reasonably 548 * quick call. 549 */ 550 Key getKeyAtTime(timeT time, timeT &ktime) const; 551 552 /** 553 * If there is another key change following the given time, return 554 * its time in nextTime and return true. If there is no further 555 * key change after the given time, return false. This is a 556 * reasonably quick call. 557 */ 558 bool getNextKeyTime(timeT time, timeT &nextTime) const; 559 560 /** 561 * Return the clef and key signature in effect at the beginning of the 562 * segment using the following rules : 563 * 564 * - Return the default clef if no clef change is preceding the first 565 * note or rest event, 566 * - else return the first clef event in the segment, 567 * - else return the default clef if the segment has no note event nor 568 * clef change in it. 569 * 570 * - Use the same rules with the key signature. 571 */ 572 void getFirstClefAndKey(Clef &clef, Key &key); 573 574 /** 575 * If segment doesn't begin with a clef and a key signature, insert 576 * default clef and/or key signature as needed. 577 */ 578 void enforceBeginWithClefAndKey(); 579 580 /** 581 * Stop sending move or resize notifications to the observers. 582 * (May be useful to avoid sending lot of unnecessary resize notifications 583 * when a segment is deleted then rebuild event by event while a linked 584 * segment is processed). 585 * Should be used with caution! 586 */ 587 void lockResizeNotifications(); 588 589 /** 590 * Revert lockResizeNotifications() effect. If segment has been move 591 * or resized, send one, and only one, notification to the observers. 592 * Should only be called after lockResizeNotifications() has been called. 593 * Nested lock/unlock calls are not allowed currently. 594 */ 595 void unlockResizeNotifications(); 596 597 /** 598 * YG: This one is only for debug 599 */ 600 void dumpObservers(); 601 602 603 ////// 604 // 605 // REPEAT, DELAY, TRANSPOSE 606 607 // Is this Segment repeating? 608 // isRepeating()609 bool isRepeating() const { return m_repeating; } 610 void setRepeating(bool value); 611 612 613 /** 614 * If this Segment is repeating, calculate and return the time at 615 * which the repeating stops. 616 * This is the time of the first part of another Segment on the same 617 * Track, if any, which follows the end of this Segment. 618 * If there is not such a Segment, instead return the end time of the 619 * Segment. 620 */ 621 timeT getRepeatEndTime() const; 622 getDelay()623 timeT getDelay() const { return m_delay; } 624 void setDelay(timeT delay); 625 getRealTimeDelay()626 RealTime getRealTimeDelay() const { return m_realTimeDelay; } 627 void setRealTimeDelay(RealTime delay); 628 getTranspose()629 int getTranspose() const { return m_transpose; } 630 void setTranspose(int transpose); 631 632 /** 633 * Return the number of verses in the lyrics. 634 */ 635 int getVerseCount(); 636 637 /** 638 * Ask to recompute the number of verses the next time getVerseCount() 639 * will be running. 640 * This method must be called each time verses are added or removed. 641 */ invalidateVerseCount()642 void invalidateVerseCount() { m_verseCount = -1; } 643 644 /** 645 * Return the verse index of lyrics associated with the segment if 646 * this one is unfolded in the notation editor. 647 * (ie the verse which have to be written under the staff among all the 648 * verses included as text of lyrics inside the segment) 649 */ getVerse()650 int getVerse() const { return m_verse; } 651 652 /** 653 * Return the verse index of lyrics associated with the segment if 654 * this one is unfolded in the notation editor. 655 * As getVerse(), but return again the first verses when going beyond 656 * the total verses count. 657 */ 658 int getVerseWrapped(); 659 660 /** 661 * Used to set the value returned by getVerse(). 662 * Should only be called from a method recomputing verse for all 663 * the segments in composition (or for the temporary segments in 664 * a notation editor) 665 */ setVerse(int verse)666 void setVerse (int verse) { m_verse = verse; } 667 668 669 670 ////// 671 // 672 // AUDIO 673 674 // Get and set Audio file Id (see the AudioFileManager) 675 // getAudioFileId()676 unsigned int getAudioFileId() const { return m_audioFileId; } 677 void setAudioFileId(unsigned int id); 678 getUnstretchedFileId()679 unsigned int getUnstretchedFileId() const { return m_unstretchedFileId; } 680 void setUnstretchedFileId(unsigned int id); 681 getStretchRatio()682 float getStretchRatio() const { return m_stretchRatio; } 683 void setStretchRatio(float ratio); 684 685 // The audio start and end times tell us how far into 686 // audio file "m_audioFileId" this Segment starts and 687 // how far into the sample the Segment finishes. 688 // getAudioStartTime()689 RealTime getAudioStartTime() const { return m_audioStartTime; } getAudioEndTime()690 RealTime getAudioEndTime() const { return m_audioEndTime; } 691 void setAudioStartTime(const RealTime &time); 692 void setAudioEndTime(const RealTime &time); 693 isAutoFading()694 bool isAutoFading() const { return m_autoFade; } 695 void setAutoFade(bool value); 696 getFadeInTime()697 RealTime getFadeInTime() const { return m_fadeInTime; } 698 void setFadeInTime(const RealTime &time); 699 getFadeOutTime()700 RealTime getFadeOutTime() const { return m_fadeOutTime; } 701 void setFadeOutTime(const RealTime &time); 702 703 ////// 704 // 705 // MISCELLANEOUS 706 707 /// Should only be called by Composition setComposition(Composition * composition)708 void setComposition(Composition *composition) { 709 m_composition = composition; 710 } 711 712 // The runtime id for this segment 713 // getRuntimeId()714 int getRuntimeId() const { return m_runtimeSegmentId; } 715 716 // Grid size for matrix view (and others probably) 717 // setSnapGridSize(int size)718 void setSnapGridSize(int size) { m_snapGridSize = size; } getSnapGridSize()719 int getSnapGridSize() const { return m_snapGridSize; } 720 721 // Other view features we might want to set on this Segment 722 // setViewFeatures(int features)723 void setViewFeatures(int features) { m_viewFeatures = features; } getViewFeatures()724 int getViewFeatures() const { return m_viewFeatures; } 725 726 /// Zoom factor for Matrix. 727 double matrixHZoomFactor; 728 /// Zoom factor for Matrix. 729 double matrixVZoomFactor; 730 731 struct Ruler 732 { RulerRuler733 Ruler() : type(), ccNumber(0) { }; 734 735 // Values: 736 // "controller" (Controller::EventType) - Controller ruler. 737 // "pitchbend" (PitchBend::EventType) - PitchBend ruler. 738 // "velocity" (BaseProperties::VELOCITY.getName()) - Velocity ruler. 739 std::string type; 740 741 // Specific CC number for Controller::EventType. 742 int ccNumber; 743 744 bool operator<(const Ruler &r) const 745 { 746 if (type == Controller::EventType && 747 r.type == Controller::EventType) 748 return (ccNumber < r.ccNumber); 749 else 750 return (type < r.type); 751 } 752 }; 753 typedef std::set<Ruler> RulerSet; 754 755 /// Rulers for the Matrix editor. 756 std::shared_ptr<RulerSet> matrixRulers; 757 /// Rulers for the Notation editor. 758 std::shared_ptr<RulerSet> notationRulers; 759 760 /** 761 * The compare class used by Composition 762 */ 763 struct SegmentCmp 764 { operatorSegmentCmp765 bool operator()(const Segment* a, const Segment* b) const 766 { 767 if (a->getTrack() == b->getTrack()) 768 return a->getStartTime() < b->getStartTime(); 769 770 return a->getTrack() < b->getTrack(); 771 } 772 }; 773 774 // This is a std::multiset because the segments aren't indexed by 775 // pointer address, they are indexed by track, then start time on 776 // a track (see SegmentCmp). And it is not unusual for two 777 // Segments to start at the same time on the same track. 778 // ??? rename: SegmentMultiSet 779 typedef std::multiset<Segment *, Segment::SegmentCmp> SegmentMultiSet; 780 781 // Get the segments in the current composition. 782 static SegmentMultiSet& getCompositionSegments(); 783 784 void addObserver(SegmentObserver *obs); 785 void removeObserver(SegmentObserver *obs); 786 787 ////// 788 // 789 // REFRESH STATUS 790 791 // delegate part of the RefreshStatusArray API 792 getNewRefreshStatusId()793 unsigned int getNewRefreshStatusId() { 794 return m_refreshStatusArray.getNewRefreshStatusId(); 795 } 796 getRefreshStatus(unsigned int id)797 SegmentRefreshStatus &getRefreshStatus(unsigned int id) { 798 return m_refreshStatusArray.getRefreshStatus(id); 799 } 800 801 void updateRefreshStatuses(timeT startTime, timeT endTime); 802 803 ////// 804 // 805 // LINKED SEGMENTS 806 807 /** 808 * Return true if the segment is connected to a SegmentLinker. 809 * This doesn't always mean that the segment is really linked : 810 * - The segment may be the only one referenced by the SegmentLinker. 811 * (Probably this should not be, but nevertheless is not impossible.) 812 * - The segment is a repeating one opened in the notation editor. 813 * It is a linked segment, but linked with temporary segments which 814 * composition doesn't know. 815 */ isLinked()816 bool isLinked() const { return m_segmentLinker; } 817 818 /** 819 * Return true if the segment is link to at least one other segment 820 * which is not a temporary one nor being outside ofthe composition 821 * (i.e. deleted). 822 */ 823 bool isTrulyLinked() const; 824 825 /** 826 * Return true if the segment is "truly link" and doesn't embbed any 827 * local change (as transpositon...). 828 * This method is intended to help exporting linked segments as repeat with 829 * volta in LilyPond. 830 */ 831 bool isPlainlyLinked() const; 832 833 /** 834 * Return true if the given segment is linked to this. 835 */ 836 bool isLinkedTo(Segment *) const; 837 838 /** 839 * Return true if the given segment is a plain link linked to the current 840 * object which is equally a plain link 841 */ 842 bool isPlainlyLinkedTo(Segment *) const; 843 getLinker()844 SegmentLinker * getLinker() const { return m_segmentLinker; } setLinker(SegmentLinker * linker)845 void setLinker(SegmentLinker *linker) { m_segmentLinker = linker; } 846 847 struct LinkTransposeParams 848 { LinkTransposeParamsLinkTransposeParams849 LinkTransposeParams() : m_changeKey(false), m_steps(0), 850 m_semitones(0), m_transposeSegmentBack(false) { } LinkTransposeParamsLinkTransposeParams851 LinkTransposeParams(bool chKey, int steps, int stones, bool transBack) : 852 m_changeKey(chKey), m_steps(steps), m_semitones(stones), 853 m_transposeSegmentBack(transBack) { } 854 bool m_changeKey; 855 int m_steps; 856 int m_semitones; 857 bool m_transposeSegmentBack; 858 }; getLinkTransposeParams()859 LinkTransposeParams getLinkTransposeParams() const { 860 return m_linkTransposeParams; } setLinkTransposeParams(LinkTransposeParams params)861 void setLinkTransposeParams(LinkTransposeParams params) { 862 m_linkTransposeParams = params; } 863 864 /** 865 * Set the segment as a temporary one. 866 * A temporary segment is always linked to some "real segment" and is not 867 * known from the composition. Such a segment is only intended to 868 * live inside one view. 869 */ 870 void setTmp(); 871 872 /** 873 * Report if the segment is "tmp" 874 */ isTmp()875 bool isTmp() const { return m_isTmp; } 876 877 /** 878 * Set the segment to display as greyed out, a visual indication 879 * that it is temporary or read-only. 880 **/ 881 void setGreyOut(); 882 883 /** 884 * Set the current segment as the reference of the linked segment group and 885 * return true. 886 * Return false if the segment is not linked and can't have a reference. 887 */ 888 bool setAsReference(); 889 890 /** 891 * Return pointer to current segment if not linked else return pointer 892 * to segment used as reference. 893 * May return 0 if segment is linked but no reference is defined. 894 */ 895 Segment * getRealSegment(); 896 897 /** 898 * Return pointer to current segment if not linked else return pointer 899 * to segment used as reference. 900 * May return 0 if segment is linked but no reference is defined. 901 */ 902 const Segment * getRealSegment() const; 903 904 /** 905 * Set the flag f for using this segment in notation. 906 * If all is false, the flag is not set for the linked segments. 907 * The default is to set the flag for each of the linked segments. 908 */ 909 void setForNotation(bool f, bool all = true); 910 911 /** 912 * Get the flag for using this segment in notation 913 */ 914 bool getForNotation() const; 915 916 /// Mark a Segment 917 /** 918 * Used by NotationView::slotAddLayer() and NotationView::slotMagicLayer(). 919 * 920 * This allows a Segment to be passed amongst the various steps of the 921 * add layer and "magic layer" (new layer from selection) processes. 922 * 923 * Only one Segment can have a given marking. setMarking() enforces this. 924 * 925 * This could be reduced to a bool if marking is only used for this purpose. 926 */ 927 void setMarking(const QString &m, Composition *comp); 928 /// Get the marking for AddLayerCommand. 929 /** 930 * This is used (eventually) by NotationView to select the Segment that 931 * was just created by AddLayerCommand. 932 */ getMarking()933 QString getMarking() const { return m_marking; } 934 935 private: 936 void checkInsertAsClefKey(Event *e) const; 937 938 /** 939 * (Re)compute the internally remembered verse count. 940 * Used by getVerseCount(). 941 */ 942 void countVerses(); 943 944 Composition *m_composition; // owns me, if it exists 945 946 timeT m_startTime; 947 timeT *m_endMarkerTime; // points to end time, or null if none 948 timeT m_endTime; 949 950 void updateEndTime(); // called after erase of item at end 951 952 TrackId m_trackId; 953 SegmentType m_type; // identifies Segment type 954 std::string m_label; // segment label 955 956 unsigned int m_colourIndex; // identifies Colour Index (default == 0) 957 958 mutable int m_id; // not id of Segment, but a value for return by getNextId 959 960 unsigned int m_audioFileId; // audio file ID (see AudioFileManager) 961 unsigned int m_unstretchedFileId; 962 float m_stretchRatio; 963 RealTime m_audioStartTime; // start time relative to start of audio file 964 RealTime m_audioEndTime; // end time relative to start of audio file 965 966 bool m_repeating; // is this segment repeating? 967 968 QSharedPointer<BasicQuantizer> m_quantizer; 969 bool m_quantize; 970 971 int m_transpose; // all Events tranpose 972 timeT m_delay; // all Events delay 973 RealTime m_realTimeDelay; // all Events delay (the delays are cumulative) 974 975 int m_highestPlayable; // suggestion for highest playable note (notation) 976 int m_lowestPlayable; // suggestion for lowest playable note (notation) 977 978 int m_percussionPitch; // pitch at which note events will display 979 980 RefreshStatusArray<SegmentRefreshStatus> m_refreshStatusArray; 981 982 struct ClefKeyCmp { 983 bool operator()(const Event *e1, const Event *e2) const; 984 }; 985 typedef std::multiset<Event*, ClefKeyCmp> ClefKeyList; 986 mutable ClefKeyList *m_clefKeyList; 987 988 /// Marking for AddLayerCommand. See setMarking(). 989 QString m_marking; 990 991 private: // stuff to support SegmentObservers 992 993 typedef std::list<SegmentObserver *> ObserverSet; 994 ObserverSet m_observers; 995 996 void notifyAdd(Event *) const; 997 void notifyRemove(Event *) const; 998 void notifyAppearanceChange() const; 999 void notifyStartChanged(timeT); 1000 void notifyEndMarkerChange(bool shorten); 1001 void notifyTransposeChange(); 1002 void notifySourceDeletion() const; 1003 1004 bool m_notifyResizeLocked; 1005 timeT m_memoStart; 1006 timeT *m_memoEndMarkerTime; 1007 1008 signals: 1009 void contentsChanged(timeT start, timeT end); 1010 public: signalChanged(timeT start,timeT end)1011 void signalChanged(timeT start, timeT end) 1012 { emit contentsChanged(start,end); } 1013 1014 private: 1015 1016 // assignment operator not provided 1017 Segment &operator=(const Segment &); 1018 1019 // Used for mapping the segment to runtime things like PlayableAudioFiles at 1020 // the sequencer. 1021 // 1022 int m_runtimeSegmentId; 1023 1024 // Remember the last used snap grid size for this segment 1025 // 1026 int m_snapGridSize; 1027 1028 // Switch for other view-specific features we want to remember in the segment 1029 // 1030 int m_viewFeatures; 1031 1032 // Audio autofading 1033 // 1034 bool m_autoFade; 1035 RealTime m_fadeInTime; 1036 RealTime m_fadeOutTime; 1037 1038 // Linked segments 1039 SegmentLinker *m_segmentLinker; 1040 LinkTransposeParams m_linkTransposeParams; 1041 bool m_isTmp; // Mark a segment (must be a link) as temporary 1042 1043 /** 1044 * Values other than `normal' make the segment act like it's not 1045 * really in the composition. Eg, setTrack won't actually move it 1046 * to track N. 1047 */ 1048 Participation m_participation; 1049 int m_verseCount; // -1 means not computed still 1050 int m_verse; // Used to distribute lyrics among repeated segments 1051 1052 bool m_forNotation; 1053 1054 }; 1055 1056 ROSEGARDENPRIVATE_EXPORT QDebug &operator<<(QDebug &, const Rosegarden::Segment &); 1057 1058 // Make it a global name. 1059 typedef Segment::SegmentMultiSet SegmentMultiSet; 1060 1061 /// Base class interface for Segment notifications. 1062 /** 1063 * See Segment::addObserver() and Segment::m_observers. 1064 */ 1065 class ROSEGARDENPRIVATE_EXPORT SegmentObserver 1066 { 1067 public: ~SegmentObserver()1068 virtual ~SegmentObserver() {} 1069 1070 /// Called after an event has been added to the segment. eventAdded(const Segment *,Event *)1071 virtual void eventAdded(const Segment *, Event *) { } 1072 1073 /** 1074 * Called after the event has been removed from the segment, 1075 * and just before it is deleted 1076 */ eventRemoved(const Segment *,Event *)1077 virtual void eventRemoved(const Segment *, Event *) { } 1078 1079 // Exists just for performance reasons. Called in lieu of calling 1080 // eventAdded or eventRemoved many times. The default just calls 1081 // both eventRemoved() and eventAdded() on every event. 1082 virtual void allEventsChanged(const Segment *); 1083 1084 /** 1085 * Called after a change in the segment that will change the way its displays, 1086 * like a label change for instance 1087 */ appearanceChanged(const Segment *)1088 virtual void appearanceChanged(const Segment *) { } 1089 1090 /// Called after a change that affects the start time of the segment. startChanged(const Segment *,timeT)1091 virtual void startChanged(const Segment *, timeT) { } 1092 1093 /// Called after the segment's end marker time has been changed. 1094 /** 1095 * @param shorten true if the marker change shortens the segment's duration 1096 */ endMarkerTimeChanged(const Segment *,bool)1097 virtual void endMarkerTimeChanged(const Segment *, bool /*shorten*/) { } 1098 1099 /// Called after a change of the segment transposition. transposeChanged(const Segment *,int)1100 virtual void transposeChanged(const Segment *, int /*transpose*/) { } 1101 1102 /** 1103 * Called from the segment dtor 1104 * All observers must implement this and call removeObserver() to 1105 * remove themselves as observers. 1106 */ 1107 virtual void segmentDeleted(const Segment *) = 0; 1108 }; 1109 1110 1111 class ROSEGARDENPRIVATE_EXPORT SegmentHelper 1112 { 1113 protected: SegmentHelper(Segment & t)1114 SegmentHelper(Segment &t) : m_segment(t) { } 1115 virtual ~SegmentHelper(); 1116 1117 typedef Segment::iterator iterator; 1118 segment()1119 Segment &segment() { return m_segment; } 1120 begin()1121 Segment::iterator begin() { return segment().begin(); } end()1122 Segment::iterator end() { return segment().end(); } 1123 isBeforeEndMarker(Segment::const_iterator i)1124 bool isBeforeEndMarker(Segment::const_iterator i) { 1125 return segment().isBeforeEndMarker(i); 1126 } 1127 insert(Event * e)1128 Segment::iterator insert(Event *e) { return segment().insert(e); } erase(Segment::iterator i)1129 void erase(Segment::iterator i) { segment().erase(i); } 1130 1131 private: 1132 Segment &m_segment; 1133 }; 1134 1135 } 1136 1137 1138 #endif 1139