Browse Source

Continue last commit; ZynAddSubFX multi-program

tags/1.9.4
falkTX 11 years ago
parent
commit
a6846272ff
5 changed files with 139 additions and 26 deletions
  1. +48
    -12
      source/backend/native/zynaddsubfx.cpp
  2. +3
    -1
      source/backend/plugin/CarlaPlugin.cpp
  3. +4
    -1
      source/backend/plugin/FluidSynthPlugin.cpp
  4. +81
    -11
      source/backend/plugin/NativePlugin.cpp
  5. +3
    -1
      source/carla_shared.py

+ 48
- 12
source/backend/native/zynaddsubfx.cpp View File

@@ -104,11 +104,14 @@ public:
: PluginDescriptorClass(host),
kMaster(new Master()),
kSampleRate(getSampleRate()),
fIsActive(false),
fThread(kMaster, host)
{
fThread.start();
maybeInitPrograms(kMaster);
//fThread.waitForStarted();

for (int i = 0; i < NUM_MIDI_PARTS; ++i)
kMaster->partonoff(i, 1);
}

~ZynAddSubFxPlugin() override
@@ -229,13 +232,13 @@ protected:

bool isOffline = false;

if (isOffline)
if (isOffline || ! fIsActive)
loadProgram(kMaster, channel, bank, program);
else
fThread.loadLater(channel, bank, program);
}

void setCustomData(const char* const key, const char* const value)
void setCustomData(const char* const key, const char* const value) override
{
CARLA_ASSERT(key != nullptr);
CARLA_ASSERT(value != nullptr);
@@ -254,6 +257,13 @@ protected:
// broken
//for (int i=0; i < NUM_MIDI_PARTS; i++)
// kMaster->setController(0, MIDI_CONTROL_ALL_SOUND_OFF, 0);

fIsActive = true;
}

void deactivate() override
{
fIsActive = false;
}

void process(float**, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents) override
@@ -371,6 +381,7 @@ private:
#endif
fQuit(false),
fChangeProgram(false),
fNextChannel(0),
fNextBank(0),
fNextProgram(0)
{
@@ -387,7 +398,7 @@ private:

void loadLater(const uint8_t channel, const uint32_t bank, const uint32_t program)
{
// TODO
fNextChannel = channel;
fNextBank = bank;
fNextProgram = program;
fChangeProgram = true;
@@ -396,6 +407,7 @@ private:
void stopLoadLater()
{
fChangeProgram = false;
fNextChannel = 0;
fNextBank = 0;
fNextProgram = 0;
}
@@ -489,12 +501,17 @@ private:
if (fChangeProgram)
{
fChangeProgram = false;
loadProgram(kMaster, 0, fNextBank, fNextProgram); // TODO
loadProgram(kMaster, fNextChannel, fNextBank, fNextProgram);
fNextChannel = 0;
fNextBank = 0;
fNextProgram = 0;
}

carla_msleep(15);
carla_msleep(15);
}
else
{
carla_msleep(30);
}
}

#ifdef WANT_ZYNADDSUBFX_UI
@@ -533,12 +550,14 @@ private:

bool fQuit;
bool fChangeProgram;
uint8_t fNextChannel;
uint32_t fNextBank;
uint32_t fNextProgram;
};

Master* const kMaster;
const unsigned kSampleRate;
bool fIsActive;

ZynThread fThread;

@@ -601,26 +620,28 @@ public:
return;
doSearch = false;

sPrograms.append(new ProgramInfo(0, 0, "default"));

pthread_mutex_lock(&master->mutex);

// refresh banks
master->bank.rescanforbanks();

for (uint32_t i=0, size = master->bank.banks.size(); i < size; i++)
for (uint32_t i=0, size = master->bank.banks.size(); i < size; ++i)
{
if (master->bank.banks[i].dir.empty())
continue;

master->bank.loadbank(master->bank.banks[i].dir);

for (unsigned int instrument = 0; instrument < BANK_SIZE; instrument++)
for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument)
{
const std::string insName(master->bank.getname(instrument));

if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
continue;

sPrograms.append(new ProgramInfo(i, instrument, insName.c_str()));
sPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str()));
}
}

@@ -629,16 +650,31 @@ public:

