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_SOUNDDRIVER_H 17 #define RG_SOUNDDRIVER_H 18 19 #include "base/Device.h" 20 #include "base/Instrument.h" // For InstrumentId... 21 #include "base/MidiProgram.h" // For MidiByte... 22 #include "base/RealTime.h" 23 #include "MappedEvent.h" 24 #include "MappedInstrument.h" 25 #include "MappedDevice.h" 26 #include "Scavenger.h" 27 #include "AudioPlayQueue.h" 28 29 #include "RIFFAudioFile.h" // For SubFormat enum 30 31 #include <QString> 32 #include <QStringList> 33 34 #include <set> 35 #include <vector> 36 37 38 namespace Rosegarden 39 { 40 41 42 // Current recording status - whether we're monitoring anything 43 // or recording. 44 enum RecordStatus { RECORD_OFF, RECORD_ON }; 45 46 typedef unsigned SoundDriverStatus; 47 enum 48 { 49 NO_DRIVER = 0x00, // Nothing's OK 50 AUDIO_OK = 0x01, 51 MIDI_OK = 0x02 52 }; 53 54 /// Used for MMC and MTC, not for JACK transport 55 enum TransportSyncStatus 56 { 57 TRANSPORT_OFF, 58 TRANSPORT_SOURCE, 59 TRANSPORT_FOLLOWER 60 }; 61 62 63 class RosegardenSequencer; 64 class MappedEventList; 65 class MappedStudio; 66 67 68 /// Abstract Base Class (ABC) to support sound drivers, such as ALSA. 69 /** 70 * This ABC provides the generic driver support for 71 * these drivers with the Sequencer class owning an instance 72 * of a sub class of this class and directing it as required 73 * by RosegardenSequencer itself. 74 */ 75 class SoundDriver 76 { 77 public: 78 SoundDriver(MappedStudio *studio, const QString &name); 79 virtual ~SoundDriver(); 80 81 82 // *** General *** 83 initialise()84 virtual bool initialise() { return true; } getStatus()85 SoundDriverStatus getStatus() const { return m_driverStatus; } getStatusLog()86 virtual QString getStatusLog() { return ""; } shutdown()87 virtual void shutdown() { } 88 89 90 // *** Devices and Connections *** 91 addDevice(Device::DeviceType,DeviceId,InstrumentId,MidiDevice::DeviceDirection)92 virtual bool addDevice(Device::DeviceType, 93 DeviceId, 94 InstrumentId, 95 MidiDevice::DeviceDirection) 96 { return false; } removeDevice(DeviceId)97 virtual void removeDevice(DeviceId) { } removeAllDevices()98 virtual void removeAllDevices() { } renameDevice(DeviceId,QString)99 virtual void renameDevice(DeviceId, QString) { } 100 101 /// Poll for new clients (for new Devices/Instruments) checkForNewClients()102 virtual void checkForNewClients() { } 103 getConnections(Device::DeviceType,MidiDevice::DeviceDirection)104 virtual unsigned int getConnections(Device::DeviceType, 105 MidiDevice::DeviceDirection) { return 0; } getConnection(Device::DeviceType,MidiDevice::DeviceDirection,unsigned int)106 virtual QString getConnection(Device::DeviceType, 107 MidiDevice::DeviceDirection, 108 unsigned int) { return ""; } getConnection(DeviceId)109 virtual QString getConnection(DeviceId) { return ""; } setConnection(DeviceId,QString)110 virtual void setConnection( 111 DeviceId /* deviceId */, 112 QString /* idealConnection */) { } setPlausibleConnection(DeviceId deviceId,QString idealConnection,bool)113 virtual void setPlausibleConnection( 114 DeviceId deviceId, 115 QString idealConnection, 116 bool /* recordDevice */) 117 { setConnection(deviceId, idealConnection); } connectSomething()118 virtual void connectSomething() { } 119 120 121 // *** Sequencer *** 122 getTimers()123 virtual unsigned int getTimers() { return 0; } getTimer(unsigned int)124 virtual QString getTimer(unsigned int) { return ""; } getCurrentTimer()125 virtual QString getCurrentTimer() { return ""; } setCurrentTimer(QString)126 virtual void setCurrentTimer(QString) { } 127 initialisePlayback(const RealTime &)128 virtual void initialisePlayback(const RealTime & /*position*/) { } 129 void setMappedInstrument(MappedInstrument *mI); stopPlayback()130 virtual void stopPlayback() { } record(RecordStatus,const std::vector<InstrumentId> &,const std::vector<QString> &)131 virtual bool record( 132 RecordStatus /*recordStatus*/, 133 const std::vector<InstrumentId> & /*armedInstruments*/, 134 const std::vector<QString> & /*audioFileNames*/) 135 { return false; } 136 /// stop recording, continue playing punchOut()137 virtual void punchOut() { } resetPlayback(const RealTime &,const RealTime &)138 virtual void resetPlayback(const RealTime & /*oldPosition*/, 139 const RealTime & /*position*/) { } 140 isPlaying()141 bool isPlaying() const { return m_playing; } getStartPosition()142 RealTime getStartPosition() const { return m_playStartPosition; } getRecordStatus()143 RecordStatus getRecordStatus() const { return m_recordStatus; } 144 getSequencerTime()145 virtual RealTime getSequencerTime() { return RealTime(0, 0); } 146 147 /// Get incoming MIDI events from ALSA. getMappedEventList(MappedEventList &)148 virtual bool getMappedEventList(MappedEventList &) { return true; } 149 startClocks()150 virtual void startClocks() { } stopClocks()151 virtual void stopClocks() { } 152 // Are we counting? By default a subclass probably wants to 153 // return true, if it doesn't know better. areClocksRunning()154 virtual bool areClocksRunning() const { return true; } 155 156 // Process some asynchronous events processEventsOut(const MappedEventList &)157 virtual void processEventsOut(const MappedEventList & /*mC*/) { } 158 159 // Process some scheduled events on the output queue. The 160 // slice times are here so that the driver can interleave 161 // note-off events as appropriate. processEventsOut(const MappedEventList &,const RealTime &,const RealTime &)162 virtual void processEventsOut(const MappedEventList & /*mC*/, 163 const RealTime & /*sliceStart*/, 164 const RealTime & /*sliceEnd*/) { } 165 processPending()166 virtual void processPending() { } 167 168 /// Set a loop position at the driver (used for transport) setLoop(const RealTime &,const RealTime &)169 virtual void setLoop(const RealTime & /*start*/, 170 const RealTime & /*end*/) { } 171 172 virtual void sleep(const RealTime &rt); 173 174 // Set MIDI clock interval - allow redefinition above to ensure 175 // we handle this reset correctly. setMIDIClockInterval(RealTime interval)176 virtual void setMIDIClockInterval(RealTime interval) 177 { m_midiClockInterval = interval; } 178 179 // Do any bits and bobs of work that need to be done continuously 180 // (this is called repeatedly whether playing or not). runTasks()181 virtual void runTasks() { } 182 183 184 // *** Audio *** 185 setAudioBufferSizes(RealTime mix,RealTime read,RealTime write,int smallFileSize)186 void setAudioBufferSizes(RealTime mix, RealTime read, RealTime write, 187 int smallFileSize) { 188 m_audioMixBufferLength = mix; 189 m_audioReadBufferLength = read; 190 m_audioWriteBufferLength = write; 191 m_smallFileSize = smallFileSize; 192 } 193 194 // Get the driver's operating sample rate getSampleRate()195 virtual unsigned int getSampleRate() const { return 0; } 196 setAudioBussLevels(int,float,float)197 virtual void setAudioBussLevels(int /*bussId*/, 198 float /*dB*/, 199 float /*pan*/) { } 200 setAudioInstrumentLevels(InstrumentId,float,float)201 virtual void setAudioInstrumentLevels(InstrumentId /*id*/, 202 float /*dB*/, 203 float /*pan*/) { } 204 205 // Handle audio file references 206 // 207 void clearAudioFiles(); 208 bool addAudioFile(const QString &fileName, unsigned int id); 209 bool removeAudioFile(unsigned int id); 210 211 void initialiseAudioQueue(const std::vector<MappedEvent> &audioEvents); 212 const AudioPlayQueue *getAudioQueue() const; 213 getAudioRecFileFormat()214 RIFFAudioFile::SubFormat getAudioRecFileFormat() const 215 { return m_audioRecFileFormat; } 216 217 // Latencies 218 // getAudioPlayLatency()219 virtual RealTime getAudioPlayLatency() { return RealTime::zeroTime; } getAudioRecordLatency()220 virtual RealTime getAudioRecordLatency() { return RealTime::zeroTime; } getInstrumentPlayLatency(InstrumentId)221 virtual RealTime getInstrumentPlayLatency(InstrumentId) { return RealTime::zeroTime; } getMaximumPlayLatency()222 virtual RealTime getMaximumPlayLatency() { return RealTime::zeroTime; } 223 224 // Buffer sizes 225 // getAudioMixBufferLength()226 RealTime getAudioMixBufferLength() { return m_audioMixBufferLength; } getAudioReadBufferLength()227 RealTime getAudioReadBufferLength() { return m_audioReadBufferLength; } getAudioWriteBufferLength()228 RealTime getAudioWriteBufferLength() { return m_audioWriteBufferLength; } 229 getLowLatencyMode()230 bool getLowLatencyMode() const { return true; } 231 getAudioInstrumentNumbers(InstrumentId & base,int & count)232 virtual void getAudioInstrumentNumbers(InstrumentId &base, int &count) 233 { base = 0; count = 0; } getSoftSynthInstrumentNumbers(InstrumentId & base,int & count)234 virtual void getSoftSynthInstrumentNumbers(InstrumentId &base, int &count) 235 { base = 0; count = 0; } 236 getMappedStudio()237 MappedStudio *getMappedStudio() { return m_studio; } 238 239 // Report a failure back to the GUI - ideally. Default does nothing. reportFailure(MappedEvent::FailureCode)240 virtual void reportFailure(MappedEvent::FailureCode) { } 241 242 243 // *** Plugins *** 244 setPluginInstance(InstrumentId,QString,int)245 virtual void setPluginInstance(InstrumentId /*id*/, 246 QString /*identifier*/, 247 int /*position*/) { } 248 removePluginInstance(InstrumentId,int)249 virtual void removePluginInstance(InstrumentId /*id*/, 250 int /*position*/) { } 251 setPluginInstancePortValue(InstrumentId,int,unsigned long,float)252 virtual void setPluginInstancePortValue(InstrumentId /*id*/, 253 int /*position*/, 254 unsigned long /*portNumber*/, 255 float /*value*/) { } 256 getPluginInstancePortValue(InstrumentId,int,unsigned long)257 virtual float getPluginInstancePortValue(InstrumentId /*id*/, 258 int /*position*/, 259 unsigned long /*portNumber*/) 260 { return 0; } 261 setPluginInstanceBypass(InstrumentId,int,bool)262 virtual void setPluginInstanceBypass(InstrumentId /*id*/, 263 int /*position*/, 264 bool /*value*/) { } 265 getPluginInstancePrograms(InstrumentId,int)266 virtual QStringList getPluginInstancePrograms(InstrumentId /*id*/, 267 int /*position*/) 268 { return QStringList(); } 269 getPluginInstanceProgram(InstrumentId,int)270 virtual QString getPluginInstanceProgram(InstrumentId /*id*/, 271 int /*position*/) 272 { return QString(); } 273 getPluginInstanceProgram(InstrumentId,int,int,int)274 virtual QString getPluginInstanceProgram(InstrumentId /*id*/, 275 int /*position*/, 276 int /*bank*/, 277 int /*program*/) 278 { return QString(); } 279 getPluginInstanceProgram(InstrumentId,int,QString)280 virtual unsigned long getPluginInstanceProgram(InstrumentId /*id*/, 281 int /*position*/, 282 QString /*name*/) 283 { return 0; } 284 setPluginInstanceProgram(InstrumentId,int,QString)285 virtual void setPluginInstanceProgram(InstrumentId /*id*/, 286 int /*position*/, 287 QString /*program*/) { } 288 configurePlugin(InstrumentId,int,QString,QString)289 virtual QString configurePlugin(InstrumentId /*id*/, 290 int /*position*/, 291 QString /*key*/, 292 QString /*value*/) { return QString(); } 293 294 // Plugin management -- SoundDrivers should maintain a plugin 295 // scavenger which the audio process code can use for defunct 296 // plugins. Ownership of plugin is passed to the SoundDriver. claimUnwantedPlugin(void *)297 virtual void claimUnwantedPlugin(void * /*plugin*/) { } 298 299 // This causes all scavenged plugins to be destroyed. It 300 // should only be called in non-RT contexts. scavengePlugins()301 virtual void scavengePlugins() { } 302 303 304 // *** Miscellaneous *** 305 306 /*!DEVPUSH 307 308 // ??? The m_devices that these two functions used has been moved 309 // down to AlsaDriver. 310 311 // Return a MappedDevice full of the Instrument mappings 312 // that the driver has discovered. The gui can then use 313 // this list (complete with names) to generate its proper 314 // Instruments under the MidiDevice and AudioDevice. 315 // 316 MappedDevice getMappedDevice(DeviceId id); 317 318 // Return the number of devices we've found 319 // 320 unsigned int getDevices(); 321 */ 322 323 protected: 324 325 // *** General *** 326 327 /// Driver name for the audit log. 328 QString m_name; 329 330 SoundDriverStatus m_driverStatus; 331 332 333 // *** Sequencer *** 334 335 typedef std::vector<MappedInstrument *> MappedInstrumentList; 336 // This is our driver's own list of MappedInstruments and MappedDevices. 337 // These are uncoupled at this level - the Instruments and Devices float 338 // free and only index each other - the Devices hold information only like 339 // name, id and if the device is duplex capable. 340 MappedInstrumentList m_instruments; 341 342 RealTime m_playStartPosition; 343 bool m_playing; 344 RecordStatus m_recordStatus; 345 346 /// 24 MIDI clocks per quarter note. MIDI Spec section 2, page 30. 347 /** 348 * If the Composition has tempo changes, this single interval is 349 * insufficient. We should instead compute SPP based on bar/beat/pulse 350 * from the Composition. Since the GUI and sequencer are separated, 351 * the bar/beat/pulse values would need to be pushed in at play and 352 * record time. See RosegardenSequencer::m_songPosition. 353 */ 354 RealTime m_midiClockInterval; 355 356 357 // *** Audio *** 358 359 // Subclass _MUST_ scavenge this regularly. 360 Scavenger<AudioPlayQueue> m_audioQueueScavenger; 361 362 AudioPlayQueue *m_audioQueue; 363 364 /// A list of AudioFile's that we can play. 365 std::vector<AudioFile *> m_audioFiles; 366 AudioFile *getAudioFile(unsigned int id); 367 368 RealTime m_audioMixBufferLength; 369 RealTime m_audioReadBufferLength; 370 RealTime m_audioWriteBufferLength; 371 372 int m_smallFileSize; 373 374 RIFFAudioFile::SubFormat m_audioRecFileFormat; 375 376 /// Sequencer-side representation of the audio portion of the Studio. 377 MappedStudio *m_studio; 378 379 }; 380 381 382 } 383 384 #endif // RG_SOUNDDRIVER_H 385