From 24d320de34bd6e948baaf404cb25ce51fa928067 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Mon, 28 Aug 2017 11:21:10 +0200 Subject: [PATCH 1/4] Fix some memory leaks (#3779) --- include/PluginFactory.h | 13 +++++++----- include/Song.h | 4 ++-- src/core/PluginFactory.cpp | 37 ++++++++++++++-------------------- src/core/Song.cpp | 24 +++++++++------------- src/gui/editors/SongEditor.cpp | 1 + 5 files changed, 35 insertions(+), 44 deletions(-) diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 209fa655d..b2d0131ad 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -25,6 +25,8 @@ #ifndef PLUGINFACTORY_H #define PLUGINFACTORY_H +#include + #include #include @@ -39,14 +41,15 @@ public: struct PluginInfo { PluginInfo() : library(nullptr), descriptor(nullptr) {} + const QString name() const; QFileInfo file; - QLibrary* library; + std::shared_ptr library; Plugin::Descriptor* descriptor; - bool isNull() const {return library == 0;} + bool isNull() const {return ! library;} }; - typedef QList PluginInfoList; + typedef QList PluginInfoList; typedef QMultiMap DescriptorMap; PluginFactory(); @@ -80,11 +83,11 @@ public slots: private: DescriptorMap m_descriptors; PluginInfoList m_pluginInfos; - QMap m_pluginByExt; + QMap m_pluginByExt; QHash m_errors; - static PluginFactory* s_instance; + static std::unique_ptr s_instance; }; #define pluginFactory PluginFactory::instance() diff --git a/include/Song.h b/include/Song.h index be7f9e508..b8879ad9b 100644 --- a/include/Song.h +++ b/include/Song.h @@ -67,7 +67,7 @@ public: void clearErrors(); void collectError( const QString error ); bool hasErrors(); - QString* errorSummary(); + QString errorSummary(); class PlayPos : public MidiTime { @@ -359,7 +359,7 @@ private: bool m_loadingProject; - QList * m_errors; + QStringList m_errors; PlayModes m_playMode; PlayPos m_playPos[Mode_Count]; diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index cfbca8a7c..936b33cdc 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -42,7 +42,7 @@ qint64 qHash(const QFileInfo& fi) return qHash(fi.absoluteFilePath()); } -PluginFactory* PluginFactory::s_instance = nullptr; +std::unique_ptr PluginFactory::s_instance; PluginFactory::PluginFactory() { @@ -87,9 +87,9 @@ PluginFactory::~PluginFactory() PluginFactory* PluginFactory::instance() { if (s_instance == nullptr) - s_instance = new PluginFactory(); + s_instance.reset(new PluginFactory()); - return s_instance; + return s_instance.get(); } const Plugin::DescriptorList PluginFactory::descriptors() const @@ -109,16 +109,15 @@ const PluginFactory::PluginInfoList& PluginFactory::pluginInfos() const const PluginFactory::PluginInfo PluginFactory::pluginSupportingExtension(const QString& ext) { - PluginInfo* info = m_pluginByExt.value(ext, nullptr); - return info == nullptr ? PluginInfo() : *info; + return m_pluginByExt.value(ext, PluginInfo()); } const PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const { - for (const PluginInfo* info : m_pluginInfos) + for (const PluginInfo& info : m_pluginInfos) { - if (qstrcmp(info->descriptor->name, name) == 0) - return *info; + if (qstrcmp(info.descriptor->name, name) == 0) + return info; } return PluginInfo(); } @@ -150,7 +149,7 @@ void PluginFactory::discoverPlugins() for (const QFileInfo& file : files) { - QLibrary* library = new QLibrary(file.absoluteFilePath()); + auto library = std::make_shared(file.absoluteFilePath()); if (! library->load()) { m_errors[file.baseName()] = library->errorString(); @@ -167,7 +166,7 @@ void PluginFactory::discoverPlugins() descriptorName = descriptorName.mid(3); } - Plugin::Descriptor* pluginDescriptor = (Plugin::Descriptor*) library->resolve(descriptorName.toUtf8().constData()); + Plugin::Descriptor* pluginDescriptor = reinterpret_cast(library->resolve(descriptorName.toUtf8().constData())); if(pluginDescriptor == nullptr) { qWarning() << qApp->translate("PluginFactory", "LMMS plugin %1 does not have a plugin descriptor named %2!"). @@ -175,26 +174,20 @@ void PluginFactory::discoverPlugins() continue; } - PluginInfo* info = new PluginInfo; - info->file = file; - info->library = library; - info->descriptor = pluginDescriptor; + PluginInfo info; + info.file = file; + info.library = library; + info.descriptor = pluginDescriptor; pluginInfos << info; - for (const QString& ext : QString(info->descriptor->supportedFileTypes).split(',')) + for (const QString& ext : QString(info.descriptor->supportedFileTypes).split(',')) { m_pluginByExt.insert(ext, info); } - descriptors.insert(info->descriptor->type, info->descriptor); + descriptors.insert(info.descriptor->type, info.descriptor); } - - for (PluginInfo* info : m_pluginInfos) - { - delete info->library; - delete info; - } m_pluginInfos = pluginInfos; m_descriptors = descriptors; } diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 75b5adff6..a576bbcbd 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -86,7 +86,6 @@ Song::Song() : m_playing( false ), m_paused( false ), m_loadingProject( false ), - m_errors( new QList() ), m_playMode( Mode_None ), m_length( 0 ), m_patternToPlay( NULL ), @@ -1138,12 +1137,12 @@ void Song::loadProject( const QString & fileName ) { if ( gui ) { - QMessageBox::warning( NULL, tr("LMMS Error report"), *errorSummary(), + QMessageBox::warning( NULL, tr("LMMS Error report"), errorSummary(), QMessageBox::Ok ); } else { - QTextStream(stderr) << *Engine::getSong()->errorSummary() << endl; + QTextStream(stderr) << Engine::getSong()->errorSummary() << endl; } } @@ -1515,36 +1514,31 @@ void Song::removeController( Controller * controller ) void Song::clearErrors() { - m_errors->clear(); + m_errors.clear(); } void Song::collectError( const QString error ) { - m_errors->append( error ); + m_errors.append( error ); } bool Song::hasErrors() { - return ( m_errors->length() > 0 ); + return ( m_errors.length() > 0 ); } -QString* Song::errorSummary() +QString Song::errorSummary() { - QString* errors = new QString(); + QString errors = m_errors.join("\n") + '\n'; - for ( int i = 0 ; i < m_errors->length() ; i++ ) - { - errors->append( m_errors->value( i ) + "\n" ); - } - - errors->prepend( "\n\n" ); - errors->prepend( tr( "The following errors occured while loading: " ) ); + errors.prepend( "\n\n" ); + errors.prepend( tr( "The following errors occured while loading: " ) ); return errors; } diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index cf561f179..5eb7ff6e2 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -82,6 +82,7 @@ SongEditor::SongEditor( Song * song ) : m_smoothScroll( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() ), m_mode(DrawMode) { + m_zoomingModel->setParent(this); // create time-line int widgetTotal = ConfigManager::inst()->value( "ui", "compacttrackbuttons" ).toInt()==1 ? From 9d7c34098ce230d89b56b7bd887ad08bcb45b20c Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Wed, 6 Sep 2017 17:57:24 +0900 Subject: [PATCH 2/4] Fix Vibed when the "P" parameter has non-zero value (#3789) --- plugins/vibed/vibrating_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/vibed/vibrating_string.h b/plugins/vibed/vibrating_string.h index 6d620ace0..c21ed43cf 100644 --- a/plugins/vibed/vibrating_string.h +++ b/plugins/vibed/vibrating_string.h @@ -130,7 +130,7 @@ private: offset = ( m_randomize / 2.0f - m_randomize ) * r; _dl->data[i] = _scale * - _values[_dl->length - i] + + _values[_dl->length - i - 1] + offset; } for( int i = _pick; i < _dl->length; i++ ) From fe98a9aa431c1e463d698ece014c60bb99693196 Mon Sep 17 00:00:00 2001 From: DomClark Date: Thu, 24 Aug 2017 22:09:38 +0100 Subject: [PATCH 3/4] Fix some VST deadlocks/hangs --- include/MainWindow.h | 8 ++ include/RemotePlugin.h | 8 ++ plugins/vst_base/RemoteVstPlugin.cpp | 199 ++++++++++++++++++++------- plugins/vst_base/VstPlugin.cpp | 20 +-- src/gui/MainWindow.cpp | 12 +- 5 files changed, 186 insertions(+), 61 deletions(-) diff --git a/include/MainWindow.h b/include/MainWindow.h index 69b430d33..1a58f868c 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "ConfigManager.h" #include "SubWindow.h" @@ -248,4 +249,11 @@ signals: } ; +class AutoSaveThread : public QThread +{ + Q_OBJECT +public: + void run(); +} ; + #endif diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index d016c5acd..725f51c2c 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -1072,6 +1072,14 @@ RemotePluginBase::message RemotePluginBase::waitForMessage( const message & _wm, bool _busy_waiting ) { +#ifndef BUILD_REMOTE_PLUGIN_CLIENT + if( _busy_waiting ) + { + // No point processing events outside of the main thread + _busy_waiting = QThread::currentThread() == + QCoreApplication::instance()->thread(); + } +#endif while( !isInvalid() ) { #ifndef BUILD_REMOTE_PLUGIN_CLIENT diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 03e160a8d..74af607c5 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -44,6 +44,10 @@ #ifdef LMMS_BUILD_LINUX +#ifndef NOMINMAX +#define NOMINMAX +#endif + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -67,6 +71,7 @@ #include +#include #include @@ -113,7 +118,7 @@ class RemoteVstPlugin; RemoteVstPlugin * __plugin = NULL; -DWORD __GuiThreadID = 0; +HWND __MessageHwnd = NULL; @@ -244,8 +249,38 @@ public: pthread_mutex_unlock( &m_pluginLock ); } + inline bool isProcessing() const + { + return m_processing; + } + + inline void setProcessing( bool processing ) + { + m_processing = processing; + } + + inline void queueMessage( const message & m ) { + m_messageList.push( m ); + } + + inline bool shouldGiveIdle() const + { + return m_shouldGiveIdle; + } + + inline void setShouldGiveIdle( bool shouldGiveIdle ) + { + m_shouldGiveIdle = shouldGiveIdle; + } + + void idle(); + void processUIThreadMessages(); + static DWORD WINAPI processingThread( LPVOID _param ); - static DWORD WINAPI guiEventLoop( LPVOID _param ); + static bool setupMessageWindow(); + static DWORD WINAPI guiEventLoop(); + static LRESULT CALLBACK messageWndProc( HWND hwnd, UINT uMsg, + WPARAM wParam, LPARAM lParam ); private: @@ -303,6 +338,10 @@ private: bool m_initialized; pthread_mutex_t m_pluginLock; + bool m_processing; + + std::queue m_messageList; + bool m_shouldGiveIdle; float * * m_inputs; @@ -348,6 +387,9 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : m_windowHeight( 0 ), m_initialized( false ), m_pluginLock(), + m_processing( false ), + m_messageList(), + m_shouldGiveIdle( false ), m_inputs( NULL ), m_outputs( NULL ), m_midiEvents(), @@ -1418,8 +1460,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, SHOW_CALLBACK ("amc: audioMasterIdle\n" ); // call application idle routine (this will // call effEditIdle for all open editors too) - PostThreadMessage( __GuiThreadID, - WM_USER, GiveIdle, 0 ); + PostMessage( __MessageHwnd, WM_USER, GiveIdle, 0 ); return 0; case audioMasterPinConnected: @@ -1720,8 +1761,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, case audioMasterUpdateDisplay: SHOW_CALLBACK( "amc: audioMasterUpdateDisplay\n" ); // something has changed, update 'multi-fx' display - PostThreadMessage( __GuiThreadID, - WM_USER, GiveIdle, 0 ); + PostMessage( __MessageHwnd, WM_USER, GiveIdle, 0 ); return 0; #if kVstVersion > 2 @@ -1754,6 +1794,43 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, +void RemoteVstPlugin::idle() +{ + if( isProcessing() ) + { + setShouldGiveIdle( true ); + return; + } + setProcessing( true ); + pluginDispatch( effEditIdle ); + setShouldGiveIdle( false ); + setProcessing( false ); + // We might have received a message whilst idling + processUIThreadMessages(); +} + + + + +void RemoteVstPlugin::processUIThreadMessages() +{ + setProcessing( true ); + while( m_messageList.size() ) + { + processMessage( m_messageList.front() ); + m_messageList.pop(); + if( shouldGiveIdle() ) + { + pluginDispatch( effEditIdle ); + setShouldGiveIdle( false ); + } + } + setProcessing( false ); +} + + + + DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) { RemoteVstPlugin * _this = static_cast( _param ); @@ -1767,7 +1844,7 @@ DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) } else { - PostThreadMessage( __GuiThreadID, + PostMessage( __MessageHwnd, WM_USER, ProcessPluginMessage, (LPARAM) new message( m ) ); @@ -1775,7 +1852,7 @@ DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) } // notify GUI thread about shutdown - PostThreadMessage( __GuiThreadID, WM_USER, ClosePlugin, 0 ); + PostMessage( __MessageHwnd, WM_USER, ClosePlugin, 0 ); return 0; } @@ -1783,61 +1860,37 @@ DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) -DWORD WINAPI RemoteVstPlugin::guiEventLoop( LPVOID _param ) +bool RemoteVstPlugin::setupMessageWindow() { - RemoteVstPlugin * _this = static_cast( _param ); - HMODULE hInst = GetModuleHandle( NULL ); if( hInst == NULL ) { - _this->debugMessage( "guiEventLoop(): can't get " + __plugin->debugMessage( "setupMessageWindow(): can't get " "module handle\n" ); - return -1; + return false; } - HWND timerWindow = CreateWindowEx( 0, "LVSL", "dummy", + __MessageHwnd = CreateWindowEx( 0, "LVSL", "dummy", 0, 0, 0, 0, 0, NULL, NULL, hInst, NULL ); + SetWindowLongPtr( __MessageHwnd, GWLP_WNDPROC, + reinterpret_cast( RemoteVstPlugin::messageWndProc ) ); // install GUI update timer - SetTimer( timerWindow, 1000, 50, NULL ); + SetTimer( __MessageHwnd, 1000, 50, NULL ); + return true; +} + + + + +DWORD WINAPI RemoteVstPlugin::guiEventLoop() +{ MSG msg; - - bool quit = false; - while( quit == false && GetMessage( &msg, NULL, 0, 0 ) ) + while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) { TranslateMessage( &msg ); DispatchMessage( &msg ); - - if( msg.message == WM_TIMER && _this->isInitialized() ) - { - // give plugin some idle-time for GUI-update - _this->pluginDispatch( effEditIdle ); - } - else if( msg.message == WM_USER ) - { - switch( msg.wParam ) - { - case ProcessPluginMessage: - { - message * m = (message *) msg.lParam; - _this->processMessage( *m ); - delete m; - break; - } - - case GiveIdle: - _this->pluginDispatch( effEditIdle ); - break; - - case ClosePlugin: - quit = true; - break; - - default: - break; - } - } } return 0; @@ -1846,6 +1899,49 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop( LPVOID _param ) +LRESULT CALLBACK RemoteVstPlugin::messageWndProc( HWND hwnd, UINT uMsg, + WPARAM wParam, LPARAM lParam ) +{ + if( uMsg == WM_TIMER && __plugin->isInitialized() ) + { + // give plugin some idle-time for GUI-update + __plugin->idle(); + return 0; + } + else if( uMsg == WM_USER ) + { + switch( wParam ) + { + case ProcessPluginMessage: + { + message * m = (message *) lParam; + __plugin->queueMessage( *m ); + delete m; + if( !__plugin->isProcessing() ) + { + __plugin->processUIThreadMessages(); + } + return 0; + } + + case GiveIdle: + __plugin->idle(); + return 0; + + case ClosePlugin: + PostQuitMessage(0); + return 0; + + default: + break; + } + } + return DefWindowProc( hwnd, uMsg, wParam, lParam ); +} + + + + int main( int _argc, char * * _argv ) { #ifdef SYNC_WITH_SHM_FIFO @@ -1893,7 +1989,10 @@ int main( int _argc, char * * _argv ) if( __plugin->isInitialized() ) { - __GuiThreadID = GetCurrentThreadId(); + if( RemoteVstPlugin::setupMessageWindow() == false ) + { + return -1; + } if( CreateThread( NULL, 0, RemoteVstPlugin::processingThread, __plugin, 0, NULL ) == NULL ) { @@ -1901,7 +2000,7 @@ int main( int _argc, char * * _argv ) "processingThread\n" ); return -1; } - RemoteVstPlugin::guiEventLoop( __plugin ); + RemoteVstPlugin::guiEventLoop(); } diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 22c9f7c20..9873d28e5 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -389,7 +389,7 @@ int VstPlugin::currentProgram() { lock(); sendMessage( message( IdVstCurrentProgram ) ); - waitForMessage( IdVstCurrentProgram ); + waitForMessage( IdVstCurrentProgram, true ); unlock(); return m_currentProgram; @@ -401,7 +401,7 @@ const QMap & VstPlugin::parameterDump() { lock(); sendMessage( IdVstGetParameterDump ); - waitForMessage( IdVstParameterDump ); + waitForMessage( IdVstParameterDump, true ); unlock(); return m_parameterDump; @@ -528,7 +528,7 @@ void VstPlugin::openPreset( ) QSTR_TO_STDSTR( QDir::toNativeSeparators( ofd.selectedFiles()[0] ) ) ) ); - waitForMessage( IdLoadPresetFile ); + waitForMessage( IdLoadPresetFile, true ); unlock(); } } @@ -540,7 +540,7 @@ void VstPlugin::setProgram( int index ) { lock(); sendMessage( message( IdVstSetProgram ).addInt( index ) ); - waitForMessage( IdVstSetProgram ); + waitForMessage( IdVstSetProgram, true ); unlock(); } @@ -551,7 +551,7 @@ void VstPlugin::rotateProgram( int offset ) { lock(); sendMessage( message( IdVstRotateProgram ).addInt( offset ) ); - waitForMessage( IdVstRotateProgram ); + waitForMessage( IdVstRotateProgram, true ); unlock(); } @@ -562,7 +562,7 @@ void VstPlugin::loadProgramNames() { lock(); sendMessage( message( IdVstProgramNames ) ); - waitForMessage( IdVstProgramNames ); + waitForMessage( IdVstProgramNames, true ); unlock(); } @@ -599,7 +599,7 @@ void VstPlugin::savePreset( ) QSTR_TO_STDSTR( QDir::toNativeSeparators( fns ) ) ) ); - waitForMessage( IdSavePresetFile ); + waitForMessage( IdSavePresetFile, true ); unlock(); } } @@ -611,7 +611,7 @@ void VstPlugin::setParam( int i, float f ) { lock(); sendMessage( message( IdVstSetParameter ).addInt( i ).addFloat( f ) ); - //waitForMessage( IdVstSetParameter ); + //waitForMessage( IdVstSetParameter, true ); unlock(); } @@ -640,7 +640,7 @@ void VstPlugin::loadChunk( const QByteArray & _chunk ) QSTR_TO_STDSTR( QDir::toNativeSeparators( tf.fileName() ) ) ). addInt( _chunk.size() ) ); - waitForMessage( IdLoadSettingsFromFile ); + waitForMessage( IdLoadSettingsFromFile, true ); unlock(); } } @@ -659,7 +659,7 @@ QByteArray VstPlugin::saveChunk() addString( QSTR_TO_STDSTR( QDir::toNativeSeparators( tf.fileName() ) ) ) ); - waitForMessage( IdSaveSettingsToFile ); + waitForMessage( IdSaveSettingsToFile, true ); unlock(); a = tf.readAll(); } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 63b931823..f65c96066 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1541,7 +1541,9 @@ void MainWindow::autoSave() "enablerunningautosave" ).toInt() || ! Engine::getSong()->isPlaying() ) ) { - Engine::getSong()->saveProjectFile(ConfigManager::inst()->recoveryFile()); + AutoSaveThread * ast = new AutoSaveThread(); + connect( ast, SIGNAL( finished() ), ast, SLOT( deleteLater() ) ); + ast->start(); autoSaveTimerReset(); // Reset timer } else @@ -1553,3 +1555,11 @@ void MainWindow::autoSave() } } } + + + + +void AutoSaveThread::run() +{ + Engine::getSong()->saveProjectFile(ConfigManager::inst()->recoveryFile()); +} From 7429cb8155238dbc839bac45d6400740bb63e72d Mon Sep 17 00:00:00 2001 From: DomClark Date: Thu, 7 Sep 2017 22:11:11 +0100 Subject: [PATCH 4/4] Fix segfault on VST plugin I/O change --- include/RemotePlugin.h | 10 ++++++ plugins/vst_base/RemoteVstPlugin.cpp | 54 +++++++++++++++++++++++++--- src/core/RemotePlugin.cpp | 6 ++++ 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 725f51c2c..b3ac4b676 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -424,6 +424,7 @@ enum RemoteMessageIDs IdChangeSharedMemoryKey, IdChangeInputCount, IdChangeOutputCount, + IdChangeInputOutputCount, IdShowUI, IdHideUI, IdSaveSettingsToString, @@ -919,6 +920,15 @@ public: sendMessage( message( IdChangeOutputCount ).addInt( _i ) ); } + void setInputOutputCount( int i, int o ) + { + m_inputCount = i; + m_outputCount = o; + sendMessage( message( IdChangeInputOutputCount ) + .addInt( i ) + .addInt( o ) ); + } + virtual int inputCount() const { return m_inputCount; diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 74af607c5..67ce71ea8 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -249,6 +249,26 @@ public: pthread_mutex_unlock( &m_pluginLock ); } + inline void lockShm() + { + pthread_mutex_lock( &m_shmLock ); + } + + inline void unlockShm() + { + pthread_mutex_unlock( &m_shmLock ); + } + + inline bool isShmValid() + { + return m_shmValid; + } + + inline void setShmIsValid( bool valid ) + { + m_shmValid = valid; + } + inline bool isProcessing() const { return m_processing; @@ -347,6 +367,9 @@ private: float * * m_inputs; float * * m_outputs; + pthread_mutex_t m_shmLock; + bool m_shmValid; + typedef std::vector VstMidiEventList; VstMidiEventList m_midiEvents; @@ -392,6 +415,8 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : m_shouldGiveIdle( false ), m_inputs( NULL ), m_outputs( NULL ), + m_shmLock(), + m_shmValid( false ), m_midiEvents(), m_bpm( 0 ), m_currentSamplePos( 0 ), @@ -402,6 +427,7 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : { pthread_mutex_init( &m_pluginLock, NULL ); + pthread_mutex_init( &m_shmLock, NULL ); __plugin = this; @@ -500,6 +526,7 @@ RemoteVstPlugin::~RemoteVstPlugin() delete[] m_inputs; delete[] m_outputs; + pthread_mutex_destroy( &m_shmLock ); pthread_mutex_destroy( &m_pluginLock ); } @@ -836,6 +863,16 @@ void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out ) // now we're ready to fetch sound from VST-plugin + lock(); + lockShm(); + + if( !isShmValid() ) + { + unlockShm(); + unlock(); + return; + } + for( int i = 0; i < inputCount(); ++i ) { m_inputs[i] = &((float *) _in)[i * bufferSize()]; @@ -847,8 +884,6 @@ void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out ) memset( m_outputs[i], 0, bufferSize() * sizeof( float ) ); } - lock(); - #ifdef OLD_VST_SDK if( m_plugin->flags & effFlagsCanReplacing ) { @@ -864,6 +899,7 @@ void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out ) } #endif + unlockShm(); unlock(); m_currentSamplePos += bufferSize(); @@ -1380,14 +1416,19 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len ) void RemoteVstPlugin::updateInOutCount() { + lockShm(); + + setShmIsValid( false ); + + unlockShm(); + delete[] m_inputs; delete[] m_outputs; m_inputs = NULL; m_outputs = NULL; - setInputCount( inputCount() ); - setOutputCount( outputCount() ); + setInputOutputCount( inputCount(), outputCount() ); char buf[64]; sprintf( buf, "inputs: %d output: %d\n", inputCount(), outputCount() ); @@ -1842,6 +1883,11 @@ DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) { _this->processMessage( m ); } + else if( m.id == IdChangeSharedMemoryKey ) + { + _this->processMessage( m ); + _this->setShmIsValid( true ); + } else { PostMessage( __MessageHwnd, diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp index bb7e39c6a..c7756552c 100644 --- a/src/core/RemotePlugin.cpp +++ b/src/core/RemotePlugin.cpp @@ -481,6 +481,12 @@ bool RemotePlugin::processMessage( const message & _m ) resizeSharedProcessingMemory(); break; + case IdChangeInputOutputCount: + m_inputCount = _m.getInt( 0 ); + m_outputCount = _m.getInt( 1 ); + resizeSharedProcessingMemory(); + break; + case IdDebugMessage: fprintf( stderr, "RemotePlugin::DebugMessage: %s", _m.getString( 0 ).c_str() );