static void loadProgram(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program)
{
const std::string& bankdir(master->bank.banks[bank].dir);
if (bank == 0)
{
pthread_mutex_lock(&master->mutex);

master->part[channel]->defaults();
master->part[channel]->applyparameters(false);
master->partonoff(channel, 1);

pthread_mutex_unlock(&master->mutex);

return;
}

const std::string& bankdir(master->bank.banks[bank-1].dir);

if (! bankdir.empty())
{
pthread_mutex_lock(&master->mutex);

master->partonoff(channel, 1);

master->bank.loadbank(bankdir);
master->bank.loadfromslot(program, master->part[channel]);

master->applyparameters(false);
master->part[channel]->applyparameters(false);

pthread_mutex_unlock(&master->mutex);
}


+ 3
- 1
source/backend/plugin/CarlaPlugin.cpp View File

@@ -804,7 +804,9 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState)
// ---------------------------------------------------------------------
// Part 3 - set midi program

if (saveState.currentMidiBank >= 0 && saveState.currentMidiProgram >= 0 && type() != PLUGIN_SF2)
const bool usesMultiProgs(type() == PLUGIN_SF2 || (type() == PLUGIN_INTERNAL && (fHints & PLUGIN_IS_SYNTH) != 0));

if (saveState.currentMidiBank >= 0 && saveState.currentMidiProgram >= 0 && ! usesMultiProgs)
setMidiProgramById(saveState.currentMidiBank, saveState.currentMidiProgram, true, true, true);

// ---------------------------------------------------------------------


+ 4
- 1
source/backend/plugin/FluidSynthPlugin.cpp View File

@@ -451,7 +451,10 @@ public:
fCurMidiProgs[i] = index;

if (kData->ctrlChannel == static_cast<int32_t>(i))
{
kData->midiprog.current = index;
kData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fId, index, 0, 0.0f, nullptr);
}
}

++i;
@@ -977,7 +980,7 @@ public:
fCurMidiProgs[9] = 0;
}

setMidiProgram(0, false, false, false);
kData->midiprog.current = 0;
}
else
{


+ 81
- 11
source/backend/plugin/NativePlugin.cpp View File

@@ -172,7 +172,8 @@ public:
fIsUiVisible(false),
fAudioInBuffers(nullptr),
fAudioOutBuffers(nullptr),
fMidiEventCount(0)
fMidiEventCount(0),
fCurMidiProgs{0}
{
carla_debug("NativePlugin::NativePlugin(%p, %i)", engine, id);

@@ -483,9 +484,19 @@ public:
CARLA_ASSERT(fDescriptor != nullptr);
CARLA_ASSERT(fHandle != nullptr);

if (fDescriptor->get_state == nullptr)
return;
if ((fDescriptor->hints & ::PLUGIN_USES_STATE) == 0)
if (kData->midiprog.count > 0 && (fHints & PLUGIN_IS_SYNTH) != 0)
{
char strBuf[STR_MAX+1];
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i",
fCurMidiProgs[0], fCurMidiProgs[1], fCurMidiProgs[2], fCurMidiProgs[3],
fCurMidiProgs[4], fCurMidiProgs[5], fCurMidiProgs[6], fCurMidiProgs[7],
fCurMidiProgs[8], fCurMidiProgs[9], fCurMidiProgs[10], fCurMidiProgs[11],
fCurMidiProgs[12], fCurMidiProgs[13], fCurMidiProgs[14], fCurMidiProgs[15]);

CarlaPlugin::setCustomData(CUSTOM_DATA_STRING, "midiPrograms", strBuf, false);
}

if (fDescriptor->get_state == nullptr || (fDescriptor->hints & ::PLUGIN_USES_STATE) == 0)
return;

if (char* data = fDescriptor->get_state(fHandle))
@@ -514,6 +525,14 @@ public:
CarlaPlugin::setName(newName);
}

void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) override
{
if (channel < MAX_MIDI_CHANNELS)
kData->midiprog.current = fCurMidiProgs[channel];

CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
}

// -------------------------------------------------------------------
// Set data (plugin-specific stuff)

