summaryrefslogtreecommitdiff
path: root/muse2/muse
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2011-04-25 20:47:28 +0000
committerTim E. Real <termtech@rogers.com>2011-04-25 20:47:28 +0000
commit499ccec21dd2ac636fb019c98a902c351b4ec165 (patch)
tree03b867772f9d4543c2ae0e8ca49f389333ea5ad7 /muse2/muse
parent5974951aeaf0a86b83175e018d5bf35e509f5181 (diff)
Overhaul plugin module and add variable run-length ladspa + dssi processing. Please see ChangeLog.
Diffstat (limited to 'muse2/muse')
-rw-r--r--muse2/muse/CMakeLists.txt1
-rw-r--r--muse2/muse/audiotrack.cpp6
-rw-r--r--muse2/muse/controlfifo.cpp75
-rw-r--r--muse2/muse/controlfifo.h64
-rw-r--r--muse2/muse/ctrl.h3
-rw-r--r--muse2/muse/driver/alsamidi.h2
-rw-r--r--muse2/muse/driver/audiodev.h2
-rw-r--r--muse2/muse/driver/dummyaudio.cpp2
-rw-r--r--muse2/muse/driver/jackaudio.h2
-rw-r--r--muse2/muse/driver/jackmidi.h2
-rw-r--r--muse2/muse/dssihost.cpp430
-rw-r--r--muse2/muse/dssihost.h29
-rw-r--r--muse2/muse/mididev.h2
-rw-r--r--muse2/muse/mixer/astrip.cpp28
-rw-r--r--muse2/muse/mixer/panknob.cpp5
-rw-r--r--muse2/muse/osc.cpp43
-rw-r--r--muse2/muse/osc.h6
-rw-r--r--muse2/muse/plugin.cpp704
-rw-r--r--muse2/muse/plugin.h140
-rw-r--r--muse2/muse/synth.cpp5
-rw-r--r--muse2/muse/synth.h6
21 files changed, 1249 insertions, 308 deletions
diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt
index 2a630f84..2d2a9fe3 100644
--- a/muse2/muse/CMakeLists.txt
+++ b/muse2/muse/CMakeLists.txt
@@ -83,6 +83,7 @@ file (GLOB core_source_files
cobject.cpp
conf.cpp
confmport.cpp
+ controlfifo.cpp
ctrl.cpp
dssihost.cpp
event.cpp
diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp
index 98e74331..c427a55c 100644
--- a/muse2/muse/audiotrack.cpp
+++ b/muse2/muse/audiotrack.cpp
@@ -989,7 +989,8 @@ bool AudioTrack::readProperties(Xml& xml, const QString& tag)
//PluginI* p = 0;
PluginIBase* p = 0;
bool ctlfound = false;
- int m = l->id() & AC_PLUGIN_CTL_ID_MASK;
+ //int m = l->id() & AC_PLUGIN_CTL_ID_MASK;
+ unsigned m = l->id() & AC_PLUGIN_CTL_ID_MASK; // p4.0.21
int n = (l->id() >> AC_PLUGIN_CTL_BASE_POW) - 1;
if(n >= 0 && n < PipelineDepth)
{
@@ -1163,7 +1164,8 @@ void AudioTrack::mapRackPluginsToControllers()
// Ignore volume, pan, mute etc.
if(id < AC_PLUGIN_CTL_BASE)
continue;
- int param = id & AC_PLUGIN_CTL_ID_MASK;
+ //int param = id & AC_PLUGIN_CTL_ID_MASK;
+ unsigned param = id & AC_PLUGIN_CTL_ID_MASK; // p4.0.21
int idx = (id >> AC_PLUGIN_CTL_BASE_POW) - 1;
//PluginI* p = (*_efxPipe)[idx];
diff --git a/muse2/muse/controlfifo.cpp b/muse2/muse/controlfifo.cpp
new file mode 100644
index 00000000..526e88c7
--- /dev/null
+++ b/muse2/muse/controlfifo.cpp
@@ -0,0 +1,75 @@
+//=============================================================================
+// MusE
+// Linux Music Editor
+//
+// Copyright (C) 1999-2010 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "controlfifo.h"
+
+//---------------------------------------------------------
+// ControlFifo
+// put
+// return true on fifo overflow
+//---------------------------------------------------------
+
+bool ControlFifo::put(const ControlEvent& event)
+ {
+ if (size < CONTROL_FIFO_SIZE) {
+ fifo[wIndex] = event;
+ wIndex = (wIndex + 1) % CONTROL_FIFO_SIZE;
+ // q_atomic_increment(&size);
+ ++size;
+ return false;
+ }
+ return true;
+ }
+
+//---------------------------------------------------------
+// get
+//---------------------------------------------------------
+
+ControlEvent ControlFifo::get()
+ {
+ ControlEvent event(fifo[rIndex]);
+ rIndex = (rIndex + 1) % CONTROL_FIFO_SIZE;
+ // q_atomic_decrement(&size);
+ --size;
+ return event;
+ }
+
+//---------------------------------------------------------
+// peek
+//---------------------------------------------------------
+
+const ControlEvent& ControlFifo::peek(int n)
+ {
+ int idx = (rIndex + n) % CONTROL_FIFO_SIZE;
+ return fifo[idx];
+ }
+
+//---------------------------------------------------------
+// remove
+//---------------------------------------------------------
+
+void ControlFifo::remove()
+ {
+ rIndex = (rIndex + 1) % CONTROL_FIFO_SIZE;
+ // q_atomic_decrement(&size);
+ --size;
+ }
+
+
+
diff --git a/muse2/muse/controlfifo.h b/muse2/muse/controlfifo.h
new file mode 100644
index 00000000..a0b6bfd0
--- /dev/null
+++ b/muse2/muse/controlfifo.h
@@ -0,0 +1,64 @@
+//=============================================================================
+// MusE
+// Linux Music Editor
+//
+// Copyright (C) 1999-2010 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __CONTROLFIFO_H__
+#define __CONTROLFIFO_H__
+
+#define CONTROL_FIFO_SIZE 8192
+
+//---------------------------------------------------------
+// ControlEvent
+// Item struct for ControlFifo.
+//---------------------------------------------------------
+
+struct ControlEvent
+{
+ // Unique: Whether the item must not be skipped, even if it has the same
+ // (possibly rounded) frame and index as the previous item. This is mainly for
+ // dssi-vst guis, they require acknowledgment of every message.
+ bool unique;
+ unsigned idx;
+ float value;
+ unsigned frame;
+};
+
+//---------------------------------------------------------
+// ControlFifo
+//---------------------------------------------------------
+
+class ControlFifo
+{
+ ControlEvent fifo[CONTROL_FIFO_SIZE];
+ volatile int size;
+ int wIndex;
+ int rIndex;
+
+ public:
+ ControlFifo() { clear(); }
+ bool put(const ControlEvent& event); // returns true on fifo overflow
+ ControlEvent get();
+ const ControlEvent& peek(int n = 0);
+ void remove();
+ bool isEmpty() const { return size == 0; }
+ void clear() { size = 0, wIndex = 0, rIndex = 0; }
+ int getSize() const { return size; }
+};
+
+
+#endif \ No newline at end of file
diff --git a/muse2/muse/ctrl.h b/muse2/muse/ctrl.h
index 4d864b9f..955fd01f 100644
--- a/muse2/muse/ctrl.h
+++ b/muse2/muse/ctrl.h
@@ -23,7 +23,8 @@ const int AC_MUTE = 2;
#define AC_PLUGIN_CTL_BASE_POW 12
#define AC_PLUGIN_CTL_ID_MASK 0xFFF
-inline int genACnum(int plugin, int ctrl) { return (plugin + 1) * AC_PLUGIN_CTL_BASE + ctrl; }
+//inline int genACnum(int plugin, int ctrl) { return (plugin + 1) * AC_PLUGIN_CTL_BASE + ctrl; }
+inline unsigned genACnum(unsigned plugin, unsigned ctrl) { return (plugin + 1) * AC_PLUGIN_CTL_BASE + ctrl; }
class Xml;
diff --git a/muse2/muse/driver/alsamidi.h b/muse2/muse/driver/alsamidi.h
index 455ab1df..a2480c5c 100644
--- a/muse2/muse/driver/alsamidi.h
+++ b/muse2/muse/driver/alsamidi.h
@@ -44,7 +44,7 @@ class MidiAlsaDevice : public MidiDevice {
virtual void* outClientPort() { return (void*)&adr; } // That is, ALSA midi client ports can be both r/w.
virtual void writeRouting(int, Xml&) const;
- virtual inline int deviceType() { return ALSA_MIDI; }
+ virtual inline int deviceType() const { return ALSA_MIDI; }
};
extern bool initMidiAlsa();
diff --git a/muse2/muse/driver/audiodev.h b/muse2/muse/driver/audiodev.h
index af53d7de..4685b89a 100644
--- a/muse2/muse/driver/audiodev.h
+++ b/muse2/muse/driver/audiodev.h
@@ -28,7 +28,7 @@ class AudioDevice {
AudioDevice() {}
virtual ~AudioDevice() {}
- virtual int deviceType() = 0; // p3.3.52
+ virtual int deviceType() const = 0; // p3.3.52
//virtual void start() = 0;
virtual void start(int priority) = 0;
diff --git a/muse2/muse/driver/dummyaudio.cpp b/muse2/muse/driver/dummyaudio.cpp
index 597ecf2b..55f091c2 100644
--- a/muse2/muse/driver/dummyaudio.cpp
+++ b/muse2/muse/driver/dummyaudio.cpp
@@ -66,7 +66,7 @@ class DummyAudioDevice : public AudioDevice {
free(buffer);
}
- virtual inline int deviceType() { return DUMMY_AUDIO; } // p3.3.52
+ virtual inline int deviceType() const { return DUMMY_AUDIO; } // p3.3.52
//virtual void start();
virtual void start(int);
diff --git a/muse2/muse/driver/jackaudio.h b/muse2/muse/driver/jackaudio.h
index d3132efe..5be0797f 100644
--- a/muse2/muse/driver/jackaudio.h
+++ b/muse2/muse/driver/jackaudio.h
@@ -38,7 +38,7 @@ class JackAudioDevice : public AudioDevice {
virtual ~JackAudioDevice();
virtual void nullify_client() { _client = 0; }
- virtual inline int deviceType() { return JACK_AUDIO; } // p3.3.52
+ virtual inline int deviceType() const { return JACK_AUDIO; } // p3.3.52
void scanMidiPorts();
diff --git a/muse2/muse/driver/jackmidi.h b/muse2/muse/driver/jackmidi.h
index 842cbc2d..2dcf2fbb 100644
--- a/muse2/muse/driver/jackmidi.h
+++ b/muse2/muse/driver/jackmidi.h
@@ -129,7 +129,7 @@ class MidiJackDevice : public MidiDevice {
//static MidiDevice* createJackMidiDevice(QString /*name*/, int /*rwflags*/); // 1:Writable 2: Readable. Do not mix.
static MidiDevice* createJackMidiDevice(QString name = "", int rwflags = 3); // p3.3.55 1:Writable 2: Readable 3: Writable + Readable
- virtual inline int deviceType() { return JACK_MIDI; }
+ virtual inline int deviceType() const { return JACK_MIDI; }
virtual void setName(const QString&);
diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp
index f2e94dae..b91000be 100644
--- a/muse2/muse/dssihost.cpp
+++ b/muse2/muse/dssihost.cpp
@@ -48,6 +48,7 @@
#include "midiport.h"
#include "stringparam.h"
#include "plugin.h"
+#include "controlfifo.h"
//#include "al/al.h"
//#include "al/xml.h"
#include "xml.h"
@@ -550,8 +551,10 @@ DssiSynth::DssiSynth(QFileInfo& fi, const DSSI_Descriptor* d) : // ddskrjo remov
_inPlaceCapable = !LADSPA_IS_INPLACE_BROKEN(descr->Properties);
- // Blacklist vst plugins in-place configurable for now.
- if ((_inports != _outports) || (fi.completeBaseName() == QString("dssi-vst") && !config.vstInPlace))
+ // Hack: Special flag required for example for control processing.
+ _isDssiVst = fi.completeBaseName() == QString("dssi-vst");
+ // Hack: Blacklist vst plugins in-place, configurable for now.
+ if ((_inports != _outports) || (_isDssiVst && !config.vstInPlace))
_inPlaceCapable = false;
}
@@ -677,8 +680,10 @@ SynthIF* DssiSynth::createSIF(SynthI* synti)
}
_inPlaceCapable = !LADSPA_IS_INPLACE_BROKEN(descr->Properties);
- // Blacklist vst plugins in-place configurable for now.
- if((_inports != _outports) || (info.completeBaseName() == QString("dssi-vst") && !config.vstInPlace))
+ // Hack: Special flag required for example for control processing.
+ _isDssiVst = info.completeBaseName() == QString("dssi-vst");
+ // Hack: Blacklist vst plugins in-place, configurable for now.
+ if((_inports != _outports) || (_isDssiVst && !config.vstInPlace))
_inPlaceCapable = false;
}
}
@@ -1374,10 +1379,22 @@ void DssiSynthIF::setParameter(unsigned long n, float v)
return;
}
- if(!controls)
- return;
-
- controls[n].val = v;
+ //if(!controls)
+ // return;
+ //controls[n].val = v;
+ // p4.0.21
+ ControlEvent ce;
+ ce.unique = false;
+ ce.idx = n;
+ ce.value = v;
+ // Time-stamp the event. This does a possibly slightly slow call to gettimeofday via timestamp().
+ // timestamp() is more or less an estimate of the current frame. (This is exactly how ALSA events
+ // are treated when they arrive in our ALSA driver.)
+ ce.frame = audio->timestamp();
+ if(_controlFifo.put(ce))
+ {
+ fprintf(stderr, "DssiSynthIF::setParameter: fifo overflow: in control number:%ld\n", n);
+ }
// Notify that changes are to be sent upon heartbeat.
// TODO: No, at least not for now. So far, setParameter is only called during loading of stored params,
@@ -1579,7 +1596,7 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
len += 2;
//snd_seq_event_t* event = &events[nevents];
- event->queue = SND_SEQ_QUEUE_DIRECT;
+ //event->queue = SND_SEQ_QUEUE_DIRECT;
#ifdef DSSI_DEBUG
fprintf(stderr, "DssiSynthIF::processEvent midi event type:%d chn:%d a:%d b:%d\n", e.type(), chn, a, b);
@@ -1592,12 +1609,16 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
fprintf(stderr, "DssiSynthIF::processEvent midi event is ME_NOTEON\n");
#endif
+ snd_seq_ev_clear(event);
+ event->queue = SND_SEQ_QUEUE_DIRECT;
if(b)
snd_seq_ev_set_noteon(event, chn, a, b);
else
snd_seq_ev_set_noteoff(event, chn, a, 0);
break;
case ME_NOTEOFF:
+ snd_seq_ev_clear(event);
+ event->queue = SND_SEQ_QUEUE_DIRECT;
snd_seq_ev_set_noteoff(event, chn, a, 0);
break;
case ME_PROGRAM:
@@ -1665,6 +1686,8 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
#endif
b &= 0x3fff;
+ snd_seq_ev_clear(event);
+ event->queue = SND_SEQ_QUEUE_DIRECT;
snd_seq_ev_set_pitchbend(event, chn, b);
// Event pointer filled. Return true.
return true;
@@ -1697,7 +1720,7 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
int ctlnum = a;
//switch(midiControllerType(a))
if(midiControllerType(a) != MidiController::Controller7)
- return false;
+ return false; // Event pointer not filled. Return false.
else
{
/*
@@ -1782,6 +1805,8 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
#ifdef DSSI_DEBUG
printf("DssiSynthIF::processEvent non-ladspa filling midi event chn:%d dataA:%d dataB:%d\n", chn, a, b);
#endif
+ snd_seq_ev_clear(event);
+ event->queue = SND_SEQ_QUEUE_DIRECT;
snd_seq_ev_set_controller(event, chn, a, b);
return true;
}
@@ -1867,9 +1892,13 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
}
break;
case ME_PITCHBEND:
+ snd_seq_ev_clear(event);
+ event->queue = SND_SEQ_QUEUE_DIRECT;
snd_seq_ev_set_pitchbend(event, chn, a);
break;
case ME_AFTERTOUCH:
+ snd_seq_ev_clear(event);
+ event->queue = SND_SEQ_QUEUE_DIRECT;
snd_seq_ev_set_chanpress(event, chn, a);
break;
case ME_SYSEX:
@@ -1948,6 +1977,8 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
// "DssiSynthIF::processEvent midi event is ME_SYSEX"
// "WARNING: MIDI event of type ? decoded to 367 bytes, discarding"
// That might be ALSA doing that.
+ snd_seq_ev_clear(event);
+ event->queue = SND_SEQ_QUEUE_DIRECT;
snd_seq_ev_set_sysex(event, len,
//(unsigned char*)ba.data());
(unsigned char*)ca);
@@ -1964,6 +1995,8 @@ bool DssiSynthIF::processEvent(const MidiPlayEvent& e, snd_seq_event_t* event)
return true;
}
+#if 0
+
//---------------------------------------------------------
// getData
//---------------------------------------------------------
@@ -2241,6 +2274,331 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns
return i;
}
+#else
+
+//---------------------------------------------------------
+// getData
+//---------------------------------------------------------
+
+//void DssiSynthIF::getData(MidiEventList* el, unsigned pos, int ch, unsigned samples, float** data)
+iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, unsigned pos, int ports, unsigned n, float** buffer)
+{
+ //#ifdef DSSI_DEBUG
+ // fprintf(stderr, "DssiSynthIF::getData elsize:%d pos:%d ports:%d samples:%d processed already?:%d\n", el->size(), pos, ports, n, synti->processed());
+ //#endif
+
+ // Grab the control ring buffer size now.
+ //const int cbsz = _controlFifo.getSize();
+
+ // We may not be using nevents all at once - this will be just the maximum.
+ unsigned long nevents = el->size() + synti->eventFifo.getSize();
+ snd_seq_event_t events[nevents];
+ // No, do this in processEvent.
+ //memset(events, 0, sizeof(events));
+
+ //nevents = 0;
+
+ unsigned endPos = pos + n;
+ int frameOffset = audio->getFrameOffset();
+
+ // All ports must be connected to something!
+ unsigned long nop, k;
+ // First, copy the given input buffers to our local input buffers.
+ //np = portsin > synth->_inports ? synth->_inports : portsin;
+ //for(k = 0; k < np; ++k)
+ // memcpy(audioInBuffers[k], inbuffer[k], sizeof(float) * n);
+ //for(; k < portsin; ++k)
+ // memset(audioInBuffers[k], 0, sizeof(float) * n);
+
+ // Watch our limits.
+ //willyfoobar-2011-02-13
+ //old code//np = ports > synth->_outports ? synth->_outports : ports;
+ nop = ((unsigned long) ports) > synth->_outports ? synth->_outports : ((unsigned long) ports);
+ // TODO Number of inports requested?
+ //nip = ((unsigned long) iports) > synth->_inports ? synth->_inports : ((unsigned long) iports);
+
+ const DSSI_Descriptor* dssi = synth->dssi;
+ const LADSPA_Descriptor* descr = dssi->LADSPA_Plugin;
+ unsigned sample = 0;
+ int loopcount = 0; // REMOVE Tim.
+
+ // NOTE Tested: Variable run-lengths worked superbly for LADSPA and DSSI synths. But DSSI-VST definitely
+ // does NOT like changing sample run length. It crashes the plugin and Wine (but MusE keeps running!).
+ // Furthermore, it resizes the shared memory (mmap, remap) upon each run length DIFFERENT from the last.
+ // And all of this done through client-server communications. It doesn't seem designed for this technique.
+ //
+ // So we could support an alternate technique: A fixed control processing rate, in number of samples.
+ //
+ // Allow user to choose either a fixed rate or these 'packets' for LADSPA and DSSI plugins/synths,
+ // but make fixed-rate MANDATORY for DSSI-VST plugins and synths.
+ //
+ // Or K.I.S.S - Just use fixed rates only, but allow it to be changed. I'm worried about libraries and
+ // plugins other than DSSI-VST. What if they need the fixed-rate, too?
+ // How to tell, and manage it all...?
+ // But this 'packet' method sure seems to work nicely so far, so we'll throw it in...
+ //
+ // Must make this detectable for dssi vst synths, just like the plugins' in-place blacklist.
+ //const bool usefixedrate = true;
+ const bool usefixedrate = synth->_isDssiVst; // Try this.
+ // TODO Make this number a global setting.
+ // Note for dssi-vst this MUST equal audio period. It doesn't like broken-up runs (it stutters),
+ // even with fixed sizes. Could be a Wine + Jack thing, wanting a full Jack buffer's length.
+ //unsigned fixedsize = 2048;
+ unsigned fixedsize = n;
+
+ // For now, the fixed size is clamped to the audio buffer size.
+ // TODO: We could later add slower processing over several cycles -
+ // so that users can select a small audio period but a larger control period.
+ if(fixedsize > n)
+ fixedsize = n;
+
+ while(sample < n)
+ {
+ //unsigned nsamp = n;
+ //unsigned nsamp = n - sample;
+ unsigned nsamp = usefixedrate ? fixedsize : n - sample;
+ bool found = false;
+ unsigned frame = 0;
+ unsigned index = 0;
+ // Get all control ring buffer items valid for this time period...
+ //for(int m = 0; m < cbsz; ++m)
+ while(!_controlFifo.isEmpty())
+ {
+ //ControlValue v = _controlFifo.get();
+ ControlEvent v = _controlFifo.peek();
+ //printf("DssiSynthIF::getData control idx:%d frame:%d val:%f\n", v.idx, v.frame, v.value); // REMOVE Tim.
+ // Process only items in this time period. Make sure to process all
+ // subsequent items which have the same frame.
+ //if(v.frame >= (endPos + frameOffset) || (found && v.frame != frame))
+ //if(v.frame < sample || v.frame >= (sample + nsamp) || (found && v.frame != frame))
+ //if(v.frame < sample || v.frame >= (endPos + frameOffset) || (found && v.frame != frame))
+ if(v.frame < sample || v.frame >= (endPos + frameOffset)
+ //|| (found && v.frame != frame)
+ //|| (!usefixedrate && found && !v.unique && v.frame != frame)
+ || (found && !v.unique && v.frame != frame)
+ // dssi-vst needs them serialized and accounted for, no matter what. This works with fixed rate
+ // because nsamp is constant. But with packets, we need to guarantee at least one-frame spacing.
+ // Although we likely won't be using packets with dssi-vst, so it's OK for now.
+ //|| (found && v.idx == index))
+ //|| (usefixedrate && found && v.idx == index)) // Try this.
+ || (usefixedrate && found && v.unique && v.idx == index)) //
+ break;
+ _controlFifo.remove(); // Done with the ring buffer's item. Remove it.
+ if(v.idx >= synth->_controlInPorts) // Sanity check.
+ break;
+ found = true;
+ frame = v.frame;
+ index = v.idx;
+ // Set the ladspa control port value.
+ controls[v.idx].val = v.value;
+ }
+
+ //if(found)
+ if(found && !usefixedrate)
+ //nsamp = frame - sample + 1;
+ nsamp = frame - sample;
+ if(sample + nsamp >= n) // Safety check.
+ nsamp = n - sample;
+
+ //printf("DssiSynthIF::getData n:%d frame:%d sample:%d nsamp:%d pos:%d fOffset:%d loopcount:%d\n",
+ // n, frame, sample, nsamp, pos, frameOffset, loopcount); // REMOVE Tim.
+
+ // TODO: TESTING: Don't allow zero-length runs. This could/should be checked in the control loop instead.
+ // Note this means it is still possible to get stuck in the top loop (at least for a while).
+ if(nsamp == 0)
+ continue;
+
+ nevents = 0;
+ // Process event list events...
+ for(; i != el->end(); ++i)
+ {
+ //if(i->time() >= (endPos + frameOffset)) // NOTE: frameOffset? Tested, examined printouts of times: Seems OK for playback.
+ if(i->time() >= (pos + sample + nsamp + frameOffset)) // frameOffset? Test again...
+ break;
+
+ #ifdef DSSI_DEBUG
+ fprintf(stderr, "DssiSynthIF::getData eventlist event time:%d\n", i->time());
+ #endif
+
+ // p3.3.39 Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values.
+ // Same code as in MidiPort::sendEvent()
+ if(synti->midiPort() != -1)
+ {
+ MidiPort* mp = &midiPorts[synti->midiPort()];
+ if(i->type() == ME_CONTROLLER)
+ {
+ int da = i->dataA();
+ int db = i->dataB();
+ db = mp->limitValToInstrCtlRange(da, db);
+ if(!mp->setHwCtrlState(i->channel(), da, db))
+ continue;
+ //mp->setHwCtrlState(i->channel(), da, db);
+ }
+ else
+ if(i->type() == ME_PITCHBEND)
+ {
+ int da = mp->limitValToInstrCtlRange(CTRL_PITCH, i->dataA());
+ if(!mp->setHwCtrlState(i->channel(), CTRL_PITCH, da))
+ continue;
+ //mp->setHwCtrlState(i->channel(), CTRL_PITCH, da);
+ }
+ else
+ if(i->type() == ME_PROGRAM)
+ {
+ if(!mp->setHwCtrlState(i->channel(), CTRL_PROGRAM, i->dataA()))
+ continue;
+ //mp->setHwCtrlState(i->channel(), CTRL_PROGRAM, i->dataA());
+ }
+ }
+
+ // Returns false if the event was not filled. It was handled, but some other way.
+ if(processEvent(*i, &events[nevents]))
+ {
+ // Time-stamp the event. p4.0.15 Tim.
+ int ft = i->time() - frameOffset - pos;
+ if(ft < 0)
+ ft = 0;
+ //if (ft >= (int)segmentSize)
+ if (ft >= int(sample + nsamp))
+ {
+ //printf("DssiSynthIF::getData: eventlist event time:%d out of range. pos:%d offset:%d ft:%d (seg=%d)\n", i->time(), pos, frameOffset, ft, segmentSize);
+ printf("DssiSynthIF::getData: eventlist event time:%d out of range. pos:%d offset:%d ft:%d sample:%d nsamp:%d\n", i->time(), pos, frameOffset, ft, sample, nsamp);
+ ///if (ft > (int)segmentSize)
+ //ft = segmentSize - 1;
+ ft = sample + nsamp - 1;
+ }
+ // "Each event is timestamped relative to the start of the block, (mis)using the ALSA "tick time" field as a frame count.
+ // The host is responsible for ensuring that events with differing timestamps are already ordered by time." - From dssi.h
+ events[nevents].time.tick = ft;
+
+ ++nevents;
+ }
+ }
+
+ // Now process putEvent events...
+ while(!synti->eventFifo.isEmpty())
+ {
+ //MidiPlayEvent e = synti->eventFifo.get();
+ MidiPlayEvent e = synti->eventFifo.peek();
+
+ #ifdef DSSI_DEBUG
+ fprintf(stderr, "DssiSynthIF::getData eventFifo event time:%d\n", e.time());
+ #endif
+
+ //if(e.time() >= (endPos + frameOffset))
+ if(e.time() >= (pos + sample + nsamp + frameOffset))
+ break;
+
+ synti->eventFifo.remove(); // Done with ring buffer's event. Remove it.
+ // Returns false if the event was not filled. It was handled, but some other way.
+ if(processEvent(e, &events[nevents]))
+ {
+ // Time-stamp the event. p4.0.15 Tim.
+ int ft = e.time() - frameOffset - pos;
+ if(ft < 0)
+ ft = 0;
+ //if (ft >= (int)segmentSize)
+ if (ft >= int(sample + nsamp))
+ {
+ //printf("DssiSynthIF::getData: eventFifo event time:%d out of range. pos:%d offset:%d ft:%d (seg=%d)\n", e.time(), pos, frameOffset, ft, segmentSize);
+ printf("DssiSynthIF::getData: eventFifo event time:%d out of range. pos:%d offset:%d ft:%d sample:%d nsamp:%d\n", e.time(), pos, frameOffset, ft, sample, nsamp);
+ ///if (ft > (int)segmentSize)
+ //ft = segmentSize - 1;
+ ft = sample + nsamp - 1;
+ }
+ // "Each event is timestamped relative to the start of the block, (mis)using the ALSA "tick time" field as a frame count.
+ // The host is responsible for ensuring that events with differing timestamps are already ordered by time." - From dssi.h
+ events[nevents].time.tick = ft;
+
+ ++nevents;
+ }
+ }
+
+ /*
+ //
+ // p3.3.39 Handle inputs...
+ //
+ //if((song->bounceTrack != this) && !noInRoute())
+ if(!((AudioTrack*)synti)->noInRoute())
+ {
+ RouteList* irl = ((AudioTrack*)synti)->inRoutes();
+ iRoute i = irl->begin();
+ if(!i->track->isMidiTrack())
+ {
+ //if(debugMsg)
+ printf("DssiSynthIF::getData: Error: First route is a midi track route!\n");
+ }
+ else
+ {
+ int ch = i->channel == -1 ? 0 : i->channel;
+ int remch = i->remoteChannel == -1 ? 0 : i->remoteChannel;
+ int chs = i->channels == -1 ? 0 : i->channels;
+
+ // TODO:
+ //if(ch >= synth->_inports)
+ //iUsedIdx[ch] = true;
+ //if(chs == 2)
+ // iUsedIdx[ch + 1] = true;
+
+ //((AudioTrack*)i->track)->copyData(framePos, channels, nframe, bp);
+ ((AudioTrack*)i->track)->copyData(pos, ports,
+ //(i->track->type() == Track::AUDIO_SOFTSYNTH && i->channel != -1) ? i->channel : 0,
+ i->channel,
+ i->channels,
+ n, bp);
+ }
+
+ //unsigned pos, int ports, unsigned n, float** buffer
+
+ ++i;
+ for(; i != irl->end(); ++i)
+ {
+ if(i->track->isMidiTrack())
+ {
+ //if(debugMsg)
+ printf("DssiSynthIF::getData: Error: Route is a midi track route!\n");
+ continue;
+ }
+ //((AudioTrack*)i->track)->addData(framePos, channels, nframe, bp);
+ ((AudioTrack*)i->track)->addData(framePos, channels,
+ //(i->track->type() == Track::AUDIO_SOFTSYNTH && i->channel != -1) ? i->channel : 0,
+ i->channel,
+ i->channels,
+ nframe, bp);
+ }
+ }
+ */
+
+ k = 0;
+ // Connect the given buffers directly to the ports, up to a max of synth ports.
+ for(; k < nop; ++k)
+ descr->connect_port(handle, synth->oIdx[k], buffer[k] + sample);
+ // Connect the remaining ports to some local buffers (not used yet).
+ for(; k < synth->_outports; ++k)
+ descr->connect_port(handle, synth->oIdx[k], audioOutBuffers[k] + sample);
+ // Just connect all inputs to some local buffers (not used yet). TODO: Support inputs.
+ for(k = 0; k < synth->_inports; ++k)
+ descr->connect_port(handle, synth->iIdx[k], audioInBuffers[k] + sample);
+
+ // Run the synth for a period of time. This processes events and gets/fills our local buffers...
+ if(synth->dssi->run_synth)
+ {
+ synth->dssi->run_synth(handle, nsamp, events, nevents);
+ }
+ else if (synth->dssi->run_multiple_synths)
+ {
+ snd_seq_event_t* ev = events;
+ synth->dssi->run_multiple_synths(1, &handle, nsamp, &ev, &nevents);
+ }
+
+ sample += nsamp;
+ loopcount++; // REMOVE Tim.
+ }
+
+ return i;
+}
+#endif
+
//---------------------------------------------------------
// putEvent
//---------------------------------------------------------
@@ -2607,7 +2965,7 @@ int DssiSynthIF::oscControl(unsigned long port, float value)
//LADSPA_Data value = argv[1]->f;
#ifdef DSSI_DEBUG
- printf("DssiSynthIF::oscControl received oscControl port:%ld val:%f\n", port, value);
+ printf("DssiSynthIF::oscControl received oscControl port:%ld val:%f\n", port, value);
#endif
//int controlPorts = synth->_controlInPorts;
@@ -2641,19 +2999,17 @@ int DssiSynthIF::oscControl(unsigned long port, float value)
// because dssi-vst is WAITING FOR A RESPONSE. (A CHANGE in the control port value).
// It will output something like "...4 events expected..." and count that number down as 4 actual control port value CHANGES
// are done here in response. Normally it says "...0 events expected..." when MusE is the one doing the DSSI control changes.
- // TODO: (Done) May need FIFOs on each control(!) so that the control changes get sent one per process cycle.
- // Observed countdown not actually going to zero upon string of changes.
//
// NOTE: NOTE: This line in RemoteVSTServer::setParameter(int p, float v) in dssi-vst-server.cpp :
//
// " if (tv.tv_sec > m_lastGuiComms.tv_sec + 10) "
//
// explains an observation that after ten seconds, the server automatically clears the expected number to 0.
- // TODO: Now MusE should forget about all the VST fifo events past ten+ (?) seconds. Add event timestamps...
// You can't send any 'new' values until either you a): send all the expected events or b): wait ten seconds.
// (Because the server simply ignores the 'expected' messages.)
//
// Well, at least here are the fifos. Try this ...
+ /*
OscControlFifo* cfifo = _oscif.oscFifo(cport);
if(cfifo)
{
@@ -2669,6 +3025,21 @@ int DssiSynthIF::oscControl(unsigned long port, float value)
fprintf(stderr, "DssiSynthIF::oscControl: fifo overflow: in control number:%ld\n", cport);
}
}
+ */
+ // p4.0.21
+ ControlEvent ce;
+ ce.unique = synth->_isDssiVst; // Special for messages from vst gui to host - requires processing every message.
+ ce.idx = cport;
+ ce.value = value;
+ // Time-stamp the event. This does a possibly slightly slow call to gettimeofday via timestamp().
+ // timestamp() is more or less an estimate of the current frame. (This is exactly how ALSA events
+ // are treated when they arrive in our ALSA driver.)
+ ce.frame = audio->timestamp();
+ if(_controlFifo.put(ce))
+ {
+ fprintf(stderr, "DssiSynthIF::oscControl: fifo overflow: in control number:%ld\n", cport);
+ }
+
//const DSSI_Descriptor* dssi = synth->dssi;
//const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin;
@@ -2976,7 +3347,8 @@ int DssiSynthIF::getControllerInfo(int id, const char** name, int* ctrl, int* mi
///int i = synth->pIdx[id];
//int i = synth->pIdx[k];
- int i = controls[id].idx;
+ //int i = controls[id].idx;
+ unsigned i = controls[id].idx; // p4.0.21
//ladspaDefaultValue(ld, i, &controls[id].val);
@@ -3103,7 +3475,8 @@ int DssiSynthIF::totalInChannels() const
bool DssiSynthIF::on() const { return true; } // Synth is not part of a rack plugin chain. Always on.
void DssiSynthIF::setOn(bool /*val*/) { }
-int DssiSynthIF::pluginID() { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->UniqueID : 0; }
+//int DssiSynthIF::pluginID() { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->UniqueID : 0; }
+unsigned DssiSynthIF::pluginID() { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->UniqueID : 0; }
//int DssiSynthIF::id() { return 0; } // Synth is not part of a rack plugin chain. Always 0.
int DssiSynthIF::id() { return MAX_PLUGINS; } // Set for special block reserved for dssi synth. p4.0.20
QString DssiSynthIF::pluginLabel() const { return (synth && synth->dssi) ? QString(synth->dssi->LADSPA_Plugin->Label) : QString(); }
@@ -3112,18 +3485,27 @@ QString DssiSynthIF::lib() const { return synth ? sy
QString DssiSynthIF::dirPath() const { return synth ? synth->absolutePath() : QString(); }
QString DssiSynthIF::fileName() const { return synth ? synth->fileName() : QString(); }
AudioTrack* DssiSynthIF::track() { return (AudioTrack*)synti; }
-void DssiSynthIF::enableController(int i, bool v) { controls[i].enCtrl = v; }
-bool DssiSynthIF::controllerEnabled(int i) const { return controls[i].enCtrl; }
-bool DssiSynthIF::controllerEnabled2(int i) const { return controls[i].en2Ctrl; }
+//void DssiSynthIF::enableController(int i, bool v) { controls[i].enCtrl = v; }
+//bool DssiSynthIF::controllerEnabled(int i) const { return controls[i].enCtrl; }
+//bool DssiSynthIF::controllerEnabled2(int i) const { return controls[i].en2Ctrl; }
+void DssiSynthIF::enableController(unsigned i, bool v) { controls[i].enCtrl = v; }
+bool DssiSynthIF::controllerEnabled(unsigned i) const { return controls[i].enCtrl; }
+bool DssiSynthIF::controllerEnabled2(unsigned i) const { return controls[i].en2Ctrl; }
void DssiSynthIF::updateControllers() { }
void DssiSynthIF::writeConfiguration(int /*level*/, Xml& /*xml*/) { }
bool DssiSynthIF::readConfiguration(Xml& /*xml*/, bool /*readPreset*/) { return false; }
-int DssiSynthIF::parameters() const { return synth ? synth->_controlInPorts : 0; }
-void DssiSynthIF::setParam(int i, double val) { setParameter(i, val); }
-double DssiSynthIF::param(int i) const { return getParameter(i); }
-const char* DssiSynthIF::paramName(int i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortNames[controls[i].idx] : 0; }
+//int DssiSynthIF::parameters() const { return synth ? synth->_controlInPorts : 0; }
+//void DssiSynthIF::setParam(int i, double val) { setParameter(i, val); }
+//double DssiSynthIF::param(int i) const { return getParameter(i); }
+//const char* DssiSynthIF::paramName(int i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortNames[controls[i].idx] : 0; }
//LADSPA_PortRangeHint DssiSynthIF::range(int i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortRangeHints[i] : 0; }
-LADSPA_PortRangeHint DssiSynthIF::range(int i) { return synth->dssi->LADSPA_Plugin->PortRangeHints[controls[i].idx]; }
+//LADSPA_PortRangeHint DssiSynthIF::range(int i) { return synth->dssi->LADSPA_Plugin->PortRangeHints[controls[i].idx]; }
+unsigned DssiSynthIF::parameters() const { return synth ? synth->_controlInPorts : 0; }
+void DssiSynthIF::setParam(unsigned i, float val) { setParameter(i, val); }
+float DssiSynthIF::param(unsigned i) const { return getParameter(i); }
+const char* DssiSynthIF::paramName(unsigned i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortNames[controls[i].idx] : 0; }
+//LADSPA_PortRangeHint DssiSynthIF::range(unsigned i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortRangeHints[i] : 0; }
+LADSPA_PortRangeHint DssiSynthIF::range(unsigned i) { return synth->dssi->LADSPA_Plugin->PortRangeHints[controls[i].idx]; }
#else //DSSI_SUPPORT
diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h
index a98cfd87..27c0eae4 100644
--- a/muse2/muse/dssihost.h
+++ b/muse2/muse/dssihost.h
@@ -75,6 +75,8 @@ class DssiSynth : public Synth {
MidiCtl2LadspaPortMap port2MidiCtlMap; // Maps DSSI port numbers to midi controller numbers.
bool _hasGui;
bool _inPlaceCapable;
+ // Hack: Special flag required.
+ bool _isDssiVst;
public:
//DssiSynth(const QFileInfo* fi, QString l) : Synth(fi, l) {
@@ -236,7 +238,8 @@ class DssiSynthIF : public SynthIF, public PluginIBase
//-------------------------
bool on() const;
void setOn(bool /*val*/);
- int pluginID();
+ //int pluginID();
+ unsigned pluginID(); // p4.0.21
int id();
QString pluginLabel() const;
QString name() const;
@@ -244,17 +247,25 @@ class DssiSynthIF : public SynthIF, public PluginIBase
QString dirPath() const;
QString fileName() const;
AudioTrack* track();
- void enableController(int /*i*/, bool v = true);
- bool controllerEnabled(int /*i*/) const;
- bool controllerEnabled2(int /*i*/) const;
+ //void enableController(int /*i*/, bool v = true);
+ //bool controllerEnabled(int /*i*/) const;
+ //bool controllerEnabled2(int /*i*/) const;
+ void enableController(unsigned /*i*/, bool v = true); // p4.0.21
+ bool controllerEnabled(unsigned /*i*/) const;
+ bool controllerEnabled2(unsigned /*i*/) const;
void updateControllers();
void writeConfiguration(int /*level*/, Xml& /*xml*/);
bool readConfiguration(Xml& /*xml*/, bool readPreset=false);
- int parameters() const;
- void setParam(int /*i*/, double /*val*/);
- double param(int /*i*/) const;
- const char* paramName(int /*i*/);
- LADSPA_PortRangeHint range(int /*i*/);
+ //int parameters() const;
+ //void setParam(int /*i*/, double /*val*/);
+ //double param(int /*i*/) const;
+ //const char* paramName(int /*i*/);
+ //LADSPA_PortRangeHint range(int /*i*/);
+ unsigned parameters() const; // p4.0.21
+ void setParam(unsigned /*i*/, float /*val*/);
+ float param(unsigned /*i*/) const;
+ const char* paramName(unsigned /*i*/);
+ LADSPA_PortRangeHint range(unsigned /*i*/);
friend class DssiSynth;
};
diff --git a/muse2/muse/mididev.h b/muse2/muse/mididev.h
index 6ac93729..275bd014 100644
--- a/muse2/muse/mididev.h
+++ b/muse2/muse/mididev.h
@@ -77,7 +77,7 @@ class MidiDevice {
MidiDevice(const QString& name);
virtual ~MidiDevice() {}
- virtual int deviceType() = 0;
+ virtual int deviceType() const = 0;
//virtual void* clientPort() { return 0; }
// p3.3.55
diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp
index 2f1a2262..265061ad 100644
--- a/muse2/muse/mixer/astrip.cpp
+++ b/muse2/muse/mixer/astrip.cpp
@@ -430,7 +430,10 @@ void AudioStrip::volumeChanged(double val)
else
vol = pow(10.0, val/20.0);
volume = vol;
- audio->msgSetVolume((AudioTrack*)track, vol);
+ //audio->msgSetVolume((AudioTrack*)track, vol);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ ((AudioTrack*)track)->setVolume(vol);
+
((AudioTrack*)track)->recordAutomation(AC_VOLUME, vol);
song->update(SC_TRACK_MODIFIED); // for graphical automation update
@@ -455,7 +458,10 @@ void AudioStrip::volumePressed()
else
vol = pow(10.0, val/20.0);
volume = vol;
- audio->msgSetVolume((AudioTrack*)track, volume);
+ //audio->msgSetVolume((AudioTrack*)track, volume);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ ((AudioTrack*)track)->setVolume(volume);
+
((AudioTrack*)track)->startAutoRecord(AC_VOLUME, volume);
}
@@ -498,7 +504,10 @@ void AudioStrip::volLabelChanged(double val)
vol = pow(10.0, val/20.0);
volume = vol;
slider->setValue(val);
- audio->msgSetVolume((AudioTrack*)track, vol);
+ //audio->msgSetVolume((AudioTrack*)track, vol);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ ((AudioTrack*)track)->setVolume(vol);
+
((AudioTrack*)track)->startAutoRecord(AC_VOLUME, vol);
}
@@ -513,7 +522,10 @@ void AudioStrip::panChanged(double val)
track->enablePanController(false);
panVal = val;
- audio->msgSetPan(((AudioTrack*)track), val);
+ //audio->msgSetPan(((AudioTrack*)track), val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ ((AudioTrack*)track)->setPan(val);
+
((AudioTrack*)track)->recordAutomation(AC_PAN, val);
}
@@ -528,7 +540,9 @@ void AudioStrip::panPressed()
track->enablePanController(false);
panVal = pan->value();
- audio->msgSetPan(((AudioTrack*)track), panVal);
+ //audio->msgSetPan(((AudioTrack*)track), panVal);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ ((AudioTrack*)track)->setPan(panVal);
((AudioTrack*)track)->startAutoRecord(AC_PAN, panVal);
}
@@ -563,7 +577,9 @@ void AudioStrip::panLabelChanged(double val)
panVal = val;
pan->setValue(val);
- audio->msgSetPan((AudioTrack*)track, val);
+ //audio->msgSetPan((AudioTrack*)track, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ ((AudioTrack*)track)->setPan(val);
((AudioTrack*)track)->startAutoRecord(AC_PAN, val);
}
diff --git a/muse2/muse/mixer/panknob.cpp b/muse2/muse/mixer/panknob.cpp
index 065c1bd1..c99f0bd5 100644
--- a/muse2/muse/mixer/panknob.cpp
+++ b/muse2/muse/mixer/panknob.cpp
@@ -8,6 +8,7 @@
#include "../audio.h"
#include "panknob.h"
+#include "track.h"
//---------------------------------------------------------
// PanKnob
@@ -26,7 +27,9 @@ PanKnob::PanKnob(QWidget* parent, AudioTrack* s)
void PanKnob::valueChanged(double val)
{
- audio->msgSetPan(src, val);
+ //audio->msgSetPan(src, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ src->setPan(val);
}
diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp
index edaede1f..9f9a5531 100644
--- a/muse2/muse/osc.cpp
+++ b/muse2/muse/osc.cpp
@@ -405,6 +405,7 @@ void stopOSC()
+/*
//---------------------------------------------------------
// OscControlFifo
// put
@@ -456,7 +457,7 @@ void OscControlFifo::remove()
// q_atomic_decrement(&size);
--size;
}
-
+*/
//---------------------------------------------------------
@@ -483,7 +484,7 @@ OscIF::OscIF()
_oscGuiQProc = 0;
_oscGuiVisible = false;
- _oscControlFifos = 0;
+ //_oscControlFifos = 0;
}
OscIF::~OscIF()
@@ -530,10 +531,11 @@ OscIF::~OscIF()
if(_uiOscPath)
free(_uiOscPath);
- if(_oscControlFifos)
- delete[] _oscControlFifos;
+ //if(_oscControlFifos)
+ // delete[] _oscControlFifos;
}
+/*
//---------------------------------------------------------
// oscFifo
//---------------------------------------------------------
@@ -544,6 +546,7 @@ OscControlFifo* OscIF::oscFifo(unsigned long i) const
return 0;
return &_oscControlFifos[i];
}
+*/
//---------------------------------------------------------
// oscUpdate
@@ -1135,15 +1138,15 @@ bool OscIF::oscGuiVisible() const
void OscDssiIF::oscSetSynthIF(DssiSynthIF* s)
{
_oscSynthIF = s;
- if(_oscControlFifos)
- delete[] _oscControlFifos;
- _oscControlFifos = 0;
+ //if(_oscControlFifos)
+ // delete[] _oscControlFifos;
+ //_oscControlFifos = 0;
- if(_oscSynthIF && _oscSynthIF->dssiSynth())
- {
- unsigned long ports = _oscSynthIF->dssiSynth()->inControls();
- _oscControlFifos = new OscControlFifo[ports];
- }
+ //if(_oscSynthIF && _oscSynthIF->dssiSynth())
+ //{
+ // unsigned long ports = _oscSynthIF->dssiSynth()->inControls();
+ // _oscControlFifos = new OscControlFifo[ports];
+ //}
}
//---------------------------------------------------------
@@ -1327,15 +1330,15 @@ bool OscDssiIF::oscInitGui()
void OscEffectIF::oscSetPluginI(PluginI* s)
{
_oscPluginI = s;
- if(_oscControlFifos)
- delete[] _oscControlFifos;
- _oscControlFifos = 0;
+ //if(_oscControlFifos)
+ // delete[] _oscControlFifos;
+ //_oscControlFifos = 0;
- if(_oscPluginI && _oscPluginI->plugin())
- {
- unsigned long ports = _oscPluginI->plugin()->controlInPorts();
- _oscControlFifos = new OscControlFifo[ports];
- }
+ //if(_oscPluginI && _oscPluginI->plugin())
+ //{
+ // unsigned long ports = _oscPluginI->plugin()->controlInPorts();
+ // _oscControlFifos = new OscControlFifo[ports];
+ //}
}
//---------------------------------------------------------
diff --git a/muse2/muse/osc.h b/muse2/muse/osc.h
index ea94451b..02c30de4 100644
--- a/muse2/muse/osc.h
+++ b/muse2/muse/osc.h
@@ -34,6 +34,7 @@ class QString;
class PluginI;
class OscIF;
+/*
// Keep the OSC fifo small. There may be thousands of controls, and each control needs a fifo.
// Oops, no, if the user keeps adjusting a slider without releasing the mouse button, then all of the
// events are sent at once upon releasing the button, meaning there might be thousands of events at once.
@@ -73,6 +74,7 @@ class OscControlFifo
void clear() { size = 0, wIndex = 0, rIndex = 0; }
int getSize() const { return size; }
};
+*/
//---------------------------------------------------------
// OscIF
@@ -137,7 +139,7 @@ class OscIF
char* _uiOscShowPath;
bool _oscGuiVisible;
- OscControlFifo* _oscControlFifos;
+ //OscControlFifo* _oscControlFifos;
virtual bool oscInitGui(const QString& /*typ*/, const QString& /*baseName*/, const QString& /*name*/,
const QString& /*label*/, const QString& /*filePath*/, const QString& /*guiPath*/);
@@ -146,7 +148,7 @@ class OscIF
OscIF();
virtual ~OscIF();
- OscControlFifo* oscFifo(unsigned long) const;
+ //OscControlFifo* oscFifo(unsigned long) const;
virtual int oscUpdate(lo_arg**);
virtual int oscProgram(lo_arg**) { return 0; }
diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp
index 06e72e4e..7dd2486f 100644
--- a/muse2/muse/plugin.cpp
+++ b/muse2/muse/plugin.cpp
@@ -44,6 +44,7 @@
#include "slider.h"
#include "midictrl.h"
#include "plugin.h"
+#include "controlfifo.h"
#include "xml.h"
#include "icons.h"
#include "song.h"
@@ -84,7 +85,8 @@ QStringList PluginDialog::sortItems = QStringList();
// ladspa2MidiControlValues
//---------------------------------------------------------
-bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, int port, int ctlnum, int* min, int* max, int* def)
+//bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, int port, int ctlnum, int* min, int* max, int* def)
+bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, unsigned port, int ctlnum, int* min, int* max, int* def)
{
LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
LADSPA_PortRangeHintDescriptor desc = range.HintDescriptor;
@@ -274,7 +276,8 @@ bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, int port, int ctl
// midi2LadspaValue
//---------------------------------------------------------
-float midi2LadspaValue(const LADSPA_Descriptor* plugin, int port, int ctlnum, int val)
+//float midi2LadspaValue(const LADSPA_Descriptor* plugin, int port, int ctlnum, int val)
+float midi2LadspaValue(const LADSPA_Descriptor* plugin, unsigned port, int ctlnum, int val)
{
LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
LADSPA_PortRangeHintDescriptor desc = range.HintDescriptor;
@@ -448,7 +451,8 @@ float midi2LadspaValue(const LADSPA_Descriptor* plugin, int port, int ctlnum, in
// ladspa2MidiController
//---------------------------------------------------------
-MidiController* ladspa2MidiController(const LADSPA_Descriptor* plugin, int port, int ctlnum)
+//MidiController* ladspa2MidiController(const LADSPA_Descriptor* plugin, int port, int ctlnum)
+MidiController* ladspa2MidiController(const LADSPA_Descriptor* plugin, unsigned port, int ctlnum)
{
int min, max, def;
@@ -467,85 +471,96 @@ MidiController* ladspa2MidiController(const LADSPA_Descriptor* plugin, int port,
//---------------------------------------------------------------------------------
//float ladspaDefaultValue(const LADSPA_Descriptor* plugin, int k)
-bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, int port, float* val)
+//bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, int port, float* val)
+bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned port, float* val)
{
- LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
- LADSPA_PortRangeHintDescriptor rh = range.HintDescriptor;
-// bool isLog = LADSPA_IS_HINT_LOGARITHMIC(rh);
- //double val = 1.0;
- float m = (rh & LADSPA_HINT_SAMPLE_RATE) ? float(sampleRate) : 1.0f;
- if (LADSPA_IS_HINT_DEFAULT_MINIMUM(rh))
+ if(port < plugin->PortCount)
{
- *val = range.LowerBound * m;
- return true;
- }
- else if (LADSPA_IS_HINT_DEFAULT_LOW(rh))
- {
- if (LADSPA_IS_HINT_LOGARITHMIC(rh))
- {
- *val = exp(fast_log10(range.LowerBound * m) * .75 +
- log(range.UpperBound * m) * .25);
- return true;
- }
- else
- {
- *val = range.LowerBound*.75*m + range.UpperBound*.25*m;
+ LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
+ LADSPA_PortRangeHintDescriptor rh = range.HintDescriptor;
+ // bool isLog = LADSPA_IS_HINT_LOGARITHMIC(rh);
+ //double val = 1.0;
+ float m = (rh & LADSPA_HINT_SAMPLE_RATE) ? float(sampleRate) : 1.0f;
+ if (LADSPA_IS_HINT_DEFAULT_MINIMUM(rh))
+ {
+ *val = range.LowerBound * m;
+ return true;
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_LOW(rh))
+ {
+ if (LADSPA_IS_HINT_LOGARITHMIC(rh))
+ {
+ //*val = exp(fast_log10(range.LowerBound * m) * .75 +
+ // log(range.UpperBound * m) * .25);
+ // p4.0.21 And below...
+ *val = expf(fast_log10(range.LowerBound * m) * .75 + // Why fast_log10?
+ logf(range.UpperBound * m) * .25);
+ return true;
+ }
+ else
+ {
+ *val = range.LowerBound*.75*m + range.UpperBound*.25*m;
+ return true;
+ }
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(rh))
+ {
+ if (LADSPA_IS_HINT_LOGARITHMIC(rh))
+ {
+ //*val = exp(log(range.LowerBound * m) * .5 +
+ // log10(range.UpperBound * m) * .5);
+ *val = expf(logf(range.LowerBound * m) * .5 +
+ log10f(range.UpperBound * m) * .5); // Why log10?
+ return true;
+ }
+ else
+ {
+ *val = range.LowerBound*.5*m + range.UpperBound*.5*m;
+ return true;
+ }
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_HIGH(rh))
+ {
+ if (LADSPA_IS_HINT_LOGARITHMIC(rh))
+ {
+ //*val = exp(log(range.LowerBound * m) * .25 +
+ // log(range.UpperBound * m) * .75);
+ *val = expf(logf(range.LowerBound * m) * .25 +
+ logf(range.UpperBound * m) * .75);
+ return true;
+ }
+ else
+ {
+ *val = range.LowerBound*.25*m + range.UpperBound*.75*m;
+ return true;
+ }
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(rh))
+ {
+ *val = range.UpperBound*m;
return true;
- }
- }
- else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(rh))
- {
- if (LADSPA_IS_HINT_LOGARITHMIC(rh))
- {
- *val = exp(log(range.LowerBound * m) * .5 +
- log10(range.UpperBound * m) * .5);
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_0(rh))
+ {
+ *val = 0.0;
return true;
- }
- else
- {
- *val = range.LowerBound*.5*m + range.UpperBound*.5*m;
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_1(rh))
+ {
+ *val = 1.0;
return true;
- }
- }
- else if (LADSPA_IS_HINT_DEFAULT_HIGH(rh))
- {
- if (LADSPA_IS_HINT_LOGARITHMIC(rh))
- {
- *val = exp(log(range.LowerBound * m) * .25 +
- log(range.UpperBound * m) * .75);
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_100(rh))
+ {
+ *val = 100.0;
return true;
- }
- else
- {
- *val = range.LowerBound*.25*m + range.UpperBound*.75*m;
+ }
+ else if (LADSPA_IS_HINT_DEFAULT_440(rh))
+ {
+ *val = 440.0;
return true;
- }
- }
- else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(rh))
- {
- *val = range.UpperBound*m;
- return true;
+ }
}
- else if (LADSPA_IS_HINT_DEFAULT_0(rh))
- {
- *val = 0.0;
- return true;
- }
- else if (LADSPA_IS_HINT_DEFAULT_1(rh))
- {
- *val = 1.0;
- return true;
- }
- else if (LADSPA_IS_HINT_DEFAULT_100(rh))
- {
- *val = 100.0;
- return true;
- }
- else if (LADSPA_IS_HINT_DEFAULT_440(rh))
- {
- *val = 440.0;
- return true;
- }
// No default found. Set return value to 1.0, but return false.
*val = 1.0;
@@ -556,9 +571,10 @@ bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, int port, float* val)
// ladspaControlRange
//---------------------------------------------------------
-void ladspaControlRange(const LADSPA_Descriptor* plugin, int i, float* min, float* max)
+//void ladspaControlRange(const LADSPA_Descriptor* plugin, int i, float* min, float* max)
+void ladspaControlRange(const LADSPA_Descriptor* plugin, unsigned port, float* min, float* max)
{
- LADSPA_PortRangeHint range = plugin->PortRangeHints[i];
+ LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
LADSPA_PortRangeHintDescriptor desc = range.HintDescriptor;
if (desc & LADSPA_HINT_TOGGLED) {
*min = 0.0;
@@ -690,7 +706,10 @@ Plugin::Plugin(QFileInfo* f, const LADSPA_Descriptor* d, bool isDssi)
// EnsembleLite (EnsLite VST) has the flag set, but it is a vst synth and is not involved here!
// Yet many (all?) ladspa vst effect plugins exhibit this problem.
// Changed by Tim. p3.3.14
- if ((_inports != _outports) || (fi.completeBaseName() == QString("dssi-vst") && !config.vstInPlace))
+ // Hack: Special Flag required for example for control processing.
+ _isDssiVst = fi.completeBaseName() == QString("dssi-vst");
+ // Hack: Blacklist vst plugins in-place, configurable for now.
+ if ((_inports != _outports) || (_isDssiVst && !config.vstInPlace))
_inPlaceCapable = false;
}
@@ -756,7 +775,8 @@ int Plugin::incReferences(int val)
if(dssi)
{
const DSSI_Descriptor* descr;
- for(int i = 0;; ++i)
+ //for(int i = 0;; ++i)
+ for(unsigned i = 0;; ++i) // p4.0.21
{
descr = dssi(i);
if(descr == NULL)
@@ -787,7 +807,8 @@ int Plugin::incReferences(int val)
if(ladspadf)
{
const LADSPA_Descriptor* descr;
- for(int i = 0;; ++i)
+ //for(int i = 0;; ++i)
+ for(unsigned i = 0;; ++i) // p4.0.21
{
descr = ladspadf(i);
if(descr == NULL)
@@ -863,8 +884,10 @@ int Plugin::incReferences(int val)
_inPlaceCapable = !LADSPA_IS_INPLACE_BROKEN(plugin->Properties);
- // Blacklist vst plugins in-place configurable for now.
- if ((_inports != _outports) || (fi.completeBaseName() == QString("dssi-vst") && !config.vstInPlace))
+ // Hack: Special flag required for example for control processing.
+ _isDssiVst = fi.completeBaseName() == QString("dssi-vst");
+ // Hack: Blacklist vst plugins in-place, configurable for now.
+ if ((_inports != _outports) || (_isDssiVst && !config.vstInPlace))
_inPlaceCapable = false;
}
}
@@ -921,32 +944,46 @@ void Plugin::range(unsigned long i, float* min, float* max) const
// defaultValue
//---------------------------------------------------------
-double Plugin::defaultValue(unsigned long port) const
+//double Plugin::defaultValue(unsigned long port) const
+float Plugin::defaultValue(unsigned long port) const
{
+ // p4.0.21
+ float val;
+ ladspaDefaultValue(plugin, port, &val);
+ return val;
+
+ /*
if(port >= plugin->PortCount)
return 0.0;
LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
LADSPA_PortRangeHintDescriptor rh = range.HintDescriptor;
- double val = 1.0;
+ //double val = 1.0;
+ float val = 1.0;
if (LADSPA_IS_HINT_DEFAULT_MINIMUM(rh))
val = range.LowerBound;
else if (LADSPA_IS_HINT_DEFAULT_LOW(rh))
if (LADSPA_IS_HINT_LOGARITHMIC(range.HintDescriptor))
- val = exp(fast_log10(range.LowerBound) * .75 +
- log(range.UpperBound) * .25);
+ //val = exp(fast_log10(range.LowerBound) * .75 +
+ // log(range.UpperBound) * .25);
+ val = expf(fast_log10(range.LowerBound) * .75 +
+ logf(range.UpperBound) * .25);
else
val = range.LowerBound*.75 + range.UpperBound*.25;
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(rh))
if (LADSPA_IS_HINT_LOGARITHMIC(range.HintDescriptor))
- val = exp(log(range.LowerBound) * .5 +
- log(range.UpperBound) * .5);
+ //val = exp(log(range.LowerBound) * .5 +
+ // log(range.UpperBound) * .5);
+ val = expf(logf(range.LowerBound) * .5 +
+ logf(range.UpperBound) * .5);
else
val = range.LowerBound*.5 + range.UpperBound*.5;
else if (LADSPA_IS_HINT_DEFAULT_HIGH(rh))
if (LADSPA_IS_HINT_LOGARITHMIC(range.HintDescriptor))
- val = exp(log(range.LowerBound) * .25 +
- log(range.UpperBound) * .75);
+ //val = exp(log(range.LowerBound) * .25 +
+ // log(range.UpperBound) * .75);
+ val = expf(logf(range.LowerBound) * .25 +
+ logf(range.UpperBound) * .75);
else
val = range.LowerBound*.25 + range.UpperBound*.75;
else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(rh))
@@ -961,6 +998,7 @@ double Plugin::defaultValue(unsigned long port) const
val = 440.0;
return val;
+ */
}
//---------------------------------------------------------
@@ -981,7 +1019,8 @@ static void loadPluginLib(QFileInfo* fi)
if(dssi)
{
const DSSI_Descriptor* descr;
- for (int i = 0;; ++i)
+ //for (int i = 0;; ++i)
+ for (unsigned i = 0;; ++i) // p4.0.21
{
descr = dssi(i);
if (descr == 0)
@@ -1033,7 +1072,8 @@ static void loadPluginLib(QFileInfo* fi)
}
const LADSPA_Descriptor* descr;
- for (int i = 0;; ++i)
+ //for (int i = 0;; ++i)
+ for (unsigned i = 0;; ++i) // p4.0.21
{
descr = ladspa(i);
if (descr == NULL)
@@ -1444,7 +1484,8 @@ bool Pipeline::nativeGuiVisible(int idx)
// apply
//---------------------------------------------------------
-void Pipeline::apply(int ports, unsigned long nframes, float** buffer1)
+//void Pipeline::apply(int ports, unsigned long nframes, float** buffer1)
+void Pipeline::apply(unsigned ports, unsigned nframes, float** buffer1)
{
// prepare a second set of buffers in case a plugin is not
// capable of inPlace processing
@@ -1467,26 +1508,31 @@ void Pipeline::apply(int ports, unsigned long nframes, float** buffer1)
{
if (swap)
//p->connect(ports, buffer2, buffer2);
- p->connect(ports, buffer, buffer);
+ //p->connect(ports, buffer, buffer);
+ p->apply(nframes, ports, buffer, buffer); // p4.0.21
else
- p->connect(ports, buffer1, buffer1);
+ //p->connect(ports, buffer1, buffer1);
+ p->apply(nframes, ports, buffer1, buffer1); //
}
else
{
if (swap)
//p->connect(ports, buffer2, buffer1);
- p->connect(ports, buffer, buffer1);
+ //p->connect(ports, buffer, buffer1);
+ p->apply(nframes, ports, buffer, buffer1); //
else
//p->connect(ports, buffer1, buffer2);
- p->connect(ports, buffer1, buffer);
+ //p->connect(ports, buffer1, buffer);
+ p->apply(nframes, ports, buffer1, buffer); //
swap = !swap;
}
- p->apply(nframes);
+ //p->apply(nframes); // Rem. p4.0.21
}
}
if (swap)
{
- for (int i = 0; i < ports; ++i)
+ //for (int i = 0; i < ports; ++i)
+ for (unsigned i = 0; i < ports; ++i) // p4.0.21
//memcpy(buffer1[i], buffer2[i], sizeof(float) * nframes);
//memcpy(buffer1[i], buffer[i], sizeof(float) * nframes);
AL::dsp->cpy(buffer1[i], buffer[i], nframes);
@@ -1648,10 +1694,13 @@ void PluginI::updateControllers()
if(!_track)
return;
- for(int i = 0; i < controlPorts; ++i)
+ //for(int i = 0; i < controlPorts; ++i)
+ for(unsigned i = 0; i < controlPorts; ++i)
//audio->msgSetPluginCtrlVal(this, genACnum(_id, i), controls[i].val);
// p3.3.43
- audio->msgSetPluginCtrlVal(_track, genACnum(_id, i), controls[i].val);
+ //audio->msgSetPluginCtrlVal(_track, genACnum(_id, i), controls[i].val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ _track->setPluginCtrlVal(genACnum(_id, i), controls[i].val);
}
//---------------------------------------------------------
@@ -1722,8 +1771,10 @@ void PluginI::setChannels(int c)
}
}
- int curPort = 0;
- int curOutPort = 0;
+ //int curPort = 0;
+ //int curOutPort = 0;
+ unsigned long curPort = 0; // p4.0.21
+ unsigned long curOutPort = 0;
unsigned long ports = _plugin->ports();
for (unsigned long k = 0; k < ports; ++k)
{
@@ -1752,13 +1803,47 @@ void PluginI::setChannels(int c)
}
//---------------------------------------------------------
+// setParam
+//---------------------------------------------------------
+
+void PluginI::setParam(unsigned i, float val)
+{
+ //controls[i].tmpVal = val;
+
+ // p4.0.21
+ if(i >= _plugin->_controlInPorts)
+ //if(i >= controlPorts)
+ {
+ printf("PluginI::setParameter param number %u out of range of ports:%ld\n", i, _plugin->_controlInPorts);
+ return;
+ }
+ ControlEvent ce;
+ ce.unique = false;
+ ce.idx = i;
+ ce.value = val;
+ // Time-stamp the event. This does a possibly slightly slow call to gettimeofday via timestamp().
+ // timestamp() is more or less an estimate of the current frame. (This is exactly how ALSA events
+ // are treated when they arrive in our ALSA driver.)
+ ce.frame = audio->timestamp();
+ if(_controlFifo.put(ce))
+ {
+ fprintf(stderr, "PluginI::setParameter: fifo overflow: in control number:%u\n", i);
+ }
+
+ // Notify that changes are to be sent upon heartbeat.
+ // TODO: No, at least not for now. So far, setParameter is only called during loading of stored params,
+ // and we don't want this interfering with oscUpdate which also sends the values.
+ //synti->_guiUpdateControls[n] = true;
+}
+
+//---------------------------------------------------------
// defaultValue
//---------------------------------------------------------
-double PluginI::defaultValue(unsigned int param) const
+//double PluginI::defaultValue(unsigned int param) const
+float PluginI::defaultValue(unsigned param) const
{
-//#warning controlPorts should really be unsigned
- if(param >= (unsigned)controlPorts)
+ if(param >= controlPorts)
return 0.0;
return _plugin->defaultValue(controls[param].idx);
@@ -1872,8 +1957,10 @@ bool PluginI::initPluginInstance(Plugin* plug, int c)
controls = new Port[controlPorts];
controlsOut = new Port[controlOutPorts];
- int i = 0;
- int ii = 0;
+ //int i = 0;
+ //int ii = 0;
+ unsigned long curPort = 0;
+ unsigned long curOutPort = 0;
for(unsigned long k = 0; k < ports; ++k)
{
LADSPA_PortDescriptor pd = _plugin->portd(k);
@@ -1881,27 +1968,31 @@ bool PluginI::initPluginInstance(Plugin* plug, int c)
{
if(pd & LADSPA_PORT_INPUT)
{
- double val = _plugin->defaultValue(k);
- controls[i].val = val;
- controls[i].tmpVal = val;
- controls[i].enCtrl = true;
- controls[i].en2Ctrl = true;
- ++i;
+ //double val = _plugin->defaultValue(k);
+ float val = _plugin->defaultValue(k); // p4.0.21
+ controls[curPort].val = val;
+ controls[curPort].tmpVal = val;
+ controls[curPort].enCtrl = true;
+ controls[curPort].en2Ctrl = true;
+ ++curPort;
}
else
if(pd & LADSPA_PORT_OUTPUT)
{
//double val = _plugin->defaultValue(k);
- controlsOut[ii].val = 0.0;
- controlsOut[ii].tmpVal = 0.0;
- controlsOut[ii].enCtrl = false;
- controlsOut[ii].en2Ctrl = false;
- ++ii;
+ //float val = _plugin->defaultValue(k);
+ controlsOut[curOutPort].val = 0.0;
+ controlsOut[curOutPort].tmpVal = 0.0;
+ controlsOut[curOutPort].enCtrl = false;
+ controlsOut[curOutPort].en2Ctrl = false;
+ ++curOutPort;
}
}
}
- unsigned long curPort = 0;
- unsigned long curOutPort = 0;
+ //unsigned long curPort = 0;
+ //unsigned long curOutPort = 0;
+ curPort = 0;
+ curOutPort = 0;
for(unsigned long k = 0; k < ports; ++k)
{
LADSPA_PortDescriptor pd = _plugin->portd(k);
@@ -1932,13 +2023,16 @@ bool PluginI::initPluginInstance(Plugin* plug, int c)
// connect
//---------------------------------------------------------
-void PluginI::connect(int ports, float** src, float** dst)
+//void PluginI::connect(int ports, float** src, float** dst)
+void PluginI::connect(unsigned ports, unsigned offset, float** src, float** dst)
{
- int port = 0;
+ //int port = 0;
+ unsigned port = 0; // p4.0.21
for (int i = 0; i < instances; ++i) {
for (unsigned long k = 0; k < _plugin->ports(); ++k) {
if (isAudioIn(k)) {
- _plugin->connectPort(handle[i], k, src[port]);
+ //_plugin->connectPort(handle[i], k, src[port]);
+ _plugin->connectPort(handle[i], k, src[port] + offset); // p4.0.21
port = (port + 1) % ports;
}
}
@@ -1947,7 +2041,8 @@ void PluginI::connect(int ports, float** src, float** dst)
for (int i = 0; i < instances; ++i) {
for (unsigned long k = 0; k < _plugin->ports(); ++k) {
if (isAudioOut(k)) {
- _plugin->connectPort(handle[i], k, dst[port]);
+ // _plugin->connectPort(handle[i], k, dst[port]);
+ _plugin->connectPort(handle[i], k, dst[port] + offset); // p4.0.21
port = (port + 1) % ports; // overwrite output?
// ++port;
// if (port >= ports) {
@@ -1979,7 +2074,8 @@ void PluginI::activate()
for (int i = 0; i < instances; ++i)
_plugin->activate(handle[i]);
if (initControlValues) {
- for (int i = 0; i < controlPorts; ++i) {
+ //for (int i = 0; i < controlPorts; ++i) {
+ for (unsigned i = 0; i < controlPorts; ++i) {
controls[i].val = controls[i].tmpVal;
}
}
@@ -1987,7 +2083,8 @@ void PluginI::activate()
//
// get initial control values from plugin
//
- for (int i = 0; i < controlPorts; ++i) {
+ //for (int i = 0; i < controlPorts; ++i) {
+ for (unsigned i = 0; i < controlPorts; ++i) {
controls[i].tmpVal = controls[i].val;
}
}
@@ -1998,11 +2095,14 @@ void PluginI::activate()
// set plugin instance controller value by name
//---------------------------------------------------------
-bool PluginI::setControl(const QString& s, double val)
+//bool PluginI::setControl(const QString& s, double val)
+bool PluginI::setControl(const QString& s, float val)
{
- for (int i = 0; i < controlPorts; ++i) {
+ //for (int i = 0; i < controlPorts; ++i) {
+ for (unsigned i = 0; i < controlPorts; ++i) {
if (_plugin->portName(controls[i].idx) == s) {
- controls[i].val = controls[i].tmpVal = val;
+ //controls[i].val = controls[i].tmpVal = val;
+ setParam(i, val); // p4.0.21
return false;
}
}
@@ -2023,8 +2123,10 @@ void PluginI::writeConfiguration(int level, Xml& xml)
//_plugin->lib().toLatin1().constData(), _plugin->label().toLatin1().constData(), channel);
Xml::xmlString(_plugin->lib()).toLatin1().constData(), Xml::xmlString(_plugin->label()).toLatin1().constData(), channel);
- for (int i = 0; i < controlPorts; ++i) {
- int idx = controls[i].idx;
+ //for (int i = 0; i < controlPorts; ++i) {
+ //int idx = controls[i].idx;
+ for (unsigned i = 0; i < controlPorts; ++i) { // p4.0.21
+ unsigned idx = controls[i].idx; //
QString s("control name=\"%1\" val=\"%2\" /");
//xml.tag(level, s.arg(_plugin->portName(idx)).arg(controls[i].tmpVal).toLatin1().constData());
xml.tag(level, s.arg(Xml::xmlString(_plugin->portName(idx)).toLatin1().constData()).arg(controls[i].tmpVal).toLatin1().constData());
@@ -2052,7 +2154,8 @@ bool PluginI::loadControl(Xml& xml)
QString file;
QString label;
QString name("mops");
- double val = 0.0;
+ //double val = 0.0;
+ float val = 0.0; // p4.0.21
for (;;) {
Xml::Token token = xml.parse();
@@ -2069,7 +2172,8 @@ bool PluginI::loadControl(Xml& xml)
if (tag == "name")
name = xml.s2();
else if (tag == "val")
- val = xml.s2().toDouble();
+ //val = xml.s2().toDouble();
+ val = xml.s2().toFloat(); // p4.0.21
break;
case Xml::TagEnd:
if (tag == "control") {
@@ -2307,7 +2411,8 @@ void PluginIBase::deleteGui()
void PluginI::enableAllControllers(bool v)
{
- for(int i = 0; i < controlPorts; ++i)
+ //for(int i = 0; i < controlPorts; ++i)
+ for(unsigned i = 0; i < controlPorts; ++i)
controls[i].enCtrl = v;
}
@@ -2317,7 +2422,8 @@ void PluginI::enableAllControllers(bool v)
void PluginI::enable2AllControllers(bool v)
{
- for(int i = 0; i < controlPorts; ++i)
+ //for(int i = 0; i < controlPorts; ++i)
+ for(unsigned i = 0; i < controlPorts; ++i)
controls[i].en2Ctrl = v;
}
@@ -2325,7 +2431,9 @@ void PluginI::enable2AllControllers(bool v)
// apply
//---------------------------------------------------------
-void PluginI::apply(int n)
+/*
+//void PluginI::apply(int n)
+void PluginI::apply(unsigned n)
{
// Process control value changes.
//if(automation && _track && _track->automationType() != AUTO_OFF && _id != -1)
@@ -2412,6 +2520,156 @@ void PluginI::apply(int n)
_plugin->apply(handle[i], n);
}
}
+*/
+
+#if 1
+// p4.0.21
+void PluginI::apply(unsigned n, unsigned ports, float** bufIn, float** bufOut)
+{
+ // Process control value changes.
+ //if(automation && _track && _track->automationType() != AUTO_OFF && _id != -1)
+ //{
+ // for(int i = 0; i < controlPorts; ++i)
+ // {
+ // if( controls[i].enCtrl && controls[i].en2Ctrl )
+ // controls[i].tmpVal = _track->pluginCtrlVal(genACnum(_id, i));
+ // }
+ //}
+
+ //unsigned endPos = pos + n;
+ int frameOffset = audio->getFrameOffset();
+
+ unsigned sample = 0;
+ int loopcount = 0; // REMOVE Tim.
+
+ // Must make this detectable for dssi vst effects.
+ //const bool usefixedrate = true;
+ const bool usefixedrate = _plugin->_isDssiVst; // Try this.
+ // TODO Make this number a global setting.
+ // Note for dssi-vst this MUST equal audio period. It doesn't like broken-up runs (it stutters),
+ // even with fixed sizes. Could be a Wine + Jack thing, wanting a full Jack buffer's length.
+ //unsigned fixedsize = 2048;
+ unsigned fixedsize = n;
+
+ // For now, the fixed size is clamped to the audio buffer size.
+ // TODO: We could later add slower processing over several cycles -
+ // so that users can select a small audio period but a larger control period.
+ if(fixedsize > n)
+ fixedsize = n;
+
+ // Process automation control values now.
+ // TODO: This needs to be respect frame resolution. Put this inside the sample loop below.
+ for(unsigned long k = 0; k < controlPorts; ++k)
+ {
+ if(automation && _track && _track->automationType() != AUTO_OFF && _id != -1)
+ {
+ if(controls[k].enCtrl && controls[k].en2Ctrl )
+ controls[k].tmpVal = _track->pluginCtrlVal(genACnum(_id, k));
+ }
+ }
+
+ while(sample < n)
+ {
+ //unsigned nsamp = n;
+ //unsigned nsamp = n - sample;
+ unsigned nsamp = usefixedrate ? fixedsize : n - sample;
+ bool found = false;
+ unsigned frame = 0;
+ unsigned index = 0;
+ // Get all control ring buffer items valid for this time period...
+ //for(int m = 0; m < cbsz; ++m)
+ while(!_controlFifo.isEmpty())
+ {
+ //ControlValue v = _controlFifo.get();
+ ControlEvent v = _controlFifo.peek();
+ //printf("PluginI::apply control idx:%d frame:%d val:%f\n", v.idx, v.frame, v.value); // REMOVE Tim.
+ // Process only items in this time period. Make sure to process all
+ // subsequent items which have the same frame.
+ //if(v.frame >= (endPos + frameOffset) || (found && v.frame != frame))
+ //if(v.frame < sample || v.frame >= (sample + nsamp) || (found && v.frame != frame))
+ //if(v.frame < sample || v.frame >= (endPos + frameOffset) || (found && v.frame != frame))
+ //if(v.frame < sample || v.frame >= (endPos + frameOffset)
+ if(v.frame < sample || v.frame >= frameOffset
+ //|| (found && v.frame != frame)
+ //|| (!usefixedrate && found && !v.unique && v.frame != frame)
+ || (found && !v.unique && v.frame != frame)
+ // dssi-vst needs them serialized and accounted for, no matter what. This works with fixed rate
+ // because nsamp is constant. But with packets, we need to guarantee at least one-frame spacing.
+ // Although we likely won't be using packets with dssi-vst, so it's OK for now.
+ //|| (found && v.idx == index))
+ //|| (usefixedrate && found && v.idx == index)) // Try this.
+ || (usefixedrate && found && v.unique && v.idx == index)) //
+ break;
+ _controlFifo.remove(); // Done with the ring buffer's item. Remove it.
+ //if(v.idx >= controlPorts) // Sanity check.
+ if(v.idx >= _plugin->_controlInPorts)
+ break;
+ found = true;
+ frame = v.frame;
+ index = v.idx;
+ // Set the ladspa control port value.
+ //controls[v.idx].val = v.value;
+ controls[v.idx].tmpVal = v.value;
+
+ // Need to update the automation value, otherwise it overwrites later with the last automation value.
+ if(_track && _id != -1)
+ {
+ // Since we are now in the audio thread context, there's no need to send a message,
+ // just modify directly.
+ //audio->msgSetPluginCtrlVal(this, genACnum(_id, k), controls[k].val);
+ // p3.3.43
+ //audio->msgSetPluginCtrlVal(_track, genACnum(_id, k), controls[k].val);
+ _track->setPluginCtrlVal(genACnum(_id, v.idx), v.value);
+
+ // Record automation.
+ // NO! Take care of this immediately in the OSC control handler, because we don't want
+ // any delay.
+ // OTOH Since this is the actual place and time where the control ports values
+ // are set, best to reflect what happens here to automation.
+ // However for dssi-vst it might be best to handle it that way.
+
+ //AutomationType at = _track->automationType();
+ // TODO: Taken from our native gui control handlers.
+ // This may need modification or may cause problems -
+ // we don't have the luxury of access to the dssi gui controls !
+ //if(at == AUTO_WRITE || (audio->isPlaying() && at == AUTO_TOUCH))
+ // enableController(k, false);
+ //_track->recordAutomation(id, v.value);
+ }
+ }
+
+ // Now update the actual values from the temporary values...
+ for(unsigned long k = 0; k < controlPorts; ++k)
+ controls[k].val = controls[k].tmpVal;
+
+ //if(found)
+ if(found && !usefixedrate)
+ //nsamp = frame - sample + 1;
+ nsamp = frame - sample;
+ if(sample + nsamp >= n) // Safety check.
+ nsamp = n - sample;
+
+ //printf("PluginI::apply ports:%d n:%d frame:%d sample:%d nsamp:%d fOffset:%d loopcount:%d\n",
+ // ports, n, frame, sample, nsamp, frameOffset, loopcount); // REMOVE Tim.
+
+ // TODO: TESTING: Don't allow zero-length runs. This could/should be checked in the control loop instead.
+ // Note this means it is still possible to get stuck in the top loop (at least for a while).
+ if(nsamp == 0)
+ continue;
+
+ connect(ports, sample, bufIn, bufOut);
+
+ for(int i = 0; i < instances; ++i)
+ {
+ //fprintf(stderr, "PluginI::apply handle %d\n", i);
+ _plugin->apply(handle[i], nsamp);
+ }
+
+ sample += nsamp;
+ loopcount++; // REMOVE Tim.
+ }
+}
+#endif
//---------------------------------------------------------
// oscConfigure
@@ -2544,7 +2802,8 @@ int PluginI::oscUpdate()
// Send current control values.
//unsigned long ports = controlPorts;
- for(int i = 0; i < controlPorts; ++i)
+ //for(int i = 0; i < controlPorts; ++i)
+ for(unsigned i = 0; i < controlPorts; ++i)
{
//unsigned long k = synth->pIdx(i);
//_oscIF.oscSendControl(k, controls[i]);
@@ -2576,15 +2835,15 @@ int PluginI::oscControl(unsigned long port, float value)
//if(port >= controlPorts)
//if(port < 0 || port >= _plugin->rpIdx.size())
- //{
- //fprintf(stderr, "DssiSynthIF::oscControl: port number:%d is out of range of number of ports:%d\n", port, controlPorts);
- // fprintf(stderr, "PluginI::oscControl: port number:%d is out of range of index list size:%d\n", port, _plugin->rpIdx.size());
- // return 0;
- //}
+ if(port >= _plugin->rpIdx.size())
+ {
+ fprintf(stderr, "PluginI::oscControl: port number:%ld is out of range of index list size:%d\n", port, _plugin->rpIdx.size());
+ return 0;
+ }
// Convert from DSSI port number to control input port index.
- //unsigned long cport = _plugin->rpIdx[port];
- unsigned long cport = _plugin->port2InCtrl(port);
+ unsigned long cport = _plugin->rpIdx[port];
+ //unsigned long cport = _plugin->port2InCtrl(port);
if((int)cport == -1)
{
@@ -2607,6 +2866,7 @@ int PluginI::oscControl(unsigned long port, float value)
// TODO: May need FIFOs on each control(!) so that the control changes get sent one per process cycle!
// Observed countdown not actually going to zero upon string of changes.
// Try this ...
+ /*
OscControlFifo* cfifo = _oscif.oscFifo(cport);
if(cfifo)
{
@@ -2622,16 +2882,32 @@ int PluginI::oscControl(unsigned long port, float value)
fprintf(stderr, "PluginI::oscControl: fifo overflow: in control number:%ld\n", cport);
}
}
+ */
+ // p4.0.21
+ ControlEvent ce;
+ ce.unique = _plugin->_isDssiVst; // Special for messages from vst gui to host - requires processing every message.
+ ce.idx = cport;
+ ce.value = value;
+ // Time-stamp the event. This does a possibly slightly slow call to gettimeofday via timestamp().
+ // timestamp() is more or less an estimate of the current frame. (This is exactly how ALSA events
+ // are treated when they arrive in our ALSA driver.)
+ ce.frame = audio->timestamp();
+ if(_controlFifo.put(ce))
+ {
+ fprintf(stderr, "PluginI::oscControl: fifo overflow: in control number:%ld\n", cport);
+ }
+
// Record automation:
// Take care of this immediately, because we don't want the silly delay associated with
// processing the fifo one-at-a-time in the apply().
- // NOTE: Ahh crap! We don't receive control events until the user RELEASES a control !
+ // NOTE: With some vsts we don't receive control events until the user RELEASES a control.
// So the events all arrive at once when the user releases a control.
// That makes this pretty useless... But what the heck...
if(_track && _id != -1)
{
- int id = genACnum(_id, cport);
+ //int id = genACnum(_id, cport);
+ unsigned id = genACnum(_id, cport);
AutomationType at = _track->automationType();
// TODO: Taken from our native gui control handlers.
@@ -2880,10 +3156,14 @@ void PluginDialog::fillPlugs(int nbr)
{
pList->clear();
for (iPlugin i = plugins.begin(); i != plugins.end(); ++i) {
- int ai = i->inports();
- int ao = i->outports();
- int ci = i->controlInPorts();
- int co = i->controlOutPorts();
+ //int ai = i->inports();
+ //int ao = i->outports();
+ //int ci = i->controlInPorts();
+ //int co = i->controlOutPorts();
+ unsigned ai = i->inports(); // p4.0.21
+ unsigned ao = i->outports();
+ unsigned ci = i->controlInPorts();
+ unsigned co = i->controlOutPorts();
bool addFlag = false;
switch (nbr) {
case SEL_SM: // stereo & mono
@@ -2928,10 +3208,14 @@ void PluginDialog::fillPlugs(const QString &sortValue)
{
pList->clear();
for (iPlugin i = plugins.begin(); i != plugins.end(); ++i) {
- int ai = i->inports();
- int ao = i->outports();
- int ci = i->controlInPorts();
- int co = i->controlOutPorts();
+ //int ai = i->inports();
+ //int ao = i->outports();
+ //int ci = i->controlInPorts();
+ //int co = i->controlOutPorts();
+ unsigned ai = i->inports(); // p4.0.21
+ unsigned ao = i->outports();
+ unsigned ci = i->controlInPorts();
+ unsigned co = i->controlOutPorts();
bool addFlag = false;
@@ -3045,16 +3329,24 @@ PluginGui::PluginGui(PluginIBase* p)
const char* name = ba.constData();
if (*name !='P')
continue;
- int parameter = -1;
- sscanf(name, "P%d", &parameter);
- if (parameter == -1)
- continue;
+ //int parameter = -1;
+ //sscanf(name, "P%d", &parameter);
+ //if (parameter == -1)
+ // continue;
+ unsigned parameter; // p4.0.21
+ int rv = sscanf(name, "P%u", &parameter);
+ if(rv != 1)
+ continue;
++nobj;
}
it = l.begin();
gw = new GuiWidgets[nobj];
nobj = 0;
QSignalMapper* mapper = new QSignalMapper(this);
+
+ // FIXME: There's no unsigned for gui params. We would need to limit nobj to MAXINT. // p4.0.21
+ // FIXME: Our Slider class uses doubles for values, giving some problems with float conversion. // p4.0.21
+
connect(mapper, SIGNAL(mapped(int)), SLOT(guiParamChanged(int)));
QSignalMapper* mapperPressed = new QSignalMapper(this);
@@ -3068,10 +3360,14 @@ PluginGui::PluginGui(PluginIBase* p)
const char* name = ba.constData();
if (*name !='P')
continue;
- int parameter = -1;
- sscanf(name, "P%d", &parameter);
- if (parameter == -1)
- continue;
+ //int parameter = -1;
+ //sscanf(name, "P%d", &parameter);
+ //if (parameter == -1)
+ // continue;
+ unsigned parameter; // p4.0.21
+ int rv = sscanf(name, "P%u", &parameter);
+ if(rv != 1)
+ continue;
mapper->setMapping(obj, nobj);
mapperPressed->setMapping(obj, nobj);
@@ -3085,7 +3381,8 @@ PluginGui::PluginGui(PluginIBase* p)
gw[nobj].type = GuiWidgets::SLIDER;
((Slider*)obj)->setId(nobj);
((Slider*)obj)->setCursorHoming(true);
- for(int i = 0; i < nobj; i++)
+ //for(int i = 0; i < nobj; i++)
+ for(unsigned i = 0; i < nobj; i++) // p4.0.21
{
if(gw[i].type == GuiWidgets::DOUBLE_LABEL && gw[i].param == parameter)
((DoubleLabel*)gw[i].widget)->setSlider((Slider*)obj);
@@ -3098,7 +3395,8 @@ PluginGui::PluginGui(PluginIBase* p)
else if (strcmp(obj->metaObject()->className(), "DoubleLabel") == 0) {
gw[nobj].type = GuiWidgets::DOUBLE_LABEL;
((DoubleLabel*)obj)->setId(nobj);
- for(int i = 0; i < nobj; i++)
+ //for(int i = 0; i < nobj; i++)
+ for(unsigned i = 0; i < nobj; i++)
{
if(gw[i].type == GuiWidgets::SLIDER && gw[i].param == parameter)
{
@@ -3141,7 +3439,8 @@ PluginGui::PluginGui(PluginIBase* p)
mw->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
- int n = plugin->parameters();
+ //int n = plugin->parameters();
+ unsigned n = plugin->parameters(); // p4.0.21
params = new GuiParam[n];
// Changed p3.3.43
@@ -3155,7 +3454,8 @@ PluginGui::PluginGui(PluginIBase* p)
QFontMetrics fm = fontMetrics();
int h = fm.height() + 4;
- for (int i = 0; i < n; ++i) {
+ //for (int i = 0; i < n; ++i) {
+ for (unsigned i = 0; i < n; ++i) { // p4.0.21
QLabel* label = 0;
LADSPA_PortRangeHint range = plugin->range(i);
double lower = 0.0; // default values
@@ -3301,7 +3601,7 @@ void PluginGui::ctrlPressed(int param)
if(params[param].type == GuiParam::GUI_SLIDER)
{
- double val = ((Slider*)params[param].actuator)->value();
+ double val = ((Slider*)params[param].actuator)->value();
if (LADSPA_IS_HINT_LOGARITHMIC(params[param].hint))
val = pow(10.0, val/20.0);
else if (LADSPA_IS_HINT_INTEGER(params[param].hint))
@@ -3315,14 +3615,17 @@ void PluginGui::ctrlPressed(int param)
if(track)
{
// p3.3.43
- audio->msgSetPluginCtrlVal(track, id, val);
+ //audio->msgSetPluginCtrlVal(track, id, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
}
}
else if(params[param].type == GuiParam::GUI_SWITCH)
{
- double val = (double)((CheckBox*)params[param].actuator)->isChecked();
+ //double val = (double)((CheckBox*)params[param].actuator)->isChecked();
+ float val = (float)((CheckBox*)params[param].actuator)->isChecked(); // p4.0.21
plugin->setParam(param, val);
// p3.3.43
@@ -3331,7 +3634,9 @@ void PluginGui::ctrlPressed(int param)
if(track)
{
// p3.3.43
- audio->msgSetPluginCtrlVal(track, id, val);
+ //audio->msgSetPluginCtrlVal(track, id, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
}
@@ -3423,7 +3728,9 @@ void PluginGui::sliderChanged(double val, int param)
if(track)
{
// p3.3.43
- audio->msgSetPluginCtrlVal(track, id, val);
+ //audio->msgSetPluginCtrlVal(track, id, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ track->setPluginCtrlVal(id, val);
track->recordAutomation(id, val);
}
@@ -3465,7 +3772,9 @@ void PluginGui::labelChanged(double val, int param)
if(track)
{
// p3.3.43
- audio->msgSetPluginCtrlVal(track, id, val);
+ //audio->msgSetPluginCtrlVal(track, id, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
}
@@ -3596,7 +3905,8 @@ void PluginGui::setOn(bool val)
void PluginGui::updateValues()
{
if (params) {
- for (int i = 0; i < plugin->parameters(); ++i) {
+ //for (int i = 0; i < plugin->parameters(); ++i) {
+ for (unsigned i = 0; i < plugin->parameters(); ++i) { // p4.0.21
GuiParam* gp = &params[i];
if (gp->type == GuiParam::GUI_SLIDER) {
double lv = plugin->param(i);
@@ -3617,17 +3927,20 @@ void PluginGui::updateValues()
}
}
else if (gw) {
- for (int i = 0; i < nobj; ++i) {
+ //for (int i = 0; i < nobj; ++i) {
+ for (unsigned i = 0; i < nobj; ++i) { // p4.0.21
QWidget* widget = gw[i].widget;
int type = gw[i].type;
- int param = gw[i].param;
- double val = plugin->param(param);
+ //int param = gw[i].param;
+ //double val = plugin->param(param);
+ unsigned param = gw[i].param; // p4.0.21
+ float val = plugin->param(param);
switch(type) {
case GuiWidgets::SLIDER:
- ((Slider*)widget)->setValue(val);
+ ((Slider*)widget)->setValue(val); // Note conversion to double
break;
case GuiWidgets::DOUBLE_LABEL:
- ((DoubleLabel*)widget)->setValue(val);
+ ((DoubleLabel*)widget)->setValue(val); // Note conversion to double
break;
case GuiWidgets::QCHECKBOX:
((QCheckBox*)widget)->setChecked(int(val));
@@ -3652,7 +3965,8 @@ void PluginGui::updateControls()
if(at == AUTO_OFF)
return;
if (params) {
- for (int i = 0; i < plugin->parameters(); ++i) {
+ //for (int i = 0; i < plugin->parameters(); ++i) {
+ for (unsigned i = 0; i < plugin->parameters(); ++i) { // p4.0.21
GuiParam* gp = &params[i];
if (gp->type == GuiParam::GUI_SLIDER) {
if( plugin->controllerEnabled(i) && plugin->controllerEnabled2(i) )
@@ -3698,10 +4012,12 @@ void PluginGui::updateControls()
}
}
else if (gw) {
- for (int i = 0; i < nobj; ++i) {
+ //for (int i = 0; i < nobj; ++i) {
+ for (unsigned i = 0; i < nobj; ++i) { // p4.0.21
QWidget* widget = gw[i].widget;
int type = gw[i].type;
- int param = gw[i].param;
+ //int param = gw[i].param;
+ unsigned param = gw[i].param; // p4.0.21
switch(type) {
case GuiWidgets::SLIDER:
if( plugin->controllerEnabled(param) && plugin->controllerEnabled2(param) )
@@ -3771,7 +4087,8 @@ void PluginGui::updateControls()
void PluginGui::guiParamChanged(int idx)
{
QWidget* w = gw[idx].widget;
- int param = gw[idx].param;
+ //int param = gw[idx].param;
+ unsigned param = gw[idx].param; // p4.0.21
int type = gw[idx].type;
AutomationType at = AUTO_OFF;
@@ -3798,7 +4115,8 @@ void PluginGui::guiParamChanged(int idx)
break;
}
- for (int i = 0; i < nobj; ++i) {
+ //for (int i = 0; i < nobj; ++i) {
+ for (unsigned i = 0; i < nobj; ++i) { // p4.0.21
QWidget* widget = gw[i].widget;
if (widget == w || param != gw[i].param)
continue;
@@ -3830,7 +4148,9 @@ void PluginGui::guiParamChanged(int idx)
//if(track)
//{
// p3.3.43
- audio->msgSetPluginCtrlVal(track, id, val);
+ //audio->msgSetPluginCtrlVal(track, id, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ track->setPluginCtrlVal(id, val);
switch(type)
{
@@ -3853,7 +4173,8 @@ void PluginGui::guiParamChanged(int idx)
void PluginGui::guiParamPressed(int idx)
{
- int param = gw[idx].param;
+ //int param = gw[idx].param;
+ unsigned param = gw[idx].param; // p4.0.21
AutomationType at = AUTO_OFF;
AudioTrack* track = plugin->track();
@@ -3893,7 +4214,8 @@ void PluginGui::guiParamPressed(int idx)
void PluginGui::guiParamReleased(int idx)
{
- int param = gw[idx].param;
+ //int param = gw[idx].param;
+ unsigned param = gw[idx].param; // p4.0.21
int type = gw[idx].type;
AutomationType at = AUTO_OFF;
@@ -3938,7 +4260,8 @@ void PluginGui::guiParamReleased(int idx)
void PluginGui::guiSliderPressed(int idx)
{
- int param = gw[idx].param;
+ //int param = gw[idx].param;
+ unsigned param = gw[idx].param; // p4.0.21
QWidget *w = gw[idx].widget;
AutomationType at = AUTO_OFF;
@@ -3961,12 +4284,15 @@ void PluginGui::guiSliderPressed(int idx)
//audio->msgSetPluginCtrlVal(((PluginI*)plugin), id, val);
// p3.3.43
- audio->msgSetPluginCtrlVal(track, id, val);
+ //audio->msgSetPluginCtrlVal(track, id, val);
+ // p4.0.21 audio->msgXXX waits. Do we really need to?
+ track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
// Needed so that paging a slider updates a label or other buddy control.
- for (int i = 0; i < nobj; ++i) {
+ //for (int i = 0; i < nobj; ++i) {
+ for (unsigned i = 0; i < nobj; ++i) { // p4.0.21
QWidget* widget = gw[i].widget;
if (widget == w || param != gw[i].param)
continue;
diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h
index 41da1bfb..2d78a335 100644
--- a/muse2/muse/plugin.h
+++ b/muse2/muse/plugin.h
@@ -22,6 +22,7 @@
#include "globals.h"
#include "globaldefs.h"
#include "ctrl.h"
+#include "controlfifo.h"
//#include "stringparam.h"
@@ -78,7 +79,10 @@ class PluginBase
//---------------------------------------------------------
class Plugin {
+
protected:
+ friend class PluginI;
+
void* _handle;
int _references;
int _instNo;
@@ -92,6 +96,9 @@ class Plugin {
QString _copyright;
bool _isDssi;
+ // Hack: Special flag required.
+ bool _isDssiVst;
+
#ifdef DSSI_SUPPORT
const DSSI_Descriptor* dssi_descr;
#endif
@@ -138,11 +145,13 @@ class Plugin {
if (plugin && plugin->cleanup)
plugin->cleanup(handle);
}
- void connectPort(LADSPA_Handle handle, int port, float* value) {
+ //void connectPort(LADSPA_Handle handle, int port, float* value) {
+ void connectPort(LADSPA_Handle handle, unsigned port, float* value) { // p4.0.21
if(plugin)
plugin->connect_port(handle, port, value);
}
- void apply(LADSPA_Handle handle, int n) {
+ //void apply(LADSPA_Handle handle, int n) {
+ void apply(LADSPA_Handle handle, unsigned n) { // p4.0.21
if(plugin)
plugin->run(handle, n);
}
@@ -165,7 +174,8 @@ class Plugin {
return plugin->PortRangeHints[i];
}
- double defaultValue(unsigned long port) const;
+ //double defaultValue(unsigned long port) const;
+ float defaultValue(unsigned long port) const; // p4.0.21
void range(unsigned long i, float*, float*) const;
const char* portName(unsigned long i) {
@@ -173,7 +183,7 @@ class Plugin {
}
// Returns (int)-1 if not an input control.
- unsigned long port2InCtrl(unsigned long p) { return p >= rpIdx.size() ? (unsigned long)-1 : rpIdx[p]; }
+ //unsigned long port2InCtrl(unsigned long p) { return p >= rpIdx.size() ? (unsigned long)-1 : rpIdx[p]; }
unsigned long inports() const { return _inports; }
unsigned long outports() const { return _outports; }
@@ -218,7 +228,8 @@ class PluginList : public std::list<Plugin> {
//---------------------------------------------------------
struct Port {
- int idx;
+ //int idx;
+ unsigned idx;
float val;
float tmpVal;
@@ -251,7 +262,8 @@ struct GuiWidgets {
};
QWidget* widget;
int type;
- int param;
+ //int param;
+ unsigned param; // p4.0.21
};
class PluginI;
@@ -296,6 +308,7 @@ class PluginBase
class PluginIBase
{
protected:
+ ControlFifo _controlFifo;
PluginGui* _gui;
void makeGui();
@@ -305,7 +318,8 @@ class PluginIBase
~PluginIBase();
virtual bool on() const = 0;
virtual void setOn(bool /*val*/) = 0;
- virtual int pluginID() = 0;
+ //virtual int pluginID() = 0;
+ virtual unsigned pluginID() = 0; // p4.0.21
virtual int id() = 0;
virtual QString pluginLabel() const = 0;
virtual QString name() const = 0;
@@ -315,19 +329,27 @@ class PluginIBase
virtual AudioTrack* track() = 0;
- virtual void enableController(int /*i*/, bool /*v*/ = true) = 0;
- virtual bool controllerEnabled(int /*i*/) const = 0;
- virtual bool controllerEnabled2(int /*i*/) const = 0;
+ //virtual void enableController(int /*i*/, bool /*v*/ = true) = 0;
+ //virtual bool controllerEnabled(int /*i*/) const = 0;
+ //virtual bool controllerEnabled2(int /*i*/) const = 0;
+ virtual void enableController(unsigned /*i*/, bool /*v*/ = true) = 0; // p4.0.21
+ virtual bool controllerEnabled(unsigned /*i*/) const = 0;
+ virtual bool controllerEnabled2(unsigned /*i*/) const = 0;
virtual void updateControllers() = 0;
virtual void writeConfiguration(int /*level*/, Xml& /*xml*/) = 0;
virtual bool readConfiguration(Xml& /*xml*/, bool /*readPreset*/=false) = 0;
- virtual int parameters() const = 0;
- virtual void setParam(int /*i*/, double /*val*/) = 0;
- virtual double param(int /*i*/) const = 0;
- virtual const char* paramName(int /*i*/) = 0;
- virtual LADSPA_PortRangeHint range(int /*i*/) = 0;
+ //virtual int parameters() const = 0;
+ //virtual void setParam(int /*i*/, double /*val*/) = 0;
+ //virtual double param(int /*i*/) const = 0;
+ //virtual const char* paramName(int /*i*/) = 0;
+ //virtual LADSPA_PortRangeHint range(int /*i*/) = 0;
+ virtual unsigned parameters() const = 0; // p4.0.21
+ virtual void setParam(unsigned /*i*/, float /*val*/) = 0;
+ virtual float param(unsigned /*i*/) const = 0;
+ virtual const char* paramName(unsigned /*i*/) = 0;
+ virtual LADSPA_PortRangeHint range(unsigned /*i*/) = 0;
QString dssi_ui_filename() const;
//virtual void showGui(bool) = 0; // p4.0.20
@@ -347,7 +369,8 @@ class PluginGui : public QMainWindow {
PluginIBase* plugin; // plugin instance
GuiParam* params;
- int nobj; // number of widgets in gw
+ //int nobj;
+ unsigned nobj; // number of widgets in gw // p4.0.21
GuiWidgets* gw;
QAction* onOff;
@@ -404,8 +427,11 @@ class PluginI : public PluginIBase {
Port* controls;
Port* controlsOut;
- int controlPorts;
- int controlOutPorts;
+ //int controlPorts;
+ //int controlOutPorts;
+ unsigned controlPorts; // p4.0.21
+ unsigned controlOutPorts; //
+
///PluginGui* _gui;
bool _on;
bool initControlValues;
@@ -436,20 +462,29 @@ class PluginI : public PluginIBase {
void setTrack(AudioTrack* t) { _track = t; }
AudioTrack* track() { return _track; }
- int pluginID() { return _plugin->id(); }
+ //int pluginID() { return _plugin->id(); }
+ unsigned pluginID() { return _plugin->id(); } // p4.0.21
void setID(int i);
int id() { return _id; }
void updateControllers();
bool initPluginInstance(Plugin*, int channels);
void setChannels(int);
- void connect(int ports, float** src, float** dst);
- void apply(int n);
-
- void enableController(int i, bool v = true) { controls[i].enCtrl = v; }
- bool controllerEnabled(int i) const { return controls[i].enCtrl; }
- void enable2Controller(int i, bool v = true) { controls[i].en2Ctrl = v; }
- bool controllerEnabled2(int i) const { return controls[i].en2Ctrl; }
+ //void connect(int ports, float** src, float** dst);
+ //void apply(int n);
+ //void connect(unsigned ports, float** src, float** dst);
+ //void apply(unsigned n);
+ void connect(unsigned ports, unsigned offset, float** src, float** dst); // p4.0.21
+ void apply(unsigned n, unsigned ports, float** bufIn, float** bufOut); //
+
+ //void enableController(int i, bool v = true) { controls[i].enCtrl = v; }
+ //bool controllerEnabled(int i) const { return controls[i].enCtrl; }
+ //void enable2Controller(int i, bool v = true) { controls[i].en2Ctrl = v; }
+ //bool controllerEnabled2(int i) const { return controls[i].en2Ctrl; }
+ void enableController(unsigned i, bool v = true) { controls[i].enCtrl = v; } // p4.0.21
+ bool controllerEnabled(unsigned i) const { return controls[i].enCtrl; }
+ void enable2Controller(unsigned i, bool v = true) { controls[i].en2Ctrl = v; }
+ bool controllerEnabled2(unsigned i) const { return controls[i].en2Ctrl; }
void enableAllControllers(bool v = true);
void enable2AllControllers(bool v = true);
@@ -481,7 +516,8 @@ class PluginI : public PluginIBase {
void writeConfiguration(int level, Xml& xml);
bool readConfiguration(Xml& xml, bool readPreset=false);
bool loadControl(Xml& xml);
- bool setControl(const QString& s, double val);
+ //bool setControl(const QString& s, double val);
+ bool setControl(const QString& s, float val); // p4.0.21
void showGui();
void showGui(bool);
bool isDssiPlugin() const { return _plugin->isDssiPlugin(); }
@@ -490,17 +526,29 @@ class PluginI : public PluginIBase {
bool isShowNativeGuiPending() { return _showNativeGuiPending; }
bool guiVisible();
bool nativeGuiVisible();
- int parameters() const { return controlPorts; }
- void setParam(int i, double val) { controls[i].tmpVal = val; }
- double param(int i) const { return controls[i].val; }
- double defaultValue(unsigned int param) const;
- const char* paramName(int i) { return _plugin->portName(controls[i].idx); }
- LADSPA_PortDescriptor portd(int i) const { return _plugin->portd(controls[i].idx); }
- void range(int i, float* min, float* max) const { _plugin->range(controls[i].idx, min, max); }
- bool isAudioIn(int k) { return (_plugin->portd(k) & AUDIO_IN) == AUDIO_IN; }
- bool isAudioOut(int k) { return (_plugin->portd(k) & AUDIO_OUT) == AUDIO_OUT; }
+ //int parameters() const { return controlPorts; }
+ //void setParam(int i, double val) { controls[i].tmpVal = val; }
+ //double param(int i) const { return controls[i].val; }
+ //double defaultValue(unsigned int param) const;
+ //const char* paramName(int i) { return _plugin->portName(controls[i].idx); }
+ //LADSPA_PortDescriptor portd(int i) const { return _plugin->portd(controls[i].idx); }
+ //void range(int i, float* min, float* max) const { _plugin->range(controls[i].idx, min, max); }
+ //bool isAudioIn(int k) { return (_plugin->portd(k) & AUDIO_IN) == AUDIO_IN; }
+ //bool isAudioOut(int k) { return (_plugin->portd(k) & AUDIO_OUT) == AUDIO_OUT; }
+ //LADSPA_PortRangeHint range(int i) { return _plugin->range(controls[i].idx); }
+ // p4.0.21
+ unsigned parameters() const { return controlPorts; }
+ //void setParam(unsigned i, float val) { controls[i].tmpVal = val; }
+ void setParam(unsigned i, float val);
+ float param(unsigned i) const { return controls[i].val; }
+ float defaultValue(unsigned param) const;
+ const char* paramName(unsigned i) { return _plugin->portName(controls[i].idx); }
+ LADSPA_PortDescriptor portd(unsigned i) const { return _plugin->portd(controls[i].idx); }
+ void range(unsigned i, float* min, float* max) const { _plugin->range(controls[i].idx, min, max); }
+ bool isAudioIn(unsigned k) { return (_plugin->portd(k) & AUDIO_IN) == AUDIO_IN; }
+ bool isAudioOut(unsigned k) { return (_plugin->portd(k) & AUDIO_OUT) == AUDIO_OUT; }
+ LADSPA_PortRangeHint range(unsigned i) { return _plugin->range(controls[i].idx); }
bool inPlaceCapable() const { return _plugin->inPlaceCapable(); }
- LADSPA_PortRangeHint range(int i) { return _plugin->range(controls[i].idx); }
};
//---------------------------------------------------------
@@ -533,7 +581,8 @@ class Pipeline : public std::vector<PluginI*> {
void deleteAllGuis();
bool guiVisible(int);
bool nativeGuiVisible(int);
- void apply(int ports, unsigned long nframes, float** buffer);
+ //void apply(int ports, unsigned long nframes, float** buffer);
+ void apply(unsigned ports, unsigned nframes, float** buffer); // p4.0.21
void move(int idx, bool up);
bool empty(int idx) const;
void setChannels(int);
@@ -581,11 +630,16 @@ class PluginDialog : public QDialog {
extern void initPlugins();
extern PluginList plugins;
-extern bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, int port, float* val);
-extern void ladspaControlRange(const LADSPA_Descriptor* plugin, int i, float* min, float* max);
-extern bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, int port, int ctlnum, int* min, int* max, int* def);
-//extern MidiController* ladspa2MidiController(const LADSPA_Descriptor* plugin, int port, int ctlnum);
-extern float midi2LadspaValue(const LADSPA_Descriptor* plugin, int port, int ctlnum, int val);
+//extern bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, int port, float* val);
+//extern void ladspaControlRange(const LADSPA_Descriptor* plugin, int i, float* min, float* max);
+//extern bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, int port, int ctlnum, int* min, int* max, int* def);
+//extern float midi2LadspaValue(const LADSPA_Descriptor* plugin, int port, int ctlnum, int val);
+// p4.0.21
+extern bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned port, float* val);
+extern void ladspaControlRange(const LADSPA_Descriptor* plugin, unsigned port, float* min, float* max);
+extern bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, unsigned port, int ctlnum, int* min, int* max, int* def);
+extern float midi2LadspaValue(const LADSPA_Descriptor* plugin, unsigned port, int ctlnum, int val);
+//extern MidiController* ladspa2MidiController(const LADSPA_Descriptor* plugin, unsigned port, int ctlnum);
#endif
diff --git a/muse2/muse/synth.cpp b/muse2/muse/synth.cpp
index 6212340f..521c7d63 100644
--- a/muse2/muse/synth.cpp
+++ b/muse2/muse/synth.cpp
@@ -917,8 +917,9 @@ void SynthI::preProcessAlways()
// Clear any accumulated play events.
playEvents()->clear();
// Eat up any fifo events.
- while(!eventFifo.isEmpty())
- eventFifo.get();
+ //while(!eventFifo.isEmpty())
+ // eventFifo.get();
+ eventFifo.clear(); // p4.0.21 Duh, clear is the same but faster AND safer, right?
}
}
diff --git a/muse2/muse/synth.h b/muse2/muse/synth.h
index 100d7bd6..b11ea2d9 100644
--- a/muse2/muse/synth.h
+++ b/muse2/muse/synth.h
@@ -149,8 +149,8 @@ class SynthIF {
virtual const char* getPatchName(int, int, MType, bool) = 0;
virtual void populatePatchPopup(QMenu*, int, MType, bool) = 0;
virtual void write(int level, Xml& xml) const = 0;
- virtual float getParameter(unsigned long idx) const = 0;
- virtual void setParameter(unsigned long idx, float value) = 0;
+ virtual float getParameter(unsigned long idx) const = 0;
+ virtual void setParameter(unsigned long idx, float value) = 0;
virtual int getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max, int* initval) = 0;
};
@@ -211,7 +211,7 @@ class SynthI : public AudioTrack, public MidiDevice,
//SynthI* clone() const { return new SynthI(*this); }
SynthI* clone(bool /*cloneParts*/) const { return new SynthI(*this); }
- virtual inline int deviceType() { return SYNTH_MIDI; }
+ virtual inline int deviceType() const { return SYNTH_MIDI; }
SynthIF* sif() const { return _sif; }
bool initInstance(Synth* s, const QString& instanceName);