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_COMPOSITION_H 17 #define RG_COMPOSITION_H 18 19 20 #include "RealTime.h" 21 #include "base/Segment.h" 22 #include "Track.h" 23 #include "Configuration.h" 24 #include "XmlExportable.h" 25 #include "ColourMap.h" 26 #include "TriggerSegment.h" 27 28 #include "Marker.h" 29 30 // Qt 31 #include <QtCore/QWeakPointer> 32 33 // System 34 #include <set> 35 #include <map> 36 37 namespace Rosegarden 38 { 39 // We store tempo in quarter-notes per minute * 10^5 (hundred 40 // thousandths of a quarter-note per minute). This means the maximum 41 // tempo in a 32-bit integer is about 21400 qpm. We use a signed int 42 // for compatibility with the Event integer type -- but note that we 43 // use 0 (rather than -1) to indicate "tempo not set", by convention 44 // (though see usage of target tempo in e.g. addTempoAtTime). 45 typedef int tempoT; 46 47 class Quantizer; 48 class BasicQuantizer; 49 class NotationQuantizer; 50 51 class CompositionObserver; 52 53 /// Composition contains a complete representation of a piece of music. 54 /** 55 * It is a container for multiple Segment objects (m_segments), as well as 56 * any associated non-Event data. 57 * 58 * The Composition owns the Segment objects it holds, and deletes them on 59 * destruction. See deleteSegment() and detachSegment(). 60 */ 61 class ROSEGARDENPRIVATE_EXPORT Composition : public XmlExportable 62 { 63 friend class Track; // to call notifyTrackChanged() 64 friend class Segment; // to call notifySegmentRepeatChanged() 65 66 public: 67 typedef SegmentMultiSet::iterator iterator; 68 typedef SegmentMultiSet::const_iterator const_iterator; 69 70 typedef std::vector<Segment *> SegmentVec; 71 72 typedef std::map<TrackId, Track*> trackcontainer; 73 typedef trackcontainer::iterator trackiterator; 74 typedef trackcontainer::const_iterator trackconstiterator; 75 76 typedef std::vector<Marker*> markercontainer; 77 typedef markercontainer::iterator markeriterator; 78 typedef markercontainer::const_iterator markerconstiterator; 79 80 typedef std::set<TriggerSegmentRec *, TriggerSegmentCmp> triggersegmentcontainer; 81 typedef triggersegmentcontainer::iterator triggersegmentcontaineriterator; 82 typedef triggersegmentcontainer::const_iterator triggersegmentcontainerconstiterator; 83 84 typedef std::set<TrackId> recordtrackcontainer; 85 typedef recordtrackcontainer::iterator recordtrackiterator; 86 typedef recordtrackcontainer::const_iterator recordtrackconstiterator; 87 88 Composition(); 89 ~Composition() override; 90 91 private: 92 Composition(const Composition &); 93 Composition &operator=(const Composition &); 94 public: 95 96 /** 97 * Remove everything from the Composition. 98 */ 99 void clear(); 100 101 /** 102 * Return the absolute end time of the segment that ends last 103 */ 104 timeT getDuration() const; 105 106 107 ////// 108 // 109 // START AND END MARKERS 110 getStartMarker()111 timeT getStartMarker() const { return m_startMarker; } getEndMarker()112 timeT getEndMarker() const { return m_endMarker; } autoExpandEnabled()113 bool autoExpandEnabled() { return m_autoExpand; } 114 115 void setStartMarker(const timeT &sM); 116 void setEndMarker(const timeT &eM); setAutoExpand(bool autoExpand)117 void setAutoExpand(bool autoExpand) { m_autoExpand = autoExpand; } 118 119 120 ////// 121 // 122 // INSTRUMENT & TRACK 123 124 Track* getTrackById(TrackId track) const; 125 126 bool haveTrack(TrackId track) const; 127 128 Track* getTrackByPosition(int position) const; 129 130 int getTrackPositionById(TrackId track) const; // -1 if not found 131 getTracks()132 trackcontainer& getTracks() { return m_tracks; } 133 getTracks()134 const trackcontainer& getTracks() const { return m_tracks; } 135 136 // Reset id and position 137 // unused 138 // void resetTrackIdAndPosition(TrackId oldId, TrackId newId, int position); 139 140 TrackId getMinTrackId() const; 141 TrackId getMaxTrackId() const; 142 getRecordTracks()143 const recordtrackcontainer &getRecordTracks() const { return m_recordTracks; } 144 void setTrackRecording(TrackId track, bool recording); 145 bool isTrackRecording(TrackId track) const; 146 bool isInstrumentRecording(InstrumentId instrumentID) const; 147 148 /** 149 * rename: getSelectedTrackId() 150 * 151 * @see setSelectedTrack() 152 */ getSelectedTrack()153 TrackId getSelectedTrack() const { return m_selectedTrackId; } 154 155 InstrumentId getSelectedInstrumentId() const; 156 157 /** 158 * rename: setSelectedTrackId() 159 * 160 * @see getSelectedTrack() 161 */ 162 void setSelectedTrack(TrackId trackId); 163 164 /// Total number of tracks in the composition. getNbTracks()165 unsigned int getNbTracks() const { return m_tracks.size(); } 166 167 /** 168 * Clear out the Track container 169 */ 170 void clearTracks(); 171 172 /** 173 * Insert a new Track. The Composition takes over ownership of 174 * the track object. 175 */ 176 void addTrack(Track *track); 177 178 /** 179 * Delete a Track by index 180 */ 181 // unused 182 // void deleteTrack(TrackId track); 183 184 /** 185 * Detach a Track (revert ownership of the Track object to the 186 * caller). 187 */ 188 bool detachTrack(Track *track); 189 190 /** 191 * Get the highest running track id (generated and kept 192 * through addTrack) 193 */ 194 TrackId getNewTrackId() const; 195 196 bool hasTrack(InstrumentId) const; 197 198 /** 199 * Get the Instrument Id of a given segment. 200 **/ getInstrumentId(const Segment * segment)201 InstrumentId getInstrumentId(const Segment *segment) const { 202 if (!segment) 203 return NoInstrument; 204 205 const Track *track = getTrackById(segment->getTrack()); 206 if (!track) 207 return NoInstrument; 208 209 return track->getInstrument(); 210 }; 211 212 /** 213 * Get all segments that play on the same instrument segment s 214 * plays on and start before t. 215 */ 216 SegmentMultiSet getInstrumentSegments(Segment *s, timeT t) const; 217 218 ////// 219 // 220 // MARKERS 221 getMarkers()222 markercontainer& getMarkers() { return m_markers; } getMarkers()223 const markercontainer& getMarkers() const { return m_markers; } 224 225 /** 226 * Add a new Marker. The Composition takes ownership of the 227 * marker object. 228 */ 229 void addMarker(Marker *marker); 230 231 /** 232 * Detach a Marker (revert ownership of the Marker object to the 233 * caller). 234 */ 235 bool detachMarker(Marker *marker); 236 237 // unused 238 // bool isMarkerAtPosition(timeT time) const; 239 240 void clearMarkers(); 241 242 243 ////// 244 // 245 // SEGMENT 246 getSegments()247 SegmentMultiSet& getSegments() { return m_segments; } getSegments()248 const SegmentMultiSet& getSegments() const { return m_segments; } 249 250 Segment* getSegmentByMarking(const QString& Marking) const; 251 getNbSegments()252 unsigned int getNbSegments() const { return m_segments.size(); } 253 254 /** 255 * Add a new Segment and return an iterator pointing to it 256 * The inserted Segment is owned by the Composition object 257 */ 258 iterator addSegment(Segment*); 259 260 /** 261 * Delete the Segment pointed to by the specified iterator 262 * 263 * NOTE: The Segment is deleted from the Composition and 264 * destroyed 265 */ 266 void deleteSegment(iterator); 267 268 /** 269 * Delete the Segment if it is part of the Composition 270 * \return true if the Segment was found and deleted 271 * 272 * NOTE: The Segment is deleted from the composition and 273 * destroyed 274 */ 275 bool deleteSegment(Segment*); 276 277 /** 278 * DO NOT USE THIS METHOD 279 * 280 * Set a Segment's start time while keeping the integrity of the 281 * Composition multiset. 282 * 283 * The segment is removed and re-inserted from the composition 284 * so the ordering is preserved. 285 */ 286 void setSegmentStartTime(Segment*, timeT); 287 288 /** 289 * Test whether a Segment exists in this Composition. 290 */ 291 bool contains(const Segment *); 292 293 /** 294 * Return an iterator pointing at the given Segment, or end() 295 * if it does not exist in this Composition. 296 */ 297 iterator findSegment(const Segment *); 298 299 /** 300 * Remove the Segment if it is part of the Composition, 301 * but do not destroy it (passing it to addSegment again 302 * would restore it correctly). 303 * \return true if the Segment was found and removed 304 * 305 * NOTE: Many of the Segment methods will fail if the 306 * Segment is not in a Composition. You should not 307 * expect to do anything meaningful with a Segment that 308 * has been detached from the Composition in this way. 309 */ 310 bool detachSegment(Segment*); 311 312 /** 313 * Add a new Segment which has been "weakly detached" 314 * 315 * Like addSegment(), but doesn't send the segmentAdded signal 316 * nor updating refresh statuses 317 */ 318 iterator weakAddSegment(Segment*); 319 320 /** 321 * Detach a segment which you're going to re-add (with weakAddSegment) 322 * later. 323 * Like detachSegment(), but without sending the segmentDeleted signal 324 * nor updating refresh statuses. 325 */ 326 bool weakDetachSegment(Segment*); 327 328 /** 329 * Get the largest number of segments that "overlap" at any one 330 * time on the given track. I have given this function a nice 331 * long name to make it feel important. 332 */ 333 int getMaxContemporaneousSegmentsOnTrack(TrackId track) const; 334 335 /** 336 * Retrieve a "vertical" index for this segment within its track. 337 * Currently this is based on studying the way that segments on 338 * the track overlap and returning the lowest integer such that no 339 * prior starting segment that overlaps with this one would use 340 * the same integer. In future this could use proper voice 341 * ordering. 342 */ 343 int getSegmentVoiceIndex(const Segment *) const; 344 345 /** 346 * Add every segment in SegmentMultiSet 347 */ 348 void addAllSegments(SegmentMultiSet segments); 349 void addAllSegments(SegmentVec segments); 350 351 /** 352 * Detach every segment in SegmentMultiSet 353 */ 354 void detachAllSegments(SegmentMultiSet segments); 355 void detachAllSegments(SegmentVec segments); 356 357 ////// 358 // 359 // TRIGGER SEGMENTS 360 getTriggerSegments()361 triggersegmentcontainer &getTriggerSegments() { return m_triggerSegments; } getTriggerSegments()362 const triggersegmentcontainer &getTriggerSegments() const { return m_triggerSegments; } 363 364 /** 365 * Add a new trigger Segment with a given base pitch and base 366 * velocity, and return its record. If pitch or velocity is -1, 367 * it will be taken from the first note event in the segment 368 */ 369 TriggerSegmentRec *addTriggerSegment(Segment *, int pitch = -1, int velocity = -1); 370 371 /** 372 * Delete a trigger Segment. 373 */ 374 void deleteTriggerSegment(TriggerSegmentId); 375 376 /** 377 * Detach a trigger Segment from the Composition. 378 */ 379 void detachTriggerSegment(TriggerSegmentId); 380 381 /** 382 * Delete all trigger Segments. 383 */ 384 void clearTriggerSegments(); 385 386 /** 387 * Return the TriggerSegmentId for the given Segment, or -1 if it is 388 * not a trigger Segment. 389 */ 390 int getTriggerSegmentId(Segment *); 391 392 /** 393 * Return the Segment for a given TriggerSegmentId 394 */ 395 Segment *getTriggerSegment(TriggerSegmentId); 396 397 /** 398 * Return the TriggerSegmentRec (with Segment, base pitch, base velocity, 399 * references etc) for a given TriggerSegmentId 400 */ 401 TriggerSegmentRec *getTriggerSegmentRec(TriggerSegmentId); 402 403 /** 404 * As above for a given Event, or nullptr if none. 405 **/ 406 TriggerSegmentRec *getTriggerSegmentRec(Event* e); 407 /** 408 * Add a new trigger Segment with a given ID and base pitch and 409 * velocity. Fails and returns 0 if the ID is already in use. 410 * This is intended for use from file load or from undo/redo. 411 */ 412 TriggerSegmentRec *addTriggerSegment(Segment *, TriggerSegmentId, 413 int basePitch = -1, int baseVelocity = -1); 414 415 /** 416 * Get the ID of the next trigger segment that will be inserted. 417 */ 418 TriggerSegmentId getNextTriggerSegmentId() const; 419 420 /** 421 * Specify the next trigger ID. This is intended for use from file 422 * load only. Do not use this function unless you know what you're 423 * doing. 424 */ 425 void setNextTriggerSegmentId(TriggerSegmentId); 426 427 /** 428 * Update the trigger segment references for all trigger segments. 429 * To be called after file load. 430 */ 431 void updateTriggerSegmentReferences(); 432 433 /** 434 * Clear refresh statuses of SegmentLinker after file load. 435 */ 436 void resetLinkedSegmentRefreshStatuses(); 437 438 ////// 439 // 440 // BAR 441 442 /** 443 * Return the total number of bars in the composition 444 */ 445 int getNbBars() const; 446 447 /** 448 * Return the number of the bar that starts at or contains time t. 449 * 450 * Will happily return computed bar numbers for times before 451 * the start or beyond the real end of the composition. 452 */ 453 int getBarNumber(timeT t) const; 454 455 /** 456 * Return the starting time of bar n 457 */ getBarStart(int n)458 timeT getBarStart(int n) const { 459 return getBarRange(n).first; 460 } 461 462 /** 463 * Return the ending time of bar n 464 */ getBarEnd(int n)465 timeT getBarEnd(int n) const { 466 return getBarRange(n).second; 467 } 468 469 /** 470 * Return the time range of bar n. 471 * 472 * Will happily return theoretical timings for bars before the 473 * start or beyond the end of composition (i.e. there is no 474 * requirement that 0 <= n < getNbBars()). 475 */ 476 std::pair<timeT, timeT> getBarRange(int n) const; 477 478 /** 479 * Return the starting time of the bar that contains time t 480 */ getBarStartForTime(timeT t)481 timeT getBarStartForTime(timeT t) const { 482 return getBarRangeForTime(t).first; 483 } 484 485 /** 486 * Return the ending time of the bar that contains time t 487 */ getBarEndForTime(timeT t)488 timeT getBarEndForTime(timeT t) const { 489 return getBarRangeForTime(t).second; 490 } 491 492 /** 493 * Return the starting and ending times of the bar that contains 494 * time t. 495 * 496 * Will happily return theoretical timings for bars before the 497 * start or beyond the end of composition. 498 * 499 * ??? typedef std::pair<timeT, timeT> BarRange; 500 */ 501 std::pair<timeT, timeT> getBarRangeForTime(timeT t) const; 502 503 504 ////// 505 // 506 // TIME SIGNATURE 507 508 /** 509 * Add the given time signature at the given time. Returns the 510 * resulting index of the time signature (suitable for passing 511 * to removeTimeSignature, for example) 512 */ 513 int addTimeSignature(timeT t, TimeSignature timeSig); 514 515 /** 516 * Return the time signature in effect at time t 517 */ 518 TimeSignature getTimeSignatureAt(timeT t) const; 519 520 /** 521 * Return the time signature in effect at time t, and the time at 522 * which it came into effect 523 */ 524 timeT getTimeSignatureAt(timeT, TimeSignature &) const; 525 526 /** 527 * Return the time signature in effect in bar n. Also sets 528 * isNew to true if the time signature is a new one that did 529 * not appear in the previous bar. 530 */ 531 TimeSignature getTimeSignatureInBar(int n, bool &isNew) const; 532 533 /** 534 * Return the total number of time signature changes in the 535 * composition. 536 */ 537 int getTimeSignatureCount() const; 538 539 /** 540 * Return the index of the last time signature change before 541 * or at the given time, in a range suitable for passing to 542 * getTimeSignatureChange. Return -1 if there has been no 543 * time signature by this time. 544 */ 545 int getTimeSignatureNumberAt(timeT time) const; 546 547 /** 548 * Return the absolute time of and time signature introduced 549 * by time-signature change n. 550 */ 551 std::pair<timeT, TimeSignature> getTimeSignatureChange(int n) const; 552 553 /** 554 * Remove time signature change event n from the composition. 555 */ 556 void removeTimeSignature(int n); 557 558 559 560 ////// 561 // 562 // TEMPO 563 564 /** 565 * Return the (approximate) number of quarters per minute for a 566 * given tempo. 567 */ getTempoQpm(tempoT tempo)568 static double getTempoQpm(tempoT tempo) { return double(tempo) / 100000.0; } getTempoForQpm(double qpm)569 static tempoT getTempoForQpm(double qpm) { return tempoT(qpm * 100000 + 0.01); } 570 571 /** 572 * Return the tempo in effect at time t. If a ramped tempo change 573 * is in effect at the time, it will be properly interpolated and 574 * a computed value returned. 575 */ 576 tempoT getTempoAtTime(timeT t) const; 577 578 /** 579 * Return the tempo in effect at the current playback position. 580 */ getCurrentTempo()581 tempoT getCurrentTempo() const { return getTempoAtTime(getPosition()); } 582 583 /** 584 * Set a default tempo for the composition. This will be 585 * overridden by any tempo events encountered during playback. 586 */ setCompositionDefaultTempo(tempoT tempo)587 void setCompositionDefaultTempo(tempoT tempo) { m_defaultTempo = tempo; } getCompositionDefaultTempo()588 tempoT getCompositionDefaultTempo() const { return m_defaultTempo; } 589 590 /** 591 * Add a tempo-change event at the given time, to the given tempo. 592 * Removes any existing tempo event at that time. Returns the 593 * index of the new tempo event in a form suitable for passing to 594 * removeTempoChange. 595 * 596 * If targetTempo == -1, adds a single constant tempo change. 597 * If targetTempo == 0, adds a smooth tempo ramp from this tempo 598 * change to the next. 599 * If targetTempo > 0, adds a smooth tempo ramp from this tempo 600 * ending at targetTempo at the time of the next tempo change. 601 */ 602 int addTempoAtTime(timeT time, tempoT tempo, tempoT targetTempo = -1); 603 604 /** 605 * Return the number of tempo changes in the composition. 606 */ 607 int getTempoChangeCount() const; 608 609 /** 610 * Return the index of the last tempo change before the given 611 * time, in a range suitable for passing to getTempoChange. 612 * Return -1 if the default tempo is in effect at this time. 613 */ 614 int getTempoChangeNumberAt(timeT time) const; 615 616 /** 617 * Return the absolute time of and tempo introduced by tempo 618 * change number n. If the tempo is ramped, this returns only 619 * the starting tempo. 620 */ 621 std::pair<timeT, tempoT> getTempoChange(int n) const; 622 623 /** 624 * Return whether the tempo change number n is a ramped tempo or 625 * not, and if it is, return the target tempo for the ramp. 626 * 627 * If calculate is false, return a target tempo of 0 if the tempo 628 * change is defined to ramp to the following tempo. If calculate 629 * is true, return a target tempo equal to the following tempo in 630 * this case. 631 */ 632 std::pair<bool, tempoT> getTempoRamping(int n, bool calculate = true) const; 633 634 /** 635 * Remove tempo change event n from the composition. 636 */ 637 void removeTempoChange(int n); 638 639 /** 640 * Get the slowest assigned tempo in the composition. 641 */ getMinTempo()642 tempoT getMinTempo() const { 643 return ((m_minTempo != 0) ? m_minTempo : m_defaultTempo); 644 } 645 646 /** 647 * Get the fastest assigned tempo in the composition. 648 */ getMaxTempo()649 tempoT getMaxTempo() const { 650 return ((m_maxTempo != 0) ? m_maxTempo : m_defaultTempo); 651 } 652 653 654 ////// 655 // 656 // REAL TIME 657 658 /** 659 * Return the number of microseconds elapsed between 660 * the beginning of the composition and the given timeT time. 661 * (timeT units are independent of tempo; this takes into 662 * account any tempo changes in the first t units of time.) 663 * 664 * This is a fairly efficient operation, not dependent on the 665 * magnitude of t or the number of tempo changes in the piece. 666 */ 667 RealTime getElapsedRealTime(timeT t) const; 668 669 /** 670 * Return the nearest time in timeT units to the point at the 671 * given number of microseconds after the beginning of the 672 * composition. (timeT units are independent of tempo; this takes 673 * into account any tempo changes in the first t microseconds.) 674 * The result will be approximate, as timeT units are obviously 675 * less precise than microseconds. 676 * 677 * This is a fairly efficient operation, not dependent on the 678 * magnitude of t or the number of tempo changes in the piece. 679 */ 680 timeT getElapsedTimeForRealTime(RealTime t) const; 681 682 /** 683 * Return the number of microseconds elapsed between 684 * the two given timeT indices into the composition, taking 685 * into account any tempo changes between the two times. 686 */ getRealTimeDifference(timeT t0,timeT t1)687 RealTime getRealTimeDifference(timeT t0, timeT t1) const { 688 if (t1 > t0) return getElapsedRealTime(t1) - getElapsedRealTime(t0); 689 else return getElapsedRealTime(t0) - getElapsedRealTime(t1); 690 } 691 692 static tempoT 693 timeRatioToTempo(RealTime &realTime, 694 timeT beatTime, tempoT rampTo); 695 696 ////// 697 // 698 // OTHER TIME CONVERSIONS 699 700 /** 701 * Return (by reference) the bar number and beat/division values 702 * corresponding to a given absolute time. 703 */ 704 void getMusicalTimeForAbsoluteTime(timeT absoluteTime, 705 int &bar, int &beat, 706 int &fraction, int &remainder); 707 708 /** 709 * Return (by reference) the number of bars and beats/divisions 710 * corresponding to a given duration. The absolute time at which 711 * the duration starts is also required, so as to know the correct 712 * time signature. 713 */ 714 void getMusicalTimeForDuration(timeT absoluteTime, timeT duration, 715 int &bars, int &beats, 716 int &fractions, int &remainder); 717 718 /** 719 * Return the absolute time corresponding to a given bar number 720 * and beat/division values. 721 */ 722 timeT getAbsoluteTimeForMusicalTime(int bar, int beat, 723 int fraction, int remainder); 724 725 /** 726 * Return the duration corresponding to a given number of bars and 727 * beats/divisions. The absolute time at which the duration 728 * starts is also required, so as to know the correct time 729 * signature. 730 */ 731 timeT getDurationForMusicalTime(timeT absoluteTime, 732 int bars, int beats, 733 int fractions, int remainder); 734 735 736 /** 737 * Get the current playback position. 738 */ getPosition()739 timeT getPosition() const { return m_position; } 740 741 /** 742 * Set the current playback position. 743 */ 744 void setPosition(timeT position); 745 746 747 748 ////// 749 // 750 // LOOP 751 getLoopStart()752 timeT getLoopStart() const { return m_loopStart; } getLoopEnd()753 timeT getLoopEnd() const { return m_loopEnd;} 754 setLoopStart(const timeT & lS)755 void setLoopStart(const timeT &lS) { m_loopStart = lS; } setLoopEnd(const timeT & lE)756 void setLoopEnd(const timeT &lE) { m_loopEnd = lE; } 757 758 // Determine if we're currently looping 759 // isLooping()760 bool isLooping() const { return (m_loopStart != m_loopEnd); } 761 762 763 764 ////// 765 // 766 // OTHER STUFF 767 768 769 // Some set<> API delegation 770 /// Segment begin iterator. begin()771 iterator begin() { return m_segments.begin(); } 772 /// Segment begin iterator. begin()773 const_iterator begin() const { return m_segments.begin(); } 774 /// Segment end iterator. end()775 iterator end() { return m_segments.end(); } 776 /// Segment end iterator. end()777 const_iterator end() const { return m_segments.end(); } 778 779 780 // XML exportable method 781 // 782 std::string toXmlString() const override; 783 784 // Who's making this racket? 785 // getMetadata()786 Configuration &getMetadata() { 787 return m_metadata; 788 } getMetadata()789 const Configuration &getMetadata() const { 790 return m_metadata; 791 } 792 getCopyrightNote()793 std::string getCopyrightNote() const { 794 return m_metadata.get<String>(CompositionMetadataKeys::Copyright, 795 ""); 796 } setCopyrightNote(const std::string & cr)797 void setCopyrightNote(const std::string &cr) { 798 m_metadata.set<String>(CompositionMetadataKeys::Copyright, cr); 799 } 800 801 802 // We can have the metronome on or off while playing or 803 // recording - get and set values from here 804 // usePlayMetronome()805 bool usePlayMetronome() const { return m_playMetronome; } useRecordMetronome()806 bool useRecordMetronome() const { return m_recordMetronome; } 807 808 void setPlayMetronome(bool value); 809 void setRecordMetronome(bool value); 810 811 812 // Colour stuff getSegmentColourMap()813 ColourMap& getSegmentColourMap() { return m_segmentColourMap; } getSegmentColourMap()814 const ColourMap& getSegmentColourMap() const { return m_segmentColourMap; } 815 void setSegmentColourMap(ColourMap &newmap); 816 817 // General colourmap for non-segments 818 // getGeneralColourMap()819 ColourMap& getGeneralColourMap() { return m_generalColourMap; } 820 void setGeneralColourMap(ColourMap &newmap); 821 822 /// NotationView spacing 823 int m_notationSpacing; 824 825 826 ////// 827 // 828 // QUANTIZERS 829 830 /** 831 * Return a quantizer that quantizes to the our most basic 832 * units (i.e. a unit quantizer whose unit is our shortest 833 * note duration). 834 */ getBasicQuantizer()835 const BasicQuantizer *getBasicQuantizer() const { 836 return m_basicQuantizer; 837 } 838 839 /** 840 * Return a quantizer that does quantization for notation 841 * only. 842 */ getNotationQuantizer()843 const NotationQuantizer *getNotationQuantizer() const { 844 return m_notationQuantizer; 845 } 846 847 848 ////// 849 // 850 // REFRESH STATUS 851 852 // delegate RefreshStatusArray API getNewRefreshStatusId()853 unsigned int getNewRefreshStatusId() { 854 return m_refreshStatusArray.getNewRefreshStatusId(); 855 } 856 getRefreshStatus(unsigned int id)857 RefreshStatus& getRefreshStatus(unsigned int id) { 858 return m_refreshStatusArray.getRefreshStatus(id); 859 } 860 861 /// Set all refresh statuses to true updateRefreshStatuses()862 void updateRefreshStatuses() { 863 m_refreshStatusArray.updateRefreshStatuses(); 864 } 865 866 867 /// Change notification mechanism. 868 /// @see removeObserver() 869 /// @see notifyTracksAdded() addObserver(CompositionObserver * obs)870 void addObserver(CompositionObserver *obs) { m_observers.push_back(obs); } 871 /// Change notification mechanism. 872 /// @see addObserver() removeObserver(CompositionObserver * obs)873 void removeObserver(CompositionObserver *obs) { m_observers.remove(obs); } 874 875 /// Change notification mechanism. 876 /** 877 * See the various other "notify*" functions. 878 * 879 * These functions have been made public in the interests of improving 880 * performance. There are at least two main approaches to sending change 881 * notifications to observers. The first is to have each modifier 882 * function (e.g. deleteTrack()) send the change notification. The second 883 * is to make the change notification functions public and let the code 884 * that modifies the object also call the change notification function. 885 * The first approach is convenient and less likely to be forgotten. The 886 * second approach has the advantage of performance in situations where 887 * there are many changes being made at once. All of the changes can be 888 * made, then a single notification can be sent out once the changes are 889 * complete. With the first approach, many change notifications might get 890 * sent out, each of which might lead to a potentially costly UI update. 891 */ 892 void notifyTracksAdded(std::vector<TrackId> trackIds) const; 893 /// Change notification mechanism. 894 /** 895 * @see notifyTracksAdded() 896 */ 897 void notifyTrackChanged(Track*); 898 /// Change notification mechanism. 899 /** 900 * @see notifyTracksAdded() 901 */ 902 void notifyTracksDeleted(std::vector<TrackId> trackIds) const; 903 /// Call when the selected track is changed. 904 /** 905 * @see setSelectedTrack() 906 * @see notifyTracksAdded() 907 */ 908 void notifyTrackSelectionChanged(TrackId) const; 909 910 ////// 911 // LYRICS WITH REPEATED SEGMENTS 912 void distributeVerses(); 913 914 ////// 915 // DEBUG FACILITIES 916 void dump() const; 917 918 protected: 919 920 static const std::string TempoEventType; 921 static const PropertyName TempoProperty; 922 static const PropertyName TargetTempoProperty; 923 924 static const PropertyName NoAbsoluteTimeProperty; 925 static const PropertyName BarNumberProperty; 926 static const PropertyName TempoTimestampProperty; 927 928 929 struct ReferenceSegmentEventCmp 930 { 931 bool operator()(const Event &e1, const Event &e2) const; operatorReferenceSegmentEventCmp932 bool operator()(const Event *e1, const Event *e2) const { 933 return operator()(*e1, *e2); 934 } 935 }; 936 937 struct BarNumberComparator 938 { operatorBarNumberComparator939 bool operator()(const Event &e1, const Event &e2) const { 940 return (e1.get<Int>(BarNumberProperty) < 941 e2.get<Int>(BarNumberProperty)); 942 } operatorBarNumberComparator943 bool operator()(const Event *e1, const Event *e2) const { 944 return operator()(*e1, *e2); 945 } 946 }; 947 948 /** 949 * Ensure the selected and record trackids still point to something valid 950 * Must be called after deletion of detach of a track 951 */ 952 void checkSelectedAndRecordTracks(); 953 TrackId getClosestValidTrackId(TrackId id) const; 954 955 956 //--------------- Data members --------------------------------- 957 // 958 trackcontainer m_tracks; 959 SegmentMultiSet m_segments; 960 961 // The tracks we are armed for record on 962 // 963 recordtrackcontainer m_recordTracks; 964 965 TrackId m_selectedTrackId; 966 967 /** 968 * This is a bit like a segment, but can only contain one sort of 969 * event, and can only have one event at each absolute time 970 */ 971 class ReferenceSegment 972 { 973 974 public: 975 ReferenceSegment(std::string eventType); 976 ~ReferenceSegment(); 977 private: 978 ReferenceSegment(const ReferenceSegment &); 979 ReferenceSegment& operator=(const ReferenceSegment &); 980 public: 981 typedef std::vector<Event*>::size_type size_type; 982 typedef std::vector<Event*>::iterator iterator; 983 typedef std::vector<Event*>::const_iterator const_iterator; 984 985 iterator begin(); 986 const_iterator begin() const; 987 iterator end(); 988 const_iterator end() const; 989 990 size_type size() const; 991 bool empty() const; 992 iterator erase(iterator position); 993 void clear(); 994 995 Event* operator[] (size_type n); 996 const Event* operator[] (size_type n) const; 997 998 timeT getDuration() const; 999 1000 /// Inserts a single event, removing any existing one at that time 1001 iterator insertEvent(Event *e); // may throw Event::BadType 1002 1003 void eraseEvent(Event *e); 1004 1005 iterator findTime(timeT time); 1006 iterator findNearestTime(timeT time); 1007 1008 iterator findRealTime(RealTime time); 1009 iterator findNearestRealTime(RealTime time); 1010 getEventType()1011 std::string getEventType() const { return m_eventType; } 1012 1013 private: 1014 iterator find(Event *e); 1015 std::string m_eventType; 1016 // not a set: want random access for bars 1017 std::vector<Event*> m_events; 1018 }; 1019 1020 /// Contains time signature events 1021 mutable ReferenceSegment m_timeSigSegment; 1022 1023 /// Contains tempo events 1024 mutable ReferenceSegment m_tempoSegment; 1025 1026 /// affects m_timeSigSegment 1027 void calculateBarPositions() const; 1028 mutable bool m_barPositionsNeedCalculating; 1029 ReferenceSegment::iterator getTimeSignatureAtAux(timeT t) const; 1030 1031 /// affects m_tempoSegment 1032 void calculateTempoTimestamps() const; 1033 mutable bool m_tempoTimestampsNeedCalculating; 1034 RealTime time2RealTime(timeT time, tempoT tempo) const; 1035 RealTime time2RealTime(timeT time, tempoT tempo, 1036 timeT targetTempoTime, tempoT targetTempo) const; 1037 timeT realTime2Time(RealTime rtime, tempoT tempo) const; 1038 timeT realTime2Time(RealTime rtime, tempoT tempo, 1039 timeT targetTempoTime, tempoT targetTempo) const; 1040 bool getTempoTarget(ReferenceSegment::const_iterator i, 1041 tempoT &target, 1042 timeT &targetTime) const; 1043 1044 static RealTime getTempoTimestamp(const Event *e); 1045 static void setTempoTimestamp(Event *e, RealTime r); 1046 1047 /// No more than one armed track per instrument. 1048 void enforceArmRule(const Track *track); 1049 1050 typedef std::list<CompositionObserver *> ObserverSet; 1051 ObserverSet m_observers; 1052 1053 void notifySegmentAdded(Segment *) const; 1054 void notifySegmentRemoved(Segment *) const; 1055 void notifySegmentRepeatChanged(Segment *, bool) const; 1056 void notifySegmentRepeatEndChanged(Segment *, timeT) const; 1057 void notifySegmentEventsTimingChanged(Segment *s, timeT delay, RealTime rtDelay) const; 1058 void notifySegmentTransposeChanged(Segment *s, int transpose) const; 1059 void notifySegmentTrackChanged(Segment *s, TrackId oldId, TrackId newId) const; 1060 void notifySegmentStartChanged(Segment *, timeT); 1061 void notifySegmentEndMarkerChange(Segment *s, bool shorten); 1062 void notifyEndMarkerChange(bool shorten) const; 1063 void notifyMetronomeChanged() const; 1064 void notifyTimeSignatureChanged() const; 1065 void notifyTempoChanged() const; 1066 void notifySelectedTrackChanged() const; 1067 void notifySourceDeletion() const; 1068 1069 void clearVoiceCaches(); 1070 void rebuildVoiceCaches() const; 1071 1072 void updateExtremeTempos(); 1073 1074 BasicQuantizer *m_basicQuantizer; 1075 NotationQuantizer *m_notationQuantizer; 1076 1077 timeT m_position; 1078 tempoT m_defaultTempo; 1079 tempoT m_minTempo; // cached from tempo segment 1080 tempoT m_maxTempo; // cached from tempo segment 1081 1082 // Notional Composition markers - these define buffers for the 1083 // start and end of the piece, Segments can still exist outside 1084 // of these markers - these are for visual and playback cueing. 1085 // 1086 timeT m_startMarker; 1087 timeT m_endMarker; 1088 bool m_autoExpand; 1089 1090 // Loop start and end positions. If they're both the same 1091 // value (usually 0) then there's no loop set. 1092 // 1093 timeT m_loopStart; 1094 timeT m_loopEnd; 1095 1096 Configuration m_metadata; 1097 1098 bool m_playMetronome; 1099 bool m_recordMetronome; 1100 1101 RefreshStatusArray<RefreshStatus> m_refreshStatusArray; 1102 1103 // User defined markers in the composition 1104 // 1105 markercontainer m_markers; 1106 1107 // Trigger segments (unsorted segments fired by events elsewhere) 1108 // 1109 triggersegmentcontainer m_triggerSegments; 1110 TriggerSegmentId m_nextTriggerSegmentId; 1111 1112 ColourMap m_segmentColourMap; 1113 ColourMap m_generalColourMap; 1114 1115 // Caches of segment voice indices and track voice counts 1116 // 1117 mutable std::map<TrackId, int> m_trackVoiceCountCache; 1118 mutable std::map<const Segment *, int> m_segmentVoiceIndexCache; 1119 }; 1120 1121 1122 /// Base class for those that want notification of Composition changes. 1123 /** 1124 * If you subclass from CompositionObserver, you can then attach to a 1125 * Composition to receive notification when something changes. 1126 * 1127 * Normally all the methods in this class would be pure virtual. But 1128 * because there are so many, that imposes far too much work on the 1129 * subclass implementation in a case where it only really wants to 1130 * know about one thing, such as segments being deleted. So we have 1131 * empty default implementations, and you'll just have to take a bit 1132 * more care to make sure you really are making the correct 1133 * declarations in the subclass. 1134 */ 1135 class CompositionObserver 1136 { 1137 public: CompositionObserver()1138 CompositionObserver() : m_compositionDeleted(false) { } 1139 ~CompositionObserver()1140 virtual ~CompositionObserver() { } 1141 1142 /// A segment has been added to the Composition. segmentAdded(const Composition *,Segment *)1143 virtual void segmentAdded(const Composition *, Segment *) { } 1144 1145 /// A Segment has been removed from the Composition. 1146 /** 1147 * Called before the Segment is deleted. 1148 */ segmentRemoved(const Composition *,Segment *)1149 virtual void segmentRemoved(const Composition *, Segment *) { } 1150 1151 /// The Segment's repeat status has changed segmentRepeatChanged(const Composition *,Segment *,bool)1152 virtual void segmentRepeatChanged(const Composition *, Segment *, bool) { } 1153 1154 /// The Segment's repeat end time has changed. segmentRepeatEndChanged(const Composition *,Segment *,timeT)1155 virtual void segmentRepeatEndChanged(const Composition *, Segment *, timeT) { } 1156 1157 /// The Segment's delay timing has changed. segmentEventsTimingChanged(const Composition *,Segment *,timeT,RealTime)1158 virtual void segmentEventsTimingChanged(const Composition *, Segment *, 1159 timeT /* delay */, 1160 RealTime /* rtDelay */) { } 1161 1162 /// The Segment's transpose value has changed segmentTransposeChanged(const Composition *,Segment *,int)1163 virtual void segmentTransposeChanged(const Composition *, Segment *, 1164 int /* transpose */) { } 1165 1166 /// The Segment's start time has changed. segmentStartChanged(const Composition *,Segment *,timeT)1167 virtual void segmentStartChanged(const Composition *, Segment *, 1168 timeT /* newStartTime */) { } 1169 1170 /// The Segment's end marker time has changed segmentEndMarkerChanged(const Composition *,Segment *,bool)1171 virtual void segmentEndMarkerChanged(const Composition *, Segment *, 1172 bool /* shorten */) { } 1173 1174 /// The Segment's track has changed. segmentTrackChanged(const Composition *,Segment *,TrackId)1175 virtual void segmentTrackChanged(const Composition *, Segment *, 1176 TrackId) { } 1177 1178 /// The Composition's end time has been changed. 1179 /** 1180 * ??? rename: endTimeChanged() to differentiate from SegmentObserver. 1181 */ endMarkerTimeChanged(const Composition *,bool)1182 virtual void endMarkerTimeChanged(const Composition *, 1183 bool /* shorten */) { } 1184 1185 /// A different track has been selected. 1186 /** 1187 * This can happen when the user clicks on a track label, or presses 1188 * the up/down arrow keys to change which track is currently selected. 1189 * 1190 * See selectedTrackChanged(). 1191 */ trackSelectionChanged(const Composition *,TrackId)1192 virtual void trackSelectionChanged(const Composition *, TrackId) { } 1193 1194 /// A Track has changed (instrument id, muted status...) trackChanged(const Composition *,Track *)1195 virtual void trackChanged(const Composition *, Track *) { } 1196 tracksDeleted(const Composition *,std::vector<TrackId> &)1197 virtual void tracksDeleted(const Composition *, 1198 std::vector<TrackId> & /*trackIds*/) { } 1199 tracksAdded(const Composition *,std::vector<TrackId> &)1200 virtual void tracksAdded(const Composition *, 1201 std::vector<TrackId> & /*trackIds*/) { } 1202 1203 /// Some time signature has changed. timeSignatureChanged(const Composition *)1204 virtual void timeSignatureChanged(const Composition *) { } 1205 1206 /// Metronome status has changed (on/off) metronomeChanged(const Composition *)1207 virtual void metronomeChanged(const Composition *) { } 1208 tempoChanged(const Composition *)1209 virtual void tempoChanged(const Composition *) { } 1210 1211 /// Like trackChanged() but for the Track that is selected. 1212 /** 1213 * This avoids the need to check the TrackId with trackChanged(). 1214 * 1215 * See trackChanged(). 1216 * 1217 * ??? We can probably get rid of this easily and just use 1218 * trackChanged(). 1219 */ selectedTrackChanged(const Composition *)1220 virtual void selectedTrackChanged(const Composition *) { } 1221 1222 1223 /// Called from the Composition dtor. compositionDeleted(const Composition *)1224 virtual void compositionDeleted(const Composition *) { 1225 m_compositionDeleted = true; 1226 } 1227 isCompositionDeleted()1228 bool isCompositionDeleted() { return m_compositionDeleted; } 1229 1230 protected: 1231 bool m_compositionDeleted; 1232 }; 1233 1234 } 1235 1236 1237 #endif 1238 1239