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_CONTROLBLOCK_H 17 #define RG_CONTROLBLOCK_H 18 19 #include "base/Device.h" // DeviceId 20 #include "base/MidiProgram.h" // InstrumentId, MidiFilter 21 #include "base/Track.h" // TrackId 22 23 namespace Rosegarden 24 { 25 26 class RosegardenDocument; 27 class Studio; 28 29 struct InstrumentAndChannel 30 { 31 // Default to an invalid value. InstrumentAndChannelInstrumentAndChannel32 InstrumentAndChannel() : 33 id(0), 34 channel(-1) 35 { } InstrumentAndChannelInstrumentAndChannel36 InstrumentAndChannel(InstrumentId idIn, int channelIn) : 37 id(idIn), 38 channel(channelIn) 39 { } 40 41 InstrumentId id; 42 int channel; 43 }; 44 45 struct TrackInfo 46 { 47 public: 48 /// This should be the ctor. 49 void clear(); 50 51 /// Get instrument and channel, preparing the channel if needed. 52 /** 53 * Return the instrument id and channel number that this track plays on, 54 * preparing the channel if needed. If impossible, return an invalid 55 * instrument and channel. 56 * 57 * @author Tom Breton (Tehom) 58 */ 59 InstrumentAndChannel getChannelAsReady(Studio &studio); 60 61 /// Make track info conformant to its situation. 62 /** 63 * In particular, acquire or release a channel for thru events to 64 * play on. 65 * 66 * @author Tom Breton (Tehom) 67 */ 68 void conform(Studio &studio); 69 70 /// Release the channel that thru MIDI events played on. 71 /** 72 * @author Tom Breton (Tehom) 73 */ 74 void releaseThruChannel(Studio &studio); 75 76 /// Make the channel ready to play on. Send the program, etc. 77 /** 78 * @author Tom Breton (Tehom) 79 */ 80 void makeChannelReady(Studio &studio); 81 82 /// Adjust channel based on fixed/auto mode change. 83 void instrumentChangedFixity(Studio &studio); 84 85 /******************************************************* 86 * !!! ONLY PUT PLAIN DATA HERE - NO POINTERS EVER !!! * 87 *******************************************************/ 88 89 /// Track is no longer in the Composition. 90 bool m_deleted; 91 92 bool m_muted; 93 bool m_archived; 94 bool m_armed; 95 bool m_solo; 96 97 /// Recording filters: Device 98 DeviceId m_deviceFilter; 99 /// Recording filters: Channel 100 char m_channelFilter; 101 /// Recording filters: Thru Routing 102 Track::ThruRouting m_thruRouting; 103 104 InstrumentId m_instrumentId; 105 106 /// The channel to play thru MIDI events on, if any. 107 /** 108 * For unarmed unselected tracks, this will be an invalid channel. For 109 * fixed-channel instruments, this is the instrument's fixed channel. 110 */ 111 int m_thruChannel; 112 /// Whether the thru channel is ready - the right program has been sent, etc. 113 bool m_isThruChannelReady; 114 /// Whether we have allocated a thru channel. 115 bool m_hasThruChannel; 116 /** 117 * This duplicates information in ControlBlock. It exists so that 118 * we can check if we need a thru channel using just this class. 119 */ 120 bool m_selected; 121 /** 122 * This is usually the same as Instrument's fixedness, but can 123 * disagree briefly when fixedness changes. Meaningless if no channel. 124 */ 125 bool m_useFixedChannel; 126 127 private: 128 void allocateThruChannel(Studio &studio); 129 }; 130 131 // should be high enough for the moment 132 #define CONTROLBLOCK_MAX_NB_TRACKS 1024 133 134 /// Control data passed from GUI thread to sequencer thread. 135 /** 136 * This class contains data that is being passed from GUI threads to 137 * sequencer threads. It used to be mapped into a shared memory 138 * backed file, which had to be of fixed size and layout (with no 139 * internal pointers). The design reflects that history to an extent, 140 * though nowadays it is a simple singleton class with no such 141 * constraint. 142 * 143 * SequenceManager monitors the Composition and updates the data here. 144 * RosegardenSequencer and the mappers (e.g. InternalSegmentMapper) use 145 * the data found here. 146 * 147 * ??? It seems strange that this class/object is used for communication 148 * between threads, yet it is lock free. I suspect this is OK since 149 * we never move more than a word at a time. The only issue might 150 * be inconsistency across fields. And in that case, there is little 151 * that can really go wrong. 152 * 153 * @see SequencerDataBlock 154 */ 155 class ControlBlock 156 { 157 public: 158 static ControlBlock *getInstance(); 159 160 void setDocument(RosegardenDocument *doc); 161 162 //unsigned int getMaxTrackId() const { return m_maxTrackId; } 163 164 /// Update m_trackInfo for the track. 165 void updateTrackData(Track *); 166 167 void setInstrumentForTrack(TrackId trackId, InstrumentId); 168 InstrumentId getInstrumentForTrack(TrackId trackId) const; 169 bool isInstrumentUnused(InstrumentId instrumentId) const; 170 171 void setTrackArmed(TrackId trackId, bool armed); 172 //bool isTrackArmed(TrackId trackId) const; 173 174 void setTrackMuted(TrackId trackId, bool muted); 175 bool isTrackMuted(TrackId trackId) const; 176 bool isInstrumentMuted(InstrumentId instrumentId) const; 177 178 void setTrackArchived(TrackId trackId, bool archived); 179 bool isTrackArchived(TrackId trackId) const; 180 181 void setSolo(TrackId trackId, bool solo); 182 bool isSolo(TrackId trackId) const; 183 bool isAnyTrackInSolo() const; 184 185 void setTrackDeleted(TrackId trackId, bool deleted); 186 //bool isTrackDeleted(TrackId trackId) const; 187 188 /// Recording filters: Device 189 void setTrackDeviceFilter(TrackId trackId, DeviceId); 190 //DeviceId getTrackDeviceFilter(TrackId trackId) const; 191 192 /// Recording filters: Channel 193 void setTrackChannelFilter(TrackId trackId, char channel); 194 //char getTrackChannelFilter(TrackId trackId) const; 195 196 /// Recording filters: Thru Routing 197 void setTrackThruRouting(TrackId trackId, Track::ThruRouting thruRouting); 198 setInstrumentForMetronome(InstrumentId instId)199 void setInstrumentForMetronome(InstrumentId instId) 200 { m_metronomeInfo.m_instrumentId = instId; } 201 //InstrumentId getInstrumentForMetronome() const 202 // { return m_metronomeInfo.m_instrumentId; } 203 setMetronomeMuted(bool mute)204 void setMetronomeMuted(bool mute) { m_metronomeInfo.m_muted = mute; } isMetronomeMuted()205 bool isMetronomeMuted() const { return m_metronomeInfo.m_muted; } 206 207 void setSelectedTrack(TrackId track); getSelectedTrack()208 TrackId getSelectedTrack() const { return m_selectedTrack; } 209 setThruFilter(MidiFilter filter)210 void setThruFilter(MidiFilter filter) { m_thruFilter = filter; } getThruFilter()211 MidiFilter getThruFilter() const { return m_thruFilter; } 212 setRecordFilter(MidiFilter filter)213 void setRecordFilter(MidiFilter filter) { m_recordFilter = filter; } getRecordFilter()214 MidiFilter getRecordFilter() const { return m_recordFilter; } 215 216 /// Get the output instrument and channel for an incoming event. 217 InstrumentAndChannel getInstAndChanForEvent( 218 bool recording, DeviceId deviceId, char channel); 219 220 void vacateThruChannel(int channel); 221 void instrumentChangedProgram(InstrumentId instrumentId); 222 void instrumentChangedFixity(InstrumentId instrumentId); 223 224 private: 225 // Singleton. Use getInstance(). 226 ControlBlock(); 227 228 void clearTracks(); 229 230 RosegardenDocument *m_doc; 231 232 unsigned int m_maxTrackId; 233 234 bool m_isSelectedChannelReady; 235 MidiFilter m_thruFilter; 236 MidiFilter m_recordFilter; 237 238 TrackId m_selectedTrack; 239 240 TrackInfo m_metronomeInfo; 241 242 TrackInfo m_trackInfo[CONTROLBLOCK_MAX_NB_TRACKS]; 243 }; 244 245 } 246 247 #endif 248