/* Rosegarden A sequencer and musical notation editor. This program is Copyright 2000-2008 Guillaume Laurent , Chris Cannam , Richard Bown The moral right of the authors to claim authorship of this work has been asserted. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include #include #include #include #include "Device.h" #include "MappedComposition.h" #include "MappedInstrument.h" #include "MappedDevice.h" #include "SequencerDataBlock.h" #include "PlayableAudioFile.h" #include "Scavenger.h" #include "RIFFAudioFile.h" // for SubFormat enum // Abstract base to support SoundDrivers, such as ALSA. // // This base class provides the generic driver support for // these drivers with the Sequencer class owning an instance // of a sub class of this class and directing it and required // by the rosegardensequencer itself. // // #ifndef _SOUNDDRIVER_H_ #define _SOUNDDRIVER_H_ namespace Rosegarden { // Current recording status - whether we're monitoring anything // or recording. // typedef enum { RECORD_OFF, RECORD_ON, } RecordStatus; // Status of a SoundDriver - whether we're got an audio and // MIDI subsystem or not. This is reported right up to the // gui. // typedef enum { NO_DRIVER = 0x00, // Nothing's OK AUDIO_OK = 0x01, // AUDIO's OK MIDI_OK = 0x02, // MIDI's OK VERSION_OK = 0x04 // GUI and sequencer versions match } SoundDriverStatus; // Used for MMC and MTC, not for JACK transport // typedef enum { TRANSPORT_OFF, TRANSPORT_MASTER, TRANSPORT_SLAVE } TransportSyncStatus; // The NoteOffQueue holds a time ordered set of // pending MIDI NOTE OFF events. // class NoteOffEvent { public: NoteOffEvent() {;} NoteOffEvent(const RealTime &realTime, unsigned int pitch, MidiByte channel, InstrumentId instrument): m_realTime(realTime), m_pitch(pitch), m_channel(channel), m_instrument(instrument) {;} ~NoteOffEvent() {;} struct NoteOffEventCmp { bool operator()(NoteOffEvent *nO1, NoteOffEvent *nO2) const { return nO1->getRealTime() < nO2->getRealTime(); } }; void setRealTime(const RealTime &time) { m_realTime = time; } RealTime getRealTime() const { return m_realTime; } MidiByte getPitch() const { return m_pitch; } MidiByte getChannel() const { return m_channel; } InstrumentId getInstrument() const { return m_instrument; } private: RealTime m_realTime; MidiByte m_pitch; MidiByte m_channel; InstrumentId m_instrument; }; // The queue itself // class NoteOffQueue : public std::multiset { public: NoteOffQueue() {;} ~NoteOffQueue() {;} private: }; class MappedStudio; class ExternalTransport; class AudioPlayQueue; typedef std::vector PlayableAudioFileList; // The abstract SoundDriver // // class SoundDriver { public: SoundDriver(MappedStudio *studio, const std::string &name); virtual ~SoundDriver(); virtual bool initialise() = 0; virtual void shutdown() { } virtual void initialisePlayback(const RealTime &position) = 0; virtual void stopPlayback() = 0; virtual void punchOut() = 0; // stop recording, continue playing virtual void resetPlayback(const RealTime &oldPosition, const RealTime &position) = 0; virtual void allNotesOff() = 0; virtual RealTime getSequencerTime() = 0; virtual MappedComposition *getMappedComposition() = 0; virtual void startClocks() { } virtual void stopClocks() { } // Process some asynchronous events // virtual void processEventsOut(const MappedComposition &mC) = 0; // Process some scheduled events on the output queue. The // slice times are here so that the driver can interleave // note-off events as appropriate. // virtual void processEventsOut(const MappedComposition &mC, const RealTime &sliceStart, const RealTime &sliceEnd) = 0; // Activate a recording state. armedInstruments and audioFileNames // can be NULL if no audio tracks recording. // virtual bool record(RecordStatus recordStatus, const std::vector *armedInstruments = 0, const std::vector *audioFileNames = 0) = 0; // Process anything that's pending // virtual void processPending() = 0; // Get the driver's operating sample rate // virtual unsigned int getSampleRate() const = 0; // Plugin instance management // virtual void setPluginInstance(InstrumentId id, TQString identifier, int position) = 0; virtual void removePluginInstance(InstrumentId id, int position) = 0; // Clear down and remove all plugin instances // virtual void removePluginInstances() = 0; virtual void setPluginInstancePortValue(InstrumentId id, int position, unsigned long portNumber, float value) = 0; virtual float getPluginInstancePortValue(InstrumentId id, int position, unsigned long portNumber) = 0; virtual void setPluginInstanceBypass(InstrumentId id, int position, bool value) = 0; virtual TQStringList getPluginInstancePrograms(InstrumentId id, int position) = 0; virtual TQString getPluginInstanceProgram(InstrumentId id, int position) = 0; virtual TQString getPluginInstanceProgram(InstrumentId id, int position, int bank, int program) = 0; virtual unsigned long getPluginInstanceProgram(InstrumentId id, int position, TQString name) = 0; virtual void setPluginInstanceProgram(InstrumentId id, int position, TQString program) = 0; virtual TQString configurePlugin(InstrumentId id, int position, TQString key, TQString value) = 0; virtual void setAudioBussLevels(int bussId, float dB, float pan) = 0; virtual void setAudioInstrumentLevels(InstrumentId id, float dB, float pan) = 0; // Poll for new clients (for new Devices/Instruments) // virtual bool checkForNewClients() = 0; // Set a loop position at the driver (used for transport) // virtual void setLoop(const RealTime &loopStart, const RealTime &loopEnd) = 0; virtual void sleep(const RealTime &rt); virtual TQString getStatusLog() { return ""; } // Mapped Instruments // void setMappedInstrument(MappedInstrument *mI); MappedInstrument* getMappedInstrument(InstrumentId id); // Return the current status of the driver // unsigned int getStatus() const { return m_driverStatus; } // Are we playing? // bool isPlaying() const { return m_playing; } // Are we counting? By default a subclass probably wants to // return true, if it doesn't know better. // virtual bool areClocksRunning() const = 0; RealTime getStartPosition() const { return m_playStartPosition; } RecordStatus getRecordStatus() const { return m_recordStatus; } // Return a MappedDevice full of the Instrument mappings // that the driver has discovered. The gui can then use // this list (complete with names) to generate its proper // Instruments under the MidiDevice and AudioDevice. // MappedDevice getMappedDevice(DeviceId id); // Return the number of devices we've found // unsigned int getDevices(); virtual bool canReconnect(Device::DeviceType) { return false; } virtual DeviceId addDevice(Device::DeviceType, MidiDevice::DeviceDirection) { return Device::NO_DEVICE; } virtual void removeDevice(DeviceId) { } virtual void renameDevice(DeviceId, TQString) { } virtual unsigned int getConnections(Device::DeviceType, MidiDevice::DeviceDirection) { return 0; } virtual TQString getConnection(Device::DeviceType, MidiDevice::DeviceDirection, unsigned int) { return ""; } virtual void setConnection(DeviceId, TQString) { } virtual void setPlausibleConnection(DeviceId id, TQString c) { setConnection(id, c); } virtual unsigned int getTimers() { return 0; } virtual TQString getTimer(unsigned int) { return ""; } virtual TQString getCurrentTimer() { return ""; } virtual void setCurrentTimer(TQString) { } virtual void getAudioInstrumentNumbers(InstrumentId &, int &) = 0; virtual void getSoftSynthInstrumentNumbers(InstrumentId &, int &) = 0; // Plugin management -- SoundDrivers should maintain a plugin // scavenger which the audio process code can use for defunct // plugins. Ownership of plugin is passed to the SoundDriver. // virtual void claimUnwantedPlugin(void *plugin) = 0; // This causes all scavenged plugins to be destroyed. It // should only be called in non-RT contexts. // virtual void scavengePlugins() = 0; // Handle audio file references // void clearAudioFiles(); bool addAudioFile(const std::string &fileName, unsigned int id); bool removeAudioFile(unsigned int id); void initialiseAudioQueue(const std::vector &audioEvents); void clearAudioQueue(); const AudioPlayQueue *getAudioQueue() const; RIFFAudioFile::SubFormat getAudioRecFileFormat() const { return m_audioRecFileFormat; } // Latencies // virtual RealTime getAudioPlayLatency() { return RealTime::zeroTime; } virtual RealTime getAudioRecordLatency() { return RealTime::zeroTime; } virtual RealTime getInstrumentPlayLatency(InstrumentId) { return RealTime::zeroTime; } virtual RealTime getMaximumPlayLatency() { return RealTime::zeroTime; } // Buffer sizes // void setAudioBufferSizes(RealTime mix, RealTime read, RealTime write, int smallFileSize) { m_audioMixBufferLength = mix; m_audioReadBufferLength = read; m_audioWriteBufferLength = write; m_smallFileSize = smallFileSize; } RealTime getAudioMixBufferLength() { return m_audioMixBufferLength; } RealTime getAudioReadBufferLength() { return m_audioReadBufferLength; } RealTime getAudioWriteBufferLength() { return m_audioWriteBufferLength; } int getSmallFileSize() { return m_smallFileSize; } void setLowLatencyMode(bool ll) { m_lowLatencyMode = ll; } bool getLowLatencyMode() const { return m_lowLatencyMode; } // Cancel the playback of an audio file - either by instrument and audio file id // or by audio segment id. // void cancelAudioFile(MappedEvent *mE); // Studio linkage // MappedStudio* getMappedStudio() { return m_studio; } void setMappedStudio(MappedStudio *studio) { m_studio = studio; } // Modify MIDI record device // void setMidiRecordDevice(DeviceId id) { m_midiRecordDevice = id; } DeviceId getMIDIRecordDevice() const { return m_midiRecordDevice; } // MIDI Realtime Sync setting // TransportSyncStatus getMIDISyncStatus() const { return m_midiSyncStatus; } void setMIDISyncStatus(TransportSyncStatus status) { m_midiSyncStatus = status; } // MMC master/slave setting // TransportSyncStatus getMMCStatus() const { return m_mmcStatus; } void setMMCStatus(TransportSyncStatus status) { m_mmcStatus = status; } // MTC master/slave setting // TransportSyncStatus getMTCStatus() const { return m_mtcStatus; } void setMTCStatus(TransportSyncStatus status) { m_mtcStatus = status; } // MMC Id // int getMMCId() const { return ((int)(m_mmcId)); } void setMMCId(int id) { m_mmcId = (MidiByte)(id); } // Set MIDI clock interval - allow redefinition above to ensure // we handle this reset correctly. // virtual void setMIDIClockInterval(RealTime interval) { m_midiClockInterval = interval; } // Get and set the mapper which may optionally be used to // store recording levels etc for communication back to the GUI. // (If a subclass wants this and finds it's not there, it should // simply continue without.) // SequencerDataBlock *getSequencerDataBlock() { return m_sequencerDataBlock; } void setSequencerDataBlock(SequencerDataBlock *d) { m_sequencerDataBlock = d; } ExternalTransport *getExternalTransportControl() const { return m_externalTransport; } void setExternalTransportControl(ExternalTransport *transport) { m_externalTransport = transport; } // Do any bits and bobs of work that need to be done continuously // (this is called repeatedly whether playing or not). // virtual void runTasks() { } // Report a failure back to the GUI - ideally. Default does nothing. // virtual void reportFailure(MappedEvent::FailureCode) { } protected: // Helper functions to be implemented by subclasses // virtual void processMidiOut(const MappedComposition &mC, const RealTime &sliceStart, const RealTime &sliceEnd) = 0; virtual void generateInstruments() = 0; // Audio // AudioFile* getAudioFile(unsigned int id); std::string m_name; unsigned int m_driverStatus; RealTime m_playStartPosition; bool m_startPlayback; bool m_playing; // MIDI Note-off handling // NoteOffQueue m_noteOffQueue; // This is our driver's own list of MappedInstruments and MappedDevices. // These are uncoupled at this level - the Instruments and Devices float // free and only index each other - the Devices hold information only like // name, id and if the device is duplex capable. // typedef std::vector MappedInstrumentList; MappedInstrumentList m_instruments; typedef std::vector MappedDeviceList; MappedDeviceList m_devices; DeviceId m_midiRecordDevice; MappedComposition m_recordComposition; MappedComposition m_returnComposition; RecordStatus m_recordStatus; InstrumentId m_midiRunningId; InstrumentId m_audioRunningId; // Subclass _MUST_ scavenge this regularly: Scavenger m_audioQueueScavenger; AudioPlayQueue *m_audioQueue; // A list of AudioFiles that we can play. // std::vector m_audioFiles; RealTime m_audioMixBufferLength; RealTime m_audioReadBufferLength; RealTime m_audioWriteBufferLength; int m_smallFileSize; bool m_lowLatencyMode; RIFFAudioFile::SubFormat m_audioRecFileFormat; // Virtual studio hook // MappedStudio *m_studio; // Sequencer data block for communication back to GUI // SequencerDataBlock *m_sequencerDataBlock; // Controller to make externally originated transport requests on // ExternalTransport *m_externalTransport; // MMC and MTC status and ID // TransportSyncStatus m_midiSyncStatus; TransportSyncStatus m_mmcStatus; TransportSyncStatus m_mtcStatus; MidiByte m_mmcId; // device id // MIDI clock interval // bool m_midiClockEnabled; RealTime m_midiClockInterval; RealTime m_midiClockSendTime; // MIDI Song Position pointer // long m_midiSongPositionPointer; }; } #endif // _SOUNDDRIVER_H_