Merge branch 'stable-1.1'
Conflicts: src/core/main.cpp
This commit is contained in:
@@ -136,7 +136,7 @@ private slots:
|
||||
virtual void enterValue();
|
||||
void displayHelp();
|
||||
void friendlyUpdate();
|
||||
|
||||
void toggleScale();
|
||||
|
||||
private:
|
||||
QString displayValue() const;
|
||||
|
||||
@@ -25,10 +25,15 @@
|
||||
#ifndef LMMS_CONSTANTS_H
|
||||
#define LMMS_CONSTANTS_H
|
||||
|
||||
const float F_PI = 3.1415926535f;
|
||||
const float F_E = 2.718281828459045f;
|
||||
const float F_2PI = 2*F_PI;
|
||||
const float F_PI_2 = F_PI*0.5;
|
||||
const double D_PI = 3.14159265358979323846;
|
||||
const double D_2PI = D_PI * 2.0;
|
||||
const double D_PI_2 = D_PI * 0.5;
|
||||
const double D_E = 2.71828182845904523536;
|
||||
|
||||
const float F_PI = (float) D_PI;
|
||||
const float F_2PI = (float) D_2PI;
|
||||
const float F_PI_2 = (float) D_PI_2;
|
||||
const float F_E = (float) D_E;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ DualFilterEffect::DualFilterEffect( Model* parent, const Descriptor::SubPluginFe
|
||||
{
|
||||
m_filter1 = new basicFilters<2>( engine::mixer()->processingSampleRate() );
|
||||
m_filter2 = new basicFilters<2>( engine::mixer()->processingSampleRate() );
|
||||
|
||||
|
||||
// ensure filters get updated
|
||||
m_filter1changed = true;
|
||||
m_filter2changed = true;
|
||||
@@ -84,25 +84,41 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
|
||||
m_filter1->setFilterType( m_dfControls.m_filter1Model.value() );
|
||||
m_filter2->setFilterType( m_dfControls.m_filter2Model.value() );
|
||||
|
||||
if( m_dfControls.m_filter1Model.isValueChanged() )
|
||||
{
|
||||
m_filter1->setFilterType( m_dfControls.m_filter1Model.value() );
|
||||
m_filter1changed = true;
|
||||
}
|
||||
if( m_dfControls.m_filter2Model.isValueChanged() )
|
||||
{
|
||||
m_filter2->setFilterType( m_dfControls.m_filter2Model.value() );
|
||||
m_filter2changed = true;
|
||||
}
|
||||
|
||||
const bool enabled1 = m_dfControls.m_enabled1Model.value();
|
||||
const bool enabled2 = m_dfControls.m_enabled2Model.value();
|
||||
|
||||
// recalculate only when necessary
|
||||
if( enabled1 && m_filter1changed )
|
||||
// recalculate only when necessary: either cut/res is changed, or the changed-flag is set (filter type or samplerate changed)
|
||||
if( ( enabled1 && ( m_dfControls.m_cut1Model.isValueChanged() ||
|
||||
m_dfControls.m_res1Model.isValueChanged() ) ) || m_filter1changed )
|
||||
{
|
||||
m_filter1->calcFilterCoeffs( m_dfControls.m_cut1Model.value(), m_dfControls.m_res1Model.value() );
|
||||
m_filter1changed = false;
|
||||
}
|
||||
if( enabled2 && m_filter2changed )
|
||||
if( ( enabled2 && ( m_dfControls.m_cut2Model.isValueChanged() ||
|
||||
m_dfControls.m_res2Model.isValueChanged() ) ) || m_filter2changed )
|
||||
{
|
||||
m_filter2->calcFilterCoeffs( m_dfControls.m_cut2Model.value(), m_dfControls.m_res2Model.value() );
|
||||
m_filter2changed = false;
|
||||
}
|
||||
|
||||
|
||||
// get mix amounts for wet signals of both filters
|
||||
const float mix2 = ( ( m_dfControls.m_mixModel.value() + 1.0f ) * 0.5f );
|
||||
const float mix1 = 1.0f - mix2;
|
||||
|
||||
const float gain1 = m_dfControls.m_gain1Model.value() * 0.01f;
|
||||
const float gain2 = m_dfControls.m_gain2Model.value() * 0.01f;
|
||||
|
||||
// buffer processing loop
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
{
|
||||
@@ -110,10 +126,6 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
sample_t s1[2] = { buf[f][0], buf[f][1] }; // filter 1
|
||||
sample_t s2[2] = { buf[f][0], buf[f][1] }; // filter 2
|
||||
|
||||
// get mix amounts for wet signals of both filters
|
||||
const float mix1 = 1.0f - ( ( m_dfControls.m_mixModel.value( f ) + 1.0f ) / 2.0f );
|
||||
const float mix2 = ( ( m_dfControls.m_mixModel.value( f ) + 1.0f ) / 2.0f );
|
||||
|
||||
// update filter 1
|
||||
if( enabled1 )
|
||||
{
|
||||
@@ -121,8 +133,8 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
s1[1] = m_filter1->update( s1[1], 1 );
|
||||
|
||||
// apply gain
|
||||
s1[0] *= ( m_dfControls.m_gain1Model.value( f ) / 100.0f );
|
||||
s1[1] *= ( m_dfControls.m_gain1Model.value( f ) / 100.0f );
|
||||
s1[0] *= gain1;
|
||||
s1[1] *= gain1;
|
||||
|
||||
// apply mix
|
||||
s[0] += ( s1[0] * mix1 );
|
||||
@@ -136,8 +148,8 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
s2[1] = m_filter2->update( s2[1], 1 );
|
||||
|
||||
//apply gain
|
||||
s2[0] *= ( m_dfControls.m_gain2Model.value( f ) / 100.0f );
|
||||
s2[1] *= ( m_dfControls.m_gain2Model.value( f ) / 100.0f );
|
||||
s2[0] *= gain2;
|
||||
s2[1] *= gain2;
|
||||
|
||||
// apply mix
|
||||
s[0] += ( s2[0] * mix2 );
|
||||
|
||||
@@ -51,14 +51,6 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) :
|
||||
m_res2Model( 0.5, basicFilters<0>::minQ(), 10.0, 0.01, this, tr( "Q/Resonance 2" ) ),
|
||||
m_gain2Model( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Gain 2" ) )
|
||||
{
|
||||
connect( &m_filter1Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter1() ) );
|
||||
connect( &m_cut1Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter1() ) );
|
||||
connect( &m_res1Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter1() ) );
|
||||
|
||||
connect( &m_filter2Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter2() ) );
|
||||
connect( &m_cut2Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter2() ) );
|
||||
connect( &m_res2Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter2() ) );
|
||||
|
||||
m_filter1Model.addItem( tr( "LowPass" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "HiPass" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "BandPass csg" ), new PixmapLoader( "filter_bp" ) );
|
||||
@@ -110,17 +102,6 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) :
|
||||
|
||||
|
||||
|
||||
void DualFilterControls::updateFilter1()
|
||||
{
|
||||
m_effect->m_filter1changed = true;
|
||||
}
|
||||
|
||||
void DualFilterControls::updateFilter2()
|
||||
{
|
||||
m_effect->m_filter2changed = true;
|
||||
}
|
||||
|
||||
|
||||
void DualFilterControls::updateFilters()
|
||||
{
|
||||
// swap filters to new ones
|
||||
@@ -132,8 +113,8 @@ void DualFilterControls::updateFilters()
|
||||
|
||||
// flag filters as needing recalculation
|
||||
|
||||
updateFilter1();
|
||||
updateFilter2();
|
||||
m_effect->m_filter1changed = true;
|
||||
m_effect->m_filter2changed = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -62,8 +62,6 @@ public:
|
||||
|
||||
|
||||
private slots:
|
||||
void updateFilter1();
|
||||
void updateFilter2();
|
||||
void updateFilters();
|
||||
|
||||
private:
|
||||
|
||||
@@ -49,15 +49,16 @@ Plugin::Descriptor PLUGIN_EXPORT dynamicsprocessor_plugin_descriptor =
|
||||
|
||||
}
|
||||
|
||||
|
||||
const float DYN_NOISE_FLOOR = 0.00001f; // -100dBV noise floor
|
||||
const double DNF_LOG = 5.0;
|
||||
|
||||
dynProcEffect::dynProcEffect( Model * _parent,
|
||||
const Descriptor::SubPluginFeatures::Key * _key ) :
|
||||
Effect( &dynamicsprocessor_plugin_descriptor, _parent, _key ),
|
||||
m_dpControls( this )
|
||||
{
|
||||
currentPeak[0] = 0.0f;
|
||||
currentPeak[1] = 0.0f;
|
||||
m_currentPeak[0] = m_currentPeak[1] = DYN_NOISE_FLOOR;
|
||||
m_needsUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +69,15 @@ dynProcEffect::~dynProcEffect()
|
||||
}
|
||||
|
||||
|
||||
inline void dynProcEffect::calcAttack()
|
||||
{
|
||||
m_attCoeff = exp10( ( DNF_LOG / ( m_dpControls.m_attackModel.value() * 0.001 ) ) / engine::mixer()->processingSampleRate() );
|
||||
}
|
||||
|
||||
inline void dynProcEffect::calcRelease()
|
||||
{
|
||||
m_relCoeff = exp10( ( -DNF_LOG / ( m_dpControls.m_releaseModel.value() * 0.001 ) ) / engine::mixer()->processingSampleRate() );
|
||||
}
|
||||
|
||||
|
||||
bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
@@ -76,27 +86,10 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
//apparently we can't keep running after the decay value runs out so we'll just set the peaks to zero
|
||||
currentPeak[0] = 0.0f;
|
||||
currentPeak[1] = 0.0f;
|
||||
m_currentPeak[0] = m_currentPeak[1] = DYN_NOISE_FLOOR;
|
||||
return( false );
|
||||
|
||||
/* if( currentPeak[0] == 0.0f && currentPeak[1] == 0.0f ) return( false );
|
||||
else
|
||||
{
|
||||
if( currentPeak[0] != 0.0f )
|
||||
{
|
||||
currentPeak[0] = qMax ( currentPeak[0] -
|
||||
(( 1.0f / ( m_dpControls.m_releaseModel.value() / 1000.0f ) ) / engine::mixer()->processingSampleRate()), 0.0f );
|
||||
}
|
||||
if( currentPeak[1] != 0.0f )
|
||||
{
|
||||
currentPeak[1] = qMax ( currentPeak[1] -
|
||||
(( 1.0f / ( m_dpControls.m_releaseModel.value() / 1000.0f ) ) / engine::mixer()->processingSampleRate()), 0.0f );
|
||||
}
|
||||
|
||||
return( true );
|
||||
} */
|
||||
}
|
||||
//qDebug( "%f %f", m_currentPeak[0], m_currentPeak[1] );
|
||||
|
||||
// variables for effect
|
||||
int i = 0;
|
||||
@@ -107,100 +100,103 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
double out_sum = 0.0;
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
|
||||
const int stereoMode = m_dpControls.m_stereomodeModel.value();
|
||||
const float inputGain = m_dpControls.m_inputModel.value();
|
||||
const float outputGain = m_dpControls.m_outputModel.value();
|
||||
|
||||
const float * samples = m_dpControls.m_wavegraphModel.samples();
|
||||
|
||||
// debug code
|
||||
// qDebug( "peaks %f %f", m_currentPeak[0], m_currentPeak[1] );
|
||||
|
||||
if( m_dpControls.m_attackModel.isValueChanged() || m_needsUpdate )
|
||||
{
|
||||
calcAttack();
|
||||
}
|
||||
if( m_dpControls.m_releaseModel.isValueChanged() || m_needsUpdate )
|
||||
{
|
||||
calcRelease();
|
||||
}
|
||||
m_needsUpdate = false;
|
||||
|
||||
// debug code
|
||||
// qDebug( "peaks %f %f", currentPeak[0], currentPeak[1] );
|
||||
|
||||
float att_tmp = ( 1.0f / ( m_dpControls.m_attackModel.value() / 1000.0f ) ) / engine::mixer()->processingSampleRate();
|
||||
float rel_tmp = ( 1.0f / ( m_dpControls.m_releaseModel.value() / 1000.0f ) ) / engine::mixer()->processingSampleRate();
|
||||
|
||||
for( fpp_t f = 0; f < _frames; ++f )
|
||||
{
|
||||
sample_t s[2] = { _buf[f][0], _buf[f][1] };
|
||||
double s[2] = { _buf[f][0], _buf[f][1] };
|
||||
|
||||
// check for nan/inf because they may cause errors?
|
||||
if( isnanf( s[0] ) ) s[0] = 0.0f;
|
||||
if( isnanf( s[1] ) ) s[1] = 0.0f;
|
||||
if( isinff( s[0] ) ) s[0] = 0.0f;
|
||||
if( isinff( s[1] ) ) s[1] = 0.0f;
|
||||
|
||||
// apply input gain
|
||||
s[0] *= inputGain;
|
||||
s[1] *= inputGain;
|
||||
|
||||
// update peak values
|
||||
for ( i=0; i <= 1; i++ )
|
||||
{
|
||||
if( qAbs( s[i] ) > currentPeak[i] )
|
||||
if( qAbs( s[i] ) > m_currentPeak[i] )
|
||||
{
|
||||
currentPeak[i] = qMin ( currentPeak[i] + att_tmp, qAbs( s[i] ) );
|
||||
m_currentPeak[i] = qMin( m_currentPeak[i] * m_attCoeff, qAbs( s[i] ) );
|
||||
}
|
||||
else
|
||||
if( qAbs( s[i] ) < currentPeak[i] )
|
||||
else
|
||||
if( qAbs( s[i] ) < m_currentPeak[i] )
|
||||
{
|
||||
currentPeak[i] = qMax ( currentPeak[i] - rel_tmp, qAbs( s[i] ) );
|
||||
m_currentPeak[i] = qMax( m_currentPeak[i] * m_relCoeff, qAbs( s[i] ) );
|
||||
}
|
||||
|
||||
currentPeak[i] = qBound( 0.0f, currentPeak[i], 1.0f );
|
||||
|
||||
|
||||
m_currentPeak[i] = qBound( DYN_NOISE_FLOOR, m_currentPeak[i], 10.0f );
|
||||
}
|
||||
|
||||
// account for stereo mode
|
||||
switch( m_dpControls.m_stereomodeModel.value() )
|
||||
switch( stereoMode )
|
||||
{
|
||||
case dynProcControls::SM_Maximum:
|
||||
{
|
||||
sm_peak[0] = qMax( currentPeak[0], currentPeak[1] );
|
||||
sm_peak[1] = qMax( currentPeak[0], currentPeak[1] );
|
||||
sm_peak[0] = sm_peak[1] = qMax( m_currentPeak[0], m_currentPeak[1] );
|
||||
break;
|
||||
}
|
||||
case dynProcControls::SM_Average:
|
||||
{
|
||||
sm_peak[0] = ( currentPeak[0] + currentPeak[1] ) / 2;
|
||||
sm_peak[1] = ( currentPeak[0] + currentPeak[1] ) / 2;
|
||||
sm_peak[0] = sm_peak[1] = ( m_currentPeak[0] + m_currentPeak[1] ) * 0.5;
|
||||
break;
|
||||
}
|
||||
case dynProcControls::SM_Unlinked:
|
||||
{
|
||||
sm_peak[0] = currentPeak[0];
|
||||
sm_peak[1] = currentPeak[1];
|
||||
sm_peak[0] = m_currentPeak[0];
|
||||
sm_peak[1] = m_currentPeak[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// apply input gain
|
||||
s[0] *= m_dpControls.m_inputModel.value();
|
||||
s[1] *= m_dpControls.m_inputModel.value();
|
||||
|
||||
|
||||
// start effect
|
||||
|
||||
for ( i=0; i <= 1; i++ )
|
||||
{
|
||||
const int lookup = static_cast<int>( sm_peak[i] * 200.0f );
|
||||
const float frac = fraction( sm_peak[i] * 200.0f );
|
||||
|
||||
if( sm_peak[i] > 0 )
|
||||
{
|
||||
const float frac = fraction( sm_peak[i] * 200.0f );
|
||||
|
||||
if( sm_peak[i] > DYN_NOISE_FLOOR )
|
||||
{
|
||||
if ( lookup < 1 )
|
||||
{
|
||||
gain = frac * m_dpControls.m_wavegraphModel.samples()[0];
|
||||
gain = frac * samples[0];
|
||||
}
|
||||
else
|
||||
if ( lookup < 200 )
|
||||
{
|
||||
gain = linearInterpolate( m_dpControls.m_wavegraphModel.samples()[ lookup - 1 ],
|
||||
m_dpControls.m_wavegraphModel.samples()[ lookup ], frac );
|
||||
gain = linearInterpolate( samples[ lookup - 1 ],
|
||||
samples[ lookup ], frac );
|
||||
}
|
||||
else
|
||||
{
|
||||
gain = m_dpControls.m_wavegraphModel.samples()[199];
|
||||
gain = samples[199];
|
||||
};
|
||||
|
||||
s[i] *= ( gain / sm_peak[i] );
|
||||
|
||||
s[i] *= gain;
|
||||
s[i] /= sm_peak[i];
|
||||
}
|
||||
}
|
||||
|
||||
// apply output gain
|
||||
s[0] *= m_dpControls.m_outputModel.value();
|
||||
s[1] *= m_dpControls.m_outputModel.value();
|
||||
s[0] *= outputGain;
|
||||
s[1] *= outputGain;
|
||||
|
||||
// mix wet/dry signals
|
||||
_buf[f][0] = d * _buf[f][0] + w * s[0];
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DYNPROC_H
|
||||
#define _DYNPROC_H
|
||||
#ifndef DYNPROC_H
|
||||
#define DYNPROC_H
|
||||
|
||||
#include "Effect.h"
|
||||
#include "dynamics_processor_controls.h"
|
||||
@@ -48,11 +48,17 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void calcAttack();
|
||||
void calcRelease();
|
||||
|
||||
dynProcControls m_dpControls;
|
||||
|
||||
// this member array is needed for peak detection
|
||||
float currentPeak[2];
|
||||
float m_currentPeak[2];
|
||||
double m_attCoeff;
|
||||
double m_relCoeff;
|
||||
|
||||
bool m_needsUpdate;
|
||||
|
||||
friend class dynProcControls;
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DYNPROC_CONTROL_DIALOG_H
|
||||
#define _DYNPROC_CONTROL_DIALOG_H
|
||||
#ifndef DYNPROC_CONTROL_DIALOG_H
|
||||
#define DYNPROC_CONTROL_DIALOG_H
|
||||
|
||||
#include "EffectControlDialog.h"
|
||||
|
||||
|
||||
@@ -46,36 +46,21 @@ dynProcControls::dynProcControls( dynProcEffect * _eff ) :
|
||||
m_wavegraphModel( 0.0f, 1.0f, 200, this ),
|
||||
m_stereomodeModel( 0, 0, 2, this, tr( "Stereo mode" ) )
|
||||
{
|
||||
/* connect( &m_inputModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( changeControl() ) );
|
||||
|
||||
connect( &m_outputModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( changeControl() ) );
|
||||
|
||||
connect( &m_attackModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( changeControl() ) );
|
||||
|
||||
connect( &m_releaseModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( changeControl() ) );
|
||||
|
||||
connect( &m_stereomodeModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( changeControl() ) );
|
||||
*/
|
||||
connect( &m_wavegraphModel, SIGNAL( samplesChanged( int, int ) ),
|
||||
this, SLOT( samplesChanged( int, int ) ) );
|
||||
|
||||
connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) );
|
||||
|
||||
setDefaultShape();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dynProcControls::changeControl()
|
||||
void dynProcControls::sampleRateChanged()
|
||||
{
|
||||
// engine::getSong()->setModified();
|
||||
m_effect->m_needsUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
void dynProcControls::samplesChanged( int _begin, int _end)
|
||||
{
|
||||
engine::getSong()->setModified();
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WAVESHAPER_CONTROLS_H
|
||||
#define _WAVESHAPER_CONTROLS_H
|
||||
#ifndef DYNPROC_CONTROLS_H
|
||||
#define DYNPROC_CONTROLS_H
|
||||
|
||||
#include "EffectControls.h"
|
||||
#include "dynamics_processor_control_dialog.h"
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
private slots:
|
||||
void changeControl();
|
||||
void samplesChanged( int, int );
|
||||
void sampleRateChanged();
|
||||
|
||||
void resetClicked();
|
||||
void smoothClicked();
|
||||
|
||||
@@ -92,8 +92,6 @@ bool AutomatableModel::isAutomated() const
|
||||
|
||||
void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, const QString& name )
|
||||
{
|
||||
bool automatedOrControlled = false;
|
||||
|
||||
if( isAutomated() )
|
||||
{
|
||||
// automation needs tuple of data (name, id, value)
|
||||
@@ -102,8 +100,6 @@ void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, co
|
||||
me.setAttribute( "id", id() );
|
||||
me.setAttribute( "value", m_value );
|
||||
element.appendChild( me );
|
||||
|
||||
automatedOrControlled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -131,16 +127,15 @@ void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, co
|
||||
m_controllerConnection->saveSettings( doc, element );
|
||||
|
||||
controllerElement.appendChild( element );
|
||||
|
||||
automatedOrControlled = true;
|
||||
}
|
||||
|
||||
if( automatedOrControlled && ( m_scaleType != Linear ) )
|
||||
{ // note: if we have more scale types than two, make
|
||||
// a mapper function enums <-> string
|
||||
if(m_scaleType == Logarithmic) {
|
||||
element.setAttribute( "scale_type", "log" );
|
||||
}
|
||||
if( m_scaleType == Logarithmic )
|
||||
{
|
||||
element.setAttribute( "scale_type", "log" );
|
||||
}
|
||||
if( m_scaleType == Linear )
|
||||
{
|
||||
element.setAttribute( "scale_type", "linear" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +148,13 @@ void AutomatableModel::loadSettings( const QDomElement& element, const QString&
|
||||
if( element.hasAttribute("scale_type") ) // wrong in most cases
|
||||
{
|
||||
if( element.attribute("scale_type") == "log" )
|
||||
setScaleType( Logarithmic );
|
||||
{
|
||||
setScaleType( Logarithmic );
|
||||
}
|
||||
if( element.attribute("scale_type") == "linear" )
|
||||
{
|
||||
setScaleType( Linear );
|
||||
}
|
||||
}
|
||||
else {
|
||||
setScaleType( Linear );
|
||||
|
||||
@@ -483,12 +483,20 @@ void knob::contextMenuEvent( QContextMenuEvent * )
|
||||
|
||||
captionMenu contextMenu( model()->displayName(), this );
|
||||
addDefaultActions( &contextMenu );
|
||||
contextMenu.addAction( QPixmap(),
|
||||
model()->isScaleLogarithmic() ? tr( "Set linear" ) : tr( "Set logarithmic" ),
|
||||
this, SLOT( toggleScale() ) );
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addHelpAction();
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
void knob::toggleScale()
|
||||
{
|
||||
model()->setScaleLogarithmic( ! model()->isScaleLogarithmic() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void knob::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
|
||||
Reference in New Issue
Block a user