@@ -77,17 +77,6 @@ public: | |||
protected: | |||
void msgReceived(const char* const msg) override | |||
{ | |||
/* | |||
* TODO: | |||
* load_file load_project save_project patchbay_connect patchbay_disconnect patchbay_refresh | |||
* transport_play transport_pause transport_relocate | |||
* *add_plugin* remove_plugin remove_all_plugins rename_plugin clone_plugin replace_plugin switch_plugins | |||
* load_plugin_state save_plugin_state | |||
* set_option *set_active* set_drywet set_volume set_balance_left set_balance_right set_panning set_ctrl_channel | |||
* set_parameter_value set_parameter_midi_channel set_parameter_midi_cc set_program set_midi_program set_custom_data set_chunk_data | |||
* prepare_for_save send_midi_note show_custom_ui | |||
*/ | |||
if (std::strcmp(msg, "exiting") == 0) | |||
{ | |||
waitChildClose(); | |||
@@ -103,21 +92,196 @@ protected: | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(valueStr),); | |||
fEngine->setOption((EngineOption)option, value, valueStr); | |||
delete[] valueStr; | |||
} | |||
else if (std::strcmp(msg, "load_file") == 0) | |||
{ | |||
const char* filename; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),); | |||
fEngine->loadFile(filename); | |||
delete[] filename; | |||
} | |||
else if (std::strcmp(msg, "load_project") == 0) | |||
{ | |||
const char* filename; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),); | |||
fEngine->loadProject(filename); | |||
delete[] filename; | |||
} | |||
else if (std::strcmp(msg, "save_project") == 0) | |||
{ | |||
const char* filename; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),); | |||
fEngine->saveProject(filename); | |||
delete[] filename; | |||
} | |||
else if (std::strcmp(msg, "patchbay_connect") == 0) | |||
{ | |||
int portA, portB; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portA),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(portB),); | |||
fEngine->patchbayConnect(portA, portB); | |||
} | |||
else if (std::strcmp(msg, "patchbay_disconnect") == 0) | |||
{ | |||
int connectionId; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(connectionId),); | |||
fEngine->patchbayDisconnect(connectionId); | |||
} | |||
else if (std::strcmp(msg, "patchbay_refresh") == 0) | |||
{ | |||
fEngine->patchbayRefresh(); | |||
} | |||
else if (std::strcmp(msg, "transport_play") == 0) | |||
{ | |||
fEngine->transportPlay(); | |||
} | |||
else if (std::strcmp(msg, "transport_pause") == 0) | |||
{ | |||
fEngine->transportPause(); | |||
} | |||
else if (std::strcmp(msg, "transport_relocate") == 0) | |||
{ | |||
long frame; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsLong(frame),); | |||
fEngine->transportRelocate((uint64_t)frame); | |||
} | |||
else if (std::strcmp(msg, "add_plugin") == 0) | |||
{ | |||
int btype, ptype; | |||
const char* filename; | |||
const char* filename = nullptr; | |||
const char* name; | |||
const char* label; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(btype),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(ptype),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),); | |||
readNextLineAsString(filename); // can be null | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(name),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(label),); | |||
if (filename != nullptr && std::strcmp(filename, "(null)") == 0) | |||
{ | |||
delete[] filename; | |||
filename = nullptr; | |||
} | |||
if (std::strcmp(name, "(null)") == 0) | |||
{ | |||
delete[] name; | |||
name = nullptr; | |||
} | |||
fEngine->addPlugin((BinaryType)btype, (PluginType)ptype, filename, name, label); | |||
if (filename != nullptr) | |||
delete[] filename; | |||
if (name != nullptr) | |||
delete[] name; | |||
delete[] label; | |||
} | |||
else if (std::strcmp(msg, "remove_plugin") == 0) | |||
{ | |||
int pluginId; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
fEngine->removePlugin(pluginId); | |||
} | |||
else if (std::strcmp(msg, "remove_all_plugins") == 0) | |||
{ | |||
fEngine->removeAllPlugins(); | |||
} | |||
else if (std::strcmp(msg, "rename_plugin") == 0) | |||
{ | |||
int pluginId; | |||
const char* newName; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(newName),); | |||
/*const char* name =*/ fEngine->renamePlugin(pluginId, newName); | |||
delete[] newName; | |||
} | |||
else if (std::strcmp(msg, "clone_plugin") == 0) | |||
{ | |||
int pluginId; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
fEngine->clonePlugin(pluginId); | |||
} | |||
else if (std::strcmp(msg, "replace_plugin") == 0) | |||
{ | |||
int pluginId; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
fEngine->replacePlugin(pluginId); | |||
} | |||
else if (std::strcmp(msg, "switch_plugins") == 0) | |||
{ | |||
int pluginIdA, pluginIdB; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginIdA),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginIdB),); | |||
fEngine->switchPlugins(pluginIdA, pluginIdB); | |||
} | |||
else if (std::strcmp(msg, "load_plugin_state") == 0) | |||
{ | |||
int pluginId; | |||
const char* filename; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->loadStateFromFile(filename); | |||
delete[] filename; | |||
} | |||
else if (std::strcmp(msg, "save_plugin_state") == 0) | |||
{ | |||
int pluginId; | |||
const char* filename; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(filename),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->saveStateToFile(filename); | |||
delete[] filename; | |||
} | |||
else if (std::strcmp(msg, "set_option") == 0) | |||
{ | |||
int pluginId; | |||
int option; | |||
bool yesNo; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(option),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setOption(option, yesNo); | |||
} | |||
else if (std::strcmp(msg, "set_active") == 0) | |||
{ | |||
@@ -130,6 +294,198 @@ protected: | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setActive(onOff, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_drywet") == 0) | |||
{ | |||
int pluginId; | |||
float value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setDryWet(value, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_volume") == 0) | |||
{ | |||
int pluginId; | |||
float value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setVolume(value, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_balance_left") == 0) | |||
{ | |||
int pluginId; | |||
float value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setBalanceLeft(value, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_balance_right") == 0) | |||
{ | |||
int pluginId; | |||
float value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setBalanceRight(value, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_panning") == 0) | |||
{ | |||
int pluginId; | |||
float value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setPanning(value, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_ctrl_channel") == 0) | |||
{ | |||
int pluginId; | |||
int channel; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel),); | |||
CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS,); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setCtrlChannel(int8_t(channel), true, false); | |||
} | |||
else if (std::strcmp(msg, "set_parameter_value") == 0) | |||
{ | |||
int pluginId; | |||
int parameterId; | |||
float value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(parameterId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setParameterValue(parameterId, value, true, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_parameter_midi_channel") == 0) | |||
{ | |||
int pluginId; | |||
int parameterId; | |||
int channel; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(parameterId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel),); | |||
CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS,); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setParameterMidiChannel(parameterId, uint8_t(channel), true, false); | |||
} | |||
else if (std::strcmp(msg, "set_parameter_midi_cc") == 0) | |||
{ | |||
int pluginId; | |||
int parameterId; | |||
int cc; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(parameterId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(cc),); | |||
CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < 0x5F,); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setParameterMidiCC(parameterId, int16_t(cc), true, false); | |||
} | |||
else if (std::strcmp(msg, "set_program") == 0) | |||
{ | |||
int pluginId; | |||
int index; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setProgram(index, true, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_midi_program") == 0) | |||
{ | |||
int pluginId; | |||
int index; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setMidiProgram(index, true, true, false); | |||
} | |||
else if (std::strcmp(msg, "set_custom_data") == 0) | |||
{ | |||
int pluginId; | |||
const char* type; | |||
const char* key; | |||
const char* value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(type),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setCustomData(type, key, value, true); | |||
} | |||
else if (std::strcmp(msg, "set_chunk_data") == 0) | |||
{ | |||
int pluginId; | |||
const char* cdata; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(cdata),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->setChunkData(cdata); | |||
} | |||
else if (std::strcmp(msg, "prepare_for_save") == 0) | |||
{ | |||
int pluginId; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->prepareForSave(); | |||
} | |||
else if (std::strcmp(msg, "send_midi_note") == 0) | |||
{ | |||
int pluginId; | |||
int channel, note, velocity; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(channel),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(note),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(velocity),); | |||
CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS,); | |||
CARLA_SAFE_ASSERT_RETURN(note >= 0 && channel < MAX_MIDI_VALUE,); | |||
CARLA_SAFE_ASSERT_RETURN(velocity >= 0 && channel < MAX_MIDI_VALUE,); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->sendMidiSingleNote(uint8_t(channel), uint8_t(note), uint8_t(velocity), true, true, false); | |||
} | |||
else if (std::strcmp(msg, "show_custom_ui") == 0) | |||
{ | |||
int pluginId; | |||
bool yesNo; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(pluginId),); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(yesNo),); | |||
if (CarlaPlugin* const plugin = fEngine->getPlugin(pluginId)) | |||
plugin->showCustomUI(yesNo); | |||
} | |||
else | |||
{ | |||
carla_stderr("msgReceived : %s", msg); | |||
@@ -256,6 +612,97 @@ protected: | |||
return; | |||
char strBuf[STR_MAX+1]; | |||
switch (action) | |||
{ | |||
case ENGINE_CALLBACK_PLUGIN_ADDED: | |||
if (CarlaPlugin* const plugin = getPlugin(pluginId)) | |||
{ | |||
CARLA_SAFE_ASSERT_BREAK(plugin->getId() == pluginId); | |||
std::sprintf(strBuf, "PLUGIN_INFO_%i\n", pluginId); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%i:%i:%i:%li\n", plugin->getType(), plugin->getCategory(), plugin->getHints(), plugin->getUniqueId()); | |||
fUiServer.writeMsg(strBuf); | |||
plugin->getRealName(strBuf); | |||
fUiServer.writeAndFixMsg(strBuf); | |||
std::sprintf(strBuf, "%s", plugin->getName()); | |||
fUiServer.writeAndFixMsg(strBuf); | |||
plugin->getLabel(strBuf); | |||
fUiServer.writeAndFixMsg(strBuf); | |||
plugin->getMaker(strBuf); | |||
fUiServer.writeAndFixMsg(strBuf); | |||
plugin->getCopyright(strBuf); | |||
fUiServer.writeAndFixMsg(strBuf); | |||
std::sprintf(strBuf, "AUDIO_COUNT_%i\n", pluginId); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%i:%i\n", plugin->getAudioInCount(), plugin->getAudioOutCount()); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "MIDI_COUNT_%i\n", pluginId); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%i:%i\n", plugin->getMidiInCount(), plugin->getMidiOutCount()); | |||
fUiServer.writeMsg(strBuf); | |||
uint32_t ins, outs, count; | |||
std::sprintf(strBuf, "PARAMETER_COUNT_%i\n", pluginId); | |||
fUiServer.writeMsg(strBuf); | |||
plugin->getParameterCountInfo(ins, outs); | |||
count = plugin->getParameterCount(); | |||
std::sprintf(strBuf, "%i:%i:%i\n", ins, outs, count); | |||
fUiServer.writeMsg(strBuf); | |||
for (uint32_t i=0; i<count; ++i) | |||
{ | |||
const ParameterData& paramData(plugin->getParameterData(i)); | |||
const ParameterRanges& paramRanges(plugin->getParameterRanges(i)); | |||
std::sprintf(strBuf, "PARAMETER_DATA_%i:%i\n", pluginId, i); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%i:%i\n", paramData.type, paramData.hints); | |||
fUiServer.writeMsg(strBuf); | |||
plugin->getParameterName(i, strBuf); | |||
fUiServer.writeAndFixMsg(strBuf); | |||
plugin->getParameterUnit(i, strBuf); | |||
fUiServer.writeAndFixMsg(strBuf); | |||
std::sprintf(strBuf, "PARAMETER_MIDI_STUFF_%i:%i\n", pluginId, i); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%i:%i\n", paramData.midiChannel, paramData.midiCC); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "PARAMETER_RANGES_%i:%i\n", pluginId, i); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%f:%f:%f:%f:%f:%f\n", paramRanges.def, paramRanges.min, paramRanges.max, paramRanges.step, paramRanges.stepSmall, paramRanges.stepLarge); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "PARAMETER_VALUE_%i:%i\n", pluginId, i); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%f\n", plugin->getParameterValue(i)); | |||
fUiServer.writeMsg(strBuf); | |||
} | |||
} | |||
break; | |||
case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: | |||
std::sprintf(strBuf, "PARAMETER_VALUE_%i:%i\n", pluginId, value1); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%f\n", value3); | |||
fUiServer.writeMsg(strBuf); | |||
break; | |||
case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: | |||
std::sprintf(strBuf, "PARAMETER_DEFAULT_%i:%i\n", pluginId, value1); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%f\n", value3); | |||
fUiServer.writeMsg(strBuf); | |||
break; | |||
default: | |||
break; | |||
} | |||
std::sprintf(strBuf, "ENGINE_CALLBACK_%i\n", int(action)); | |||
fUiServer.writeMsg(strBuf); | |||
@@ -622,6 +1069,19 @@ protected: | |||
CarlaEngine::idle(); | |||
fUiServer.idle(); | |||
char strBuf[STR_MAX+1]; | |||
for (uint i=0; i < pData->curPluginCount; ++i) | |||
{ | |||
const EnginePluginData& plugData(pData->plugins[i]); | |||
std::sprintf(strBuf, "PEAKS_%i\n", i); | |||
fUiServer.writeMsg(strBuf); | |||
std::sprintf(strBuf, "%f:%f:%f:%f\n", plugData.insPeak[0], plugData.insPeak[1], plugData.outsPeak[0], plugData.outsPeak[1]); | |||
fUiServer.writeMsg(strBuf); | |||
} | |||
switch (fUiServer.getAndResetUiState()) | |||
{ | |||
case CarlaEngineNativeUI::UiNone: | |||
@@ -876,6 +1336,8 @@ private: | |||
bool fIsActive, fIsRunning; | |||
CarlaEngineNativeUI fUiServer; | |||
CarlaMutex fWriteLock; | |||
CarlaPlugin* _getFirstPlugin() const noexcept | |||
{ | |||
if (pData->curPluginCount == 0 || pData->plugins == nullptr) | |||
@@ -27,6 +27,30 @@ from time import sleep | |||
from carla_host import * | |||
from externalui import ExternalUI | |||
# ------------------------------------------------------------------------------------------------------------ | |||
# Helper object | |||
class PluginStoreInfo(object): | |||
__slots__ = [ | |||
'pluginInfo', | |||
'pluginRealName', | |||
'audioCountInfo', | |||
'midiCountInfo', | |||
'parameterCount', | |||
'parameterCountInfo', | |||
'parameterInfoS', | |||
'parameterDataS', | |||
'parameterRangeS', | |||
'parameterValueS', | |||
'programCount', | |||
'programCurrent', | |||
'programNameS', | |||
'midiProgramCount', | |||
'midiProgramCurrent', | |||
'midiProgramDataS', | |||
'peaks' | |||
] | |||
# ------------------------------------------------------------------------------------------------------------ | |||
# Host Plugin object | |||
@@ -40,6 +64,126 @@ class PluginHost(object): | |||
self.fLastError = "" | |||
self.fIsRunning = True | |||
self.fPluginsInfo = [] | |||
def _add(self, pluginId): | |||
if len(self.fPluginsInfo) != pluginId: | |||
return | |||
info = PluginStoreInfo() | |||
info.pluginInfo = PyCarlaPluginInfo | |||
info.pluginRealName = "" | |||
info.audioCountInfo = PyCarlaPortCountInfo | |||
info.midiCountInfo = PyCarlaPortCountInfo | |||
info.parameterCount = 0 | |||
info.parameterCountInfo = PyCarlaPortCountInfo | |||
info.parameterInfoS = [] | |||
info.parameterDataS = [] | |||
info.parameterRangeS = [] | |||
info.parameterValueS = [] | |||
info.programCount = 0 | |||
info.programCurrent = -1 | |||
info.programNameS = [] | |||
info.midiProgramCount = 0 | |||
info.midiProgramCurrent = -1 | |||
info.midiProgramDataS = [] | |||
info.peaks = [0.0, 0.0, 0.0, 0.0] | |||
self.fPluginsInfo.append(info) | |||
def _set_pluginInfo(self, pluginId, info): | |||
self.fPluginsInfo[pluginId].pluginInfo = info | |||
def _set_pluginRealName(self, pluginId, realName): | |||
self.fPluginsInfo[pluginId].pluginRealName = realName | |||
def _set_audioCountInfo(self, pluginId, info): | |||
self.fPluginsInfo[pluginId].audioCountInfo = info | |||
def _set_midiCountInfo(self, pluginId, info): | |||
self.fPluginsInfo[pluginId].midiCountInfo = info | |||
def _set_parameterCountInfo(self, pluginId, count, info): | |||
self.fPluginsInfo[pluginId].parameterCount = count | |||
self.fPluginsInfo[pluginId].parameterCountInfo = info | |||
# clear | |||
self.fPluginsInfo[pluginId].parameterInfoS = [] | |||
self.fPluginsInfo[pluginId].parameterDataS = [] | |||
self.fPluginsInfo[pluginId].parameterRangeS = [] | |||
self.fPluginsInfo[pluginId].parameterValueS = [] | |||
# add placeholders | |||
for x in range(count): | |||
self.fPluginsInfo[pluginId].parameterInfoS.append(PyCarlaParameterInfo) | |||
self.fPluginsInfo[pluginId].parameterDataS.append(PyParameterData) | |||
self.fPluginsInfo[pluginId].parameterRangeS.append(PyParameterRanges) | |||
self.fPluginsInfo[pluginId].parameterValueS.append(0.0) | |||
def _set_programCount(self, pluginId, count): | |||
self.fPluginsInfo[pluginId].programCount = count | |||
# clear | |||
self.fPluginsInfo[pluginId].programNameS = [] | |||
# add placeholders | |||
for x in range(count): | |||
self.fPluginsInfo[pluginId].programNameS.append("") | |||
def _set_midiProgramCount(self, pluginId, count): | |||
self.fPluginsInfo[pluginId].midiProgramCount = count | |||
# clear | |||
self.fPluginsInfo[pluginId].midiProgramDataS = [] | |||
# add placeholders | |||
for x in range(count): | |||
self.fPluginsInfo[pluginId].midiProgramDataS.append(PyMidiProgramData) | |||
def _set_parameterInfoS(self, pluginId, paramIndex, info): | |||
if paramIndex < self.fPluginsInfo[pluginId].parameterCount: | |||
self.fPluginsInfo[pluginId].parameterInfoS[paramIndex] = info | |||
def _set_parameterDataS(self, pluginId, paramIndex, data): | |||
if paramIndex < self.fPluginsInfo[pluginId].parameterCount: | |||
self.fPluginsInfo[pluginId].parameterDataS[paramIndex] = data | |||
def _set_parameterRangeS(self, pluginId, paramIndex, ranges): | |||
if paramIndex < self.fPluginsInfo[pluginId].parameterCount: | |||
self.fPluginsInfo[pluginId].parameterRangeS[paramIndex] = ranges | |||
def _set_parameterValueS(self, pluginId, paramIndex, value): | |||
if paramIndex < self.fPluginsInfo[pluginId].parameterCount: | |||
self.fPluginsInfo[pluginId].parameterValueS[paramIndex] = value | |||
def _set_parameterDefaultValue(self, pluginId, paramIndex, value): | |||
if paramIndex < self.fPluginsInfo[pluginId].parameterCount: | |||
self.fPluginsInfo[pluginId].parameterRangeS[paramIndex]['def'] = value | |||
def _set_parameterMidiChannel(self, pluginId, paramIndex, channel): | |||
if paramIndex < self.fPluginsInfo[pluginId].parameterCount: | |||
self.fPluginsInfo[pluginId].parameterDataS[paramIndex]['midiChannel'] = channel | |||
def _set_parameterMidiCC(self, pluginId, paramIndex, cc): | |||
if paramIndex < self.fPluginsInfo[pluginId].parameterCount: | |||
self.fPluginsInfo[pluginId].parameterDataS[paramIndex]['midiCC'] = cc | |||
def _set_currentProgram(self, pluginId, pIndex): | |||
self.fPluginsInfo[pluginId].programCurrent = pIndex | |||
def _set_currentMidiProgram(self, pluginId, mpIndex): | |||
self.fPluginsInfo[pluginId].midiProgramCurrent = mpIndex | |||
def _set_programNameS(self, pluginId, pIndex, name): | |||
if pIndex < self.fPluginsInfo[pluginId].programCount: | |||
self.fPluginsInfo[pluginId].programNameS[pIndex] = name | |||
def _set_midiProgramDataS(self, pluginId, mpIndex, data): | |||
if mpIndex < self.fPluginsInfo[pluginId].midiProgramCount: | |||
self.fPluginsInfo[pluginId].midiProgramDataS[mpIndex] = data | |||
def _set_peaks(self, pluginId, in1, in2, out1, out2): | |||
self.fPluginsInfo[pluginId].peaks = [in1, in2, out1, out2] | |||
# ------------------------------------------------------------------- | |||
def get_complete_license_text(self): | |||
@@ -65,7 +209,7 @@ class PluginHost(object): | |||
# ------------------------------------------------------------------- | |||
def get_internal_plugin_count(self): | |||
return int(self.lib.carla_get_internal_plugin_count()) | |||
return 0 | |||
def get_internal_plugin_info(self, index): | |||
return None | |||
@@ -188,19 +332,19 @@ class PluginHost(object): | |||
# ------------------------------------------------------------------- | |||
def get_plugin_info(self, pluginId): | |||
return PyCarlaPluginInfo | |||
return self.fPluginsInfo[pluginId].pluginInfo | |||
def get_audio_port_count_info(self, pluginId): | |||
return PyCarlaPortCountInfo | |||
return self.fPluginsInfo[pluginId].audioCountInfo | |||
def get_midi_port_count_info(self, pluginId): | |||
return PyCarlaPortCountInfo | |||
return self.fPluginsInfo[pluginId].midiCountInfo | |||
def get_parameter_count_info(self, pluginId): | |||
return PyCarlaPortCountInfo | |||
return self.fPluginsInfo[pluginId].parameterCountInfo | |||
def get_parameter_info(self, pluginId, parameterId): | |||
return PyCarlaParameterInfo | |||
return self.fPluginsInfo[pluginId].parameterInfoS[parameterId] | |||
def get_parameter_scalepoint_info(self, pluginId, parameterId, scalePointId): | |||
return PyCarlaScalePointInfo | |||
@@ -208,13 +352,13 @@ class PluginHost(object): | |||
# ------------------------------------------------------------------- | |||
def get_parameter_data(self, pluginId, parameterId): | |||
return PyParameterData | |||
return self.fPluginsInfo[pluginId].parameterDataS[parameterId] | |||
def get_parameter_ranges(self, pluginId, parameterId): | |||
return PyParameterRanges | |||
return self.fPluginsInfo[pluginId].parameterRangeS[parameterId] | |||
def get_midi_program_data(self, pluginId, midiProgramId): | |||
return PyMidiProgramData | |||
return self.fPluginsInfo[pluginId].midiProgramDataS[midiProgramId] | |||
def get_custom_data(self, pluginId, customDataId): | |||
return PyCustomData | |||
@@ -225,13 +369,13 @@ class PluginHost(object): | |||
# ------------------------------------------------------------------- | |||
def get_parameter_count(self, pluginId): | |||
return 0 | |||
return self.fPluginsInfo[pluginId].parameterCount | |||
def get_program_count(self, pluginId): | |||
return 0 | |||
return self.fPluginsInfo[pluginId].programCount | |||
def get_midi_program_count(self, pluginId): | |||
return 0 | |||
return self.fPluginsInfo[pluginId].midiProgramCount | |||
def get_custom_data_count(self, pluginId): | |||
return 0 | |||
@@ -242,33 +386,33 @@ class PluginHost(object): | |||
return "" | |||
def get_program_name(self, pluginId, programId): | |||
return "" | |||
return self.fPluginsInfo[pluginId].programNameS[programId] | |||
def get_midi_program_name(self, pluginId, midiProgramId): | |||
return "" | |||
return self.fPluginsInfo[pluginId].midiProgramDataS[midiProgramId]['label'] | |||
def get_real_plugin_name(self, pluginId): | |||
return "" | |||
return self.fPluginsInfo[pluginId].pluginRealName | |||
# ------------------------------------------------------------------- | |||
def get_current_program_index(self, pluginId): | |||
return 0 | |||
return self.fPluginsInfo[pluginId].programCurrent | |||
def get_current_midi_program_index(self, pluginId): | |||
return 0 | |||
return self.fPluginsInfo[pluginId].midiProgramCurrent | |||
def get_default_parameter_value(self, pluginId, parameterId): | |||
return 0.0 | |||
return self.fPluginsInfo[pluginId].parameterRangeS[parameterId]['def'] | |||
def get_current_parameter_value(self, pluginId, parameterId): | |||
return 0.0 | |||
return self.fPluginsInfo[pluginId].parameterValueS[parameterId] | |||
def get_input_peak_value(self, pluginId, isLeft): | |||
return 0.0 | |||
return self.fPluginsInfo[pluginId].peaks[0 if isLeft else 1] | |||
def get_output_peak_value(self, pluginId, isLeft): | |||
return 0.0 | |||
return self.fPluginsInfo[pluginId].peaks[2 if isLeft else 3] | |||
# ------------------------------------------------------------------- | |||
@@ -406,6 +550,114 @@ class CarlaMiniW(HostWindow, ExternalUI): | |||
if not msg: | |||
return True | |||
elif msg.startswith("PEAKS_"): | |||
pluginId = int(msg.replace("PEAKS_", "")) | |||
in1, in2, out1, out2 = [float(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
Carla.host._set_peaks(pluginId, in1, in2, out1, out2) | |||
elif msg.startswith("ENGINE_CALLBACK_"): | |||
action = int(msg.replace("ENGINE_CALLBACK_", "")) | |||
pluginId = int(self.fPipeRecv.readline().strip()) | |||
value1 = int(self.fPipeRecv.readline().strip()) | |||
value2 = int(self.fPipeRecv.readline().strip()) | |||
value3 = float(self.fPipeRecv.readline().strip()) | |||
valueStr = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
engineCallback(None, action, pluginId, value1, value2, value3, valueStr) | |||
elif msg.startswith("PLUGIN_INFO_"): | |||
pluginId = int(msg.replace("PLUGIN_INFO_", "")) | |||
Carla.host._add(pluginId) | |||
type_, category, hints, uniqueId = [int(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
realName = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
name = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
label = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
maker = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
copyright = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
pinfo = { | |||
'type': type_, | |||
'category': category, | |||
'hints': hints, | |||
'optionsAvailable': 0x0, # TODO | |||
'optionsEnabled': 0x0, # TODO | |||
'filename': "", # TODO | |||
'name': name, | |||
'label': label, | |||
'maker': maker, | |||
'copyright': copyright, | |||
'iconName': None, # TODO | |||
'patchbayClientId': 0, | |||
'uniqueId': uniqueId | |||
} | |||
Carla.host._set_pluginInfo(pluginId, pinfo) | |||
Carla.host._set_pluginRealName(pluginId, realName) | |||
elif msg.startswith("AUDIO_COUNT_"): | |||
pluginId = int(msg.replace("AUDIO_COUNT_", "")) | |||
ins, outs = [int(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
Carla.host._set_audioCountInfo(pluginId, {'ins': ins, 'outs': outs}) | |||
elif msg.startswith("MIDI_COUNT_"): | |||
pluginId = int(msg.replace("MIDI_COUNT_", "")) | |||
ins, outs = [int(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
Carla.host._set_midiCountInfo(pluginId, {'ins': ins, 'outs': outs}) | |||
elif msg.startswith("PARAMETER_COUNT_"): | |||
pluginId = int(msg.replace("PARAMETER_COUNT_", "")) | |||
ins, outs, count = [int(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
Carla.host._set_parameterCountInfo(pluginId, count, {'ins': ins, 'outs': outs}) | |||
elif msg.startswith("PARAMETER_DATA_"): | |||
pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_DATA_", "").split(":")] | |||
paramType, paramHints = [int(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
paramName = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
paramUnit = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
paramInfo = { | |||
'name': paramName, | |||
'symbol': "", | |||
'unit': paramUnit, | |||
'scalePointCount': 0, | |||
} | |||
Carla.host._set_parameterInfoS(pluginId, paramId, paramInfo) | |||
paramData = { | |||
'type': paramType, | |||
'hints': paramHints, | |||
'index': paramId, | |||
'rindex': -1, | |||
'midiCC': -1, | |||
'midiChannel': 0 | |||
} | |||
Carla.host._set_parameterDataS(pluginId, paramId, paramData) | |||
elif msg.startswith("PARAMETER_MIDI_STUFF_"): | |||
pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_MIDI_STUFF_", "").split(":")] | |||
midiChannel, midiCC = [int(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
Carla.host._set_parameterMidiChannel(pluginId, paramId, midiChannel) | |||
Carla.host._set_parameterMidiCC(pluginId, paramId, midiCC) | |||
elif msg.startswith("PARAMETER_RANGES_"): | |||
pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_RANGES_", "").split(":")] | |||
def_, min_, max_, step, stepSmall, stepLarge = [float(i) for i in self.fPipeRecv.readline().strip().split(":")] | |||
paramRanges = { | |||
'def': def_, | |||
'min': min_, | |||
'max': max_, | |||
'step': step, | |||
'stepSmall': stepSmall, | |||
'stepLarge': stepLarge | |||
} | |||
Carla.host._set_parameterRangeS(pluginId, paramId, paramRanges) | |||
elif msg.startswith("PARAMETER_VALUE_"): | |||
pluginId, paramId = [int(i) for i in msg.replace("PARAMETER_VALUE_", "").split(":")] | |||
paramValue = float(self.fPipeRecv.readline().strip()) | |||
Carla.host._set_parameterValueS(pluginId, paramId, paramValue) | |||
elif msg == "show": | |||
self.d_uiShow() | |||
@@ -420,15 +672,6 @@ class CarlaMiniW(HostWindow, ExternalUI): | |||
uiTitle = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
self.d_uiTitleChanged(uiTitle) | |||
elif msg.startswith("ENGINE_CALLBACK_"): | |||
action = int(msg.replace("ENGINE_CALLBACK_", "")) | |||
pluginId = int(self.fPipeRecv.readline()) | |||
value1 = int(self.fPipeRecv.readline()) | |||
value2 = int(self.fPipeRecv.readline()) | |||
value3 = float(self.fPipeRecv.readline()) | |||
valueStr = self.fPipeRecv.readline().strip().replace("\r", "\n") | |||
engineCallback(None, action, pluginId, value1, value2, value3, valueStr) | |||
else: | |||
print("unknown message: \"" + msg + "\"") | |||
@@ -182,7 +182,9 @@ class ExternalUI(object): | |||
return | |||
for line in lines: | |||
if isinstance(line, str): | |||
if line is None: | |||
line2 = "(null)" | |||
elif isinstance(line, str): | |||
line2 = line.replace("\n", "\r") | |||
else: | |||
if isinstance(line, bool): | |||
@@ -192,11 +194,8 @@ class ExternalUI(object): | |||
elif isinstance(line, float): | |||
line2 = "%.10f" % line | |||
else: | |||
try: | |||
line2 = str(line) | |||
except: | |||
print("unknown data type to send:", type(line2)) | |||
return | |||
print("unknown data type to send:", type(line)) | |||
return | |||
self.fPipeSend.write(line2 + "\n") | |||
self.fPipeSend.flush() |
@@ -309,6 +309,20 @@ public: | |||
return false; | |||
} | |||
bool readNextLineAsLong(long& value) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fIsReading, false); | |||
if (const char* const msg = readline()) | |||
{ | |||
value = std::atol(msg); | |||
delete[] msg; | |||
return true; | |||
} | |||
return false; | |||
} | |||
bool readNextLineAsFloat(float& value) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fIsReading, false); | |||
@@ -360,22 +374,40 @@ public: | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fPipeSend != -1,); | |||
const size_t size(std::strlen(msg)); | |||
const size_t size(msg != nullptr ? std::strlen(msg) : 0); | |||
char fixedMsg[size+1]; | |||
std::strcpy(fixedMsg, msg); | |||
char fixedMsg[size+2]; | |||
for (size_t i=0; i < size; ++i) | |||
if (size > 0) | |||
{ | |||
if (fixedMsg[i] == '\n') | |||
fixedMsg[i] = '\r'; | |||
} | |||
std::strcpy(fixedMsg, msg); | |||
for (size_t i=0; i < size; ++i) | |||
{ | |||
if (fixedMsg[i] == '\n') | |||
fixedMsg[i] = '\r'; | |||
} | |||
fixedMsg[size-1] = '\n'; | |||
fixedMsg[size] = '\0'; | |||
if (fixedMsg[size+1] == '\r') | |||
{ | |||
fixedMsg[size-1] = '\n'; | |||
fixedMsg[size] = '\0'; | |||
fixedMsg[size+1] = '\0'; | |||
} | |||
else | |||
{ | |||
fixedMsg[size] = '\n'; | |||
fixedMsg[size+1] = '\0'; | |||
} | |||
} | |||
else | |||
{ | |||
fixedMsg[0] = '\n'; | |||
fixedMsg[1] = '\0'; | |||
} | |||
try { | |||
::write(fPipeSend, fixedMsg, size); | |||
::write(fPipeSend, fixedMsg, size+1); | |||
} catch (...) {} | |||
} | |||