summaryrefslogtreecommitdiffstats
path: root/src/sound/JackDriver.h
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
commit145364a8af6a1fec06556221e66d4b724a62fc9a (patch)
tree53bd71a544008c518034f208d64c932dc2883f50 /src/sound/JackDriver.h
downloadrosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz
rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/sound/JackDriver.h')
-rw-r--r--src/sound/JackDriver.h297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/sound/JackDriver.h b/src/sound/JackDriver.h
new file mode 100644
index 0000000..b46080d
--- /dev/null
+++ b/src/sound/JackDriver.h
@@ -0,0 +1,297 @@
+// -*- c-basic-offset: 4 -*-
+
+/*
+ Rosegarden
+ A sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+#ifndef _JACKDRIVER_H_
+#define _JACKDRIVER_H_
+
+#ifdef HAVE_ALSA
+#ifdef HAVE_LIBJACK
+
+#include "RunnablePluginInstance.h"
+#include <jack/jack.h>
+#include "SoundDriver.h"
+#include "Instrument.h"
+#include "RealTime.h"
+#include "ExternalTransport.h"
+#include <qstringlist.h>
+
+namespace Rosegarden
+{
+
+class AlsaDriver;
+class AudioBussMixer;
+class AudioInstrumentMixer;
+class AudioFileReader;
+class AudioFileWriter;
+
+class JackDriver
+{
+public:
+ // convenience
+ typedef jack_default_audio_sample_t sample_t;
+
+ JackDriver(AlsaDriver *alsaDriver);
+ virtual ~JackDriver();
+
+ bool isOK() const { return m_ok; }
+
+ bool isTransportEnabled() { return m_jackTransportEnabled; }
+ bool isTransportMaster () { return m_jackTransportMaster; }
+
+ void setTransportEnabled(bool e) { m_jackTransportEnabled = e; }
+ void setTransportMaster (bool m) { m_jackTransportMaster = m; }
+
+ // These methods call back on the sound driver if necessary to
+ // establish the current transport location to start at or
+ // relocate to. startTransport and relocateTransport return true
+ // if they have completed and the sound driver can safely call
+ // startClocks; false if the sound driver should wait for the JACK
+ // driver to call back on startClocksApproved before starting.
+ bool startTransport();
+ bool relocateTransport();
+ void stopTransport();
+
+ RealTime getAudioPlayLatency() const;
+ RealTime getAudioRecordLatency() const;
+ RealTime getInstrumentPlayLatency(InstrumentId) const;
+ RealTime getMaximumPlayLatency() const;
+
+ // Plugin instance management
+ //
+ virtual void setPluginInstance(InstrumentId id,
+ QString identifier,
+ int position);
+
+ virtual void removePluginInstance(InstrumentId id, int position);
+
+ // Remove all plugin instances
+ //
+ virtual void removePluginInstances();
+
+ virtual void setPluginInstancePortValue(InstrumentId id,
+ int position,
+ unsigned long portNumber,
+ float value);
+
+ virtual float getPluginInstancePortValue(InstrumentId id,
+ int position,
+ unsigned long portNumber);
+
+ virtual void setPluginInstanceBypass(InstrumentId id,
+ int position,
+ bool value);
+
+ virtual QStringList getPluginInstancePrograms(InstrumentId id,
+ int position);
+
+ virtual QString getPluginInstanceProgram(InstrumentId id,
+ int position);
+
+ virtual QString getPluginInstanceProgram(InstrumentId id,
+ int position,
+ int bank,
+ int program);
+
+ virtual unsigned long getPluginInstanceProgram(InstrumentId id,
+ int position,
+ QString name);
+
+ virtual void setPluginInstanceProgram(InstrumentId id,
+ int position,
+ QString program);
+
+ virtual QString configurePlugin(InstrumentId id,
+ int position,
+ QString key, QString value);
+
+ virtual RunnablePluginInstance *getSynthPlugin(InstrumentId id);
+
+ virtual void clearSynthPluginEvents(); // when stopping
+
+ virtual unsigned int getSampleRate() const { return m_sampleRate; }
+ virtual unsigned int getBufferSize() const { return m_bufferSize; }
+
+ // A new audio file for storage of our recorded samples - the
+ // file stays open so we can append samples at will. We must
+ // explicitly close the file eventually though to make sure
+ // the integrity is correct (sample sizes must be written).
+ //
+ bool openRecordFile(InstrumentId id,
+ const std::string &fileName);
+ bool closeRecordFile(InstrumentId id,
+ AudioFileId &returnedId);
+
+ // Set or change the number of audio inputs and outputs.
+ // The first of these is slightly misnamed -- the submasters
+ // argument controls the number of busses, not ports (which
+ // may or may not exist depending on the setAudioPorts call).
+ //
+ void setAudioPorts(bool faderOuts, bool submasterOuts);
+
+ // Locks used by the disk thread and mix thread. The AlsaDriver
+ // should hold these locks whenever it wants to modify its audio
+ // play queue -- at least when adding or removing files or
+ // resetting status; it doesn't need to hold the locks when
+ // incrementing their statuses or simply reading them.
+ //
+ int getAudioQueueLocks();
+ int tryAudioQueueLocks();
+ int releaseAudioQueueLocks();
+
+ void prepareAudio(); // when repositioning etc
+ void prebufferAudio(); // when starting playback (incorporates prepareAudio)
+ void kickAudio(); // for paranoia only
+
+ // Because we don't want to do any lookups that might involve
+ // locking etc from within the JACK process thread, we instead
+ // call this regularly from the ALSA driver thread -- it looks up
+ // various bits of data such as the master fader and monitoring
+ // levels, number of inputs etc and either processes them or
+ // writes them into simple records in the JACK driver for process
+ // to read. Actually quite a lot of work.
+ //
+ void updateAudioData();
+
+ // Similarly, set data on the buss mixer to avoid the buss mixer
+ // having to call back on the mapped studio to discover it
+ //
+ void setAudioBussLevels(int bussNo, float dB, float pan);
+
+ // Likewise for instrument mixer
+ //
+ void setAudioInstrumentLevels(InstrumentId instrument, float dB, float pan);
+
+ // Called from AlsaDriver to indicate that an async MIDI event is
+ // being sent to a soft synth. JackDriver uses this to suggest
+ // that it needs to start processing soft synths, if it wasn't
+ // already. It will switch this off again itself when things
+ // fall silent.
+ //
+ void setHaveAsyncAudioEvent() { m_haveAsyncAudioEvent = true; }
+
+ RealTime getNextSliceStart(const RealTime &now) const;
+
+ // For audit purposes only.
+ size_t getFramesProcessed() const { return m_framesProcessed; }
+
+ // Reinitialise if we've been kicked off JACK -- if we can
+ //
+ void restoreIfRestorable();
+
+ // Report back to GUI via the AlsaDriver
+ //
+ void reportFailure(MappedEvent::FailureCode code);
+
+protected:
+
+ // static methods for JACK process thread:
+ static int jackProcessStatic(jack_nframes_t nframes, void *arg);
+ static int jackBufferSize(jack_nframes_t nframes, void *arg);
+ static int jackSampleRate(jack_nframes_t nframes, void *arg);
+ static void jackShutdown(void *arg);
+ static int jackXRun(void *);
+
+ // static JACK transport callbacks
+ static int jackSyncCallback(jack_transport_state_t,
+ jack_position_t *, void *);
+ static int jackTimebaseCallback(jack_transport_state_t,
+ jack_nframes_t,
+ jack_position_t *,
+ int,
+ void *);
+
+ // jackProcessStatic delegates to this
+ int jackProcess(jack_nframes_t nframes);
+ int jackProcessRecord(InstrumentId id,
+ jack_nframes_t nframes,
+ sample_t *, sample_t *, bool);
+ int jackProcessEmpty(jack_nframes_t nframes);
+
+ // other helper methods:
+
+ void initialise(bool reinitialise = false);
+
+ bool createMainOutputs();
+ bool createFaderOutputs(int audioPairs, int synthPairs);
+ bool createSubmasterOutputs(int pairs);
+ bool createRecordInputs(int pairs);
+
+ bool relocateTransportInternal(bool alsoStart);
+
+ // data members:
+
+ jack_client_t *m_client;
+
+ std::vector<jack_port_t *> m_inputPorts;
+ std::vector<jack_port_t *> m_outputInstruments;
+ std::vector<jack_port_t *> m_outputSubmasters;
+ std::vector<jack_port_t *> m_outputMonitors;
+ std::vector<jack_port_t *> m_outputMasters;
+
+ jack_nframes_t m_bufferSize;
+ jack_nframes_t m_sampleRate;
+
+ sample_t *m_tempOutBuffer;
+
+ bool m_jackTransportEnabled;
+ bool m_jackTransportMaster;
+
+ bool m_waiting;
+ jack_transport_state_t m_waitingState;
+ ExternalTransport::TransportToken m_waitingToken;
+ int m_ignoreProcessTransportCount;
+
+ AudioBussMixer *m_bussMixer;
+ AudioInstrumentMixer *m_instrumentMixer;
+ AudioFileReader *m_fileReader;
+ AudioFileWriter *m_fileWriter;
+ AlsaDriver *m_alsaDriver;
+
+ float m_masterLevel;
+ unsigned long m_directMasterAudioInstruments; // bitmap
+ unsigned long m_directMasterSynthInstruments;
+ std::map<InstrumentId, RealTime> m_instrumentLatencies;
+ RealTime m_maxInstrumentLatency;
+ bool m_haveAsyncAudioEvent;
+
+ struct RecordInputDesc {
+ int input;
+ int channel;
+ float level;
+ RecordInputDesc(int i = 1000, int c = -1, float l = 0.0f) :
+ input(i), channel(c), level(l) { }
+ };
+ typedef std::map<InstrumentId, RecordInputDesc> RecordInputMap;
+ RecordInputMap m_recordInputs;
+
+ time_t m_kickedOutAt;
+ size_t m_framesProcessed;
+ bool m_ok;
+};
+
+
+}
+
+#endif
+#endif
+
+#endif
+