37 #define DEBUG_DSSI_PROCESS 1 39 #define EVENT_BUFFER_SIZE 1023 42 static std::ostream &
operator<<(std::ostream& o,
const QString &s)
60 unsigned long sampleRate,
62 int idealChannelCount,
63 const DSSI_Descriptor* descriptor) :
68 m_descriptor(descriptor),
69 m_programCacheValid(false),
71 m_blockSize(blockSize),
72 m_idealChannelCount(idealChannelCount),
78 m_haveLastEventSendTime(false)
81 SVDEBUG <<
"DSSIPluginInstance::DSSIPluginInstance(" << identifier <<
")" 145 DSSIPluginInstance::ParameterList
154 ParameterDescriptor pd;
157 pd.identifier =
m_descriptor->LADSPA_Plugin->PortNames[pn];
158 pd.name = pd.identifier;
166 pd.isQuantized =
false;
168 pd.isQuantized =
true;
182 SVDEBUG <<
"DSSIPluginInstance::getParameter(" <<
id <<
")" << endl;
187 cerr <<
"Matches port " << i << endl;
191 SVDEBUG <<
"Returning " << v << endl;
204 SVDEBUG <<
"DSSIPluginInstance::setParameter(" <<
id <<
", " << value <<
")" << endl;
219 SVDEBUG <<
"DSSIPluginInstance::init" << endl;
224 const LADSPA_Descriptor *descriptor =
m_descriptor->LADSPA_Plugin;
226 for (
unsigned long i = 0; i < descriptor->PortCount; ++i)
228 if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[i]))
230 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
237 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i]))
239 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
241 LADSPA_Data *data =
new LADSPA_Data(0.0);
249 LADSPA_Data *data =
new LADSPA_Data(0.0);
251 std::pair<unsigned long, LADSPA_Data*>(i, data));
252 if (!strcmp(descriptor->PortNames[i],
"latency") ||
253 !strcmp(descriptor->PortNames[i],
"_latency")) {
255 cerr <<
"Wooo! We have a latency port!" << endl;
263 SVDEBUG <<
"DSSIPluginInstance::DSSIPluginInstance - " 264 <<
"unrecognised port type" << endl;
276 #ifdef DEBUG_DSSI_PROCESS 287 run(Vamp::RealTime::zeroTime);
292 #ifdef DEBUG_DSSI_PROCESS 293 SVDEBUG <<
"DSSIPluginInstance::getLatency(): latency is " << latency << endl;
318 SVDEBUG <<
"DSSIPluginInstance::setIdealChannelCount: channel count " 379 size_t nextBufferCount = pluginsInGroup * 2;
381 snd_seq_event_t **eventLocalBuffers =
new snd_seq_event_t *[nextBufferCount];
406 SVDEBUG <<
"DSSIPluginInstance::~DSSIPluginInstance" << endl;
411 for (std::set<NonRTPluginThread *>::iterator i =
463 cout <<
"DSSIPluginInstance::instantiate - plugin \"unique\" id = " 466 const LADSPA_Descriptor *descriptor =
m_descriptor->LADSPA_Plugin;
468 if (!descriptor->instantiate) {
469 cerr <<
"Bad plugin: plugin id " << descriptor->UniqueID
470 <<
":" << descriptor->Label
471 <<
" has no instantiate method!" << endl;
481 for (
unsigned long i = 0; i < descriptor->PortCount; ++i) {
483 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i]) &&
484 LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
486 int controller =
m_descriptor->get_midi_controller_for_port
489 if (controller != 0 && controller != 32 &&
490 DSSI_IS_CC(controller)) {
507 SVDEBUG <<
"DSSIPluginInstance::checkProgramCache" << endl;
515 unsigned long index = 0;
516 const DSSI_Program_Descriptor *programDescriptor;
520 d.
bank = programDescriptor->Bank;
521 d.
program = programDescriptor->Program;
522 d.
name = programDescriptor->Name;
533 DSSIPluginInstance::ProgramList
537 SVDEBUG <<
"DSSIPluginInstance::getPrograms" << endl;
544 ProgramList programs;
548 programs.push_back(i->name);
558 SVDEBUG <<
"DSSIPluginInstance::getProgram(" << bank <<
"," << program <<
")" << endl;
567 if (i->bank == bank && i->program == program)
return i->name;
570 return std::string();
577 SVDEBUG <<
"DSSIPluginInstance::getProgram(" << name <<
")" << endl;
588 if (i->name == name) {
590 rv = (rv << 16) + i->program;
614 SVDEBUG <<
"DSSIPluginInstance::selectProgram(" << program <<
")" << endl;
624 unsigned long bankNo = 0, programNo = 0;
629 if (i->name == program) {
632 programNo = i->program;
636 SVDEBUG <<
"DSSIPluginInstance::selectProgram(" << program <<
"): found at bank " << bankNo <<
", program " << programNo << endl;
652 SVDEBUG <<
"DSSIPluginInstance::selectProgram(" << program <<
"): made select_program(" << bankNo <<
"," << programNo <<
") call" << endl;
655 if (backupPortValues) {
666 SVDEBUG <<
"DSSIPluginInstance::activate" << endl;
674 SVDEBUG <<
"DSSIPluginInstance::activate: restoring program " <<
m_program << endl;
697 assert(
sizeof(LADSPA_Data) ==
sizeof(
float));
698 assert(
sizeof(
sample_t) ==
sizeof(
float));
701 int inbuf = 0, outbuf = 0;
731 SVDEBUG <<
"DSSIPluginInstance::connectPorts: set control port " << i <<
" to default value " << defaultValue << endl;
754 SVDEBUG <<
"DSSIPluginInstance::setParameterValue(" << parameter <<
") to " << value << endl;
762 if (value < f->getPortMinimum(
m_descriptor->LADSPA_Plugin, portNumber)) {
778 SVDEBUG <<
"DSSIPluginInstance::setPortValueFromController(" << port <<
") to " << cv << endl;
781 const LADSPA_Descriptor *p =
m_descriptor->LADSPA_Plugin;
782 LADSPA_PortRangeHintDescriptor d = p->PortRangeHints[port].HintDescriptor;
783 LADSPA_Data lb = p->PortRangeHints[port].LowerBound;
784 LADSPA_Data ub = p->PortRangeHints[port].UpperBound;
786 float value = (float)cv;
788 if (!LADSPA_IS_HINT_BOUNDED_BELOW(d)) {
789 if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
793 value = ub - 127.0f + value;
796 if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
802 value = lb + ((ub - lb) * value / 127.0f);
824 SVDEBUG <<
"DSSIPluginInstance::getParameterValue(" << parameter <<
")" << endl;
865 #ifdef DSSI_PROJECT_DIRECTORY_KEY 866 key = DSSI_PROJECT_DIRECTORY_KEY;
868 return std::string();
874 SVDEBUG <<
"DSSIPluginInstance::configure(" << key <<
"," << value <<
")" << endl;
889 #ifdef DSSI_RESERVED_CONFIGURE_PREFIX 890 if (QString(key.c_str()).startsWith(DSSI_RESERVED_CONFIGURE_PREFIX)) {
897 qm = std::string(
m_descriptor->LADSPA_Plugin->Label) +
": ";
902 cerr <<
"DSSIPluginInstance::configure: warning: configure returned message: \"" << qm <<
"\"" << endl;
912 #ifdef DEBUG_DSSI_PROCESS 922 #ifdef DEBUG_DSSI_PROCESS 923 cerr <<
"... clearing down" << endl;
929 snd_seq_event_t *
event = (snd_seq_event_t *)e;
930 #ifdef DEBUG_DSSI_PROCESS 931 SVDEBUG <<
"DSSIPluginInstance::sendEvent at " << eventTime << endl;
933 snd_seq_event_t ev(*event);
935 ev.time.time.tv_sec = eventTime.sec;
936 ev.time.time.tv_nsec = eventTime.nsec;
939 ev.data.note.channel = 0;
957 int controller = ev->data.control.param;
959 #ifdef DEBUG_DSSI_PROCESS 960 SVDEBUG <<
"DSSIPluginInstance::handleController " << controller << endl;
963 if (controller == 0) {
967 }
else if (controller == 32) {
971 }
else if (controller > 0 && controller < 128) {
992 bool needLock =
false;
1024 #ifdef DEBUG_DSSI_PROCESS 1025 SVDEBUG <<
"DSSIPluginInstance::run(" << blockTime <<
")" << endl;
1028 #ifdef DEBUG_DSSI_PROCESS 1030 SVDEBUG <<
"DSSIPluginInstance::run: event buffer has " 1037 snd_seq_event_t *ev = localEventBuffer + evCount;
1041 Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
1043 int frameOffset = 0;
1044 if (evTime > blockTime) {
1045 frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime,
m_sampleRate);
1048 #ifdef DEBUG_DSSI_PROCESS 1049 SVDEBUG <<
"DSSIPluginInstance::run: evTime " << evTime <<
", blockTime " << blockTime <<
", frameOffset " << frameOffset
1051 cerr <<
"Type: " << int(ev->type) <<
", pitch: " << int(ev->data.note.note) <<
", velocity: " << int(ev->data.note.velocity) << endl;
1054 if (frameOffset >=
int(count))
break;
1055 if (frameOffset < 0) {
1057 if (ev->type == SND_SEQ_EVENT_NOTEON) {
1063 ev->time.tick = frameOffset;
1066 if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
1068 }
else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
1084 SVDEBUG <<
"DSSIPluginInstance::run: making select_program(" << bank <<
"," << program <<
") call" << endl;
1091 SVDEBUG <<
"DSSIPluginInstance::run: made select_program(" << bank <<
"," << program <<
") call" << endl;
1095 #ifdef DEBUG_DSSI_PROCESS 1096 SVDEBUG <<
"DSSIPluginInstance::run: running with " << evCount <<
" events" 1101 localEventBuffer, evCount);
1103 #ifdef DEBUG_DSSI_PROCESS 1153 bool needRun =
true;
1157 #ifdef DEBUG_DSSI_PROCESS 1158 SVDEBUG <<
"DSSIPluginInstance::runGrouped(" << blockTime <<
"): this is " <<
this <<
"; " << s.size() <<
" elements in m_groupMap[" <<
m_identifier <<
"]" << endl;
1162 for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
1165 #ifdef DEBUG_DSSI_PROCESS 1166 SVDEBUG <<
"DSSIPluginInstance::runGrouped(" << blockTime <<
"): plugin " <<
instance <<
" has already been run" << endl;
1174 #ifdef DEBUG_DSSI_PROCESS 1175 SVDEBUG <<
"DSSIPluginInstance::runGrouped(" << blockTime <<
"): already run, returning" << endl;
1180 #ifdef DEBUG_DSSI_PROCESS 1181 SVDEBUG <<
"DSSIPluginInstance::runGrouped(" << blockTime <<
"): I'm the first, running" << endl;
1185 unsigned long *counts = (
unsigned long *)
1187 LADSPA_Handle *instances = (LADSPA_Handle *)
1190 for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
1196 instances[index] =
instance->m_instanceHandle;
1198 #ifdef DEBUG_DSSI_PROCESS 1199 SVDEBUG <<
"DSSIPluginInstance::runGrouped(" << blockTime <<
"): running " <<
instance << endl;
1202 if (
instance->m_pending.program >= 0 &&
1203 instance->m_descriptor->select_program) {
1204 int program =
instance->m_pending.program;
1207 instance->m_descriptor->select_program
1208 (
instance->m_instanceHandle, bank, program);
1211 while (
instance->m_eventBuffer.getReadSpace() > 0) {
1214 *ev =
instance->m_eventBuffer.peekOne();
1217 Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
1219 int frameOffset = 0;
1220 if (evTime > blockTime) {
1221 frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime,
m_sampleRate);
1224 #ifdef DEBUG_DSSI_PROCESS 1225 SVDEBUG <<
"DSSIPluginInstance::runGrouped: evTime " << evTime <<
", frameOffset " << frameOffset
1230 if (frameOffset < 0) frameOffset = 0;
1232 ev->time.tick = frameOffset;
1235 if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
1236 accept =
instance->handleController(ev);
1237 }
else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
1238 instance->m_pending.program = ev->data.control.value;
1264 SVDEBUG <<
"DSSIPluginInstance::requestMidiSend" << endl;
1275 SVDEBUG <<
"DSSIPluginInstance::midiSend" << endl;
1289 void (*runFunction)(LADSPA_Handle))
1326 cerr <<
"Bad plugin: plugin id " 1329 <<
" has no cleanup method!" << endl;
sample_t ** m_inputBuffers
DSSIPluginInstance(RealTimePluginFactory *factory, int client, QString identifier, int position, unsigned long sampleRate, size_t blockSize, int idealChannelCount, const DSSI_Descriptor *descriptor)
T peekOne(int R=0) const
Read one sample from the buffer, if available, without advancing the read pointer – i....
std::vector< LADSPA_Data > m_backupControlPortsIn
virtual void sendEvent(const Vamp::RealTime &eventTime, const void *event)
static int requestMidiSend(LADSPA_Handle instance, unsigned char ports, unsigned char channels)
static std::map< LADSPA_Handle, std::set< NonRTPluginThread * > > m_threads
int getPortDisplayHint(const LADSPA_Descriptor *, int port)
void instantiate(unsigned long sampleRate)
sample_t ** m_outputBuffers
static QString RESERVED_PROJECT_DIRECTORY_KEY
static void midiSend(LADSPA_Handle instance, snd_seq_event_t *events, unsigned long eventCount)
std::map< int, int > m_controllerMap
std::vector< std::pair< unsigned long, LADSPA_Data * > > m_controlPortsIn
void runGrouped(const Vamp::RealTime &)
virtual bool isOK() const
bool handleController(snd_seq_event_t *ev)
A very simple class that facilitates running things like plugins without locking, by collecting unwan...
virtual int getParameterDisplayHint(unsigned int parameter) const
static snd_seq_event_t ** m_groupLocalEventBuffers
void scavenge(bool clearNow=false)
Call from a non-RT thread.
virtual void run(const Vamp::RealTime &, size_t count=0)
Run for one block, starting at the given time.
virtual std::string getIdentifier() const
virtual std::string getDescription() const
ConfigurationPairMap m_configurationData
RingBuffer< snd_seq_event_t > m_eventBuffer
void selectProgramAux(std::string program, bool backupPortValues)
virtual size_t getLatency()
void reset()
Reset read and write pointers, thus emptying the buffer.
float getPortDefault(const LADSPA_Descriptor *, int port)
virtual std::string getMaker() const
void checkProgramCache() const
std::vector< ProgramDescriptor > m_cachedPrograms
virtual void clearEvents()
virtual void setIdealChannelCount(size_t channels)
virtual float getControlOutputValue(size_t n) const
std::vector< int > m_audioPortsOut
bool m_haveLastEventSendTime
float getPortMaximum(const LADSPA_Descriptor *, int port)
const DSSI_Descriptor * m_descriptor
virtual size_t getAudioInputCount() const
float getPortQuantization(const LADSPA_Descriptor *, int port)
std::vector< std::pair< unsigned long, LADSPA_Data * > > m_controlPortsOut
QDebug & operator<<(QDebug &dbg, const std::string &s)
virtual int getPluginVersion() const
static Scavenger< ScavengerArrayWrapper< snd_seq_event_t * > > m_bufferScavenger
virtual void setParameter(std::string, float)
virtual ProgramList getPrograms() const
A wrapper to permit arrays to be scavenged.
virtual ~DSSIPluginInstance()
size_t m_outputBufferCount
Vamp::RealTime m_lastRunTime
void setPortValueFromController(unsigned int portNumber, int controlValue)
virtual std::string getName() const
size_t m_idealChannelCount
virtual void selectProgram(std::string program)
virtual void setParameterValue(unsigned int parameter, float value)
int write(const T *source, int n)
Write n samples to the buffer.
#define EVENT_BUFFER_SIZE
static int requestNonRTThread(LADSPA_Handle instance, void(*runFunction)(LADSPA_Handle))
RealTimePluginFactory * m_factory
static RealTimePluginFactory * instance(QString pluginType)
virtual float getParameterDefault(unsigned int parameter) const
virtual ParameterList getParameterDescriptors() const
virtual std::string getCopyright() const
int skip(int n, int R=0)
Pretend to read n samples from the buffer, for reader R, without actually returning them (i....
virtual std::string getProgram(int bank, int program) const
virtual unsigned int getParameterCount() const
virtual std::string configure(std::string key, std::string value)
void claim(T *t)
Call from an RT thread etc., to pass ownership of t to us.
static size_t m_groupLocalEventBufferCount
static GroupMap m_groupMap
virtual float getParameterValue(unsigned int parameter) const
Vamp::RealTime m_lastEventSendTime
virtual std::string getCurrentProgram() const
int getReadSpace(int R=0) const
Return the amount of data available for reading by reader R, in samples.
virtual void detachFromGroup()
std::vector< int > m_audioPortsIn
float getPortMinimum(const LADSPA_Descriptor *, int port)
std::map< QString, PluginSet > GroupMap
virtual void discardEvents()
void initialiseGroupMembership()
virtual float getParameter(std::string) const
std::set< DSSIPluginInstance * > PluginSet
LADSPA_Handle m_instanceHandle
void(* m_runFunction)(LADSPA_Handle)