diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 264aa2155..73d70aa05 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -63,7 +63,7 @@ public: inline void setDescription( const QString& desc ) { - m_description = desc; + m_description = desc.trimmed(); } inline void setUnit( const QString& unit ) diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h deleted file mode 100644 index 34434f3ae..000000000 --- a/include/CustomTextKnob.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * CustomTextKnob.h - * - * Copyright (c) 2020 Ibuki Sugiyama
- * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#ifndef LMMS_GUI_CUSTOM_TEXT_KNOB_H -#define LMMS_GUI_CUSTOM_TEXT_KNOB_H - -#include "Knob.h" - -namespace lmms::gui -{ - - -class LMMS_EXPORT CustomTextKnob : public Knob -{ -protected: - inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible -public: - CustomTextKnob( KnobType _knob_num, const QString& label, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() ); - - CustomTextKnob( const Knob& other ) = delete; - - inline void setValueText(const QString & _value_text) - { - m_value_text = _value_text; - } - -private: - QString displayValue() const override; - -protected: - QString m_value_text; -} ; - - -} // namespace lmms::gui - -#endif // LMMS_GUI_CUSTOM_TEXT_KNOB_H diff --git a/include/FloatModelEditorBase.h b/include/FloatModelEditorBase.h index 39a3fa030..8d1ca721c 100644 --- a/include/FloatModelEditorBase.h +++ b/include/FloatModelEditorBase.h @@ -3,6 +3,7 @@ * * Copyright (c) 2004-2008 Tobias Doerffel * Copyright (c) 2023 Michael Gregorius + * Copyright (c) 2026 Dalton Messmer * * This file is part of LMMS - https://lmms.io * @@ -28,10 +29,10 @@ #include #include +#include #include "AutomatableModelView.h" - namespace lmms::gui { @@ -41,12 +42,10 @@ class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView { Q_OBJECT - mapPropertyFromModel(float, volumeRatio, setVolumeRatio, m_volumeRatio); - void initUi(const QString & name); //!< to be called by ctors public: - enum class DirectionOfManipulation + enum class DirectionOfManipulation : bool { Vertical, Horizontal @@ -62,22 +61,11 @@ public: setUnit(txt_after); } - bool isVolumeKnob() const - { - return m_volumeKnob; - } - - void setVolumeKnob(const bool val) - { - m_volumeKnob = val; - } - signals: void sliderPressed(); void sliderReleased(); void sliderMoved(float value); - protected: void contextMenuEvent(QContextMenuEvent * me) override; void dragEnterEvent(QDragEnterEvent * dee) override; @@ -98,11 +86,47 @@ protected: void leaveEvent(QEvent *event) override; virtual float getValue(const QPoint & p); - virtual QString displayValue() const; + + /** + * This method is called just prior to displaying the floating text + * in order to set its value. If the getCustomFloatingTextUpdate() method + * is not overridden, this method is also called to periodically update + * the floating text. + * + * Floating text is displayed in the following format: + * "[description] [custom text][unit]" + * + * This method controls only the "custom text" portion. + * To modify the other portions, call setDescription() or setUnit(). + */ + virtual QString getCustomFloatingText(); + + /** + * This method is called periodically while the floating text is visible + * and the value of the float model is changing, allowing dynamic updates + * of the floating text. + * + * Floating text is displayed in the following format: + * "[description] [custom text][unit]" + * + * This method controls only the "custom text" portion. + * To modify the other portions, call setDescription() or setUnit(). + * + * @returns the up-to-date value for the floating text, or std::nullopt to indicate + * nothing changed and the previous floating text value should continue being used + */ + virtual std::optional getCustomFloatingTextUpdate() + { + return getCustomFloatingText(); + } void doConnections() override; void showTextFloat(int msecBeforeDisplay, int msecDisplayTime); + void showTextFloat(); + + const SimpleTextFloat& textFloat() const { return *s_textFloat; } + void setPosition(const QPoint & p); inline float pageSize() const @@ -110,11 +134,6 @@ protected: return (model()->maxValue() - model()->minValue()) / 100.0f; } - static SimpleTextFloat * s_textFloat; - - bool m_volumeKnob; - FloatModel m_volumeRatio; - QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent float m_leftOver; bool m_buttonPressed; @@ -125,6 +144,9 @@ private slots: virtual void enterValue(); void friendlyUpdate(); void toggleScale(); + +private: + static SimpleTextFloat* s_textFloat; }; } // namespace lmms::gui diff --git a/include/Knob.h b/include/Knob.h index 1becfb0e8..c1fce824a 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -235,6 +235,25 @@ private: KnobType m_knobNum; }; + +class LMMS_EXPORT VolumeKnob : public Knob +{ + Q_OBJECT + + mapPropertyFromModel(float, volumeRatio, setVolumeRatio, m_volumeRatio); + +public: + using Knob::Knob; + +protected: + QString getCustomFloatingText() override; + void enterValue() override; + +private: + FloatModel m_volumeRatio{100.f, 0.f, 1000000.f}; +}; + + } // namespace lmms::gui #endif // LMMS_GUI_KNOB_H diff --git a/include/RemotePluginBase.h b/include/RemotePluginBase.h index b31676860..81561f103 100644 --- a/include/RemotePluginBase.h +++ b/include/RemotePluginBase.h @@ -204,19 +204,17 @@ public: write( &_i, sizeof( _i ) ); } - inline std::string readString() + std::string readString() { + std::string ret; const int len = readInt(); - if( len ) + if (len > 0) { - char * sc = new char[len + 1]; - read( sc, len ); - sc[len] = 0; - std::string s( sc ); - delete[] sc; - return s; + ret.resize(static_cast(len)); + read(ret.data(), len); + ret[len] = '\0'; } - return std::string(); + return ret; } @@ -370,9 +368,10 @@ public: { } - inline message & addString( const std::string & _s ) + template + message& addString(Args&&... args) { - data.push_back( _s ); + data.emplace_back(std::forward(args)...); return *this; } @@ -480,19 +479,17 @@ public: write( &_i, sizeof( _i ) ); } - inline std::string readString() + std::string readString() { + std::string ret; const int len = readInt(); - if( len ) + if (len > 0) { - char * sc = new char[len + 1]; - read( sc, len ); - sc[len] = 0; - std::string s( sc ); - delete[] sc; - return s; + ret.resize(static_cast(len)); + read(ret.data(), len); + ret[len] = '\0'; } - return std::string(); + return ret; } diff --git a/include/SimpleTextFloat.h b/include/SimpleTextFloat.h index 2821ca411..8db794f5b 100644 --- a/include/SimpleTextFloat.h +++ b/include/SimpleTextFloat.h @@ -22,7 +22,6 @@ * */ - #ifndef LMMS_GUI_SIMPLE_TEXT_FLOAT_H #define LMMS_GUI_SIMPLE_TEXT_FLOAT_H @@ -57,12 +56,22 @@ public: move(w->mapToGlobal(QPoint(0, 0)) + offset); } + void show(); void hide(); + //! @returns which object is currently controlling this text float (if known) + const QObject* source() const { return m_source; } + + //! Sets which object is currently controlling this text float + void setSource(const QObject* source) { m_source = source; } + private: QLabel * m_textLabel; QTimer * m_showTimer; QTimer * m_hideTimer; + + //! Which object is currently controlling this text float + const QObject* m_source = nullptr; }; } // namespace lmms::gui diff --git a/plugins/Amplifier/AmplifierControlDialog.cpp b/plugins/Amplifier/AmplifierControlDialog.cpp index 44c0e3be2..a54e7efef 100644 --- a/plugins/Amplifier/AmplifierControlDialog.cpp +++ b/plugins/Amplifier/AmplifierControlDialog.cpp @@ -46,10 +46,11 @@ AmplifierControlDialog::AmplifierControlDialog(AmplifierControls* controls) : auto makeKnob = [this](const QString& label, const QString& hintText, const QString& unit, FloatModel* model, bool isVolume) { - Knob* newKnob = new Knob(KnobType::Bright26, label, this); + Knob* newKnob = isVolume + ? new VolumeKnob(KnobType::Bright26, label, this) + : new Knob(KnobType::Bright26, label, this); newKnob->setModel(model); newKnob->setHintText(hintText, unit); - newKnob->setVolumeKnob(isVolume); return newKnob; }; diff --git a/plugins/AudioFileProcessor/AudioFileProcessorView.cpp b/plugins/AudioFileProcessor/AudioFileProcessorView.cpp index 60fb8e4dd..249a76e73 100644 --- a/plugins/AudioFileProcessor/AudioFileProcessorView.cpp +++ b/plugins/AudioFileProcessor/AudioFileProcessorView.cpp @@ -114,8 +114,7 @@ AudioFileProcessorView::AudioFileProcessorView(Instrument* instrument, m_stutterButton->setToolTip( tr("Continue sample playback across notes")); - m_ampKnob = new Knob(KnobType::Bright26, this); - m_ampKnob->setVolumeKnob(true); + m_ampKnob = new VolumeKnob(KnobType::Bright26, this); m_ampKnob->move(5, 108); m_ampKnob->setHintText(tr("Amplify:"), "%"); diff --git a/plugins/Delay/DelayControlsDialog.cpp b/plugins/Delay/DelayControlsDialog.cpp index fc15b6b49..3aa47dc3c 100644 --- a/plugins/Delay/DelayControlsDialog.cpp +++ b/plugins/Delay/DelayControlsDialog.cpp @@ -47,25 +47,21 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : auto sampleDelayKnob = new TempoSyncKnob(KnobType::Bright26, tr("DELAY"), this, Knob::LabelRendering::LegacyFixedFontSize); sampleDelayKnob->move( 10,14 ); - sampleDelayKnob->setVolumeKnob( false ); sampleDelayKnob->setModel( &controls->m_delayTimeModel ); sampleDelayKnob->setHintText( tr( "Delay time" ) + " ", " s" ); - auto feedbackKnob = new Knob(KnobType::Bright26, tr("FDBK"), this, Knob::LabelRendering::LegacyFixedFontSize); + auto feedbackKnob = new VolumeKnob(KnobType::Bright26, tr("FDBK"), this, Knob::LabelRendering::LegacyFixedFontSize); feedbackKnob->move( 11, 58 ); - feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); feedbackKnob->setHintText( tr ( "Feedback amount" ) + " " , "" ); auto lfoFreqKnob = new TempoSyncKnob(KnobType::Bright26, tr("RATE"), this, Knob::LabelRendering::LegacyFixedFontSize); lfoFreqKnob->move( 11, 119 ); - lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); lfoFreqKnob->setHintText( tr ( "LFO frequency") + " ", " s" ); auto lfoAmtKnob = new TempoSyncKnob(KnobType::Bright26, tr("AMNT"), this, Knob::LabelRendering::LegacyFixedFontSize); lfoAmtKnob->move( 11, 159 ); - lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setHintText( tr ( "LFO amount" ) + " " , " s" ); diff --git a/plugins/DualFilter/DualFilterControlDialog.cpp b/plugins/DualFilter/DualFilterControlDialog.cpp index 6d051b256..6e2dcde52 100644 --- a/plugins/DualFilter/DualFilterControlDialog.cpp +++ b/plugins/DualFilter/DualFilterControlDialog.cpp @@ -34,15 +34,6 @@ namespace lmms::gui { - -#define makeknob( name, x, y, model, label, hint, unit ) \ - Knob * name = new Knob(KnobType::Bright26, label, SMALL_FONT_SIZE, this); \ - (name) -> move( x, y ); \ - (name) ->setModel( &controls-> model ); \ - (name) ->setHintText( hint, unit ); - - - DualFilterControlDialog::DualFilterControlDialog( DualFilterControls* controls ) : EffectControlDialog( controls ) { @@ -52,16 +43,24 @@ DualFilterControlDialog::DualFilterControlDialog( DualFilterControls* controls ) setPalette( pal ); setFixedSize( 373, 109 ); - makeknob( cut1Knob, 24, 26, m_cut1Model, tr( "FREQ" ), tr( "Cutoff frequency" ), "Hz" ) - makeknob( res1Knob, 74, 26, m_res1Model, tr( "RESO" ), tr( "Resonance" ), "" ) - makeknob( gain1Knob, 124, 26, m_gain1Model, tr( "GAIN" ), tr( "Gain" ), "%" ) - makeknob( mixKnob, 173, 37, m_mixModel, tr( "MIX" ), tr( "Mix" ), "" ) - makeknob( cut2Knob, 222, 26, m_cut2Model, tr( "FREQ" ), tr( "Cutoff frequency" ), "Hz" ) - makeknob( res2Knob, 272, 26, m_res2Model, tr( "RESO" ), tr( "Resonance" ), "" ) - makeknob( gain2Knob, 322, 26, m_gain2Model, tr( "GAIN" ), tr( "Gain" ), "%" ) + auto makeKnob = [this](int x, int y, Model* model, + const QString& label, const QString& hint, const QString& unit, bool isVolumeKnob = false) + { + Knob* knob = isVolumeKnob + ? new VolumeKnob(KnobType::Bright26, label, SMALL_FONT_SIZE, this) + : new Knob(KnobType::Bright26, label, SMALL_FONT_SIZE, this); + knob->move(x, y); + knob->setModel(model); + knob->setHintText(hint, unit); + }; - gain1Knob-> setVolumeKnob( true ); - gain2Knob-> setVolumeKnob( true ); + makeKnob(24, 26, &controls->m_cut1Model, tr("FREQ"), tr("Cutoff frequency"), "Hz"); + makeKnob(74, 26, &controls->m_res1Model, tr("RESO"), tr("Resonance"), ""); + makeKnob(124, 26, &controls->m_gain1Model, tr("GAIN"), tr("Gain"), "%", true); + makeKnob(173, 37, &controls->m_mixModel, tr("MIX"), tr("Mix"), ""); + makeKnob(222, 26, &controls->m_cut2Model, tr("FREQ"), tr("Cutoff frequency"), "Hz"); + makeKnob(272, 26, &controls->m_res2Model, tr("RESO"), tr("Resonance"), ""); + makeKnob(322, 26, &controls->m_gain2Model, tr("GAIN"), tr("Gain"), "%", true); auto enabled1Toggle = new LedCheckBox("", this, tr("Filter 1 enabled"), LedCheckBox::LedColor::Green); auto enabled2Toggle = new LedCheckBox("", this, tr("Filter 2 enabled"), LedCheckBox::LedColor::Green); diff --git a/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp b/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp index b61029600..323382180 100644 --- a/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp +++ b/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp @@ -59,16 +59,14 @@ DynProcControlDialog::DynProcControlDialog( waveGraph->setGraphColor( QColor( 85, 204, 145 ) ); waveGraph -> setMaximumSize( 204, 205 ); - auto inputKnob = new Knob(KnobType::Bright26, tr("INPUT"), SMALL_FONT_SIZE, this); - inputKnob -> setVolumeKnob( true ); - inputKnob -> setVolumeRatio( 1.0 ); + auto inputKnob = new VolumeKnob(KnobType::Bright26, tr("INPUT"), SMALL_FONT_SIZE, this); + inputKnob->setVolumeRatio(1.0); inputKnob -> move( 26, 223 ); inputKnob->setModel( &_controls->m_inputModel ); inputKnob->setHintText( tr( "Input gain:" ) , "" ); - auto outputKnob = new Knob(KnobType::Bright26, tr("OUTPUT"), SMALL_FONT_SIZE, this); - outputKnob -> setVolumeKnob( true ); - outputKnob -> setVolumeRatio( 1.0 ); + auto outputKnob = new VolumeKnob(KnobType::Bright26, tr("OUTPUT"), SMALL_FONT_SIZE, this); + outputKnob->setVolumeRatio(1.0); outputKnob -> move( 76, 223 ); outputKnob->setModel( &_controls->m_outputModel ); outputKnob->setHintText( tr( "Output gain:" ) , "" ); diff --git a/plugins/Eq/EqControlsDialog.cpp b/plugins/Eq/EqControlsDialog.cpp index c7d737d87..c49a30c4b 100644 --- a/plugins/Eq/EqControlsDialog.cpp +++ b/plugins/Eq/EqControlsDialog.cpp @@ -107,14 +107,12 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : { auto resKnob = new Knob(KnobType::Bright26, this); resKnob->move( distance, 440 ); - resKnob->setVolumeKnob(false); resKnob->setModel( m_parameterWidget->getBandModels( i )->res ); if(i > 1 && i < 6) { resKnob->setHintText( tr( "Bandwidth: " ) , tr( " Octave" ) ); } else { resKnob->setHintText(tr("Resonance: "), ""); } auto freqKnob = new Knob(KnobType::Bright26, this); freqKnob->move( distance, 396 ); - freqKnob->setVolumeKnob( false ); freqKnob->setModel( m_parameterWidget->getBandModels( i )->freq ); freqKnob->setHintText( tr( "Frequency:" ), "Hz" ); diff --git a/plugins/Flanger/FlangerControlsDialog.cpp b/plugins/Flanger/FlangerControlsDialog.cpp index e8d382e52..043db4008 100644 --- a/plugins/Flanger/FlangerControlsDialog.cpp +++ b/plugins/Flanger/FlangerControlsDialog.cpp @@ -49,32 +49,26 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) : mainLayout->addLayout(knobLayout); auto delayKnob = new Knob(KnobType::Bright26, tr("DELAY"), this); - delayKnob->setVolumeKnob( false ); delayKnob->setModel( &controls->m_delayTimeModel ); delayKnob->setHintText( tr( "Delay time:" ) + " ", "s" ); auto lfoFreqKnob = new TempoSyncKnob(KnobType::Bright26, tr("RATE"), this); - lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel ); lfoFreqKnob->setHintText( tr( "Period:" ) , " Sec" ); auto lfoAmtKnob = new Knob(KnobType::Bright26, tr("AMNT"), this); - lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setHintText( tr( "Amount:" ) , "" ); auto lfoPhaseKnob = new Knob(KnobType::Bright26, tr("PHASE"), this); - lfoPhaseKnob->setVolumeKnob( false ); lfoPhaseKnob->setModel( &controls->m_lfoPhaseModel ); lfoPhaseKnob->setHintText( tr( "Phase:" ) , " degrees" ); - auto feedbackKnob = new Knob(KnobType::Bright26, tr("FDBK"), this); - feedbackKnob->setVolumeKnob( true) ; + auto feedbackKnob = new VolumeKnob(KnobType::Bright26, tr("FDBK"), this); feedbackKnob->setModel( &controls->m_feedbackModel ); feedbackKnob->setHintText( tr( "Feedback amount:" ) , "" ); - auto whiteNoiseKnob = new Knob(KnobType::Bright26, tr("NOISE"), this); - whiteNoiseKnob->setVolumeKnob( true) ; + auto whiteNoiseKnob = new VolumeKnob(KnobType::Bright26, tr("NOISE"), this); whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel ); whiteNoiseKnob->setHintText( tr( "White noise amount:" ) , "" ); diff --git a/plugins/Monstro/Monstro.cpp b/plugins/Monstro/Monstro.cpp index cb8df131d..c6fc25bb3 100644 --- a/plugins/Monstro/Monstro.cpp +++ b/plugins/Monstro/Monstro.cpp @@ -1665,41 +1665,45 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) auto view = new QWidget(_parent); view-> setFixedSize( 250, 250 ); - makeknob( m_osc1VolKnob, KNOBCOL1, O1ROW, tr( "Volume" ), "%", "osc1Knob" ) - makeknob( m_osc1PanKnob, KNOBCOL2, O1ROW, tr( "Panning" ), "", "osc1Knob" ) - makeknob( m_osc1CrsKnob, KNOBCOL3, O1ROW, tr( "Coarse detune" ), tr( " semitones" ), "osc1Knob" ) - makeknob( m_osc1FtlKnob, KNOBCOL4, O1ROW, tr( "Fine tune left" ), tr( " cents" ), "osc1Knob" ) - makeknob( m_osc1FtrKnob, KNOBCOL5, O1ROW, tr( "Fine tune right" ), tr( " cents" ), "osc1Knob" ) - makeknob( m_osc1SpoKnob, KNOBCOL6, O1ROW, tr( "Stereo phase offset" ), tr( " deg" ), "osc1Knob" ) - makeknob( m_osc1PwKnob, KNOBCOL7, O1ROW, tr( "Pulse width" ), "%", "osc1Knob" ) + auto makeTinyLed = [=, this](int x, int y, const QString& tooltip) -> PixmapButton* { + auto pb = new PixmapButton(view, nullptr); + pb->setCheckable(true); + pb->move(x, y); + pb->setActiveGraphic(PLUGIN_NAME::getIconPixmap("tinyled_on")); + pb->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("tinyled_off")); + pb->setToolTip(tooltip); + return pb; + }; - m_osc1VolKnob -> setVolumeKnob( true ); + m_osc1VolKnob = makeKnob(view, KNOBCOL1, O1ROW, tr("Volume"), "%", "osc1Knob"); + m_osc1PanKnob = makeKnob(view, KNOBCOL2, O1ROW, tr("Panning"), "", "osc1Knob"); + m_osc1CrsKnob = makeKnob(view, KNOBCOL3, O1ROW, tr("Coarse detune"), tr(" semitones"), "osc1Knob"); + m_osc1FtlKnob = makeKnob(view, KNOBCOL4, O1ROW, tr("Fine tune left"), tr(" cents"), "osc1Knob"); + m_osc1FtrKnob = makeKnob(view, KNOBCOL5, O1ROW, tr("Fine tune right"), tr(" cents"), "osc1Knob"); + m_osc1SpoKnob = makeKnob(view, KNOBCOL6, O1ROW, tr("Stereo phase offset"), tr(" deg"), "osc1Knob"); + m_osc1PwKnob = makeKnob(view, KNOBCOL7, O1ROW, tr("Pulse width"), "%", "osc1Knob"); - maketinyled( m_osc1SSRButton, 230, 34, tr( "Send sync on pulse rise" ) ) - maketinyled( m_osc1SSFButton, 230, 44, tr( "Send sync on pulse fall" ) ) + m_osc1SSRButton = makeTinyLed(230, 34, tr("Send sync on pulse rise")); + m_osc1SSFButton = makeTinyLed(230, 44, tr("Send sync on pulse fall")); - makeknob( m_osc2VolKnob, KNOBCOL1, O2ROW, tr( "Volume" ), "%", "osc2Knob" ) - makeknob( m_osc2PanKnob, KNOBCOL2, O2ROW, tr( "Panning" ), "", "osc2Knob" ) - makeknob( m_osc2CrsKnob, KNOBCOL3, O2ROW, tr( "Coarse detune" ), tr( " semitones" ), "osc2Knob" ) - makeknob( m_osc2FtlKnob, KNOBCOL4, O2ROW, tr( "Fine tune left" ), tr( " cents" ), "osc2Knob" ) - makeknob( m_osc2FtrKnob, KNOBCOL5, O2ROW, tr( "Fine tune right" ), tr( " cents" ), "osc2Knob" ) - makeknob( m_osc2SpoKnob, KNOBCOL6, O2ROW, tr( "Stereo phase offset" ), tr( " deg" ), "osc2Knob" ) - - m_osc2VolKnob -> setVolumeKnob( true ); + m_osc2VolKnob = makeKnob(view, KNOBCOL1, O2ROW, tr("Volume"), "%", "osc2Knob"); + m_osc2PanKnob = makeKnob(view, KNOBCOL2, O2ROW, tr("Panning"), "", "osc2Knob"); + m_osc2CrsKnob = makeKnob(view, KNOBCOL3, O2ROW, tr("Coarse detune"), tr(" semitones" ), "osc2Knob"); + m_osc2FtlKnob = makeKnob(view, KNOBCOL4, O2ROW, tr("Fine tune left"), tr(" cents" ), "osc2Knob"); + m_osc2FtrKnob = makeKnob(view, KNOBCOL5, O2ROW, tr("Fine tune right"), tr(" cents" ), "osc2Knob"); + m_osc2SpoKnob = makeKnob(view, KNOBCOL6, O2ROW, tr("Stereo phase offset"), tr(" deg" ), "osc2Knob"); m_osc2WaveBox = new ComboBox( view ); m_osc2WaveBox -> setGeometry( 204, O2ROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); - maketinyled( m_osc2SyncHButton, 212, O2ROW - 3, tr( "Hard sync oscillator 2" ) ) - maketinyled( m_osc2SyncRButton, 191, O2ROW - 3, tr( "Reverse sync oscillator 2" ) ) + m_osc2SyncHButton = makeTinyLed(212, O2ROW - 3, tr("Hard sync oscillator 2")); + m_osc2SyncRButton = makeTinyLed(191, O2ROW - 3, tr("Reverse sync oscillator 2")); - makeknob( m_osc3VolKnob, KNOBCOL1, O3ROW, tr( "Volume" ), "%", "osc3Knob" ) - makeknob( m_osc3PanKnob, KNOBCOL2, O3ROW, tr( "Panning" ), "", "osc3Knob" ) - makeknob( m_osc3CrsKnob, KNOBCOL3, O3ROW, tr( "Coarse detune" ), tr( " semitones" ), "osc3Knob" ) - makeknob( m_osc3SpoKnob, KNOBCOL4, O3ROW, tr( "Stereo phase offset" ), tr( " deg" ), "osc3Knob" ) - makeknob( m_osc3SubKnob, KNOBCOL5, O3ROW, tr( "Sub-osc mix" ), "", "osc3Knob" ) - - m_osc3VolKnob -> setVolumeKnob( true ); + m_osc3VolKnob = makeKnob(view, KNOBCOL1, O3ROW, tr("Volume"), "%", "osc3Knob"); + m_osc3PanKnob = makeKnob(view, KNOBCOL2, O3ROW, tr("Panning"), "", "osc3Knob"); + m_osc3CrsKnob = makeKnob(view, KNOBCOL3, O3ROW, tr("Coarse detune"), tr(" semitones"), "osc3Knob"); + m_osc3SpoKnob = makeKnob(view, KNOBCOL4, O3ROW, tr("Stereo phase offset"), tr(" deg"), "osc3Knob"); + m_osc3SubKnob = makeKnob(view, KNOBCOL5, O3ROW, tr("Sub-osc mix"), "", "osc3Knob"); m_osc3Wave1Box = new ComboBox( view ); m_osc3Wave1Box -> setGeometry( 160, O3ROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); @@ -1707,39 +1711,39 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_osc3Wave2Box = new ComboBox( view ); m_osc3Wave2Box -> setGeometry( 204, O3ROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); - maketinyled( m_osc3SyncHButton, 212, O3ROW - 3, tr( "Hard sync oscillator 3" ) ) - maketinyled( m_osc3SyncRButton, 191, O3ROW - 3, tr( "Reverse sync oscillator 3" ) ) + m_osc3SyncHButton = makeTinyLed(212, O3ROW - 3, tr("Hard sync oscillator 3")); + m_osc3SyncRButton = makeTinyLed(191, O3ROW - 3, tr("Reverse sync oscillator 3")); m_lfo1WaveBox = new ComboBox( view ); m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); - maketsknob( m_lfo1AttKnob, LFOCOL1, LFOROW, tr( "Attack" ), " ms", "lfoKnob" ) - maketsknob( m_lfo1RateKnob, LFOCOL2, LFOROW, tr( "Rate" ), " ms", "lfoKnob" ) - makeknob( m_lfo1PhsKnob, LFOCOL3, LFOROW, tr( "Phase" ), tr( " deg" ), "lfoKnob" ) + m_lfo1AttKnob = makeKnob(view, LFOCOL1, LFOROW, tr("Attack"), " ms", "lfoKnob"); + m_lfo1RateKnob = makeKnob(view, LFOCOL2, LFOROW, tr("Rate"), " ms", "lfoKnob"); + m_lfo1PhsKnob = makeKnob(view, LFOCOL3, LFOROW, tr("Phase"), tr(" deg"), "lfoKnob"); m_lfo2WaveBox = new ComboBox( view ); m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); - maketsknob(m_lfo2AttKnob, LFOCOL4, LFOROW, tr("Attack"), " ms", "lfoKnob") - maketsknob(m_lfo2RateKnob, LFOCOL5, LFOROW, tr("Rate"), " ms", "lfoKnob") - makeknob(m_lfo2PhsKnob, LFOCOL6, LFOROW, tr("Phase"), tr(" deg"), "lfoKnob") + m_lfo2AttKnob = makeKnob(view, LFOCOL4, LFOROW, tr("Attack"), " ms", "lfoKnob"); + m_lfo2RateKnob = makeKnob(view, LFOCOL5, LFOROW, tr("Rate"), " ms", "lfoKnob"); + m_lfo2PhsKnob = makeKnob(view, LFOCOL6, LFOROW, tr("Phase"), tr(" deg"), "lfoKnob"); - maketsknob(m_env1PreKnob, KNOBCOL1, E1ROW, tr("Pre-delay"), " ms", "envKnob") - maketsknob(m_env1AttKnob, KNOBCOL2, E1ROW, tr("Attack"), " ms", "envKnob") - maketsknob(m_env1HoldKnob, KNOBCOL3, E1ROW, tr("Hold"), " ms", "envKnob") - maketsknob(m_env1DecKnob, KNOBCOL4, E1ROW, tr("Decay"), " ms", "envKnob") + m_env1PreKnob = makeKnob(view, KNOBCOL1, E1ROW, tr("Pre-delay"), " ms", "envKnob"); + m_env1AttKnob = makeKnob(view, KNOBCOL2, E1ROW, tr("Attack"), " ms", "envKnob"); + m_env1HoldKnob = makeKnob(view, KNOBCOL3, E1ROW, tr("Hold"), " ms", "envKnob"); + m_env1DecKnob = makeKnob(view, KNOBCOL4, E1ROW, tr("Decay"), " ms", "envKnob"); - makeknob(m_env1SusKnob, KNOBCOL5, E1ROW, tr("Sustain"), "", "envKnob") - maketsknob(m_env1RelKnob, KNOBCOL6, E1ROW, tr("Release"), " ms", "envKnob") - makeknob(m_env1SlopeKnob, KNOBCOL7, E1ROW, tr("Slope"), "", "envKnob") + m_env1SusKnob = makeKnob(view, KNOBCOL5, E1ROW, tr("Sustain"), "", "envKnob"); + m_env1RelKnob = makeKnob(view, KNOBCOL6, E1ROW, tr("Release"), " ms", "envKnob"); + m_env1SlopeKnob = makeKnob(view, KNOBCOL7, E1ROW, tr("Slope"), "", "envKnob"); - maketsknob(m_env2PreKnob, KNOBCOL1, E2ROW, tr("Pre-delay"), " ms", "envKnob") - maketsknob(m_env2AttKnob, KNOBCOL2, E2ROW, tr("Attack"), " ms", "envKnob") - maketsknob(m_env2HoldKnob, KNOBCOL3, E2ROW, tr("Hold"), " ms", "envKnob") - maketsknob(m_env2DecKnob, KNOBCOL4, E2ROW, tr("Decay"), " ms", "envKnob") - makeknob(m_env2SusKnob, KNOBCOL5, E2ROW, tr("Sustain"), "", "envKnob") - maketsknob(m_env2RelKnob, KNOBCOL6, E2ROW, tr("Release"), " ms", "envKnob") - makeknob(m_env2SlopeKnob, KNOBCOL7, E2ROW, tr("Slope"), "", "envKnob") + m_env2PreKnob = makeKnob(view, KNOBCOL1, E2ROW, tr("Pre-delay"), " ms", "envKnob"); + m_env2AttKnob = makeKnob(view, KNOBCOL2, E2ROW, tr("Attack"), " ms", "envKnob"); + m_env2HoldKnob = makeKnob(view, KNOBCOL3, E2ROW, tr("Hold"), " ms", "envKnob"); + m_env2DecKnob = makeKnob(view, KNOBCOL4, E2ROW, tr("Decay"), " ms", "envKnob"); + m_env2SusKnob = makeKnob(view, KNOBCOL5, E2ROW, tr("Sustain"), "", "envKnob"); + m_env2RelKnob = makeKnob(view, KNOBCOL6, E2ROW, tr("Release"), " ms", "envKnob"); + m_env2SlopeKnob = makeKnob(view, KNOBCOL7, E2ROW, tr("Slope"), "", "envKnob"); // mod selector auto m_mixButton = new PixmapButton(view, nullptr); @@ -1785,60 +1789,50 @@ QWidget * MonstroView::setupMatrixView( QWidget * _parent ) auto view = new QWidget(_parent); view-> setFixedSize( 250, 250 ); - makeknob( m_vol1env1Knob, MATCOL1, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol1env2Knob, MATCOL2, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol1lfo1Knob, MATCOL3, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol1lfo2Knob, MATCOL4, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_vol2env1Knob, MATCOL1, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol2env2Knob, MATCOL2, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol2lfo1Knob, MATCOL3, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol2lfo2Knob, MATCOL4, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_vol3env1Knob, MATCOL1, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol3env2Knob, MATCOL2, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol3lfo1Knob, MATCOL3, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_vol3lfo2Knob, MATCOL4, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_phs1env1Knob, MATCOL1, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs1env2Knob, MATCOL2, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs1lfo1Knob, MATCOL3, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs1lfo2Knob, MATCOL4, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_phs2env1Knob, MATCOL1, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs2env2Knob, MATCOL2, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs2lfo1Knob, MATCOL3, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs2lfo2Knob, MATCOL4, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_phs3env1Knob, MATCOL1, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs3env2Knob, MATCOL2, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs3lfo1Knob, MATCOL3, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_phs3lfo2Knob, MATCOL4, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_pit1env1Knob, MATCOL5, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit1env2Knob, MATCOL6, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit1lfo1Knob, MATCOL7, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit1lfo2Knob, MATCOL8, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_pit2env1Knob, MATCOL5, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit2env2Knob, MATCOL6, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit2lfo1Knob, MATCOL7, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit2lfo2Knob, MATCOL8, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_pit3env1Knob, MATCOL5, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit3env2Knob, MATCOL6, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit3lfo1Knob, MATCOL7, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pit3lfo2Knob, MATCOL8, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_pw1env1Knob, MATCOL5, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pw1env2Knob, MATCOL6, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pw1lfo1Knob, MATCOL7, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_pw1lfo2Knob, MATCOL8, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" ) - - makeknob( m_sub3env1Knob, MATCOL5, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_sub3env2Knob, MATCOL6, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_sub3lfo1Knob, MATCOL7, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) - makeknob( m_sub3lfo2Knob, MATCOL8, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" ) + m_vol1env1Knob = makeKnob(view, MATCOL1, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_vol1env2Knob = makeKnob(view, MATCOL2, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_vol1lfo1Knob = makeKnob(view, MATCOL3, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_vol1lfo2Knob = makeKnob(view, MATCOL4, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_vol2env1Knob = makeKnob(view, MATCOL1, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_vol2env2Knob = makeKnob(view, MATCOL2, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_vol2lfo1Knob = makeKnob(view, MATCOL3, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_vol2lfo2Knob = makeKnob(view, MATCOL4, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_vol3env1Knob = makeKnob(view, MATCOL1, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_vol3env2Knob = makeKnob(view, MATCOL2, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_vol3lfo1Knob = makeKnob(view, MATCOL3, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_vol3lfo2Knob = makeKnob(view, MATCOL4, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_phs1env1Knob = makeKnob(view, MATCOL1, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_phs1env2Knob = makeKnob(view, MATCOL2, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_phs1lfo1Knob = makeKnob(view, MATCOL3, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_phs1lfo2Knob = makeKnob(view, MATCOL4, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_phs2env1Knob = makeKnob(view, MATCOL1, MATROW4, tr("Modulation amount"), "", "matrixKnob"); + m_phs2env2Knob = makeKnob(view, MATCOL2, MATROW4, tr("Modulation amount"), "", "matrixKnob"); + m_phs2lfo1Knob = makeKnob(view, MATCOL3, MATROW4, tr("Modulation amount"), "", "matrixKnob"); + m_phs2lfo2Knob = makeKnob(view, MATCOL4, MATROW4, tr("Modulation amount"), "", "matrixKnob"); + m_phs3env1Knob = makeKnob(view, MATCOL1, MATROW6, tr("Modulation amount"), "", "matrixKnob"); + m_phs3env2Knob = makeKnob(view, MATCOL2, MATROW6, tr("Modulation amount"), "", "matrixKnob"); + m_phs3lfo1Knob = makeKnob(view, MATCOL3, MATROW6, tr("Modulation amount"), "", "matrixKnob"); + m_phs3lfo2Knob = makeKnob(view, MATCOL4, MATROW6, tr("Modulation amount"), "", "matrixKnob"); + m_pit1env1Knob = makeKnob(view, MATCOL5, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_pit1env2Knob = makeKnob(view, MATCOL6, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_pit1lfo1Knob = makeKnob(view, MATCOL7, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_pit1lfo2Knob = makeKnob(view, MATCOL8, MATROW1, tr("Modulation amount"), "", "matrixKnob"); + m_pit2env1Knob = makeKnob(view, MATCOL5, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_pit2env2Knob = makeKnob(view, MATCOL6, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_pit2lfo1Knob = makeKnob(view, MATCOL7, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_pit2lfo2Knob = makeKnob(view, MATCOL8, MATROW3, tr("Modulation amount"), "", "matrixKnob"); + m_pit3env1Knob = makeKnob(view, MATCOL5, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_pit3env2Knob = makeKnob(view, MATCOL6, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_pit3lfo1Knob = makeKnob(view, MATCOL7, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_pit3lfo2Knob = makeKnob(view, MATCOL8, MATROW5, tr("Modulation amount"), "", "matrixKnob"); + m_pw1env1Knob = makeKnob(view, MATCOL5, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_pw1env2Knob = makeKnob(view, MATCOL6, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_pw1lfo1Knob = makeKnob(view, MATCOL7, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_pw1lfo2Knob = makeKnob(view, MATCOL8, MATROW2, tr("Modulation amount"), "", "matrixKnob"); + m_sub3env1Knob = makeKnob(view, MATCOL5, MATROW6, tr("Modulation amount"), "", "matrixKnob"); + m_sub3env2Knob = makeKnob(view, MATCOL6, MATROW6, tr("Modulation amount"), "", "matrixKnob"); + m_sub3lfo1Knob = makeKnob(view, MATCOL7, MATROW6, tr("Modulation amount"), "", "matrixKnob"); + m_sub3lfo2Knob = makeKnob(view, MATCOL8, MATROW6, tr("Modulation amount"), "", "matrixKnob"); return( view ); } diff --git a/plugins/Monstro/Monstro.h b/plugins/Monstro/Monstro.h index 4ab1fe183..a80052255 100644 --- a/plugins/Monstro/Monstro.h +++ b/plugins/Monstro/Monstro.h @@ -38,32 +38,6 @@ #include "lmms_math.h" #include "BandLimitedWave.h" -// -// UI Macros -// - -#define makeknob( name, x, y, hint, unit, oname ) \ - name = new Knob( KnobType::Styled, view ); \ - name ->move( x, y ); \ - name ->setHintText( hint, unit ); \ - name ->setObjectName( oname ); \ - name ->setFixedSize( 20, 20 ); - -#define maketsknob( name, x, y, hint, unit, oname ) \ - name = new TempoSyncKnob( KnobType::Styled, view ); \ - name ->move( x, y ); \ - name ->setHintText( hint, unit ); \ - name ->setObjectName( oname ); \ - name ->setFixedSize( 20, 20 ); - -#define maketinyled( name, x, y, ttip ) \ - name = new PixmapButton( view, nullptr ); \ - name -> setCheckable( true ); \ - name -> move( x, y ); \ - name -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "tinyled_on" ) ); \ - name -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "tinyled_off" ) ); \ - name->setToolTip(ttip); - namespace lmms { @@ -604,6 +578,18 @@ private: QWidget * setupOperatorsView( QWidget * _parent ); QWidget * setupMatrixView( QWidget * _parent ); + template + auto makeKnob(QWidget* view, int x, int y, const QString& hint, + const QString& unit, const QString& objName) -> T* + { + T* knob = new T(KnobType::Styled, view); + knob->move(x, y); + knob->setHintText(hint, unit); + knob->setObjectName(objName); + knob->setFixedSize(20, 20); + return knob; + } + ////////////////////////////////////// // // // operator view knobs // diff --git a/plugins/Organic/Organic.cpp b/plugins/Organic/Organic.cpp index 9f7aba8dd..6a102e0be 100644 --- a/plugins/Organic/Organic.cpp +++ b/plugins/Organic/Organic.cpp @@ -372,14 +372,24 @@ namespace gui class OrganicKnob : public Knob { public: - OrganicKnob( QWidget * _parent ) : - Knob( KnobType::Styled, _parent ) + OrganicKnob(QWidget* parent) + : Knob(KnobType::Styled, parent) { - setFixedSize( 21, 21 ); + setFixedSize(21, 21); } }; +class OrganicVolumeKnob : public VolumeKnob +{ +public: + OrganicVolumeKnob(QWidget* parent) + : VolumeKnob(KnobType::Styled, parent) + { + setFixedSize(21, 21); + } +}; + OrganicInstrumentView::OrganicInstrumentView( Instrument * _instrument, QWidget * _parent ) : @@ -402,8 +412,7 @@ OrganicInstrumentView::OrganicInstrumentView( Instrument * _instrument, m_fx1Knob->setObjectName( "fx1Knob" ); // setup volume-knob - m_volKnob = new OrganicKnob( this ); - m_volKnob->setVolumeKnob( true ); + m_volKnob = new OrganicVolumeKnob(this); m_volKnob->move( 60, 201 ); m_volKnob->setFixedSize( 37, 47 ); m_volKnob->setHintText( tr( "Volume:" ), "%" ); @@ -470,8 +479,7 @@ void OrganicInstrumentView::modelChanged() oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ), QString() ); // setup volume-knob - auto volKnob = new Knob(KnobType::Styled, this); - volKnob->setVolumeKnob( true ); + auto volKnob = new VolumeKnob(KnobType::Styled, this); volKnob->move( x + i * colWidth, y + rowHeight*1 ); volKnob->setFixedSize( 21, 21 ); volKnob->setHintText( tr( "Osc %1 volume:" ).arg( diff --git a/plugins/TripleOscillator/TripleOscillator.cpp b/plugins/TripleOscillator/TripleOscillator.cpp index 8c29fff90..562b0da1f 100644 --- a/plugins/TripleOscillator/TripleOscillator.cpp +++ b/plugins/TripleOscillator/TripleOscillator.cpp @@ -551,8 +551,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, int knob_y = osc_y + i * osc_h; // setup volume-knob - auto vk = new Knob(KnobType::Styled, this); - vk->setVolumeKnob( true ); + auto vk = new VolumeKnob(KnobType::Styled, this); vk->setFixedSize( 28, 35 ); vk->move( 6, knob_y ); vk->setHintText( tr( "Osc %1 volume:" ).arg( diff --git a/plugins/Vestige/Vestige.cpp b/plugins/Vestige/Vestige.cpp index 56dda1eea..eb320370d 100644 --- a/plugins/Vestige/Vestige.cpp +++ b/plugins/Vestige/Vestige.cpp @@ -22,31 +22,27 @@ * */ -#include - -#include "VstPlugin.h" - #include "Vestige.h" -#include - +#include #include #include +#include +#include #include #include #include -#include -#include -#include - +#include +#include #include "AudioEngine.h" +#include "Clipboard.h" #include "ConfigManager.h" -#include "CustomTextKnob.h" +#include "embed.h" #include "Engine.h" #include "FileDialog.h" -#include "GuiApplication.h" #include "FontHelper.h" +#include "GuiApplication.h" #include "InstrumentPlayHandle.h" #include "InstrumentTrack.h" #include "LocaleHelper.h" @@ -57,10 +53,7 @@ #include "StringPairDrag.h" #include "SubWindow.h" #include "TextFloat.h" -#include "Clipboard.h" - - -#include "embed.h" +#include "VstPlugin.h" namespace lmms { @@ -960,7 +953,7 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume const QMap & dump = m_vi->m_plugin->parameterDump(); m_vi->paramCount = dump.size(); - vstKnobs = new CustomTextKnob *[ m_vi->paramCount ]; + m_vstKnobs.reserve(m_vi->paramCount); bool hasKnobModel = true; if (m_vi->knobFModel == nullptr) { @@ -976,11 +969,10 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume std::snprintf(paramStr.data(), paramStr.size(), "param%d", i); s_dumpValues = dump[paramStr.data()].split(":"); - const auto & description = s_dumpValues.at(1); + const auto& description = s_dumpValues.at(1); - auto knob = new CustomTextKnob(KnobType::Bright26, description.left(15), this, description); - knob->setDescription(description + ":"); - vstKnobs[i] = knob; + auto knob = new VstPluginKnob{m_vi->m_plugin, i, description, this}; + m_vstKnobs.push_back(knob); if( !hasKnobModel ) { @@ -992,9 +984,10 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume FloatModel * model = m_vi->knobFModel[i]; connect( model, &FloatModel::dataChanged, this, [this, model]() { setParameter( model ); }, Qt::DirectConnection); - vstKnobs[i] ->setModel( model ); + knob->setModel(model); } - syncParameterText(); + m_vi->m_plugin->loadParameterLabels(); + m_vi->m_plugin->loadParameterDisplays(); int i = 0; for( int lrow = 1; lrow < ( int( m_vi->paramCount / 10 ) + 1 ) + 1; lrow++ ) @@ -1003,7 +996,7 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume { if( i < m_vi->paramCount ) { - l->addWidget( vstKnobs[i], lrow, lcolumn, Qt::AlignCenter ); + l->addWidget(m_vstKnobs[i], lrow, lcolumn, Qt::AlignCenter); } i++; } @@ -1054,7 +1047,8 @@ void ManageVestigeInstrumentView::syncPlugin( void ) m_vi->knobFModel[i]->setInitValue(f_value); } } - syncParameterText(); + m_vi->m_plugin->loadParameterLabels(); + m_vi->m_plugin->loadParameterDisplays(); } @@ -1069,12 +1063,12 @@ void ManageVestigeInstrumentView::displayAutomatedOnly( void ) if( !( m_vi->knobFModel[ i ]->isAutomated() || m_vi->knobFModel[ i ]->controllerConnection() ) ) { - if( vstKnobs[ i ]->isVisible() == true && isAuto ) + if (m_vstKnobs[i]->isVisible() && isAuto) { - vstKnobs[ i ]->hide(); + m_vstKnobs[i]->hide(); m_displayAutomatedOnly->setText( "All" ); } else { - vstKnobs[ i ]->show(); + m_vstKnobs[i]->show(); m_displayAutomatedOnly->setText( "Automated" ); } } @@ -1089,15 +1083,10 @@ ManageVestigeInstrumentView::~ManageVestigeInstrumentView() for( int i = 0; i < m_vi->paramCount; i++ ) { delete m_vi->knobFModel[ i ]; - delete vstKnobs[ i ]; + delete m_vstKnobs[i]; } } - if (vstKnobs != nullptr) { - delete []vstKnobs; - vstKnobs = nullptr; - } - if( m_vi->knobFModel != nullptr ) { delete [] m_vi->knobFModel; @@ -1130,40 +1119,9 @@ void ManageVestigeInstrumentView::setParameter( Model * action ) if ( m_vi->m_plugin != nullptr ) { 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 3bdd0644e..8dd955c77 100644 --- a/plugins/Vestige/Vestige.h +++ b/plugins/Vestige/Vestige.h @@ -47,10 +47,10 @@ class VstPlugin; namespace gui { -class PixmapButton; -class CustomTextKnob; -class VestigeInstrumentView; class ManageVestigeInstrumentView; +class PixmapButton; +class VestigeInstrumentView; +class VstPluginKnob; } // namespace gui @@ -108,23 +108,19 @@ class ManageVestigeInstrumentView : public InstrumentViewFixedSize Q_OBJECT public: ManageVestigeInstrumentView( Instrument * _instrument, QWidget * _parent, VestigeInstrument * m_vi2 ); - virtual ~ManageVestigeInstrumentView(); - + ~ManageVestigeInstrumentView() override; protected slots: void syncPlugin(); void displayAutomatedOnly(); void setParameter( lmms::Model * action ); - void syncParameterText(); void closeWindow(); - protected: virtual void dragEnterEvent( QDragEnterEvent * _dee ); virtual void dropEvent( QDropEvent * _de ); virtual void paintEvent( QPaintEvent * _pe ); - private: VestigeInstrument * m_vi; @@ -133,9 +129,8 @@ private: QPushButton * m_syncButton; QPushButton * m_displayAutomatedOnly; QPushButton * m_closeButton; - CustomTextKnob ** vstKnobs; - -} ; + std::vector m_vstKnobs; +}; class VestigeInstrumentView : public InstrumentViewFixedSize diff --git a/plugins/Vibed/Vibed.cpp b/plugins/Vibed/Vibed.cpp index ff21f8133..1c9804541 100644 --- a/plugins/Vibed/Vibed.cpp +++ b/plugins/Vibed/Vibed.cpp @@ -293,7 +293,6 @@ VibedView::VibedView(Instrument* instrument, QWidget* parent) : pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); setPalette(pal); - m_volumeKnob.setVolumeKnob(true); m_volumeKnob.move(103, 142); m_volumeKnob.setHintText(tr("String volume:"), ""); diff --git a/plugins/Vibed/Vibed.h b/plugins/Vibed/Vibed.h index e3929925f..82d651a93 100644 --- a/plugins/Vibed/Vibed.h +++ b/plugins/Vibed/Vibed.h @@ -116,7 +116,7 @@ private: void modelChanged() override; // String-related - Knob m_volumeKnob; + VolumeKnob m_volumeKnob; Knob m_stiffnessKnob; Knob m_pickKnob; Knob m_pickupKnob; diff --git a/plugins/VstBase/RemoteVstPlugin.cpp b/plugins/VstBase/RemoteVstPlugin.cpp index 748ed1046..7343078ea 100644 --- a/plugins/VstBase/RemoteVstPlugin.cpp +++ b/plugins/VstBase/RemoteVstPlugin.cpp @@ -246,9 +246,15 @@ public: // determine name of current program const char * programName(); - void getParameterDisplays(); + void loadAllParameterDisplays(); - void getParameterLabels(); + void loadAllParameterLabels(); + + //! Updates a parameter display that has already been loaded + void updateParameterDisplay(int index); + + //! Updates a parameter label that has already been loaded + void updateParameterLabel(int index); // send name of current program back to host void sendCurrentProgramName(); @@ -670,14 +676,21 @@ bool RemoteVstPlugin::processMessage( const message & _m ) //sendMessage( IdVstSetParameter ); break; - case IdVstParameterDisplays: - getParameterDisplays(); + case IdVstLoadAllParameterDisplays: + loadAllParameterDisplays(); break; - case IdVstParameterLabels: - getParameterLabels(); + case IdVstLoadAllParameterLabels: + loadAllParameterLabels(); break; + case IdVstUpdateParameterDisplay: + updateParameterDisplay(_m.getInt()); + break; + + case IdVstUpdateParameterLabel: + updateParameterLabel(_m.getInt()); + break; case IdVstIdleUpdate: { @@ -1202,7 +1215,7 @@ const char * RemoteVstPlugin::programName() // join the ParameterDisplays (stringified values without units) and send them to host -void RemoteVstPlugin::getParameterDisplays() +void RemoteVstPlugin::loadAllParameterDisplays() { std::string paramDisplays; static char buf[9]; // buffer for getting string @@ -1217,13 +1230,13 @@ void RemoteVstPlugin::getParameterDisplays() paramDisplays += buf; } - sendMessage( message( IdVstParameterDisplays ).addString( paramDisplays.c_str() ) ); + sendMessage(message(IdVstLoadAllParameterDisplays).addString(std::move(paramDisplays))); } // join the ParameterLabels (units) and send them to host -void RemoteVstPlugin::getParameterLabels() +void RemoteVstPlugin::loadAllParameterLabels() { std::string paramLabels; static char buf[9]; // buffer for getting string @@ -1238,7 +1251,35 @@ void RemoteVstPlugin::getParameterLabels() paramLabels += buf; } - sendMessage( message( IdVstParameterLabels ).addString( paramLabels.c_str() ) ); + sendMessage(message(IdVstLoadAllParameterLabels).addString(std::move(paramLabels))); +} + + + + +void RemoteVstPlugin::updateParameterDisplay(int index) +{ + assert(index < m_plugin->numParams); + + static char display[9] = {}; + pluginDispatch(effGetParamDisplay, index, 0, display); + display[8] = '\0'; + + sendMessage(message(IdVstUpdateParameterDisplay).addInt(index).addString(display)); +} + + + + +void RemoteVstPlugin::updateParameterLabel(int index) +{ + assert(index < m_plugin->numParams); + + static char label[9] = {}; + pluginDispatch(effGetParamLabel, index, 0, label); + label[8] = '\0'; + + sendMessage(message(IdVstUpdateParameterLabel).addInt(index).addString(label)); } diff --git a/plugins/VstBase/VstPlugin.cpp b/plugins/VstBase/VstPlugin.cpp index c224d0d5f..2789ebd89 100644 --- a/plugins/VstBase/VstPlugin.cpp +++ b/plugins/VstBase/VstPlugin.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #if defined(LMMS_BUILD_LINUX) && (QT_VERSION < QT_VERSION_CHECK(6,0,0)) # include @@ -50,10 +51,12 @@ #include "AudioEngine.h" #include "ConfigManager.h" #include "FileDialog.h" +#include "FontHelper.h" #include "GuiApplication.h" #include "LocaleHelper.h" #include "MainWindow.h" #include "PathUtil.h" +#include "SimpleTextFloat.h" #include "Song.h" #ifdef LMMS_BUILD_LINUX @@ -456,12 +459,38 @@ bool VstPlugin::processMessage( const message & _m ) m_allProgramNames = _m.getQString(); break; - case IdVstParameterLabels: - m_allParameterLabels = _m.getQString(); + case IdVstLoadAllParameterLabels: + { + const auto labels = _m.getQString(); + m_allParameterLabels.clear(); + for (int i = 0; i < labels.size();) + { + const int length = labels[i].digitValue(); + m_allParameterLabels.push_back(labels.mid(i + 1, length)); + i += length + 1; + } + break; + } + + case IdVstLoadAllParameterDisplays: + { + const auto displays = _m.getQString(); + m_allParameterDisplays.clear(); + for (int i = 0; i < displays.size();) + { + const int length = displays[i].digitValue(); + m_allParameterDisplays.push_back(displays.mid(i + 1, length)); + i += length + 1; + } + break; + } + + case IdVstUpdateParameterLabel: + m_allParameterLabels.at(static_cast(_m.getInt(0))) = _m.getQString(1); break; - case IdVstParameterDisplays: - m_allParameterDisplays = _m.getQString(); + case IdVstUpdateParameterDisplay: + m_allParameterDisplays.at(static_cast(_m.getInt(0))) = _m.getQString(1); break; case IdVstPluginUniqueID: @@ -554,8 +583,8 @@ void VstPlugin::loadProgramNames() void VstPlugin::loadParameterLabels() { lock(); - sendMessage( message( IdVstParameterLabels ) ); - waitForMessage( IdVstParameterLabels, true ); + sendMessage(message(IdVstLoadAllParameterLabels)); + waitForMessage(IdVstLoadAllParameterLabels, true); unlock(); } @@ -565,8 +594,30 @@ void VstPlugin::loadParameterLabels() void VstPlugin::loadParameterDisplays() { lock(); - sendMessage( message( IdVstParameterDisplays ) ); - waitForMessage( IdVstParameterDisplays, true ); + sendMessage(message(IdVstLoadAllParameterDisplays)); + waitForMessage(IdVstLoadAllParameterDisplays, true); + unlock(); +} + + + + +void VstPlugin::updateParameterLabel(int index) +{ + lock(); + sendMessage(message(IdVstUpdateParameterLabel).addInt(index)); + waitForMessage(IdVstUpdateParameterLabel, true); + unlock(); +} + + + + +void VstPlugin::updateParameterDisplay(int index) +{ + lock(); + sendMessage(message(IdVstUpdateParameterDisplay).addInt(index)); + waitForMessage(IdVstUpdateParameterDisplay, true); unlock(); } @@ -813,5 +864,69 @@ QString VstPlugin::embedMethod() const return m_embedMethod; } +namespace gui { +VstPluginKnob::VstPluginKnob(VstPlugin* plugin, int paramIndex, const QString& name, QWidget* parent) + : gui::Knob{gui::KnobType::Bright26, name.left(15), SMALL_FONT_SIZE, parent, name} + , m_plugin{plugin} + , m_paramIndex{paramIndex} +{ + assert(m_plugin != nullptr); + setDescription(name + ":"); +} + +void VstPluginKnob::timerEvent(QTimerEvent* event) +{ + if (event->timerId() != m_rateLimitTimerId) { return; } + + if (textFloat().source() != static_cast(this)) + { + // This knob is no longer controlling the text float, + // so we don't need the timer to continue running. + killTimer(m_rateLimitTimerId); + m_rateLimitTimerId = 0; + return; + } + + // Enough time has passed, so time for an update + m_updateNow = true; +} + +auto VstPluginKnob::getCustomFloatingText() -> QString +{ + constexpr auto updatesPerSecond = 15; + + if (m_rateLimitTimerId == 0) + { + // Use a timer to control the rate of text float updates. + // Otherwise the CPU will spike when the parameter emits a bunch of dataChanged() + // events in a short period of time - i.e. when the parameter's value changes rapidly. + m_rateLimitTimerId = startTimer(std::chrono::milliseconds{1000} / updatesPerSecond); + } + + return getParameterText(); +} + +auto VstPluginKnob::getCustomFloatingTextUpdate() -> std::optional +{ + if (!m_updateNow) { return std::nullopt; } + m_updateNow = false; + + return getParameterText(); +} + +auto VstPluginKnob::getParameterText() const -> QString +{ + m_plugin->updateParameterLabel(m_paramIndex); + m_plugin->updateParameterDisplay(m_paramIndex); + + const auto& paramLabels = m_plugin->allParameterLabels(); + const auto& paramDisplays = m_plugin->allParameterDisplays(); + assert(paramLabels.size() == paramDisplays.size()); + + assert(m_paramIndex < paramLabels.size()); + return paramDisplays[m_paramIndex] + ' ' + paramLabels[m_paramIndex]; +} + +} // namespace gui } // namespace lmms diff --git a/plugins/VstBase/VstPlugin.h b/plugins/VstBase/VstPlugin.h index 03e732970..22a5ca6ef 100644 --- a/plugins/VstBase/VstPlugin.h +++ b/plugins/VstBase/VstPlugin.h @@ -31,6 +31,7 @@ #include #include +#include "Knob.h" #include "JournallingObject.h" #include "RemotePlugin.h" @@ -91,12 +92,12 @@ public: return m_allProgramNames; } - inline const QString& allParameterLabels() const + const std::vector& allParameterLabels() const { return m_allParameterLabels; } - inline const QString& allParameterDisplays() const + const std::vector& allParameterDisplays() const { return m_allParameterDisplays; } @@ -132,6 +133,8 @@ public slots: void loadProgramNames(); void loadParameterLabels(); void loadParameterDisplays(); + void updateParameterLabel(int index); + void updateParameterDisplay(int index); void savePreset(); void setParam( int i, float f ); void idleUpdate(); @@ -160,8 +163,8 @@ private: QString m_productString; QString m_currentProgramName; QString m_allProgramNames; - QString m_allParameterLabels; - QString m_allParameterDisplays; + std::vector m_allParameterLabels; + std::vector m_allParameterDisplays; QString p_name; @@ -173,7 +176,30 @@ private: } ; +namespace gui { +class VSTBASE_EXPORT VstPluginKnob : public Knob +{ +public: + VstPluginKnob(VstPlugin* plugin, int paramIndex, const QString& name, QWidget* parent); + ~VstPluginKnob() override = default; + +private: + void timerEvent(QTimerEvent* event) override; + + auto getCustomFloatingText() -> QString override; + auto getCustomFloatingTextUpdate() -> std::optional override; + + auto getParameterText() const -> QString; + + VstPlugin* m_plugin = nullptr; + int m_paramIndex = 0; + + int m_rateLimitTimerId = 0; + bool m_updateNow = false; +}; + +} // namespace gui } // namespace lmms #endif diff --git a/plugins/VstBase/communication.h b/plugins/VstBase/communication.h index 50351d38e..d3f564774 100644 --- a/plugins/VstBase/communication.h +++ b/plugins/VstBase/communication.h @@ -69,8 +69,10 @@ enum VstRemoteMessageIDs IdVstSetProgram, IdVstRotateProgram, IdVstIdleUpdate, - IdVstParameterDisplays, - IdVstParameterLabels, + IdVstLoadAllParameterDisplays, + IdVstLoadAllParameterLabels, + IdVstUpdateParameterDisplay, + IdVstUpdateParameterLabel, // remoteVstPlugin -> vstPlugin IdVstFailedLoadingPlugin, diff --git a/plugins/VstEffect/VstEffectControls.cpp b/plugins/VstEffect/VstEffectControls.cpp index de4516014..0459bd84a 100644 --- a/plugins/VstEffect/VstEffectControls.cpp +++ b/plugins/VstEffect/VstEffectControls.cpp @@ -22,7 +22,10 @@ * */ +#include "VstEffectControls.h" + #include +#include #include #include #include @@ -30,18 +33,14 @@ #include #include "embed.h" -#include "CustomTextKnob.h" -#include "VstEffectControls.h" +#include "GuiApplication.h" +#include "LocaleHelper.h" +#include "MainWindow.h" +#include "SubWindow.h" #include "VstEffectControlDialog.h" #include "VstEffect.h" #include "VstPlugin.h" -#include "LocaleHelper.h" -#include "MainWindow.h" -#include "GuiApplication.h" -#include "SubWindow.h" -#include - namespace lmms { @@ -362,7 +361,7 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls * const QMap & dump = m_effect->m_plugin->parameterDump(); m_vi->paramCount = dump.size(); - vstKnobs = new CustomTextKnob *[ m_vi->paramCount ]; + m_vstKnobs.reserve(m_vi->paramCount); bool hasKnobModel = true; if (m_vi->knobFModel.empty()) @@ -379,11 +378,10 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls * std::snprintf(paramStr.data(), paramStr.size(), "param%d", i); s_dumpValues = dump[paramStr.data()].split(":"); - const auto & description = s_dumpValues.at(1); + const auto& description = s_dumpValues.at(1); - auto knob = new CustomTextKnob(KnobType::Bright26, description.left(15), widget, description); - knob->setDescription(description + ":"); - vstKnobs[i] = knob; + auto knob = new VstPluginKnob{m_effect->m_plugin.get(), i, description, widget}; + m_vstKnobs.push_back(knob); if( !hasKnobModel ) { @@ -395,9 +393,10 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls * FloatModel * model = m_vi->knobFModel[i]; connect( model, &FloatModel::dataChanged, this, [this, model]() { setParameter( model ); }, Qt::DirectConnection); - vstKnobs[ i ] ->setModel( model ); + knob->setModel(model); } - syncParameterText(); + m_effect->m_plugin->loadParameterLabels(); + m_effect->m_plugin->loadParameterDisplays(); int i = 0; for( int lrow = 1; lrow < ( int( m_vi->paramCount / 10 ) + 1 ) + 1; lrow++ ) @@ -406,7 +405,7 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls * { if( i < m_vi->paramCount ) { - l->addWidget( vstKnobs[i], lrow, lcolumn, Qt::AlignCenter ); + l->addWidget(m_vstKnobs[i], lrow, lcolumn, Qt::AlignCenter); } i++; } @@ -459,7 +458,8 @@ void ManageVSTEffectView::syncPlugin() m_vi2->knobFModel[i]->setInitValue(f_value); } } - syncParameterText(); + m_effect->m_plugin->loadParameterLabels(); + m_effect->m_plugin->loadParameterDisplays(); } @@ -474,12 +474,12 @@ void ManageVSTEffectView::displayAutomatedOnly() if( !( m_vi2->knobFModel[ i ]->isAutomated() || m_vi2->knobFModel[ i ]->controllerConnection() ) ) { - if( vstKnobs[ i ]->isVisible() == true && isAuto ) + if (m_vstKnobs[i]->isVisible() && isAuto) { - vstKnobs[ i ]->hide(); + m_vstKnobs[i]->hide(); m_displayAutomatedOnly->setText( "All" ); } else { - vstKnobs[ i ]->show(); + m_vstKnobs[i]->show(); m_displayAutomatedOnly->setText( "Automated" ); } } @@ -495,43 +495,9 @@ void ManageVSTEffectView::setParameter( Model * action ) if ( m_effect->m_plugin != nullptr ) { 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]); - } -} - - - ManageVSTEffectView::~ManageVSTEffectView() { if (!m_vi2->knobFModel.empty()) @@ -539,16 +505,10 @@ ManageVSTEffectView::~ManageVSTEffectView() for( int i = 0; i < m_vi2->paramCount; i++ ) { delete m_vi2->knobFModel[ i ]; - delete vstKnobs[ i ]; + delete m_vstKnobs[i]; } } - if( vstKnobs != nullptr ) - { - delete [] vstKnobs; - vstKnobs = nullptr; - } - m_vi2->knobFModel.clear(); if( m_vi2->m_scrollArea != nullptr ) diff --git a/plugins/VstEffect/VstEffectControls.h b/plugins/VstEffect/VstEffectControls.h index e2bea36e8..e1b4e13b4 100644 --- a/plugins/VstEffect/VstEffectControls.h +++ b/plugins/VstEffect/VstEffectControls.h @@ -44,9 +44,9 @@ class VstEffect; namespace gui { -class CustomTextKnob; class ManageVSTEffectView; class VstEffectControlDialog; +class VstPluginKnob; } @@ -120,11 +120,9 @@ protected slots: void syncPlugin(); void displayAutomatedOnly(); void setParameter( lmms::Model * action ); - void syncParameterText(); void closeWindow(); private: - // static QPixmap * s_artwork; VstEffectControls * m_vi2; @@ -139,9 +137,8 @@ private: QPushButton * m_syncButton; QPushButton * m_displayAutomatedOnly; QPushButton * m_closeButton; - CustomTextKnob ** vstKnobs; - -} ; + std::vector m_vstKnobs; +}; } // namespace gui diff --git a/plugins/Watsyn/Watsyn.cpp b/plugins/Watsyn/Watsyn.cpp index 455f4cdc9..532d2093e 100644 --- a/plugins/Watsyn/Watsyn.cpp +++ b/plugins/Watsyn/Watsyn.cpp @@ -684,46 +684,40 @@ WatsynView::WatsynView( Instrument * _instrument, // knobs... lots of em - makeknob( a1_volKnob, 130, A1ROW, tr( "Volume" ), "%", "aKnob" ) - makeknob( a2_volKnob, 130, A2ROW, tr( "Volume" ), "%", "aKnob" ) - makeknob( b1_volKnob, 130, B1ROW, tr( "Volume" ), "%", "bKnob" ) - makeknob( b2_volKnob, 130, B2ROW, tr( "Volume" ), "%", "bKnob" ) + a1_volKnob = makeKnob(130, A1ROW, tr("Volume"), "%", "aKnob"); + a2_volKnob = makeKnob(130, A2ROW, tr("Volume"), "%", "aKnob"); + b1_volKnob = makeKnob(130, B1ROW, tr("Volume"), "%", "bKnob"); + b2_volKnob = makeKnob(130, B2ROW, tr("Volume"), "%", "bKnob"); - makeknob( a1_panKnob, 154, A1ROW, tr( "Panning" ), "", "aKnob" ) - makeknob( a2_panKnob, 154, A2ROW, tr( "Panning" ), "", "aKnob" ) - makeknob( b1_panKnob, 154, B1ROW, tr( "Panning" ), "", "bKnob" ) - makeknob( b2_panKnob, 154, B2ROW, tr( "Panning" ), "", "bKnob" ) + a1_panKnob = makeKnob(154, A1ROW, tr("Panning"), "", "aKnob"); + a2_panKnob = makeKnob(154, A2ROW, tr("Panning"), "", "aKnob"); + b1_panKnob = makeKnob(154, B1ROW, tr("Panning"), "", "bKnob"); + b2_panKnob = makeKnob(154, B2ROW, tr("Panning"), "", "bKnob"); - makeknob( a1_multKnob, 178, A1ROW, tr( "Freq. multiplier" ), "/8", "aKnob" ) - makeknob( a2_multKnob, 178, A2ROW, tr( "Freq. multiplier" ), "/8", "aKnob" ) - makeknob( b1_multKnob, 178, B1ROW, tr( "Freq. multiplier" ), "/8", "bKnob" ) - makeknob( b2_multKnob, 178, B2ROW, tr( "Freq. multiplier" ), "/8", "bKnob" ) + a1_multKnob = makeKnob(178, A1ROW, tr("Freq. multiplier"), "/8", "aKnob"); + a2_multKnob = makeKnob(178, A2ROW, tr("Freq. multiplier"), "/8", "aKnob"); + b1_multKnob = makeKnob(178, B1ROW, tr("Freq. multiplier"), "/8", "bKnob"); + b2_multKnob = makeKnob(178, B2ROW, tr("Freq. multiplier"), "/8", "bKnob"); - makeknob( a1_ltuneKnob, 202, A1ROW, tr( "Left detune" ), tr( " cents" ), "aKnob" ) - makeknob( a2_ltuneKnob, 202, A2ROW, tr( "Left detune" ), tr( " cents" ), "aKnob" ) - makeknob( b1_ltuneKnob, 202, B1ROW, tr( "Left detune" ), tr( " cents" ), "bKnob" ) - makeknob( b2_ltuneKnob, 202, B2ROW, tr( "Left detune" ), tr( " cents" ), "bKnob" ) + a1_ltuneKnob = makeKnob(202, A1ROW, tr("Left detune"), tr(" cents"), "aKnob"); + a2_ltuneKnob = makeKnob(202, A2ROW, tr("Left detune"), tr(" cents"), "aKnob"); + b1_ltuneKnob = makeKnob(202, B1ROW, tr("Left detune"), tr(" cents"), "bKnob"); + b2_ltuneKnob = makeKnob(202, B2ROW, tr("Left detune"), tr(" cents"), "bKnob"); - makeknob( a1_rtuneKnob, 226, A1ROW, tr( "Right detune" ), tr( " cents" ), "aKnob" ) - makeknob( a2_rtuneKnob, 226, A2ROW, tr( "Right detune" ), tr( " cents" ), "aKnob" ) - makeknob( b1_rtuneKnob, 226, B1ROW, tr( "Right detune" ), tr( " cents" ), "bKnob" ) - makeknob( b2_rtuneKnob, 226, B2ROW, tr( "Right detune" ), tr( " cents" ), "bKnob" ) + a1_rtuneKnob = makeKnob(226, A1ROW, tr("Right detune"), tr(" cents"), "aKnob"); + a2_rtuneKnob = makeKnob(226, A2ROW, tr("Right detune"), tr(" cents"), "aKnob"); + b1_rtuneKnob = makeKnob(226, B1ROW, tr("Right detune"), tr(" cents"), "bKnob"); + b2_rtuneKnob = makeKnob(226, B2ROW, tr("Right detune"), tr(" cents"), "bKnob"); - makeknob( m_abmixKnob, 4, 3, tr( "A-B Mix" ), "", "mixKnob" ) + m_abmixKnob = makeKnob(4, 3, tr("A-B Mix"), "", "mixKnob"); - makeknob( m_envAmtKnob, 88, 3, tr( "Mix envelope amount" ), "", "mixenvKnob" ) + m_envAmtKnob = makeKnob(88, 3, tr("Mix envelope amount"), "", "mixenvKnob"); - maketsknob( m_envAttKnob, 88, A1ROW, tr( "Mix envelope attack" ), " ms", "mixenvKnob" ) - maketsknob( m_envHoldKnob, 88, A2ROW, tr( "Mix envelope hold" ), " ms", "mixenvKnob" ) - maketsknob( m_envDecKnob, 88, B1ROW, tr( "Mix envelope decay" ), " ms", "mixenvKnob" ) + m_envAttKnob = makeKnob(88, A1ROW, tr("Mix envelope attack"), " ms", "mixenvKnob"); + m_envHoldKnob = makeKnob(88, A2ROW, tr("Mix envelope hold"), " ms", "mixenvKnob"); + m_envDecKnob = makeKnob(88, B1ROW, tr("Mix envelope decay"), " ms", "mixenvKnob"); - makeknob( m_xtalkKnob, 88, B2ROW, tr( "Crosstalk" ), "", "xtalkKnob" ) - -// let's set volume knobs - a1_volKnob -> setVolumeKnob( true ); - a2_volKnob -> setVolumeKnob( true ); - b1_volKnob -> setVolumeKnob( true ); - b2_volKnob -> setVolumeKnob( true ); + m_xtalkKnob = makeKnob(88, B2ROW, tr("Crosstalk"), "", "xtalkKnob"); m_abmixKnob -> setFixedSize( 31, 31 ); diff --git a/plugins/Watsyn/Watsyn.h b/plugins/Watsyn/Watsyn.h index 1e0ba0c78..b45bcebc4 100644 --- a/plugins/Watsyn/Watsyn.h +++ b/plugins/Watsyn/Watsyn.h @@ -37,21 +37,6 @@ namespace lmms { - -#define makeknob( name, x, y, hint, unit, oname ) \ - name = new Knob( KnobType::Styled, this ); \ - name ->move( x, y ); \ - name ->setHintText( hint, unit ); \ - name ->setObjectName( oname ); \ - name ->setFixedSize( 19, 19 ); - -#define maketsknob( name, x, y, hint, unit, oname ) \ - name = new TempoSyncKnob( KnobType::Styled, this ); \ - name ->move( x, y ); \ - name ->setHintText( hint, unit ); \ - name ->setObjectName( oname ); \ - name ->setFixedSize( 19, 19 ); - #define A1ROW 26 #define A2ROW 49 #define B1ROW 72 @@ -325,6 +310,18 @@ protected slots: private: void modelChanged() override; + template + auto makeKnob(int x, int y, const QString& hint, const QString& unit, + const QString& objName) -> T* + { + T* knob = new T(KnobType::Styled, this); + knob->move(x, y); + knob->setHintText(hint, unit); + knob->setObjectName(objName); + knob->setFixedSize(19, 19); + return knob; + }; + // knobs Knob * a1_volKnob; Knob * a2_volKnob; diff --git a/plugins/WaveShaper/WaveShaperControlDialog.cpp b/plugins/WaveShaper/WaveShaperControlDialog.cpp index 17955fe28..76fb89984 100644 --- a/plugins/WaveShaper/WaveShaperControlDialog.cpp +++ b/plugins/WaveShaper/WaveShaperControlDialog.cpp @@ -60,16 +60,14 @@ WaveShaperControlDialog::WaveShaperControlDialog( waveGraph->setGraphColor( QColor( 85, 204, 145 ) ); waveGraph -> setMaximumSize( 204, 205 ); - auto inputKnob = new Knob(KnobType::Bright26, tr("INPUT"), SMALL_FONT_SIZE, this); - inputKnob -> setVolumeKnob( true ); - inputKnob -> setVolumeRatio( 1.0 ); + auto inputKnob = new VolumeKnob(KnobType::Bright26, tr("INPUT"), SMALL_FONT_SIZE, this); + inputKnob->setVolumeRatio(1.0); inputKnob -> move( 26, 225 ); inputKnob->setModel( &_controls->m_inputModel ); inputKnob->setHintText( tr( "Input gain:" ) , "" ); - auto outputKnob = new Knob(KnobType::Bright26, tr("OUTPUT"), SMALL_FONT_SIZE, this); - outputKnob -> setVolumeKnob( true ); - outputKnob -> setVolumeRatio( 1.0 ); + auto outputKnob = new VolumeKnob(KnobType::Bright26, tr("OUTPUT"), SMALL_FONT_SIZE, this); + outputKnob->setVolumeRatio(1.0); outputKnob -> move( 76, 225 ); outputKnob->setModel( &_controls->m_outputModel ); outputKnob->setHintText( tr( "Output gain:" ), "" ); diff --git a/src/common/RemotePluginBase.cpp b/src/common/RemotePluginBase.cpp index e23e6939b..c6179fc2f 100644 --- a/src/common/RemotePluginBase.cpp +++ b/src/common/RemotePluginBase.cpp @@ -172,6 +172,7 @@ RemotePluginBase::message RemotePluginBase::waitForMessage( #ifndef BUILD_REMOTE_PLUGIN_CLIENT if (_busy_waiting && !messagesLeft()) { + // FIXME: Can hang sometimes (due to too many messages?) QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents, 50); continue; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 061d05eb4..ebe1e623a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -104,7 +104,6 @@ SET(LMMS_SRCS gui/widgets/CPULoadWidget.cpp gui/widgets/CaptionMenu.cpp gui/widgets/ComboBox.cpp - gui/widgets/CustomTextKnob.cpp gui/widgets/Draggable.cpp gui/widgets/Fader.cpp gui/widgets/FloatModelEditorBase.cpp diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index 872e7ad20..56106a4c8 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -108,8 +108,7 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView* stv) basicControlsLayout->addLayout(soloMuteLayout, 0, 0, 2, 1, widgetAlignment); // set up volume knob - m_volumeKnob = new Knob(KnobType::Bright26, nullptr, tr("Sample volume")); - m_volumeKnob->setVolumeKnob(true); + m_volumeKnob = new VolumeKnob(KnobType::Bright26, nullptr, tr("Sample volume")); m_volumeKnob->setHintText(tr("Volume:"), "%"); basicControlsLayout->addWidget(m_volumeKnob, 0, 1); diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 71d2eadd8..f01c6961a 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -152,8 +152,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : basicControlsLayout->addLayout(soloMuteLayout, 0, 0, 2, 1, widgetAlignment); // set up volume knob - m_volumeKnob = new Knob( KnobType::Bright26, nullptr, tr( "Volume" ) ); - m_volumeKnob->setVolumeKnob( true ); + m_volumeKnob = new VolumeKnob(KnobType::Bright26, nullptr, tr("Volume")); m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); basicControlsLayout->addWidget(m_volumeKnob, 0, 1); diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 782b4e6a6..f682a4584 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -83,8 +83,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_mixerChannelNumber = new MixerChannelLcdSpinBox(2, getTrackSettingsWidget(), tr("Mixer channel"), this); m_mixerChannelNumber->show(); - m_volumeKnob = new Knob(KnobType::Small17, tr("VOL"), getTrackSettingsWidget(), Knob::LabelRendering::LegacyFixedFontSize, tr("VOL")); - m_volumeKnob->setVolumeKnob( true ); + m_volumeKnob = new VolumeKnob(KnobType::Small17, tr("VOL"), getTrackSettingsWidget(), Knob::LabelRendering::LegacyFixedFontSize, tr("VOL")); m_volumeKnob->setModel( &_it->m_volumeModel ); m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); m_volumeKnob->show(); diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index ffccfda38..6d1c0f13f 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -67,8 +67,7 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : m_mixerChannelNumber = new MixerChannelLcdSpinBox(2, getTrackSettingsWidget(), tr("Mixer channel"), this); m_mixerChannelNumber->show(); - m_volumeKnob = new Knob(KnobType::Small17, tr("VOL"), getTrackSettingsWidget(), Knob::LabelRendering::LegacyFixedFontSize, tr("Track volume")); - m_volumeKnob->setVolumeKnob( true ); + m_volumeKnob = new VolumeKnob(KnobType::Small17, tr("VOL"), getTrackSettingsWidget(), Knob::LabelRendering::LegacyFixedFontSize, tr("Track volume")); m_volumeKnob->setModel( &_t->m_volumeModel ); m_volumeKnob->setHintText( tr( "Channel volume:" ), "%" ); m_volumeKnob->show(); diff --git a/src/gui/widgets/CustomTextKnob.cpp b/src/gui/widgets/CustomTextKnob.cpp deleted file mode 100644 index 062359157..000000000 --- a/src/gui/widgets/CustomTextKnob.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CustomTextKnob.cpp - * - * Copyright (c) 2020 Ibuki Sugiyama
- * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include "CustomTextKnob.h" -#include "FontHelper.h" - -namespace lmms::gui -{ - - -CustomTextKnob::CustomTextKnob( KnobType _knob_num, const QString& label, QWidget * _parent, const QString & _name, const QString & _value_text ) : - Knob( _knob_num, _parent, _name ), - m_value_text( _value_text ) -{ - setFont(adjustedToPixelSize(font(), SMALL_FONT_SIZE)); - setLabel(label); -} - -QString CustomTextKnob::displayValue() const -{ - return m_description.trimmed() + m_value_text; -} - - -} // namespace lmms::gui diff --git a/src/gui/widgets/Draggable.cpp b/src/gui/widgets/Draggable.cpp index 9decb8838..989a480b1 100644 --- a/src/gui/widgets/Draggable.cpp +++ b/src/gui/widgets/Draggable.cpp @@ -107,8 +107,8 @@ void Draggable::mouseMoveEvent(QMouseEvent* me) emit sliderMoved(model()->value()); m_lastMousePos = pPos; - s_textFloat->setText(displayValue()); - s_textFloat->moveGlobal(this, QPoint(width() + 2, 0)); + + showTextFloat(); } } diff --git a/src/gui/widgets/FloatModelEditorBase.cpp b/src/gui/widgets/FloatModelEditorBase.cpp index 2fe62f499..50cc64072 100644 --- a/src/gui/widgets/FloatModelEditorBase.cpp +++ b/src/gui/widgets/FloatModelEditorBase.cpp @@ -3,6 +3,7 @@ * * Copyright (c) 2004-2014 Tobias Doerffel * Copyright (c) 2023 Michael Gregorius + * Copyright (c) 2026 Dalton Messmer * * This file is part of LMMS - https://lmms.io * @@ -28,6 +29,7 @@ #include #include #include +#include #include "lmms_math.h" #include "DeprecationHelper.h" @@ -50,8 +52,6 @@ SimpleTextFloat * FloatModelEditorBase::s_textFloat = nullptr; FloatModelEditorBase::FloatModelEditorBase(DirectionOfManipulation directionOfManipulation, QWidget * parent, const QString & name) : QWidget(parent), FloatModelView(new FloatModel(0, 0, 0, 1, nullptr, name, true), this), - m_volumeKnob(false), - m_volumeRatio(100.0, 0.0, 1000000.0), m_buttonPressed(false), m_directionOfManipulation(directionOfManipulation) { @@ -76,16 +76,34 @@ void FloatModelEditorBase::initUi(const QString & name) void FloatModelEditorBase::showTextFloat(int msecBeforeDisplay, int msecDisplayTime) { - s_textFloat->setText(displayValue()); + if (s_textFloat->source() != this) + { + s_textFloat->setText(m_description + ' ' + getCustomFloatingText() + m_unit); + s_textFloat->setSource(this); + } + s_textFloat->moveGlobal(this, QPoint(width() + 2, 0)); s_textFloat->showWithDelay(msecBeforeDisplay, msecDisplayTime); } +void FloatModelEditorBase::showTextFloat() +{ + if (s_textFloat->source() != this) + { + s_textFloat->setText(m_description + ' ' + getCustomFloatingText() + m_unit); + s_textFloat->setSource(this); + } + + s_textFloat->moveGlobal(this, QPoint(width() + 2, 0)); + s_textFloat->show(); +} + + float FloatModelEditorBase::getValue(const QPoint & p) { // Find out which direction/coordinate is relevant for this control - int const coordinate = m_directionOfManipulation == DirectionOfManipulation::Vertical ? p.y() : -p.x(); + const int coordinate = m_directionOfManipulation == DirectionOfManipulation::Vertical ? p.y() : -p.x(); // knob value increase is linear to mouse movement float value = .4f * coordinate; @@ -172,11 +190,6 @@ void FloatModelEditorBase::mousePressEvent(QMouseEvent * me) emit sliderPressed(); showTextFloat(0, 0); - - s_textFloat->setText(displayValue()); - s_textFloat->moveGlobal(this, - QPoint(width() + 2, 0)); - s_textFloat->show(); m_buttonPressed = true; } else if (me->button() == Qt::LeftButton && @@ -205,8 +218,8 @@ void FloatModelEditorBase::mouseMoveEvent(QMouseEvent * me) // original position for next time is current position m_lastMousePos = pos; } - s_textFloat->setText(displayValue()); - s_textFloat->show(); + + showTextFloat(); } @@ -264,16 +277,16 @@ void FloatModelEditorBase::paintEvent(QPaintEvent *) { QPainter p(this); - QColor const foreground(3, 94, 97); + const auto foreground = QColor{3, 94, 97}; - auto const * mod = model(); - auto const minValue = mod->minValue(); - auto const maxValue = mod->maxValue(); - auto const range = maxValue - minValue; + const auto* mod = model(); + const auto minValue = mod->minValue(); + const auto maxValue = mod->maxValue(); + const auto range = maxValue - minValue; // Compute the percentage // min + x * (max - min) = v <=> x = (v - min) / (max - min) - auto const percentage = range == 0 ? 1. : (mod->value() - minValue) / range; + const auto percentage = range == 0 ? 1. : (mod->value() - minValue) / range; QRect r = rect(); p.setPen(foreground); @@ -289,15 +302,15 @@ void FloatModelEditorBase::wheelEvent(QWheelEvent * we) float direction = deltaY > 0 ? 1 : -1; auto * m = model(); - float const step = m->step(); - float const range = m->range(); + const float step = m->step(); + const float range = m->range(); // This is the default number of steps or mouse wheel events that it takes to sweep // from the lowest value to the highest value. // It might be modified if the user presses modifier keys. See below. float numberOfStepsForFullSweep = 100.; - auto const modKeys = we->modifiers(); + const auto modKeys = we->modifiers(); if (modKeys == Qt::ShiftModifier) { // The shift is intended to go through the values in very coarse steps as in: @@ -319,7 +332,7 @@ void FloatModelEditorBase::wheelEvent(QWheelEvent * we) // left and right. Account for this quirk. if (deltaY == 0) { - int const deltaX = we->angleDelta().x(); + const int deltaX = we->angleDelta().x(); if (deltaX != 0) { direction = deltaX > 0 ? 1 : -1; @@ -340,9 +353,7 @@ void FloatModelEditorBase::wheelEvent(QWheelEvent * we) const int inc = direction * stepMult; model()->incValue(inc); - s_textFloat->setText(displayValue()); - s_textFloat->moveGlobal(this, QPoint(width() + 2, 0)); - s_textFloat->showWithTimeout(1000); + showTextFloat(0, 1000); emit sliderMoved(model()->value()); } @@ -377,44 +388,23 @@ void FloatModelEditorBase::setPosition(const QPoint & p) void FloatModelEditorBase::enterValue() { - bool ok; - float new_val; - - if (isVolumeKnob()) - { - auto const initalValue = model()->getRoundedValue() / 100.0; - auto const initialDbValue = initalValue > 0. ? ampToDbfs(initalValue) : -96; - - new_val = QInputDialog::getDouble( - this, tr("Set value"), - tr("Please enter a new value between -96.0 dBFS and %1 dBFS:").arg(ampToDbfs(model()->maxValue() / 100.0f)), - initialDbValue, -96.0, ampToDbfs(model()->maxValue() / 100.0f), model()->getDigitCount(), &ok); - - if (new_val <= -96.0) - { - new_val = 0.0f; - } - else - { - new_val = dbfsToAmp(new_val) * 100.0; - } - } - else - { - new_val = QInputDialog::getDouble( - this, tr("Set value"), - tr("Please enter a new value between " - "%1 and %2:"). - arg(model()->minValue()). - arg(model()->maxValue()), - model()->getRoundedValue(), - model()->minValue(), - model()->maxValue(), model()->getDigitCount(), &ok); - } + bool ok = false; + const float newVal = QInputDialog::getDouble( + this, + tr("Set value"), + tr("Please enter a new value between %1 and %2:") + .arg(model()->minValue()) + .arg(model()->maxValue()), + model()->getRoundedValue(), + model()->minValue(), + model()->maxValue(), + model()->getDigitCount(), + &ok + ); if (ok) { - model()->setValue(new_val); + model()->setValue(newVal); } } @@ -430,24 +420,24 @@ void FloatModelEditorBase::friendlyUpdate() && Controller::runningFrames() % (256 * 4) != 0) { return; } + // If this float model is currently controlling the TextFloat... + if (textFloat().source() == this) + { + // ...and if the text changed since last time... + if (auto updatedText = getCustomFloatingTextUpdate()) + { + // ...then update the floating text + s_textFloat->setText(m_description + ' ' + std::move(*updatedText) + m_unit); + } + } + update(); } -QString FloatModelEditorBase::displayValue() const +QString FloatModelEditorBase::getCustomFloatingText() { - if (isVolumeKnob()) - { - auto const valueToVolumeRatio = model()->getRoundedValue() / volumeRatio(); - return m_description.trimmed() + ( - valueToVolumeRatio == 0. - ? QString(" -∞ dBFS") - : QString(" %1 dBFS").arg(ampToDbfs(valueToVolumeRatio), 3, 'f', 2) - ); - } - - return m_description.trimmed() + QString(" %1"). - arg(model()->getRoundedValue()) + m_unit; + return QString::number(model()->getRoundedValue()); } diff --git a/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index e1a083c38..9f1976c19 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -24,12 +24,13 @@ #include "Knob.h" +#include #include -#include #include "DeprecationHelper.h" #include "embed.h" #include "FontHelper.h" +#include "lmms_math.h" #include @@ -530,6 +531,46 @@ void Knob::changeEvent(QEvent * ev) } } +QString VolumeKnob::getCustomFloatingText() +{ + const auto valueToVolumeRatio = model()->getRoundedValue() / volumeRatio(); + return valueToVolumeRatio == 0. + ? QString("-∞ dBFS") + : QString("%1 dBFS").arg(ampToDbfs(valueToVolumeRatio), 3, 'f', 2); +} + +void VolumeKnob::enterValue() +{ + const auto initalValue = model()->getRoundedValue() / 100.0; + const auto initialDbValue = initalValue > 0. ? ampToDbfs(initalValue) : -96; + + bool ok = false; + float newVal = QInputDialog::getDouble( + this, + tr("Set value"), + tr("Please enter a new value between -96.0 dBFS and %1 dBFS:") + .arg(ampToDbfs(model()->maxValue() / 100.0f)), + initialDbValue, + -96.0, + ampToDbfs(model()->maxValue() / 100.0f), + model()->getDigitCount(), + &ok + ); + + if (newVal <= -96.0) + { + newVal = 0.0f; + } + else + { + newVal = dbfsToAmp(newVal) * 100.0; + } + + if (ok) + { + model()->setValue(newVal); + } +} void convertPixmapToGrayScale(QPixmap& pixMap) { diff --git a/src/gui/widgets/SimpleTextFloat.cpp b/src/gui/widgets/SimpleTextFloat.cpp index 4e08f4cfb..219ec0934 100644 --- a/src/gui/widgets/SimpleTextFloat.cpp +++ b/src/gui/widgets/SimpleTextFloat.cpp @@ -76,8 +76,15 @@ void SimpleTextFloat::showWithDelay(int msecBeforeDisplay, int msecDisplayTime) } } +void SimpleTextFloat::show() +{ + m_hideTimer->start(); + QWidget::show(); +} + void SimpleTextFloat::hide() { + m_source = nullptr; m_showTimer->stop(); m_hideTimer->stop(); QWidget::hide();