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