|  | @@ -21,20 +21,57 @@ | 
														
													
														
															
																|  |  | #include "carla_plugin.h" |  |  | #include "carla_plugin.h" | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | #include <QtCore/QFile> |  |  | #include <QtCore/QFile> | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | #ifndef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | #include <QtCore/QTimerEvent> |  |  | #include <QtCore/QTimerEvent> | 
														
													
														
															
																|  |  | #include <QtGui/QApplication> |  |  | #include <QtGui/QApplication> | 
														
													
														
															
																|  |  | #include <QtGui/QDialog> |  |  | #include <QtGui/QDialog> | 
														
													
														
															
																|  |  |  |  |  | #include <QtGui/QVBoxLayout> | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | #ifdef Q_OS_UNIX | 
														
													
														
															
																|  |  |  |  |  | #include <signal.h> | 
														
													
														
															
																|  |  | #endif |  |  | #endif | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | static HINSTANCE hInstGlobal = nullptr; |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | static int qargc = 0; |  |  |  | 
														
													
														
															
																|  |  | static char* qargv[] = { nullptr }; |  |  |  | 
														
													
														
															
																|  |  |  |  |  | static int    qargc = 0; | 
														
													
														
															
																|  |  |  |  |  | static char** qargv = nullptr; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | bool qcloseNow = false; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | #if defined(Q_OS_UNIX) | 
														
													
														
															
																|  |  |  |  |  | void closeSignalHandler(int) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qcloseNow = true; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | #elif defined(Q_OS_WIN) | 
														
													
														
															
																|  |  |  |  |  | BOOL WINAPI closeSignalHandler(DWORD dwCtrlType) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | if (dwCtrlType == CTRL_C_EVENT) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qcloseNow = true; | 
														
													
														
															
																|  |  |  |  |  | return TRUE; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | return FALSE; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | #endif |  |  | #endif | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | void initSignalHandler() | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | #if defined(Q_OS_UNIX) | 
														
													
														
															
																|  |  |  |  |  | struct sigaction sint, sterm; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | sint.sa_handler = closeSignalHandler; | 
														
													
														
															
																|  |  |  |  |  | sigemptyset(&sint.sa_mask); | 
														
													
														
															
																|  |  |  |  |  | sint.sa_flags |= SA_RESTART; | 
														
													
														
															
																|  |  |  |  |  | sigaction(SIGINT, &sint, 0); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | sterm.sa_handler = closeSignalHandler; | 
														
													
														
															
																|  |  |  |  |  | sigemptyset(&sterm.sa_mask); | 
														
													
														
															
																|  |  |  |  |  | sterm.sa_flags |= SA_RESTART; | 
														
													
														
															
																|  |  |  |  |  | sigaction(SIGTERM, &sterm, 0); | 
														
													
														
															
																|  |  |  |  |  | #elif defined(Q_OS_WIN) | 
														
													
														
															
																|  |  |  |  |  | SetConsoleCtrlHandler(closeSignalHandler, TRUE); | 
														
													
														
															
																|  |  |  |  |  | #endif | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  | CARLA_BRIDGE_START_NAMESPACE |  |  | CARLA_BRIDGE_START_NAMESPACE | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | // ------------------------------------------------------------------------- |  |  | // ------------------------------------------------------------------------- | 
														
													
												
													
														
															
																|  | @@ -65,6 +102,7 @@ public: | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void setParameter(const int32_t rindex, const double value) |  |  | void setParameter(const int32_t rindex, const double value) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qDebug("CarlaPluginClient::setParameter(%i, %g)", rindex, value); | 
														
													
														
															
																|  |  | Q_ASSERT(plugin); |  |  | Q_ASSERT(plugin); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (! plugin) |  |  | if (! plugin) | 
														
													
												
													
														
															
																|  | @@ -75,6 +113,7 @@ public: | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void setProgram(const uint32_t index) |  |  | void setProgram(const uint32_t index) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qDebug("CarlaPluginClient::setProgram(%i)", index); | 
														
													
														
															
																|  |  | Q_ASSERT(plugin && index < plugin->programCount()); |  |  | Q_ASSERT(plugin && index < plugin->programCount()); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (! plugin) |  |  | if (! plugin) | 
														
													
												
													
														
															
																|  | @@ -87,6 +126,7 @@ public: | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void setMidiProgram(const uint32_t bank, const uint32_t program) |  |  | void setMidiProgram(const uint32_t bank, const uint32_t program) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qDebug("CarlaPluginClient::setMidiProgram(%i, %i)", bank, program); | 
														
													
														
															
																|  |  | Q_ASSERT(plugin); |  |  | Q_ASSERT(plugin); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (! plugin) |  |  | if (! plugin) | 
														
													
												
													
														
															
																|  | @@ -97,6 +137,7 @@ public: | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) |  |  | void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qDebug("CarlaPluginClient::noteOn(%i, %i, %i)", channel, note, velo); | 
														
													
														
															
																|  |  | Q_ASSERT(plugin); |  |  | Q_ASSERT(plugin); | 
														
													
														
															
																|  |  | Q_ASSERT(velo > 0); |  |  | Q_ASSERT(velo > 0); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
												
													
														
															
																|  | @@ -108,6 +149,7 @@ public: | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void noteOff(const uint8_t channel, const uint8_t note) |  |  | void noteOff(const uint8_t channel, const uint8_t note) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qDebug("CarlaPluginClient::noteOn(%i, %i)", channel, note); | 
														
													
														
															
																|  |  | Q_ASSERT(plugin); |  |  | Q_ASSERT(plugin); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (! plugin) |  |  | if (! plugin) | 
														
													
												
													
														
															
																|  | @@ -203,21 +245,35 @@ public: | 
														
													
														
															
																|  |  | //plugin->showGui(true); |  |  | //plugin->showGui(true); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | void showGui(const bool yesNo) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qDebug("CarlaPluginClient::showGui(%s)", bool2str(yesNo)); | 
														
													
														
															
																|  |  |  |  |  | Q_ASSERT(plugin); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | if (! plugin) | 
														
													
														
															
																|  |  |  |  |  | return; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | plugin->showGui(yesNo); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  | // --------------------------------------------------------------------- |  |  | // --------------------------------------------------------------------- | 
														
													
														
															
																|  |  | // callback |  |  | // callback | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void handleCallback(const CarlaBackend::CallbackType action, const int value1, const int value2, const double value3) |  |  | void handleCallback(const CarlaBackend::CallbackType action, const int value1, const int value2, const double value3) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qDebug("CarlaPluginClient::handleCallback(%s, %i, %i, %g)", CarlaBackend::CallbackType2str(action), value1, value2, value3); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | // FIXME - those OSC calls should be on the engine | 
														
													
														
															
																|  |  | switch (action) |  |  | switch (action) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | case CarlaBackend::CALLBACK_PARAMETER_VALUE_CHANGED: |  |  | case CarlaBackend::CALLBACK_PARAMETER_VALUE_CHANGED: | 
														
													
														
															
																|  |  | //osc_send_control(value1, value3); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | engine->osc_send_bridge_set_parameter_value(value1, value3); | 
														
													
														
															
																|  |  | break; |  |  | break; | 
														
													
														
															
																|  |  | case CarlaBackend::CALLBACK_PROGRAM_CHANGED: |  |  | case CarlaBackend::CALLBACK_PROGRAM_CHANGED: | 
														
													
														
															
																|  |  | //osc_send_program(value1); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | engine->osc_send_bridge_set_program(value1); | 
														
													
														
															
																|  |  | break; |  |  | break; | 
														
													
														
															
																|  |  | case CarlaBackend::CALLBACK_MIDI_PROGRAM_CHANGED: |  |  | case CarlaBackend::CALLBACK_MIDI_PROGRAM_CHANGED: | 
														
													
														
															
																|  |  | //osc_send_midi_program(value1, value2, false); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | engine->osc_send_bridge_set_midi_program(value1); | 
														
													
														
															
																|  |  | break; |  |  | break; | 
														
													
														
															
																|  |  | case CarlaBackend::CALLBACK_NOTE_ON: |  |  | case CarlaBackend::CALLBACK_NOTE_ON: | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
												
													
														
															
																|  | @@ -283,7 +339,6 @@ private: | 
														
													
														
															
																|  |  | // ------------------------------------------------------------------------- |  |  | // ------------------------------------------------------------------------- | 
														
													
														
															
																|  |  | // toolkit |  |  | // toolkit | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | #ifndef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | class BridgeApplication : public QApplication |  |  | class BridgeApplication : public QApplication | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | public: |  |  | public: | 
														
													
												
													
														
															
																|  | @@ -305,6 +360,9 @@ public: | 
														
													
														
															
																|  |  | protected: |  |  | protected: | 
														
													
														
															
																|  |  | void timerEvent(QTimerEvent* const event) |  |  | void timerEvent(QTimerEvent* const event) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  |  |  |  | if (qcloseNow) | 
														
													
														
															
																|  |  |  |  |  | return quit(); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  | if (event->timerId() == msgTimer) |  |  | if (event->timerId() == msgTimer) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | if (m_client) |  |  | if (m_client) | 
														
													
												
													
														
															
																|  | @@ -323,7 +381,6 @@ private: | 
														
													
														
															
																|  |  | int msgTimer; |  |  | int msgTimer; | 
														
													
														
															
																|  |  | CarlaPluginClient* m_client; |  |  | CarlaPluginClient* m_client; | 
														
													
														
															
																|  |  | }; |  |  | }; | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | class CarlaToolkitPlugin : public CarlaToolkit |  |  | class CarlaToolkitPlugin : public CarlaToolkit | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
												
													
														
															
																|  | @@ -332,55 +389,28 @@ public: | 
														
													
														
															
																|  |  | : CarlaToolkit("carla-bridge-plugin") |  |  | : CarlaToolkit("carla-bridge-plugin") | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::CarlaToolkitPlugin()"); |  |  | qDebug("CarlaToolkitPlugin::CarlaToolkitPlugin()"); | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | closeNow = false; |  |  |  | 
														
													
														
															
																|  |  | hwnd = nullptr; |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | app = nullptr; |  |  | app = nullptr; | 
														
													
														
															
																|  |  | dialog = nullptr; |  |  | dialog = nullptr; | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | ~CarlaToolkitPlugin() |  |  | ~CarlaToolkitPlugin() | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::~CarlaToolkitPlugin()"); |  |  | qDebug("CarlaToolkitPlugin::~CarlaToolkitPlugin()"); | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(! closeNow); |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(! app); |  |  | Q_ASSERT(! app); | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void init() |  |  | void init() | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::init()"); |  |  | qDebug("CarlaToolkitPlugin::init()"); | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(! closeNow); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | WNDCLASSEXA wc; |  |  |  | 
														
													
														
															
																|  |  | wc.cbSize        = sizeof(WNDCLASSEXA); |  |  |  | 
														
													
														
															
																|  |  | wc.style         = 0; |  |  |  | 
														
													
														
															
																|  |  | wc.lpfnWndProc   = windowProcA; |  |  |  | 
														
													
														
															
																|  |  | wc.cbClsExtra    = 0; |  |  |  | 
														
													
														
															
																|  |  | wc.cbWndExtra    = 0; |  |  |  | 
														
													
														
															
																|  |  | wc.hInstance     = hInstGlobal; |  |  |  | 
														
													
														
															
																|  |  | wc.hIcon         = LoadIconA(nullptr, IDI_APPLICATION); |  |  |  | 
														
													
														
															
																|  |  | wc.hCursor       = LoadCursorA(nullptr, IDC_ARROW); |  |  |  | 
														
													
														
															
																|  |  | wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND; |  |  |  | 
														
													
														
															
																|  |  | wc.lpszMenuName  = "MENU_CARLA_BRIDGE"; |  |  |  | 
														
													
														
															
																|  |  | wc.lpszClassName = "CLASS_CARLA_BRIDGE"; |  |  |  | 
														
													
														
															
																|  |  | wc.hIconSm       = nullptr; |  |  |  | 
														
													
														
															
																|  |  | RegisterClassExA(&wc); |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(! app); |  |  | Q_ASSERT(! app); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | app = new BridgeApplication; |  |  | app = new BridgeApplication; | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void exec(CarlaClient* const client, const bool showGui) |  |  | void exec(CarlaClient* const client, const bool showGui) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::exec(%p)", client); |  |  | qDebug("CarlaToolkitPlugin::exec(%p)", client); | 
														
													
														
															
																|  |  |  |  |  | Q_ASSERT(app); | 
														
													
														
															
																|  |  | Q_ASSERT(client); |  |  | Q_ASSERT(client); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | m_client = client; |  |  | m_client = client; | 
														
													
												
													
														
															
																|  | @@ -395,55 +425,12 @@ public: | 
														
													
														
															
																|  |  | m_client->sendOscBridgeUpdate(); |  |  | m_client->sendOscBridgeUpdate(); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(! closeNow); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | MSG msg; |  |  |  | 
														
													
														
															
																|  |  | CarlaPluginClient* const pluginClient = (CarlaPluginClient*)client; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | while (! closeNow) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | //pluginClient->runMessages(); |  |  |  | 
														
													
														
															
																|  |  | //pluginClient->idle(); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | //if (closeNow) |  |  |  | 
														
													
														
															
																|  |  | //    break; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | while (GetMessageA(&msg, hwnd, 0, 0) > 0) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | //if (PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE)) |  |  |  | 
														
													
														
															
																|  |  | //{ |  |  |  | 
														
													
														
															
																|  |  | //TranslateMessage(&msg); |  |  |  | 
														
													
														
															
																|  |  | DispatchMessageA(&msg); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | pluginClient->runMessages(); |  |  |  | 
														
													
														
															
																|  |  | pluginClient->idle(); |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | //if (closeNow) |  |  |  | 
														
													
														
															
																|  |  | //    break; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | //carla_msleep(50); |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(app); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | app->exec((CarlaPluginClient*)client); |  |  | app->exec((CarlaPluginClient*)client); | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void quit() |  |  | void quit() | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::quit()"); |  |  | qDebug("CarlaToolkitPlugin::quit()"); | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | if (closeNow && hwnd) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | DestroyWindow(hwnd); |  |  |  | 
														
													
														
															
																|  |  | hwnd = nullptr; |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | closeNow = true; |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(app); |  |  | Q_ASSERT(app); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (dialog) |  |  | if (dialog) | 
														
													
												
													
														
															
																|  | @@ -462,126 +449,66 @@ public: | 
														
													
														
															
																|  |  | delete app; |  |  | delete app; | 
														
													
														
															
																|  |  | app = nullptr; |  |  | app = nullptr; | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void show() |  |  | void show() | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::show()"); |  |  | qDebug("CarlaToolkitPlugin::show()"); | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(hwnd); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (hwnd) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | ShowWindow(hwnd, SW_SHOWNORMAL); |  |  |  | 
														
													
														
															
																|  |  | UpdateWindow(hwnd); |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(dialog); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if (m_client) | 
														
													
														
															
																|  |  |  |  |  | ((CarlaPluginClient*)m_client)->showGui(true); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (dialog) |  |  | if (dialog) | 
														
													
														
															
																|  |  | dialog->show(); |  |  | dialog->show(); | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void hide() |  |  | void hide() | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::hide()"); |  |  | qDebug("CarlaToolkitPlugin::hide()"); | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(hwnd); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (hwnd) |  |  |  | 
														
													
														
															
																|  |  | ShowWindow(hwnd, SW_HIDE); |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(dialog); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if (m_client) | 
														
													
														
															
																|  |  |  |  |  | ((CarlaPluginClient*)m_client)->showGui(false); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (dialog) |  |  | if (dialog) | 
														
													
														
															
																|  |  | dialog->show(); |  |  | dialog->show(); | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void resize(int width, int height) |  |  | void resize(int width, int height) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qDebug("CarlaToolkitPlugin::resize(%i, %i)", width, height); |  |  | qDebug("CarlaToolkitPlugin::resize(%i, %i)", width, height); | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(hwnd); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | if (hwnd) |  |  |  | 
														
													
														
															
																|  |  | SetWindowPos(hwnd, 0, 0, 0, width + 6, height + 25, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(dialog); |  |  | Q_ASSERT(dialog); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (dialog) |  |  | if (dialog) | 
														
													
														
															
																|  |  | dialog->setFixedSize(width, height); |  |  | dialog->setFixedSize(width, height); | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | // --------------------------------------------------------------------- |  |  | // --------------------------------------------------------------------- | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | void createWindow(const char* const pluginName) |  |  |  | 
														
													
														
															
																|  |  |  |  |  | void createWindow(const char* const pluginName, const bool createLayout) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | hwnd = CreateWindowA("CLASS_CARLA_BRIDGE", pluginName, WS_OVERLAPPEDWINDOW &~ WS_THICKFRAME &~ WS_MAXIMIZEBOX, |  |  |  | 
														
													
														
															
																|  |  | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, |  |  |  | 
														
													
														
															
																|  |  | HWND_DESKTOP, nullptr, hInstGlobal, nullptr); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)this); |  |  |  | 
														
													
														
															
																|  |  | SetWindowPos(hwnd, 0, 0, 0, 1100 + 6, 600 + 25, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | dialog = new QDialog(nullptr); |  |  | dialog = new QDialog(nullptr); | 
														
													
														
															
																|  |  | dialog->resize(10, 10); |  |  | dialog->resize(10, 10); | 
														
													
														
															
																|  |  | //window->setLayout(new QVBoxLayout(dialog); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | if (createLayout) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | QVBoxLayout* const layout = new QVBoxLayout(dialog); | 
														
													
														
															
																|  |  |  |  |  | dialog->setContentsMargins(0, 0, 0, 0); | 
														
													
														
															
																|  |  |  |  |  | dialog->setLayout(layout); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  | dialog->setWindowTitle(QString("%1 (GUI)").arg(pluginName)); |  |  | dialog->setWindowTitle(QString("%1 (GUI)").arg(pluginName)); | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | CarlaBackend::GuiDataHandle getWindowHandle() const |  |  | CarlaBackend::GuiDataHandle getWindowHandle() const | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | return hwnd; |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | return dialog; |  |  | return dialog; | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | // --------------------------------------------------------------------- |  |  | // --------------------------------------------------------------------- | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | private: |  |  | private: | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | bool closeNow; |  |  |  | 
														
													
														
															
																|  |  | HWND hwnd; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | void handleWindowCloseMessageA() |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | //m_client->quequeMessage(MESSAGE_QUIT, 0, 0, 0.0); |  |  |  | 
														
													
														
															
																|  |  | //m_client->quequeMessage(MESSAGE_SHOW_GUI, 0, 0, 0.0); |  |  |  | 
														
													
														
															
																|  |  | closeNow = true; |  |  |  | 
														
													
														
															
																|  |  | m_client->sendOscConfigure(CarlaBackend::CARLA_BRIDGE_MSG_HIDE_GUI, ""); |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | static LRESULT CALLBACK windowProcA(HWND _hwnd, UINT message, WPARAM wParam, LPARAM lParam) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | qDebug("windowProcA(%p, %i, %li, %li)", _hwnd, message, wParam, lParam); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | if (message == WM_CLOSE || message == WM_DESTROY) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | CarlaToolkitPlugin* const toolkit = (CarlaToolkitPlugin*)GetWindowLongPtrA(_hwnd, GWLP_USERDATA); |  |  |  | 
														
													
														
															
																|  |  | Q_ASSERT(toolkit); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | if (toolkit) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | toolkit->handleWindowCloseMessageA(); |  |  |  | 
														
													
														
															
																|  |  | return TRUE; |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | return DefWindowProcA(_hwnd, message, wParam, lParam); |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | BridgeApplication* app; |  |  | BridgeApplication* app; | 
														
													
														
															
																|  |  | QDialog* dialog; |  |  | QDialog* dialog; | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | }; |  |  | }; | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | CarlaToolkit* CarlaToolkit::createNew(const char* const) |  |  | CarlaToolkit* CarlaToolkit::createNew(const char* const) | 
														
													
												
													
														
															
																|  | @@ -593,72 +520,17 @@ CarlaToolkit* CarlaToolkit::createNew(const char* const) | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | CARLA_BRIDGE_END_NAMESPACE |  |  | CARLA_BRIDGE_END_NAMESPACE | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | #ifdef __WINE__ |  |  |  | 
														
													
														
															
																|  |  | int WINAPI WinMain(HINSTANCE hInstX, HINSTANCE, LPSTR, int) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | hInstGlobal = hInstX; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | #define MAXCMDTOKENS 128 |  |  |  | 
														
													
														
															
																|  |  | int argc; |  |  |  | 
														
													
														
															
																|  |  | LPSTR argv[MAXCMDTOKENS]; |  |  |  | 
														
													
														
															
																|  |  | LPSTR p = GetCommandLine(); |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | char command[256]; |  |  |  | 
														
													
														
															
																|  |  | char *args; |  |  |  | 
														
													
														
															
																|  |  | char *d, *e; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | argc = 0; |  |  |  | 
														
													
														
															
																|  |  | args = (char *)malloc(lstrlen(p)+1); |  |  |  | 
														
													
														
															
																|  |  | if (args == (char *)NULL) { |  |  |  | 
														
													
														
															
																|  |  | qCritical("Insufficient memory in WinMain()"); |  |  |  | 
														
													
														
															
																|  |  | return 1; |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | // Parse command line handling quotes. |  |  |  | 
														
													
														
															
																|  |  | d = args; |  |  |  | 
														
													
														
															
																|  |  | while (*p) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | // for each argument |  |  |  | 
														
													
														
															
																|  |  | if (argc >= MAXCMDTOKENS - 1) |  |  |  | 
														
													
														
															
																|  |  | break; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | e = d; |  |  |  | 
														
													
														
															
																|  |  | while ((*p) && (*p != ' ')) { |  |  |  | 
														
													
														
															
																|  |  | if (*p == '\042') { |  |  |  | 
														
													
														
															
																|  |  | // Remove quotes, skipping over embedded spaces. |  |  |  | 
														
													
														
															
																|  |  | // Doesn't handle embedded quotes. |  |  |  | 
														
													
														
															
																|  |  | p++; |  |  |  | 
														
													
														
															
																|  |  | while ((*p) && (*p != '\042')) |  |  |  | 
														
													
														
															
																|  |  | *d++ =*p++; |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | else |  |  |  | 
														
													
														
															
																|  |  | *d++ = *p; |  |  |  | 
														
													
														
															
																|  |  | if (*p) |  |  |  | 
														
													
														
															
																|  |  | p++; |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | *d++ = '\0'; |  |  |  | 
														
													
														
															
																|  |  | argv[argc++] = e; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | while ((*p) && (*p == ' ')) |  |  |  | 
														
													
														
															
																|  |  | p++;        // Skip over trailing spaces |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | argv[argc] = 0; |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | if (strlen(argv[0]) == 0) |  |  |  | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | GetModuleFileName(hInstGlobal, command, sizeof(command)-1); |  |  |  | 
														
													
														
															
																|  |  | argv[0] = command; |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | #else |  |  |  | 
														
													
														
															
																|  |  | int main(int argc, char* argv[]) |  |  | int main(int argc, char* argv[]) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | #endif |  |  |  | 
														
													
														
															
																|  |  | if (argc != 6) |  |  | if (argc != 6) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | qWarning("usage: %s <osc-url|\"null\"> <type> <filename> <name|\"(none)\"> <label>", argv[0]); |  |  | qWarning("usage: %s <osc-url|\"null\"> <type> <filename> <name|\"(none)\"> <label>", argv[0]); | 
														
													
														
															
																|  |  | return 1; |  |  | return 1; | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | qargc = argc; | 
														
													
														
															
																|  |  |  |  |  | qargv = argv; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  | const char* const oscUrl   = argv[1]; |  |  | const char* const oscUrl   = argv[1]; | 
														
													
														
															
																|  |  | const char* const stype    = argv[2]; |  |  | const char* const stype    = argv[2]; | 
														
													
														
															
																|  |  | const char* const filename = argv[3]; |  |  | const char* const filename = argv[3]; | 
														
													
												
													
														
															
																|  | @@ -709,9 +581,16 @@ int main(int argc, char* argv[]) | 
														
													
														
															
																|  |  | client.registerOscEngine(&engine); |  |  | client.registerOscEngine(&engine); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | // Init engine |  |  | // Init engine | 
														
													
														
															
																|  |  | QString engName = QString("%1 (master)").arg(label); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | QString engName = QString("%1 (master)").arg(name ? name : label); | 
														
													
														
															
																|  |  | engName.truncate(engine.maxClientNameSize()); |  |  | engName.truncate(engine.maxClientNameSize()); | 
														
													
														
															
																|  |  | engine.init(engName.toUtf8().constData()); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | if (! engine.init(engName.toUtf8().constData())) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | qWarning("Bridge engine failed to start, error was:\n%s", CarlaBackend::getLastError()); | 
														
													
														
															
																|  |  |  |  |  | engine.close(); | 
														
													
														
															
																|  |  |  |  |  | toolkit.quit(); | 
														
													
														
															
																|  |  |  |  |  | return 2; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | /// Init plugin |  |  | /// Init plugin | 
														
													
														
															
																|  |  | short id = engine.addPlugin(itype, filename, name, label); |  |  | short id = engine.addPlugin(itype, filename, name, label); | 
														
													
												
													
														
															
																|  | @@ -722,17 +601,19 @@ int main(int argc, char* argv[]) | 
														
													
														
															
																|  |  | CarlaBackend::CarlaPlugin* const plugin = engine.getPlugin(id); |  |  | CarlaBackend::CarlaPlugin* const plugin = engine.getPlugin(id); | 
														
													
														
															
																|  |  | client.setStuff(&engine, plugin); |  |  | client.setStuff(&engine, plugin); | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | // create window if needed | 
														
													
														
															
																|  |  |  |  |  | bool guiResizable; | 
														
													
														
															
																|  |  |  |  |  | CarlaBackend::GuiType guiType; | 
														
													
														
															
																|  |  |  |  |  | plugin->getGuiInfo(&guiType, &guiResizable); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | if (guiType == CarlaBackend::GUI_INTERNAL_QT4 || guiType == CarlaBackend::GUI_INTERNAL_COCOA || guiType == CarlaBackend::GUI_INTERNAL_HWND || guiType == CarlaBackend::GUI_INTERNAL_X11) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
														
															
																|  |  | // create window if needed |  |  |  | 
														
													
														
															
																|  |  | toolkit.createWindow(plugin->name()); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | toolkit.createWindow(plugin->name(), (guiType == CarlaBackend::GUI_INTERNAL_QT4)); | 
														
													
														
															
																|  |  | plugin->setGuiData(toolkit.getWindowHandle()); |  |  | plugin->setGuiData(toolkit.getWindowHandle()); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (! useOsc) |  |  | if (! useOsc) | 
														
													
														
															
																|  |  | { |  |  |  | 
														
													
														
															
																|  |  | plugin->setActive(true, false, false); |  |  | plugin->setActive(true, false, false); | 
														
													
														
															
																|  |  | plugin->showGui(true); |  |  |  | 
														
													
														
															
																|  |  | } |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | ret = 0; |  |  | ret = 0; | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
												
													
														
															
																|  | @@ -743,7 +624,10 @@ int main(int argc, char* argv[]) | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (ret == 0) |  |  | if (ret == 0) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | initSignalHandler(); | 
														
													
														
															
																|  |  | toolkit.exec(&client, !useOsc); |  |  | toolkit.exec(&client, !useOsc); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | engine.removeAllPlugins(); |  |  | engine.removeAllPlugins(); | 
														
													
														
															
																|  |  | engine.close(); |  |  | engine.close(); | 
														
													
												
													
														
															
																|  | 
 |