| @@ -49,13 +49,14 @@ const unsigned int MAX_PARAMETERS = 200; //!< Default value for the maximum numb | |||||
| * \see CarlaPlugin::hints() | * \see CarlaPlugin::hints() | ||||
| * @{ | * @{ | ||||
| */ | */ | ||||
| const unsigned int PLUGIN_IS_BRIDGE = 0x01; //!< Plugin is a bridge (ie, BridgePlugin). This hint is required because "bridge" itself is not a plugin type. | |||||
| const unsigned int PLUGIN_IS_SYNTH = 0x02; //!< Plugin is a synthesizer (produces sound). | |||||
| const unsigned int PLUGIN_HAS_GUI = 0x04; //!< Plugin has its own custom GUI. | |||||
| const unsigned int PLUGIN_USES_CHUNKS = 0x08; //!< Plugin uses chunks to save internal data.\see CarlaPlugin::chunkData() | |||||
| const unsigned int PLUGIN_CAN_DRYWET = 0x10; //!< Plugin can make use of Dry/Wet controls. | |||||
| const unsigned int PLUGIN_CAN_VOLUME = 0x20; //!< Plugin can make use of Volume controls. | |||||
| const unsigned int PLUGIN_CAN_BALANCE = 0x40; //!< Plugin can make use of Left & Right Balance controls. | |||||
| const unsigned int PLUGIN_IS_BRIDGE = 0x01; //!< Plugin is a bridge (ie, BridgePlugin). This hint is required because "bridge" itself is not a plugin type. | |||||
| const unsigned int PLUGIN_IS_SYNTH = 0x02; //!< Plugin is a synthesizer (produces sound). | |||||
| const unsigned int PLUGIN_HAS_GUI = 0x04; //!< Plugin has its own custom GUI. | |||||
| const unsigned int PLUGIN_USES_CHUNKS = 0x08; //!< Plugin uses chunks to save internal data.\see CarlaPlugin::chunkData() | |||||
| const unsigned int PLUGIN_USES_SINGLE_THREAD = 0x10; //!< Plugin has its own custom GUI. | |||||
| const unsigned int PLUGIN_CAN_DRYWET = 0x20; //!< Plugin can make use of Dry/Wet controls. | |||||
| const unsigned int PLUGIN_CAN_VOLUME = 0x40; //!< Plugin can make use of Volume controls. | |||||
| const unsigned int PLUGIN_CAN_BALANCE = 0x80; //!< Plugin can make use of Left & Right Balance controls. | |||||
| /**@}*/ | /**@}*/ | ||||
| /*! | /*! | ||||
| @@ -187,6 +187,7 @@ public: | |||||
| short getNewPluginId() const; | short getNewPluginId() const; | ||||
| CarlaPlugin* getPlugin(const unsigned short id) const; | CarlaPlugin* getPlugin(const unsigned short id) const; | ||||
| CarlaPlugin* getPluginUnchecked(const unsigned short id) const { return m_carlaPlugins[id]; } | |||||
| const char* getUniqueName(const char* const name); | const char* getUniqueName(const char* const name); | ||||
| short addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr); | short addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr); | ||||
| @@ -202,11 +203,6 @@ public: | |||||
| m_carlaPlugins[id] = plugin; | m_carlaPlugins[id] = plugin; | ||||
| } | } | ||||
| CarlaPlugin* __getPlugin(const unsigned short id) const | |||||
| { | |||||
| return m_carlaPlugins[id]; | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Information (base) | // Information (base) | ||||
| @@ -317,7 +317,7 @@ void CarlaEngineJack::handleProcessCallback(uint32_t nframes) | |||||
| { | { | ||||
| for (unsigned short i=0; i < MAX_PLUGINS; i++) | for (unsigned short i=0; i < MAX_PLUGINS; i++) | ||||
| { | { | ||||
| CarlaPlugin* const plugin = __getPlugin(i); | |||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | if (plugin && plugin->enabled()) | ||||
| { | { | ||||
| @@ -451,7 +451,7 @@ void CarlaEngineJack::handleProcessCallback(uint32_t nframes) | |||||
| // process plugins | // process plugins | ||||
| for (unsigned short i=0; i < MAX_PLUGINS; i++) | for (unsigned short i=0; i < MAX_PLUGINS; i++) | ||||
| { | { | ||||
| CarlaPlugin* const plugin = __getPlugin(i); | |||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | if (plugin && plugin->enabled()) | ||||
| { | { | ||||
| @@ -207,7 +207,7 @@ void CarlaEngineRtAudio::handleProcessCallback(void* outputBuffer, void* inputBu | |||||
| // process plugins | // process plugins | ||||
| for (unsigned short i=0; i < MAX_PLUGINS; i++) | for (unsigned short i=0; i < MAX_PLUGINS; i++) | ||||
| { | { | ||||
| CarlaPlugin* const plugin = __getPlugin(i); | |||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | if (plugin && plugin->enabled()) | ||||
| { | { | ||||
| @@ -265,7 +265,7 @@ int CarlaOsc::handle_register(const int argc, const lo_arg* const* const argv, c | |||||
| for (unsigned short i=0; i < CarlaBackend::MAX_PLUGINS; i++) | for (unsigned short i=0; i < CarlaBackend::MAX_PLUGINS; i++) | ||||
| { | { | ||||
| CarlaBackend::CarlaPlugin* const plugin = engine->__getPlugin(i); | |||||
| CarlaBackend::CarlaPlugin* const plugin = engine->getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | if (plugin && plugin->enabled()) | ||||
| plugin->registerToOsc(); | plugin->registerToOsc(); | ||||
| @@ -503,6 +503,18 @@ public: | |||||
| return ¶m.ranges[parameterId]; | return ¶m.ranges[parameterId]; | ||||
| } | } | ||||
| /*! | |||||
| * Check if a parameter is out output type. | |||||
| * | |||||
| * \see PARAMETER_OUTPUT | |||||
| */ | |||||
| bool parameterIsOutput(uint32_t parameterId) const | |||||
| { | |||||
| Q_ASSERT(parameterId < param.count); | |||||
| return (param.data[parameterId].type == PARAMETER_OUTPUT); | |||||
| } | |||||
| /*! | /*! | ||||
| * Get the MIDI program at \a index. | * Get the MIDI program at \a index. | ||||
| * | * | ||||
| @@ -695,21 +707,17 @@ public: | |||||
| */ | */ | ||||
| void getParameterCountInfo(uint32_t* ins, uint32_t* outs, uint32_t* total) | void getParameterCountInfo(uint32_t* ins, uint32_t* outs, uint32_t* total) | ||||
| { | { | ||||
| uint32_t _ins = 0; | |||||
| uint32_t _outs = 0; | |||||
| uint32_t _total = param.count; | |||||
| *ins = 0; | |||||
| *outs = 0; | |||||
| *total = param.count; | |||||
| for (uint32_t i=0; i < param.count; i++) | for (uint32_t i=0; i < param.count; i++) | ||||
| { | { | ||||
| if (param.data[i].type == PARAMETER_INPUT) | if (param.data[i].type == PARAMETER_INPUT) | ||||
| _ins += 1; | |||||
| *ins += 1; | |||||
| else if (param.data[i].type == PARAMETER_OUTPUT) | else if (param.data[i].type == PARAMETER_OUTPUT) | ||||
| _outs += 1; | |||||
| *outs += 1; | |||||
| } | } | ||||
| *ins = _ins; | |||||
| *outs = _outs; | |||||
| *total = _total; | |||||
| } | } | ||||
| /*! | /*! | ||||
| @@ -1252,36 +1260,19 @@ public: | |||||
| */ | */ | ||||
| virtual void idleGui() | virtual void idleGui() | ||||
| { | { | ||||
| m_needsParamUpdate = false; | |||||
| m_needsProgUpdate = false; | |||||
| if (! m_enabled) | if (! m_enabled) | ||||
| return; | return; | ||||
| // ------------------------------------------------------- | |||||
| // Process postponed events | |||||
| postEventsRun(); | |||||
| // ------------------------------------------------------- | |||||
| // Update parameters (OSC) | |||||
| updateOscParameterOutputs(); | |||||
| // ------------------------------------------------------- | |||||
| // Send peak values (OSC) | |||||
| if (x_engine->isOscControllerRegisted()) | |||||
| if (m_hints & PLUGIN_USES_SINGLE_THREAD) | |||||
| { | { | ||||
| if (audioInCount() > 0) | |||||
| { | |||||
| x_engine->osc_send_set_input_peak_value(m_id, 1, x_engine->getInputPeak(m_id, 0)); | |||||
| x_engine->osc_send_set_input_peak_value(m_id, 2, x_engine->getInputPeak(m_id, 1)); | |||||
| } | |||||
| if (audioOutCount() > 0) | |||||
| // Process postponed events | |||||
| postEventsRun(); | |||||
| // Update parameter outputs | |||||
| for (uint32_t i=0; i < param.count; i++) | |||||
| { | { | ||||
| x_engine->osc_send_set_output_peak_value(m_id, 1, x_engine->getOutputPeak(m_id, 0)); | |||||
| x_engine->osc_send_set_output_peak_value(m_id, 2, x_engine->getOutputPeak(m_id, 1)); | |||||
| if (param.data[i].type == PARAMETER_OUTPUT) | |||||
| uiParameterChange(i, getParameterValue(i)); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1550,34 +1541,6 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| /*! | |||||
| * TODO | |||||
| */ | |||||
| void updateOscParameterOutputs() | |||||
| { | |||||
| // Check if it needs update | |||||
| bool updatePortsGui = (osc.data.target && (m_hints & PLUGIN_IS_BRIDGE) == 0); | |||||
| if (! (x_engine->isOscControllerRegisted() || updatePortsGui)) | |||||
| return; | |||||
| // Update | |||||
| double value; | |||||
| for (uint32_t i=0; i < param.count; i++) | |||||
| { | |||||
| if (param.data[i].type == PARAMETER_OUTPUT /*&& (paramData->hints & PARAMETER_IS_AUTOMABLE) > 0*/) | |||||
| { | |||||
| value = getParameterValue(i); | |||||
| if (updatePortsGui) | |||||
| osc_send_control(&osc.data, param.data[i].rindex, value); | |||||
| x_engine->osc_send_set_parameter_value(m_id, i, value); | |||||
| } | |||||
| } | |||||
| } | |||||
| /*! | /*! | ||||
| * Clear the plugin's internal OSC data. | * Clear the plugin's internal OSC data. | ||||
| */ | */ | ||||
| @@ -1744,16 +1707,15 @@ public: | |||||
| switch (event->type) | switch (event->type) | ||||
| { | { | ||||
| case PluginPostEventNull: | case PluginPostEventNull: | ||||
| return; | |||||
| break; | |||||
| case PluginPostEventDebug: | case PluginPostEventDebug: | ||||
| x_engine->callback(CALLBACK_DEBUG, m_id, event->value1, event->value2, event->value3); | x_engine->callback(CALLBACK_DEBUG, m_id, event->value1, event->value2, event->value3); | ||||
| break; | break; | ||||
| case PluginPostEventParameterChange: | case PluginPostEventParameterChange: | ||||
| // Update OSC based UIs | |||||
| m_needsParamUpdate = true; | |||||
| osc_send_control(&osc.data, event->value1, event->value3); | |||||
| // Update UI | |||||
| uiParameterChange(event->value1, event->value3); | |||||
| // Update OSC control client | // Update OSC control client | ||||
| x_engine->osc_send_set_parameter_value(m_id, event->value1, event->value3); | x_engine->osc_send_set_parameter_value(m_id, event->value1, event->value3); | ||||
| @@ -1763,9 +1725,8 @@ public: | |||||
| break; | break; | ||||
| case PluginPostEventProgramChange: | case PluginPostEventProgramChange: | ||||
| // Update OSC based UIs | |||||
| m_needsProgUpdate = true; | |||||
| osc_send_program(&osc.data, event->value1); | |||||
| // Update UI | |||||
| uiProgramChange(event->value1); | |||||
| // Update OSC control client | // Update OSC control client | ||||
| x_engine->osc_send_set_program(m_id, event->value1); | x_engine->osc_send_set_program(m_id, event->value1); | ||||
| @@ -1778,16 +1739,8 @@ public: | |||||
| break; | break; | ||||
| case PluginPostEventMidiProgramChange: | case PluginPostEventMidiProgramChange: | ||||
| // Update OSC based UIs | |||||
| m_needsProgUpdate = true; | |||||
| if (m_type == PLUGIN_DSSI) | |||||
| { | |||||
| if (event->value1 >= 0 && event->value1 < (int32_t)midiprog.count) | |||||
| osc_send_program(&osc.data, midiprog.data[event->value1].bank, midiprog.data[event->value1].program); | |||||
| } | |||||
| else | |||||
| osc_send_midi_program(&osc.data, event->value1); | |||||
| // Update UI | |||||
| uiMidiProgramChange(event->value1); | |||||
| // Update OSC control client | // Update OSC control client | ||||
| x_engine->osc_send_set_midi_program(m_id, event->value1); | x_engine->osc_send_set_midi_program(m_id, event->value1); | ||||
| @@ -1797,19 +1750,11 @@ public: | |||||
| // Update Host | // Update Host | ||||
| x_engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, m_id, event->value1, 0, 0.0); | x_engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, m_id, event->value1, 0, 0.0); | ||||
| //} | |||||
| break; | break; | ||||
| case PluginPostEventNoteOn: | case PluginPostEventNoteOn: | ||||
| // Update OSC based UIs | |||||
| if (osc.data.target) | |||||
| { | |||||
| uint8_t midiData[4] = { 0 }; | |||||
| midiData[1] = MIDI_STATUS_NOTE_ON + event->value1; | |||||
| midiData[2] = event->value2; | |||||
| midiData[3] = rint(event->value3); | |||||
| osc_send_midi(&osc.data, midiData); | |||||
| } | |||||
| // Update UI | |||||
| uiNoteOn(event->value1, event->value2, rint(event->value3)); | |||||
| // Update OSC control client | // Update OSC control client | ||||
| x_engine->osc_send_note_on(m_id, event->value1, event->value2, event->value3); | x_engine->osc_send_note_on(m_id, event->value1, event->value2, event->value3); | ||||
| @@ -1819,14 +1764,8 @@ public: | |||||
| break; | break; | ||||
| case PluginPostEventNoteOff: | case PluginPostEventNoteOff: | ||||
| // Update OSC based UIs | |||||
| if (osc.data.target) | |||||
| { | |||||
| uint8_t midiData[4] = { 0 }; | |||||
| midiData[1] = MIDI_STATUS_NOTE_OFF + event->value1; | |||||
| midiData[2] = event->value2; | |||||
| osc_send_midi(&osc.data, midiData); | |||||
| } | |||||
| // Update UI | |||||
| uiNoteOff(event->value1, event->value2); | |||||
| // Update OSC control client | // Update OSC control client | ||||
| x_engine->osc_send_note_off(m_id, event->value1, event->value2); | x_engine->osc_send_note_off(m_id, event->value1, event->value2); | ||||
| @@ -1838,6 +1777,53 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| /*! | |||||
| * TODO | |||||
| */ | |||||
| virtual void uiParameterChange(uint32_t index, double value) | |||||
| { | |||||
| Q_ASSERT(index < param.count); | |||||
| Q_UNUSED(index); | |||||
| Q_UNUSED(value); | |||||
| } | |||||
| /*! | |||||
| * TODO | |||||
| */ | |||||
| virtual void uiProgramChange(uint32_t index) | |||||
| { | |||||
| Q_ASSERT(index < prog.count); | |||||
| Q_UNUSED(index); | |||||
| } | |||||
| /*! | |||||
| * TODO | |||||
| */ | |||||
| virtual void uiMidiProgramChange(uint32_t index) | |||||
| { | |||||
| Q_ASSERT(index < midiprog.count); | |||||
| Q_UNUSED(index); | |||||
| } | |||||
| /*! | |||||
| * TODO | |||||
| */ | |||||
| virtual void uiNoteOn(uint8_t channel, uint8_t note, uint8_t velo) | |||||
| { | |||||
| Q_UNUSED(channel); | |||||
| Q_UNUSED(note); | |||||
| Q_UNUSED(velo); | |||||
| } | |||||
| /*! | |||||
| * TODO | |||||
| */ | |||||
| virtual void uiNoteOff(uint8_t channel, uint8_t note) | |||||
| { | |||||
| Q_UNUSED(channel); | |||||
| Q_UNUSED(note); | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Cleanup | // Cleanup | ||||
| @@ -2048,11 +2034,10 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| protected: | protected: | ||||
| // static | |||||
| unsigned short m_id; | unsigned short m_id; | ||||
| CarlaEngine* const x_engine; | CarlaEngine* const x_engine; | ||||
| CarlaEngineClient* x_client; | |||||
| // non-static | |||||
| PluginType m_type; | PluginType m_type; | ||||
| unsigned int m_hints; | unsigned int m_hints; | ||||
| @@ -2067,10 +2052,6 @@ protected: | |||||
| int8_t cin_channel; | int8_t cin_channel; | ||||
| double x_drywet, x_vol, x_bal_left, x_bal_right; | double x_drywet, x_vol, x_bal_left, x_bal_right; | ||||
| CarlaEngineClient* x_client; | |||||
| bool m_needsParamUpdate; | |||||
| bool m_needsProgUpdate; | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Storage Data | // Storage Data | ||||
| @@ -40,6 +40,9 @@ void CarlaCheckThread::stopNow() | |||||
| { | { | ||||
| m_stopNow = true; | m_stopNow = true; | ||||
| // TESTING - let processing finish first | |||||
| QMutexLocker(&this->mutex); // FIXME | |||||
| if (isRunning() && ! wait(200)) | if (isRunning() && ! wait(200)) | ||||
| { | { | ||||
| quit(); | quit(); | ||||
| @@ -53,32 +56,60 @@ void CarlaCheckThread::run() | |||||
| { | { | ||||
| qDebug("CarlaCheckThread::run()"); | qDebug("CarlaCheckThread::run()"); | ||||
| bool oscControllerRegisted, usesSingleThread; | |||||
| unsigned short id; | |||||
| double value; | |||||
| m_stopNow = false; | m_stopNow = false; | ||||
| while (engine->isRunning() && ! m_stopNow) | while (engine->isRunning() && ! m_stopNow) | ||||
| { | { | ||||
| QMutexLocker(&this->mutex); // FIXME | |||||
| oscControllerRegisted = engine->isOscControllerRegisted(); | |||||
| for (unsigned short i=0; i < CarlaBackend::MAX_PLUGINS; i++) | for (unsigned short i=0; i < CarlaBackend::MAX_PLUGINS; i++) | ||||
| { | { | ||||
| CarlaBackend::CarlaPlugin* const plugin = engine->__getPlugin(i); | |||||
| CarlaBackend::CarlaPlugin* const plugin = engine->getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | if (plugin && plugin->enabled()) | ||||
| { | { | ||||
| id = plugin->id(); | |||||
| usesSingleThread = (plugin->hints() & CarlaBackend::PLUGIN_USES_SINGLE_THREAD); | |||||
| // ------------------------------------------------------- | // ------------------------------------------------------- | ||||
| // Process postponed events | // Process postponed events | ||||
| plugin->postEventsRun(); | |||||
| if (! usesSingleThread) | |||||
| plugin->postEventsRun(); | |||||
| // ------------------------------------------------------- | // ------------------------------------------------------- | ||||
| // Update parameters (OSC) | |||||
| // Update parameter outputs | |||||
| plugin->updateOscParameterOutputs(); | |||||
| if (oscControllerRegisted || ! usesSingleThread) | |||||
| { | |||||
| for (uint32_t i=0; i < plugin->parameterCount(); i++) | |||||
| { | |||||
| if (plugin->parameterIsOutput(i)) | |||||
| { | |||||
| value = plugin->getParameterValue(i); | |||||
| // Update UI | |||||
| if (! usesSingleThread) | |||||
| plugin->uiParameterChange(i, value); | |||||
| // Update OSC control client | |||||
| if (oscControllerRegisted) | |||||
| engine->osc_send_set_parameter_value(id, i, value); | |||||
| } | |||||
| } | |||||
| } | |||||
| // ------------------------------------------------------- | // ------------------------------------------------------- | ||||
| // Send peak values (OSC) | |||||
| // Update OSC control client | |||||
| if (engine->isOscControllerRegisted()) | |||||
| if (oscControllerRegisted) | |||||
| { | { | ||||
| const unsigned short id = plugin->id(); | |||||
| // Peak values | |||||
| if (plugin->audioInCount() > 0) | if (plugin->audioInCount() > 0) | ||||
| { | { | ||||
| engine->osc_send_set_input_peak_value(id, 1, engine->getInputPeak(id, 0)); | engine->osc_send_set_input_peak_value(id, 1, engine->getInputPeak(id, 0)); | ||||
| @@ -146,7 +177,7 @@ void CarlaPluginThread::run() | |||||
| { | { | ||||
| qDebug("CarlaPluginThread::run()"); | qDebug("CarlaPluginThread::run()"); | ||||
| if (m_process == nullptr) | |||||
| if (! m_process) | |||||
| m_process = new QProcess(nullptr); | m_process = new QProcess(nullptr); | ||||
| m_process->setProcessChannelMode(QProcess::ForwardedChannels); | m_process->setProcessChannelMode(QProcess::ForwardedChannels); | ||||
| @@ -156,21 +187,21 @@ void CarlaPluginThread::run() | |||||
| switch (mode) | switch (mode) | ||||
| { | { | ||||
| case PLUGIN_THREAD_DSSI_GUI: | case PLUGIN_THREAD_DSSI_GUI: | ||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id()); | |||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id()); | |||||
| /* filename */ arguments << plugin->filename(); | /* filename */ arguments << plugin->filename(); | ||||
| /* label */ arguments << m_label; | /* label */ arguments << m_label; | ||||
| /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name()); | /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name()); | ||||
| break; | break; | ||||
| case PLUGIN_THREAD_LV2_GUI: | case PLUGIN_THREAD_LV2_GUI: | ||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id()); | |||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id()); | |||||
| /* URI */ arguments << m_label; | /* URI */ arguments << m_label; | ||||
| /* ui-URI */ arguments << m_data1; | /* ui-URI */ arguments << m_data1; | ||||
| /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name()); | /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name()); | ||||
| break; | break; | ||||
| case PLUGIN_THREAD_VST_GUI: | case PLUGIN_THREAD_VST_GUI: | ||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id()); | |||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id()); | |||||
| /* filename */ arguments << plugin->filename(); | /* filename */ arguments << plugin->filename(); | ||||
| /* label */ arguments << m_label; | /* label */ arguments << m_label; | ||||
| /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name()); | /* ui-title */ arguments << QString("%1 (GUI)").arg(plugin->name()); | ||||
| @@ -183,7 +214,7 @@ void CarlaPluginThread::run() | |||||
| if (! name) | if (! name) | ||||
| name = "(none)"; | name = "(none)"; | ||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath()).arg(plugin->id()); | |||||
| /* osc_url */ arguments << QString("%1/%2").arg(engine->getOscServerPath(), plugin->id()); | |||||
| /* stype */ arguments << m_data1; | /* stype */ arguments << m_data1; | ||||
| /* filename */ arguments << plugin->filename(); | /* filename */ arguments << plugin->filename(); | ||||
| /* name */ arguments << name; | /* name */ arguments << name; | ||||
| @@ -20,6 +20,7 @@ | |||||
| #include "carla_backend.h" | #include "carla_backend.h" | ||||
| #include <QtCore/QMutex> | |||||
| #include <QtCore/QThread> | #include <QtCore/QThread> | ||||
| class QProcess; | class QProcess; | ||||
| @@ -35,11 +36,22 @@ public: | |||||
| void stopNow(); | void stopNow(); | ||||
| void lock() | |||||
| { | |||||
| mutex.lock(); | |||||
| } | |||||
| void unlock() | |||||
| { | |||||
| mutex.unlock(); | |||||
| } | |||||
| protected: | protected: | ||||
| void run(); | void run(); | ||||
| private: | private: | ||||
| CarlaBackend::CarlaEngine* const engine; | CarlaBackend::CarlaEngine* const engine; | ||||
| QMutex mutex; | |||||
| bool m_stopNow; | bool m_stopNow; | ||||
| }; | }; | ||||
| @@ -1325,6 +1325,54 @@ public: | |||||
| m_activeBefore = m_active; | m_activeBefore = m_active; | ||||
| } | } | ||||
| // ------------------------------------------------------------------- | |||||
| // Post-poned events | |||||
| void uiParameterChange(uint32_t index, double value) | |||||
| { | |||||
| Q_ASSERT(index < param.count); | |||||
| if (index >= param.count) | |||||
| return; | |||||
| if (! osc.data.target) | |||||
| return; | |||||
| osc_send_control(&osc.data, param.data[index].rindex, value); | |||||
| } | |||||
| void uiMidiProgramChange(uint32_t index) | |||||
| { | |||||
| Q_ASSERT(index < midiprog.count); | |||||
| if (index >= midiprog.count) | |||||
| return; | |||||
| if (! osc.data.target) | |||||
| return; | |||||
| osc_send_program(&osc.data, midiprog.data[index].bank, midiprog.data[index].program); | |||||
| } | |||||
| void uiNoteOn(uint8_t channel, uint8_t note, uint8_t velo) | |||||
| { | |||||
| if (! osc.data.target) | |||||
| return; | |||||
| uint8_t midiData[4] = { 0 }; | |||||
| midiData[1] = MIDI_STATUS_NOTE_ON + channel; | |||||
| midiData[2] = note; | |||||
| midiData[3] = velo; | |||||
| osc_send_midi(&osc.data, midiData); | |||||
| } | |||||
| void uiNoteOff(uint8_t channel, uint8_t note) | |||||
| { | |||||
| if (! osc.data.target) | |||||
| return; | |||||
| uint8_t midiData[4] = { 0 }; | |||||
| midiData[1] = MIDI_STATUS_NOTE_OFF + channel; | |||||
| midiData[2] = note; | |||||
| osc_send_midi(&osc.data, midiData); | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Cleanup | // Cleanup | ||||
| @@ -907,27 +907,11 @@ public: | |||||
| void idleGui() | void idleGui() | ||||
| { | { | ||||
| if (ui.handle && ui.descriptor && gui.type != GUI_EXTERNAL_OSC) | |||||
| { | |||||
| // Update output port values | |||||
| if (ui.descriptor->port_event) | |||||
| { | |||||
| float value; | |||||
| // Update external UI | |||||
| if (ui.handle && ui.descriptor && ui.widget && gui.type == GUI_EXTERNAL_LV2) | |||||
| LV2_EXTERNAL_UI_RUN((lv2_external_ui*)ui.widget); | |||||
| for (uint32_t i=0; i < param.count; i++) | |||||
| { | |||||
| if (param.data[i].type == PARAMETER_OUTPUT) | |||||
| { | |||||
| value = getParameterValue(i); | |||||
| ui.descriptor->port_event(ui.handle, param.data[i].rindex, sizeof(float), 0, &value); | |||||
| } | |||||
| } | |||||
| } | |||||
| // Update UI | |||||
| if (ui.widget && gui.type == GUI_EXTERNAL_LV2) | |||||
| LV2_EXTERNAL_UI_RUN((lv2_external_ui*)ui.widget); | |||||
| } | |||||
| CarlaPlugin::idleGui(); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -2300,6 +2284,51 @@ public: | |||||
| m_activeBefore = m_active; | m_activeBefore = m_active; | ||||
| } | } | ||||
| // ------------------------------------------------------------------- | |||||
| // Post-poned events | |||||
| void uiParameterChange(uint32_t index, double value) | |||||
| { | |||||
| Q_ASSERT(index < param.count); | |||||
| if (index >= param.count) | |||||
| return; | |||||
| if (osc.data.target) | |||||
| osc_send_control(&osc.data, param.data[index].rindex, value); | |||||
| else if (ui.handle && ui.descriptor && ui.descriptor->port_event) | |||||
| { | |||||
| float valuef = value; | |||||
| ui.descriptor->port_event(ui.handle, param.data[index].rindex, sizeof(float), 0, &valuef); | |||||
| } | |||||
| } | |||||
| void uiMidiProgramChange(uint32_t index) | |||||
| { | |||||
| Q_ASSERT(index < midiprog.count); | |||||
| if (index >= midiprog.count) | |||||
| return; | |||||
| if (osc.data.target) | |||||
| osc_send_program(&osc.data, midiprog.data[index].bank, midiprog.data[index].program); | |||||
| else if (ext.uiprograms) | |||||
| ext.uiprograms->select_program(ui.handle, midiprog.data[index].bank, midiprog.data[index].program); | |||||
| } | |||||
| void uiNoteOn(uint8_t channel, uint8_t note, uint8_t velo) | |||||
| { | |||||
| // TODO | |||||
| Q_UNUSED(channel); | |||||
| Q_UNUSED(note); | |||||
| Q_UNUSED(velo); | |||||
| } | |||||
| void uiNoteOff(uint8_t channel, uint8_t note) | |||||
| { | |||||
| // TODO | |||||
| Q_UNUSED(channel); | |||||
| Q_UNUSED(note); | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Cleanup | // Cleanup | ||||
| @@ -3662,6 +3691,7 @@ public: | |||||
| gui.type = GUI_INTERNAL_QT4; | gui.type = GUI_INTERNAL_QT4; | ||||
| gui.resizable = isUiResizable(); | gui.resizable = isUiResizable(); | ||||
| ui.handle = ui.descriptor->instantiate(ui.descriptor, descriptor->URI, ui.rdf_descriptor->Bundle, carla_lv2_ui_write_function, this, &ui.widget, features); | ui.handle = ui.descriptor->instantiate(ui.descriptor, descriptor->URI, ui.rdf_descriptor->Bundle, carla_lv2_ui_write_function, this, &ui.widget, features); | ||||
| m_hints |= PLUGIN_USES_SINGLE_THREAD; | |||||
| updateUi(); | updateUi(); | ||||
| break; | break; | ||||
| @@ -3689,6 +3719,7 @@ public: | |||||
| gui.type = GUI_EXTERNAL_SUIL; | gui.type = GUI_EXTERNAL_SUIL; | ||||
| gui.resizable = isUiResizable(); | gui.resizable = isUiResizable(); | ||||
| suil.handle = suil_instance_new(suil.host, this, LV2_UI__Qt4UI, rdf_descriptor->URI, ui.rdf_descriptor->URI, get_lv2_ui_uri(ui.rdf_descriptor->Type), ui.rdf_descriptor->Bundle, ui.rdf_descriptor->Binary, features); | suil.handle = suil_instance_new(suil.host, this, LV2_UI__Qt4UI, rdf_descriptor->URI, ui.rdf_descriptor->URI, get_lv2_ui_uri(ui.rdf_descriptor->Type), ui.rdf_descriptor->Bundle, ui.rdf_descriptor->Binary, features); | ||||
| m_hints |= PLUGIN_USES_SINGLE_THREAD; | |||||
| if (suil.handle) | if (suil.handle) | ||||
| { | { | ||||
| @@ -312,6 +312,8 @@ public: | |||||
| // FIXME | // FIXME | ||||
| if (gui.visible) | if (gui.visible) | ||||
| effect->dispatcher(effect, effEditIdle, 0, 0, nullptr, 0.0f); | effect->dispatcher(effect, effEditIdle, 0, 0, nullptr, 0.0f); | ||||
| CarlaPlugin::idleGui(); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -171,7 +171,7 @@ private: | |||||
| : d1(0), d2(0), d3(0) {} | : d1(0), d2(0), d3(0) {} | ||||
| }; | }; | ||||
| static const unsigned short MAX_SIZE = 128; | |||||
| static const unsigned short MAX_SIZE = 512; | |||||
| datatype data[MAX_SIZE]; | datatype data[MAX_SIZE]; | ||||
| unsigned short index; | unsigned short index; | ||||
| bool empty, full; | bool empty, full; | ||||
| @@ -53,13 +53,14 @@ MAX_PLUGINS = 99 | |||||
| MAX_PARAMETERS = 200 | MAX_PARAMETERS = 200 | ||||
| # plugin hints | # plugin hints | ||||
| PLUGIN_IS_BRIDGE = 0x01 | |||||
| PLUGIN_IS_SYNTH = 0x02 | |||||
| PLUGIN_HAS_GUI = 0x04 | |||||
| PLUGIN_USES_CHUNKS = 0x08 | |||||
| PLUGIN_CAN_DRYWET = 0x10 | |||||
| PLUGIN_CAN_VOLUME = 0x20 | |||||
| PLUGIN_CAN_BALANCE = 0x40 | |||||
| PLUGIN_IS_BRIDGE = 0x01 | |||||
| PLUGIN_IS_SYNTH = 0x02 | |||||
| PLUGIN_HAS_GUI = 0x04 | |||||
| PLUGIN_USES_CHUNKS = 0x08 | |||||
| PLUGIN_USES_SINGLE_THREAD = 0x10 | |||||
| PLUGIN_CAN_DRYWET = 0x20 | |||||
| PLUGIN_CAN_VOLUME = 0x40 | |||||
| PLUGIN_CAN_BALANCE = 0x80 | |||||
| # parameter hints | # parameter hints | ||||
| PARAMETER_IS_BOOLEAN = 0x01 | PARAMETER_IS_BOOLEAN = 0x01 | ||||