diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h new file mode 100644 index 000000000..baaf88205 --- /dev/null +++ b/include/CustomTextKnob.h @@ -0,0 +1,30 @@ +/* Text customizable knob */ +#ifndef CUSTOM_TEXT_KNOB_H +#define CUSTOM_TEXT_KNOB_H + +#include "Knob.h" + +class LMMS_EXPORT CustomTextKnob : public Knob +{ +protected: + inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible +public: + CustomTextKnob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() ); + + CustomTextKnob( QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor + + CustomTextKnob( const Knob& other ) = delete; + + inline void setValueText(const QString & _value_text) + { + m_value_text = _value_text; + } + +private: + virtual QString displayValue() const; + +protected: + QString m_value_text; +} ; + +#endif diff --git a/include/Knob.h b/include/Knob.h index 4f8064731..0bba58afd 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -143,7 +143,7 @@ private slots: void toggleScale(); private: - QString displayValue() const; + virtual QString displayValue() const; void doConnections() override; diff --git a/include/aeffectx.h b/include/aeffectx.h index 133d925ac..b7a78dfad 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -97,6 +97,8 @@ const int effClose = 1; // currently unused const int effSetProgram = 2; // currently unused const int effGetProgram = 3; // currently unused const int effGetProgramName = 5; // currently unused +const int effGetParamLabel = 6; +const int effGetParamDisplay = 7; const int effGetParamName = 8; // currently unused const int effSetSampleRate = 10; const int effSetBlockSize = 11; diff --git a/plugins/VstEffect/VstEffectControls.cpp b/plugins/VstEffect/VstEffectControls.cpp index a0f97ce71..ab7408388 100644 --- a/plugins/VstEffect/VstEffectControls.cpp +++ b/plugins/VstEffect/VstEffectControls.cpp @@ -350,7 +350,7 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * const QMap & dump = m_effect->m_plugin->parameterDump(); m_vi->paramCount = dump.size(); - vstKnobs = new Knob *[ m_vi->paramCount ]; + vstKnobs = new CustomTextKnob *[ m_vi->paramCount ]; bool hasKnobModel = true; if (m_vi->knobFModel == NULL) { @@ -366,8 +366,8 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * sprintf( paramStr, "param%d", i); s_dumpValues = dump[ paramStr ].split( ":" ); - vstKnobs[ i ] = new Knob( knobBright_26, widget, s_dumpValues.at( 1 ) ); - vstKnobs[ i ]->setHintText( s_dumpValues.at( 1 ) + ":", "" ); + vstKnobs[ i ] = new CustomTextKnob( knobBright_26, widget, s_dumpValues.at( 1 ) ); + vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" ); vstKnobs[ i ]->setLabel( s_dumpValues.at( 1 ).left( 15 ) ); if( !hasKnobModel ) @@ -382,6 +382,7 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * [this, model]() { setParameter( model ); }, Qt::DirectConnection); vstKnobs[ i ] ->setModel( model ); } + syncParameterText(); int i = 0; for( int lrow = 1; lrow < ( int( m_vi->paramCount / 10 ) + 1 ) + 1; lrow++ ) @@ -444,6 +445,7 @@ void manageVSTEffectView::syncPlugin( void ) m_vi2->knobFModel[ i ]->setInitValue( f_value ); } } + syncParameterText(); } @@ -479,9 +481,40 @@ void manageVSTEffectView::setParameter( Model * action ) if ( m_effect->m_plugin != NULL ) { m_effect->m_plugin->setParam( knobUNID, m_vi2->knobFModel[knobUNID]->value() ); + syncParameterText(); } } +void manageVSTEffectView::syncParameterText() +{ + m_effect->m_plugin->loadParameterLabels(); + m_effect->m_plugin->loadParameterDisplays(); + + QString paramLabelStr = m_effect->m_plugin->allParameterLabels(); + QString paramDisplayStr = m_effect->m_plugin->allParameterDisplays(); + + QStringList paramLabelList; + QStringList paramDisplayList; + + for( int i = 0; i < paramLabelStr.size(); ) + { + const int length = paramLabelStr[i].digitValue(); + paramLabelList.append(paramLabelStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramDisplayStr.size(); ) + { + const int length = paramDisplayStr[i].digitValue(); + paramDisplayList.append(paramDisplayStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramLabelList.size(); ++i ) + { + vstKnobs[i]->setValueText(paramDisplayList[i] + ' ' + paramLabelList[i]); + } +} diff --git a/plugins/VstEffect/VstEffectControls.h b/plugins/VstEffect/VstEffectControls.h index 092669f94..cb98d0f43 100644 --- a/plugins/VstEffect/VstEffectControls.h +++ b/plugins/VstEffect/VstEffectControls.h @@ -34,7 +34,7 @@ #include #include -#include "Knob.h" +#include "CustomTextKnob.h" #include #include #include @@ -111,6 +111,7 @@ protected slots: void syncPlugin( void ); void displayAutomatedOnly( void ); void setParameter( Model * action ); + void syncParameterText(); void closeWindow(); private: @@ -129,7 +130,7 @@ private: QPushButton * m_syncButton; QPushButton * m_displayAutomatedOnly; QPushButton * m_closeButton; - Knob ** vstKnobs; + CustomTextKnob ** vstKnobs; } ; diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 9efd3c97b..0d75992a4 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -38,6 +38,8 @@ #include #include +#include + #include "ConfigManager.h" #include "BufferManager.h" #include "ConfigManager.h" @@ -965,7 +967,7 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume const QMap & dump = m_vi->m_plugin->parameterDump(); m_vi->paramCount = dump.size(); - vstKnobs = new Knob *[ m_vi->paramCount ]; + vstKnobs = new CustomTextKnob *[ m_vi->paramCount ]; bool hasKnobModel = true; if (m_vi->knobFModel == NULL) { @@ -981,8 +983,8 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume sprintf( paramStr, "param%d", i); s_dumpValues = dump[ paramStr ].split( ":" ); - vstKnobs[ i ] = new Knob( knobBright_26, this, s_dumpValues.at( 1 ) ); - vstKnobs[ i ]->setHintText( s_dumpValues.at( 1 ) + ":", "" ); + vstKnobs[ i ] = new CustomTextKnob( knobBright_26, this, s_dumpValues.at( 1 ) ); + vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" ); vstKnobs[ i ]->setLabel( s_dumpValues.at( 1 ).left( 15 ) ); if( !hasKnobModel ) @@ -997,6 +999,7 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume [this, model]() { setParameter( model ); }, Qt::DirectConnection); vstKnobs[i] ->setModel( model ); } + syncParameterText(); int i = 0; for( int lrow = 1; lrow < ( int( m_vi->paramCount / 10 ) + 1 ) + 1; lrow++ ) @@ -1057,6 +1060,7 @@ void manageVestigeInstrumentView::syncPlugin( void ) m_vi->knobFModel[ i ]->setInitValue( f_value ); } } + syncParameterText(); } @@ -1132,6 +1136,38 @@ void manageVestigeInstrumentView::setParameter( Model * action ) if ( m_vi->m_plugin != NULL ) { m_vi->m_plugin->setParam( knobUNID, m_vi->knobFModel[knobUNID]->value() ); + syncParameterText(); + } +} + +void manageVestigeInstrumentView::syncParameterText() +{ + m_vi->m_plugin->loadParameterLabels(); + m_vi->m_plugin->loadParameterDisplays(); + + QString paramLabelStr = m_vi->m_plugin->allParameterLabels(); + QString paramDisplayStr = m_vi->m_plugin->allParameterDisplays(); + + QStringList paramLabelList; + QStringList paramDisplayList; + + for( int i = 0; i < paramLabelStr.size(); ) + { + const int length = paramLabelStr[i].digitValue(); + paramLabelList.append(paramLabelStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramDisplayStr.size(); ) + { + const int length = paramDisplayStr[i].digitValue(); + paramDisplayList.append(paramDisplayStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramLabelList.size(); ++i ) + { + vstKnobs[i]->setValueText(paramDisplayList[i] + ' ' + paramLabelList[i]); } } diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 7090fee1e..ae4f803cf 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -34,7 +34,7 @@ #include "Instrument.h" #include "InstrumentView.h" #include "Note.h" -#include "Knob.h" +#include "CustomTextKnob.h" #include "SubWindow.h" #include "AutomatableModel.h" @@ -109,6 +109,7 @@ protected slots: void syncPlugin( void ); void displayAutomatedOnly( void ); void setParameter( Model * action ); + void syncParameterText(); void closeWindow(); @@ -128,7 +129,7 @@ private: QPushButton * m_syncButton; QPushButton * m_displayAutomatedOnly; QPushButton * m_closeButton; - Knob ** vstKnobs; + CustomTextKnob ** vstKnobs; } ; diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index a103c0652..942c9e960 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -70,6 +70,8 @@ #include #include #include +#include +#include #include @@ -223,6 +225,10 @@ public: // determine name of current program const char * programName(); + void getParameterDisplays(); + + void getParameterLabels(); + // send name of current program back to host void sendCurrentProgramName(); @@ -660,6 +666,14 @@ bool RemoteVstPlugin::processMessage( const message & _m ) //sendMessage( IdVstSetParameter ); break; + case IdVstParameterDisplays: + getParameterDisplays(); + break; + + case IdVstParameterLabels: + getParameterLabels(); + break; + case IdVstIdleUpdate: { @@ -1068,6 +1082,49 @@ const char * RemoteVstPlugin::programName() +// join the ParameterDisplays (stringified values without units) and send them to host +void RemoteVstPlugin::getParameterDisplays() +{ + std::string paramDisplays; + static char buf[9]; // buffer for getting string + for (int i=0; i< m_plugin->numParams; ++i) + { + memset( buf, 0, sizeof( buf ) ); // fill with '\0' because got string may not to be ended with '\0' + pluginDispatch( effGetParamDisplay, i, 0, buf ); + buf[8] = 0; + + // each field shaped like: [length:number][content:string] + paramDisplays += '0' + strlen(buf); // add length descriptor (length is up to 8) + paramDisplays += buf; + } + + sendMessage( message( IdVstParameterDisplays ).addString( paramDisplays.c_str() ) ); +} + + + +// join the ParameterLabels (units) and send them to host +void RemoteVstPlugin::getParameterLabels() +{ + std::string paramLabels; + static char buf[9]; // buffer for getting string + for (int i=0; i< m_plugin->numParams; ++i) + { + memset( buf, 0, sizeof( buf ) ); // fill with '\0' because got string may not to be ended with '\0' + pluginDispatch( effGetParamLabel, i, 0, buf ); + buf[8] = 0; + + // each field shaped like: [length:number][content:string] + paramLabels += '0' + strlen(buf); // add length descriptor (length is up to 8) + paramLabels += buf; + } + + sendMessage( message( IdVstParameterLabels ).addString( paramLabels.c_str() ) ); +} + + + + void RemoteVstPlugin::sendCurrentProgramName() { char presName[64]; diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 8d86f576f..cd4844b81 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -438,6 +438,14 @@ bool VstPlugin::processMessage( const message & _m ) m_allProgramNames = _m.getQString(); break; + case IdVstParameterLabels: + m_allParameterLabels = _m.getQString(); + break; + + case IdVstParameterDisplays: + m_allParameterDisplays = _m.getQString(); + break; + case IdVstPluginUniqueID: // TODO: display graphically in case of failure printf("unique ID: %s\n", _m.getString().c_str() ); @@ -531,6 +539,28 @@ void VstPlugin::loadProgramNames() +void VstPlugin::loadParameterLabels() +{ + lock(); + sendMessage( message( IdVstParameterLabels ) ); + waitForMessage( IdVstParameterLabels, true ); + unlock(); +} + + + + +void VstPlugin::loadParameterDisplays() +{ + lock(); + sendMessage( message( IdVstParameterDisplays ) ); + waitForMessage( IdVstParameterDisplays, true ); + unlock(); +} + + + + void VstPlugin::savePreset( ) { QString presName = currentProgramName().isEmpty() ? tr(": default") : currentProgramName(); diff --git a/plugins/vst_base/VstPlugin.h b/plugins/vst_base/VstPlugin.h index 26e7fec36..e05031256 100644 --- a/plugins/vst_base/VstPlugin.h +++ b/plugins/vst_base/VstPlugin.h @@ -91,6 +91,16 @@ public: return m_allProgramNames; } + inline const QString& allParameterLabels() const + { + return m_allParameterLabels; + } + + inline const QString& allParameterDisplays() const + { + return m_allParameterDisplays; + } + int currentProgram(); const QMap & parameterDump(); @@ -120,6 +130,8 @@ public slots: void setProgram( int index ); void rotateProgram( int offset ); void loadProgramNames(); + void loadParameterLabels(); + void loadParameterDisplays(); void savePreset( void ); void setParam( int i, float f ); void idleUpdate(); @@ -148,6 +160,8 @@ private: QString m_productString; QString m_currentProgramName; QString m_allProgramNames; + QString m_allParameterLabels; + QString m_allParameterDisplays; QString p_name; diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index 756fd7557..c25b213d1 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -67,6 +67,8 @@ enum VstRemoteMessageIDs IdVstSetProgram, IdVstRotateProgram, IdVstIdleUpdate, + IdVstParameterDisplays, + IdVstParameterLabels, // remoteVstPlugin -> vstPlugin IdVstFailedLoadingPlugin, diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index a340867a8..759be3872 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -54,6 +54,7 @@ SET(LMMS_SRCS gui/widgets/ControllerView.cpp gui/widgets/Controls.cpp gui/widgets/CPULoadWidget.cpp + gui/widgets/CustomTextKnob.cpp gui/widgets/EffectRackView.cpp gui/widgets/EffectView.cpp gui/widgets/EnvelopeAndLfoView.cpp diff --git a/src/gui/widgets/CustomTextKnob.cpp b/src/gui/widgets/CustomTextKnob.cpp new file mode 100644 index 000000000..149b3494b --- /dev/null +++ b/src/gui/widgets/CustomTextKnob.cpp @@ -0,0 +1,14 @@ +#include "CustomTextKnob.h" + +CustomTextKnob::CustomTextKnob( knobTypes _knob_num, QWidget * _parent, const QString & _name, const QString & _value_text ) : + Knob( _knob_num, _parent, _name ), + m_value_text( _value_text ) {} + +CustomTextKnob::CustomTextKnob( QWidget * _parent, const QString & _name, const QString & _value_text ) : //!< default ctor + Knob( _parent, _name ), + m_value_text( _value_text ) {} + +QString CustomTextKnob::displayValue() const +{ + return m_description.trimmed() + m_value_text; +}