/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Rosegarden A MIDI and audio sequencer and musical notation editor. Copyright 2000-2011 the Rosegarden development team. 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. */ #ifndef _ROSEGARDEN_SEQUENCER_H_ #define _ROSEGARDEN_SEQUENCER_H_ // RosegardenSequencer is the sequencer application for Rosegarden. // It owns a Sequencer object which wraps the ALSA // and JACK funtionality. At this level we deal with comms with // the Rosegarden GUI application, the high level marshalling of data // and main event loop of the sequencer. [rwb] // // include files for Qt #include #include #include "base/Composition.h" #include "gui/application/TransportStatus.h" #include "RosegardenSequencerIface.h" #include "sound/MappedEventList.h" #include "base/Event.h" #include "sound/MappedStudio.h" #include "sound/ExternalTransport.h" #include "sound/MappedSegment.h" #include namespace Rosegarden { // forward declaration of the RosegardenGUI classes class RosegardenDocument; class RosegardenMainViewWidget; class MappedInstrument; class SoundDriver; /** * The sequencer application */ class RosegardenSequencer : public RosegardenSequencerIface, public ExternalTransport { public: ~RosegardenSequencer(); static RosegardenSequencer *getInstance(); void lock(); void unlock(); // -------- START OF INTERFACE METHODS -------- // // // Quit virtual void quit(); // Based on RealTime timestamps // bool play(const RealTime &position, const RealTime &readAhead, const RealTime &audioMix, const RealTime &audioRead, const RealTime &audioWrite, long smallFileSize); // recording bool record(const RealTime &position, const RealTime &readAhead, const RealTime &audioMix, const RealTime &audioRead, const RealTime &audioWrite, long smallFileSize, long recordMode); virtual bool punchOut(); // looping void setLoop(const RealTime &loopStart, const RealTime &loopEnd); // Jump to a pointer in the playback virtual void jumpTo(const RealTime &rt); // Return the Sound system status (audio/MIDI) // virtual unsigned int getSoundDriverStatus(const QString &guiVersion); // Add and remove Audio files on the sequencer // virtual bool addAudioFile(const QString &fileName, int id); virtual bool removeAudioFile(int id); // Deletes all the audio files and clears down any flapping i/o handles // virtual void clearAllAudioFiles(); // stops the sequencer // virtual void stop(); // Set a MappedInstrument at the Sequencer // virtual void setMappedInstrument(int type, unsigned char channel, unsigned int id); virtual void processMappedEvent(MappedEvent mE); /*!DEVPUSH virtual unsigned int getDevices(); virtual MappedDevice getMappedDevice(unsigned int id); */ virtual int canReconnect(Device::DeviceType deviceType); virtual bool addDevice(Device::DeviceType type, DeviceId id, InstrumentId baseInstrumentId, MidiDevice::DeviceDirection direction); virtual void removeDevice(unsigned int id); virtual void removeAllDevices(); virtual void renameDevice(unsigned int id, QString name); virtual unsigned int getConnections(Device::DeviceType type, MidiDevice::DeviceDirection direction); virtual QString getConnection(Device::DeviceType type, MidiDevice::DeviceDirection direction, unsigned int connectionNo); virtual QString getConnection(DeviceId id); virtual void setConnection(unsigned int deviceId, QString connection); virtual void setPlausibleConnection(unsigned int deviceId, QString idealConnection); virtual void connectSomething(); virtual unsigned int getTimers(); virtual QString getTimer(unsigned int n); virtual QString getCurrentTimer(); virtual void setCurrentTimer(QString timer); virtual void setLowLatencyMode(bool); // Audio latencies // virtual RealTime getAudioPlayLatency(); virtual RealTime getAudioRecordLatency(); // Set a MappedObject // virtual void setMappedProperty(int id, const QString &property, float value); // Set many properties on many MappedObjects // virtual void setMappedProperties(const MappedObjectIdList &ids, const MappedObjectPropertyList &properties, const MappedObjectValueList &values); // Set a MappedObject to a string // virtual void setMappedProperty(int id, const QString &property, const QString &value); // Set a MappedObject to a property list. Return value is // error string if any. // virtual QString setMappedPropertyList(int id, const QString &property, const MappedObjectPropertyList &values); // Get a MappedObject for a type // virtual int getMappedObjectId(int type); // Get a Property list from an Object // virtual std::vector getPropertyList(int id, const QString &property); virtual std::vector getPluginInformation(); virtual QString getPluginProgram(int id, int bank, int program); virtual unsigned long getPluginProgram(int id, const QString &name); // Set a plugin port // virtual void setMappedPort(int pluginId, unsigned long portId, float value); virtual float getMappedPort(int pluginId, unsigned long portId); // Create a MappedObject virtual int createMappedObject(int type); // Destroy an object // virtual bool destroyMappedObject(int id); // Connect two objects // virtual void connectMappedObjects(int id1, int id2); // Disconnect two objects // virtual void disconnectMappedObjects(int id1, int id2); // Disconnect an object from everything // virtual void disconnectMappedObject(int id); // Sample rate // virtual unsigned int getSampleRate() const; // Clear the studio // virtual void clearStudio(); // Debug stuff, to check MappedSegment::iterator virtual void dumpFirstSegment(); virtual void segmentModified(MappedSegment *); virtual void segmentAdded(MappedSegment *); virtual void segmentAboutToBeDeleted(MappedSegment *); virtual void compositionAboutToBeDeleted(); virtual void remapTracks(); // Set Quarter note length // virtual void setQuarterNoteLength(RealTime rt); // Get a status report // virtual QString getStatusLog(); bool getNextTransportRequest(TransportRequest &request, RealTime &time); MappedEventList pullAsynchronousMidiQueue(); // // // // -------- END OF INTERFACE -------- void setStatus(TransportStatus status) { m_transportStatus = status; } TransportStatus getStatus() { return m_transportStatus; } // Process the first chunk of Sequencer events bool startPlaying(); // Process all subsequent events bool keepPlaying(); // Update internal clock and send GUI position pointer movement void updateClocks(); // These two methods process any pending MIDI or audio // and send them up to the gui for storage and display // void processRecordedMidi(); void processRecordedAudio(); // Called during stopped or playing operation to process // any pending incoming MIDI events that aren't being // recorded (i.e. for display in Transport or on Mixer) // void processAsynchronousEvents(); // Sleep for the given time, approximately. Called from the main // loop in order to lighten CPU load (i.e. the timing quality of // the sequencer does not depend on this being accurate). A good // implementation of this call would return right away when an // incoming MIDI event needed to be handled. // void sleep(const RealTime &rt); // Removes from a MappedEventList the events not matching // the supplied filer. // void applyFiltering(MappedEventList *mC, MidiFilter filter, bool filterControlDevice); // This method assigns an Instrument to each MappedEvent // belongin to the MappedEventList, and sends the // transformed events to the driver to be played. // void routeEvents(MappedEventList *mC, bool useSelectedTrack); // Are we looping? // bool isLooping() const { return !(m_loopStart == m_loopEnd); } // the call itself void sequencerAlive(); // check for new external clients (ALSA sequencer or whatever) -- // polled regularly void checkForNewClients(); // Initialise the virtual studio at this end of the link // void initialiseStudio(); // --------- EXTERNAL TRANSPORT INTERFACE METHODS -------- // // Whereas the interface (above) is for the GUI to call to // make the sequencer follow its wishes, this interface is for // external clients to call (via some low-level audio callback) // and requires sychronising with the GUI. TransportToken transportChange(TransportRequest); TransportToken transportJump(TransportRequest, RealTime); bool isTransportSyncComplete(TransportToken token); TransportToken getInvalidTransportToken() const { return 0; } protected: RosegardenSequencer(); // get events whilst handling loop // void fetchEvents(MappedEventList &, const RealTime &start, const RealTime &end, bool firstFetch); // just get a slice of events between markers // void getSlice(MappedEventList &, const RealTime &start, const RealTime &end, bool firstFetch); // adjust event times according to relative instrument latencies // void applyLatencyCompensation(MappedEventList &); void rationalisePlayingAudio(); void setEndOfCompReached(bool e) { m_isEndOfCompReached = e; } bool isEndOfCompReached() { return m_isEndOfCompReached; } void incrementTransportToken(); //--------------- Data members --------------------------------- SoundDriver *m_driver; TransportStatus m_transportStatus; // Position pointer RealTime m_songPosition; RealTime m_lastFetchSongPosition; RealTime m_readAhead; RealTime m_audioMix; RealTime m_audioRead; RealTime m_audioWrite; int m_smallFileSize; RealTime m_loopStart; RealTime m_loopEnd; std::vector m_instruments; // MappedStudio holds all of our session-persistent information - // sliders and what have you. It's also streamable over DCOP // so you can reconstruct it at either end of the link for // presentation, storage etc. // MappedStudio *m_studio; // mmap segments // MappedSegmentsMetaIterator m_metaIterator; RealTime m_lastStartTime; // m_asyncOutQueue is not a MappedEventList: order of receipt // matters in ordering, timestamp doesn't std::deque m_asyncOutQueue; // m_asyncInQueue is a MappedEventList because its events are // properly timestamped and should be ordered thus MappedEventList m_asyncInQueue; typedef std::pair TransportPair; std::deque m_transportRequests; TransportToken m_transportToken; bool m_isEndOfCompReached; QMutex m_mutex; QMutex m_transportRequestMutex; QMutex m_asyncQueueMutex; static RosegardenSequencer *m_instance; static QMutex m_instanceMutex; }; } #endif // _ROSEGARDEN_SEQUENCER_APP_H_