@@ -569,6 +588,41 @@ public:
fDescriptor->set_state(fHandle2, value);
}
}
else if (std::strcmp(key, "midiPrograms") == 0 && fDescriptor->set_midi_program != nullptr)
{
QStringList midiProgramList(QString(value).split(":", QString::SkipEmptyParts));

if (midiProgramList.count() == MAX_MIDI_CHANNELS)
{
uint i = 0;
foreach (const QString& midiProg, midiProgramList)
{
bool ok;
uint index = midiProg.toUInt(&ok);

if (ok && index < kData->midiprog.count)
{
const uint32_t bank = kData->midiprog.data[index].bank;
const uint32_t program = kData->midiprog.data[index].program;

fDescriptor->set_midi_program(fHandle, i, bank, program);

if (fHandle2 != nullptr)
fDescriptor->set_midi_program(fHandle2, i, bank, program);

fCurMidiProgs[i] = index;

if (kData->ctrlChannel == static_cast<int32_t>(i))
{
kData->midiprog.current = index;
kData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fId, index, 0, 0.0f, nullptr);
}
}

++i;
}
}
}
else
{
if (fDescriptor->set_custom_data != nullptr)
@@ -603,17 +657,23 @@ public:
else if (index > static_cast<int32_t>(kData->midiprog.count))
return;

if ((fHints & PLUGIN_IS_SYNTH) != 0 && (kData->ctrlChannel < 0 || kData->ctrlChannel >= MAX_MIDI_CHANNELS))
return;

if (index >= 0)
{
const uint8_t channel = (kData->ctrlChannel >= 0 || kData->ctrlChannel < MAX_MIDI_CHANNELS) ? kData->ctrlChannel : 0;
const uint32_t bank = kData->midiprog.data[index].bank;
const uint32_t program = kData->midiprog.data[index].program;

const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));

fDescriptor->set_midi_program(fHandle, 0, bank, program); // TODO
fDescriptor->set_midi_program(fHandle, channel, bank, program);

if (fHandle2 != nullptr)
fDescriptor->set_midi_program(fHandle2, 0, bank, program); // TODO
fDescriptor->set_midi_program(fHandle2, channel, bank, program);

fCurMidiProgs[channel] = index;
}

CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
@@ -1072,7 +1132,7 @@ public:

// Query new programs
uint32_t count = 0;
if (fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_info != nullptr)
if (fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_info != nullptr && fDescriptor->set_midi_program != nullptr)
count = fDescriptor->get_midi_program_count(fHandle);

if (count > 0)
@@ -1452,16 +1512,24 @@ public:
break;

case kEngineControlEventTypeMidiProgram:
if (event.channel == kData->ctrlChannel && (fOptions & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
if (event.channel < MAX_MIDI_CHANNELS && (fOptions & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
{
const uint32_t nextProgramId = ctrlEvent.param;
const uint32_t nextProgramId(ctrlEvent.param);

for (k=0; k < kData->midiprog.count; ++k)
{
if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId)
{
setMidiProgram(k, false, false, false);
postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0f);
fDescriptor->set_midi_program(fHandle, event.channel, nextBankId, nextProgramId);

if (fHandle2 != nullptr)
fDescriptor->set_midi_program(fHandle2, event.channel, nextBankId, nextProgramId);

fCurMidiProgs[event.channel] = k;

if (event.channel == kData->ctrlChannel)
postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0f);

break;
}
}
@@ -2188,6 +2256,8 @@ private:
uint32_t fMidiEventCount;
::MidiEvent fMidiEvents[MAX_MIDI_EVENTS*2];

int32_t fCurMidiProgs[MAX_MIDI_CHANNELS];

NativePluginMidiData fMidiIn;
NativePluginMidiData fMidiOut;



+ 3
- 1
source/carla_shared.py View File

@@ -1900,7 +1900,9 @@ class PluginEdit(QDialog):
self.fTabIconTimers.append(ICON_STATE_NULL)

def _updateCtrlMidiProgram(self):
if self.fPluginInfo['type'] != PLUGIN_SF2:
if self.fPluginInfo['type'] not in (PLUGIN_INTERNAL, PLUGIN_SF2):
return
elif not self.fPluginInfo['hints'] & PLUGIN_IS_SYNTH:
return

if self.fControlChannel == -1:


Loading…
Cancel
Save