From b1593d3895276d4897846d87eb9e0ac4fe0737c8 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 8 Oct 2004 13:50:20 +0000 Subject: [PATCH] * Ensure frame offsets for MIDI events get passed through to the VST properly. * Make plugin test whether there are any candidate DLLs in VST_PATH, and omit to run the scanner if there are none. --- dssi-vst-scanner.cpp | 2 +- dssi-vst-server.cpp | 21 ++++++++++----------- dssi-vst.cpp | 15 +++++++++++---- rdwrops.cpp | 24 +++++++++++++++++------- rdwrops.h | 4 ++-- remoteplugin.h | 2 +- remotepluginclient.cpp | 16 ++++++++++++---- remotepluginclient.h | 4 +++- remotepluginserver.cpp | 10 ++++++---- remotepluginserver.h | 3 ++- remotevstclient.cpp | 35 +++++++++++++++++++++++++++++++++++ vstsynth.cpp | 2 +- 12 files changed, 101 insertions(+), 37 deletions(-) diff --git a/dssi-vst-scanner.cpp b/dssi-vst-scanner.cpp index 00d5e54..c879e4d 100644 --- a/dssi-vst-scanner.cpp +++ b/dssi-vst-scanner.cpp @@ -117,7 +117,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow) { char *destFile = 0; - cout << "DSSI VST plugin scanner v0.2" << endl; + cout << "DSSI VST plugin scanner v0.3" << endl; cout << "Copyright (c) 2004 Chris Cannam - Fervent Software" << endl; if (cmdline && cmdline[0]) destFile = strdup(cmdline); diff --git a/dssi-vst-server.cpp b/dssi-vst-server.cpp index 4e7b64b..a707dde 100644 --- a/dssi-vst-server.cpp +++ b/dssi-vst-server.cpp @@ -76,7 +76,9 @@ class RemoteVSTServer : public RemotePluginServer virtual void setCurrentProgram(int); virtual bool hasMIDIInput() { return m_hasMIDI; } - virtual void sendMIDIData(unsigned char *data, int length); + virtual void sendMIDIData(unsigned char *data, + int *frameOffsets, + int events); virtual void process(float **inputs, float **outputs) { inProcessThread = true; @@ -260,10 +262,8 @@ RemoteVSTServer::setCurrentProgram(int p) } void -RemoteVSTServer::sendMIDIData(unsigned char *data, int len) +RemoteVSTServer::sendMIDIData(unsigned char *data, int *frameOffsets, int events) { - std::cerr << "host: sendMIDIData length " << len << std::endl; - #define MIDI_EVENT_BUFFER_COUNT 1024 static VstMidiEvent vme[MIDI_EVENT_BUFFER_COUNT]; static char evbuf[sizeof(VstMidiEvent *) * MIDI_EVENT_BUFFER_COUNT + @@ -273,20 +273,19 @@ RemoteVSTServer::sendMIDIData(unsigned char *data, int len) vstev->reserved = 0; int ix = 0; - int count = len/3; - if (count > MIDI_EVENT_BUFFER_COUNT) { - std::cerr << "vstserv: WARNING: " << count << " MIDI events received " + if (events > MIDI_EVENT_BUFFER_COUNT) { + std::cerr << "vstserv: WARNING: " << events << " MIDI events received " << "for " << MIDI_EVENT_BUFFER_COUNT << "-event buffer" << std::endl; - count = MIDI_EVENT_BUFFER_COUNT; + events = MIDI_EVENT_BUFFER_COUNT; } - while (ix < count) { + while (ix < events) { vme[ix].type = kVstMidiType; vme[ix].byteSize = 24; - vme[ix].deltaFrames = 0; + vme[ix].deltaFrames = (frameOffsets ? frameOffsets[ix] : 0); vme[ix].flags = 0; vme[ix].noteLength = 0; vme[ix].noteOffset = 0; @@ -311,7 +310,7 @@ RemoteVSTServer::sendMIDIData(unsigned char *data, int len) ++ix; } - vstev->numEvents = count; + vstev->numEvents = events; if (!m_plugin->dispatcher(m_plugin, effProcessEvents, 0, 0, vstev, 0)) { cerr << "WARNING: " << ix << " MIDI event(s) rejected by plugin" << endl; } diff --git a/dssi-vst.cpp b/dssi-vst.cpp index 2d012a3..6b8e728 100644 --- a/dssi-vst.cpp +++ b/dssi-vst.cpp @@ -19,7 +19,8 @@ #include #include -#define MIDI_BUFFER_SIZE 1024 +// Should be divisible by three +#define MIDI_BUFFER_SIZE 1023 class DSSIVSTPluginInstance { @@ -68,6 +69,7 @@ class DSSIVSTPluginInstance unsigned long m_programCount; unsigned char m_decodeBuffer[MIDI_BUFFER_SIZE]; + int m_frameOffsetsBuffer[MIDI_BUFFER_SIZE / 3]; snd_midi_event_t *m_alsaDecoder; bool m_pendingProgram; @@ -332,12 +334,17 @@ DSSIVSTPluginInstance::runSynth(unsigned long sampleCount, if (m_alsaDecoder) { unsigned long index = 0; + unsigned long i; - for (unsigned long i = 0; i < eventCount; ++i) { + for (i = 0; i < eventCount; ++i) { snd_seq_event_t *ev = &events[i]; - + if (index >= MIDI_BUFFER_SIZE - 4) break; + + std::cout << "DSSIVSTPluginInstance::runSynth: event at offset " << ev->time.tick << std::endl; + + m_frameOffsetsBuffer[i] = ev->time.tick; long count = snd_midi_event_decode(m_alsaDecoder, m_decodeBuffer + index, @@ -358,7 +365,7 @@ DSSIVSTPluginInstance::runSynth(unsigned long sampleCount, } if (index > 0) { - m_plugin->sendMIDIData(m_decodeBuffer, index); + m_plugin->sendMIDIData(m_decodeBuffer, m_frameOffsetsBuffer, i); } } } catch (RemotePluginClosedException) { diff --git a/rdwrops.cpp b/rdwrops.cpp index 4d172d6..b38a6a2 100644 --- a/rdwrops.cpp +++ b/rdwrops.cpp @@ -119,16 +119,26 @@ rdwr_readFloat(int fd, const char *file, int line) } extern unsigned char * -rdwr_readMIDIData(int fd, int &len, const char *file, int line) +rdwr_readMIDIData(int fd, int **frameoffsets, int &events, const char *file, int line) { static unsigned char *buf = 0; - static int bufLen = 0; - rdwr_tryRead(fd, &len, sizeof(int), file, line); - if (len > bufLen) { + static int *frameoffbuf = 0; + static int bufEvts = 0; + + rdwr_tryRead(fd, &events, sizeof(int), file, line); + + if (events > bufEvts) { delete buf; - buf = new unsigned char[len]; - bufLen = len; + delete frameoffbuf; + buf = new unsigned char[events * 3]; + frameoffbuf = new int[events]; + bufEvts = events; } - rdwr_tryRead(fd, buf, len, file, line); + + rdwr_tryRead(fd, buf, events * 3, file, line); + rdwr_tryRead(fd, frameoffbuf, events * sizeof(int), file, line); + + if (frameoffsets) *frameoffsets = frameoffbuf; return buf; } + diff --git a/rdwrops.h b/rdwrops.h index d916efe..88ae81e 100644 --- a/rdwrops.h +++ b/rdwrops.h @@ -19,7 +19,7 @@ extern void rdwr_writeInt(int fd, int i, const char *file, int line); extern int rdwr_readInt(int fd, const char *file, int line); extern void rdwr_writeFloat(int fd, float f, const char *file, int line); extern float rdwr_readFloat(int fd, const char *file, int line); -extern unsigned char *rdwr_readMIDIData(int fd, int &len, const char *file, int line); +extern unsigned char *rdwr_readMIDIData(int fd, int **frameoffsets, int &events, const char *file, int line); #define tryRead(a, b, c) rdwr_tryRead(a, b, c, __FILE__, __LINE__) #define tryWrite(a, b, c) rdwr_tryWrite(a, b, c, __FILE__, __LINE__) @@ -30,6 +30,6 @@ extern unsigned char *rdwr_readMIDIData(int fd, int &len, const char *file, int #define readInt(a) rdwr_readInt(a, __FILE__, __LINE__) #define writeFloat(a, b) rdwr_writeFloat(a, b, __FILE__, __LINE__) #define readFloat(a) rdwr_readFloat(a, __FILE__, __LINE__) -#define readMIDIData(a, b) rdwr_readMIDIData(a, b, __FILE__, __LINE__) +#define readMIDIData(a, b, c) rdwr_readMIDIData(a, b, c, __FILE__, __LINE__) #endif diff --git a/remoteplugin.h b/remoteplugin.h index b31ee49..30c30ea 100644 --- a/remoteplugin.h +++ b/remoteplugin.h @@ -8,7 +8,7 @@ #ifndef REMOTE_PLUGIN_H #define REMOTE_PLUGIN_H -static const float RemotePluginVersion = 0.9; +static const float RemotePluginVersion = 0.95; enum RemotePluginDebugLevel { RemotePluginDebugNone, diff --git a/remotepluginclient.cpp b/remotepluginclient.cpp index 0c020bd..f16b6a4 100644 --- a/remotepluginclient.cpp +++ b/remotepluginclient.cpp @@ -382,12 +382,20 @@ RemotePluginClient::setCurrentProgram(int n) } void -RemotePluginClient::sendMIDIData(unsigned char *data, int length) +RemotePluginClient::sendMIDIData(unsigned char *data, int *frameoffsets, int events) { - std::cerr << "client: sendMIDIData length " << length << std::endl; writeOpcode(m_processFd, RemotePluginSendMIDIData); - writeInt(m_processFd, length); - tryWrite(m_processFd, data, length); + writeInt(m_processFd, events); + tryWrite(m_processFd, data, events * 3); + + if (!frameoffsets) { + // This should not happen with a good client, but we'd better + // cope as well as possible with the lazy ol' degenerates + frameoffsets = (int *)alloca(events * sizeof(int)); + memset(frameoffsets, 0, events * sizeof(int)); + } + + tryWrite(m_processFd, frameoffsets, events * sizeof(int)); } void diff --git a/remotepluginclient.h b/remotepluginclient.h index 79afd32..48cbd09 100644 --- a/remotepluginclient.h +++ b/remotepluginclient.h @@ -48,7 +48,9 @@ class RemotePluginClient void setCurrentProgram(int); bool hasMIDIInput(); - void sendMIDIData(unsigned char *data, int length); + + // Must be three bytes per event + void sendMIDIData(unsigned char *data, int *frameoffsets, int events); // Either inputs or outputs may be NULL if (and only if) there are none void process(float **inputs, float **outputs); diff --git a/remotepluginserver.cpp b/remotepluginserver.cpp index 7444d7c..b6a6cff 100644 --- a/remotepluginserver.cpp +++ b/remotepluginserver.cpp @@ -241,10 +241,12 @@ RemotePluginServer::dispatchProcess() } else if (opcode == RemotePluginSendMIDIData) { - int len = 0; - unsigned char *data = readMIDIData(m_processFd, len); - std::cerr << "server: sendMIDIData length " << len << std::endl; - sendMIDIData(data, len); + int events = 0; + int *frameoffsets = 0; + unsigned char *data = readMIDIData(m_processFd, &frameoffsets, events); + if (events && data && frameoffsets) { + sendMIDIData(data, frameoffsets, events); + } } } diff --git a/remotepluginserver.h b/remotepluginserver.h index 4c050e3..cd1ef7d 100644 --- a/remotepluginserver.h +++ b/remotepluginserver.h @@ -43,7 +43,8 @@ class RemotePluginServer virtual bool hasMIDIInput() { return false; } virtual void sendMIDIData(unsigned char *data, - int length) { return; } + int *frameOffsets, + int events) { return; } virtual void process(float **inputs, float **outputs) = 0; diff --git a/remotevstclient.cpp b/remotevstclient.cpp index dbc6ab3..84559c7 100644 --- a/remotevstclient.cpp +++ b/remotevstclient.cpp @@ -92,6 +92,41 @@ RemoteVSTClient::~RemoteVSTClient() void RemoteVSTClient::queryPlugins(std::vector &plugins) { + // First check whether there are any DLLs in the same VST path as + // the scanner uses. If not, we know immediately there are no + // plugins and we don't need to run the (Wine-based) scanner. + + std::vector vstPath = Paths::getPath + ("VST_PATH", "/usr/local/lib/vst:/usr/lib/vst", "/vst"); + + bool haveDll = false; + + for (size_t i = 0; i < vstPath.size(); ++i) { + + std::string vstDir = vstPath[i]; + DIR *directory = opendir(vstDir.c_str()); + if (!directory) continue; + struct dirent *entry; + + while ((entry = readdir(directory))) { + + std::string libname = entry->d_name; + + if (libname[0] != '.' && + libname.length() >= 5 && + (libname.substr(libname.length() - 4) == ".dll" || + libname.substr(libname.length() - 4) == ".DLL")) { + haveDll = true; + break; + } + } + + closedir(directory); + if (haveDll) break; + } + + if (!haveDll) return; + char fifoFile[60]; sprintf(fifoFile, "/tmp/rplugin_qry_XXXXXX"); diff --git a/vstsynth.cpp b/vstsynth.cpp index 09e2a70..0118df4 100644 --- a/vstsynth.cpp +++ b/vstsynth.cpp @@ -257,7 +257,7 @@ jackProcess(jack_nframes_t nframes, void *arg) pthread_mutex_lock(&pluginMutex); if (alsaDecoderIndex > 0) { - plugin->sendMIDIData(alsaDecoderBuffer, alsaDecoderIndex); + plugin->sendMIDIData(alsaDecoderBuffer, 0, alsaDecoderIndex); alsaDecoderIndex = 0; }