Files
lmms/src/core/LadspaControl.cpp
Hyunjin Song 6d7ce58dec Merge branch 'stable-1.2'
# Conflicts:
#	CMakeLists.txt
#	cmake/linux/package_linux.sh.in
#	src/3rdparty/CMakeLists.txt
#	src/core/Track.cpp
#	src/gui/editors/PianoRoll.cpp
#	src/tracks/SampleTrack.cpp
2019-05-06 15:46:17 +09:00

382 lines
8.4 KiB
C++

/*
* LadspaControl.cpp - model for controlling a LADSPA port
*
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2006-2008 Danny McRae <khjklujn/at/users.sourceforge.net>
*
* 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 <cstdio>
#include "LadspaControl.h"
#include "LadspaBase.h"
LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port,
bool _link ) :
Model( _parent ),
m_link( _link ),
m_port( _port ),
m_linkEnabledModel( _link, this, tr( "Link channels" ) ),
m_toggledModel( false, this, m_port->name ),
m_knobModel( 0, 0, 0, 1, this, m_port->name ),
m_tempoSyncKnobModel( 0, 0, 0, 1, m_port->max, this, m_port->name )
{
if( m_link )
{
connect( &m_linkEnabledModel, SIGNAL( dataChanged() ),
this, SLOT( linkStateChanged() ),
Qt::DirectConnection );
}
switch( m_port->data_type )
{
case TOGGLED:
m_toggledModel.setInitValue(
static_cast<bool>( m_port->def ) );
connect( &m_toggledModel, SIGNAL( dataChanged() ),
this, SLOT( ledChanged() ) );
if( m_port->def == 1.0f )
{
m_toggledModel.setValue( true );
}
// TODO: careful: we must prevent saved scales
m_toggledModel.setScaleLogarithmic( m_port->suggests_logscale );
break;
case INTEGER:
case ENUM:
m_knobModel.setRange( static_cast<int>( m_port->max ),
static_cast<int>( m_port->min ),
1 + static_cast<int>( m_port->max -
m_port->min ) / 400 );
m_knobModel.setInitValue(
static_cast<int>( m_port->def ) );
connect( &m_knobModel, SIGNAL( dataChanged() ),
this, SLOT( knobChanged() ) );
// TODO: careful: we must prevent saved scales
m_knobModel.setScaleLogarithmic( m_port->suggests_logscale );
break;
case FLOATING:
m_knobModel.setRange( m_port->min, m_port->max,
( m_port->max - m_port->min )
/ ( m_port->name.toUpper() == "GAIN"
&& m_port->max == 10.0f ? 4000.0f :
( m_port->suggests_logscale ? 8000.0f : 800.0f ) ) );
m_knobModel.setInitValue( m_port->def );
connect( &m_knobModel, SIGNAL( dataChanged() ),
this, SLOT( knobChanged() ) );
// TODO: careful: we must prevent saved scales
m_knobModel.setScaleLogarithmic( m_port->suggests_logscale );
break;
case TIME:
m_tempoSyncKnobModel.setRange( m_port->min, m_port->max,
( m_port->max -
m_port->min ) / 800.0f );
m_tempoSyncKnobModel.setInitValue( m_port->def );
connect( &m_tempoSyncKnobModel, SIGNAL( dataChanged() ),
this, SLOT( tempoKnobChanged() ) );
// TODO: careful: we must prevent saved scales
m_tempoSyncKnobModel.setScaleLogarithmic( m_port->suggests_logscale );
break;
default:
break;
}
}
LadspaControl::~LadspaControl()
{
}
LADSPA_Data LadspaControl::value()
{
switch( m_port->data_type )
{
case TOGGLED:
return static_cast<LADSPA_Data>( m_toggledModel.value() );
case INTEGER:
case ENUM:
case FLOATING:
return static_cast<LADSPA_Data>( m_knobModel.value() );
case TIME:
return static_cast<LADSPA_Data>( m_tempoSyncKnobModel.value() );
default:
qWarning( "LadspaControl::value(): BAD BAD BAD\n" );
break;
}
return 0;
}
ValueBuffer * LadspaControl::valueBuffer()
{
switch( m_port->data_type )
{
case TOGGLED:
case INTEGER:
case ENUM:
return NULL;
case FLOATING:
return m_knobModel.valueBuffer();
case TIME:
return m_tempoSyncKnobModel.valueBuffer();
default:
qWarning( "LadspaControl::valueBuffer(): BAD BAD BAD\n" );
break;
}
return NULL;
}
void LadspaControl::setValue( LADSPA_Data _value )
{
switch( m_port->data_type )
{
case TOGGLED:
m_toggledModel.setValue( static_cast<bool>( _value ) );
break;
case INTEGER:
case ENUM:
m_knobModel.setValue( static_cast<int>( _value ) );
break;
case FLOATING:
m_knobModel.setValue( static_cast<float>( _value ) );
break;
case TIME:
m_tempoSyncKnobModel.setValue( static_cast<float>(
_value ) );
break;
default:
printf("LadspaControl::setValue BAD BAD BAD\n");
break;
}
}
void LadspaControl::saveSettings( QDomDocument& doc,
QDomElement& parent,
const QString& name )
{
QDomElement e = doc.createElement( name );
if( m_link )
{
m_linkEnabledModel.saveSettings( doc, e, "link" );
}
switch( m_port->data_type )
{
case TOGGLED:
m_toggledModel.saveSettings( doc, e, "data" );
break;
case INTEGER:
case ENUM:
case FLOATING:
m_knobModel.saveSettings( doc, e, "data" );
break;
case TIME:
m_tempoSyncKnobModel.saveSettings( doc, e, "data" );
break;
default:
printf("LadspaControl::saveSettings BAD BAD BAD\n");
break;
}
parent.appendChild( e );
}
void LadspaControl::loadSettings( const QDomElement& parent, const QString& name )
{
QString dataModelName = "data";
QString linkModelName = "link";
QDomElement e = parent.namedItem( name ).toElement();
if(e.isNull())
{
// the port exists in the current effect, but not in the
// savefile => it's a new port, so load the default value
if( m_link )
m_linkEnabledModel.setValue(m_linkEnabledModel.initValue());
switch( m_port->data_type )
{
case TOGGLED:
m_toggledModel.setValue(m_toggledModel.initValue());
break;
case INTEGER:
case ENUM:
case FLOATING:
m_knobModel.setValue(m_knobModel.initValue());
break;
case TIME:
m_tempoSyncKnobModel.setValue(m_tempoSyncKnobModel.initValue());
break;
default:
printf("LadspaControl::loadSettings BAD BAD BAD\n");
break;
}
}
else
{
// COMPAT < 1.0.0: detect old data format where there's either no dedicated sub
// element or there's a direct sub element with automation link information
if( e.isNull() || e.hasAttribute( "id" ) )
{
dataModelName = name;
linkModelName = name + "link";
e = parent;
}
if( m_link )
{
m_linkEnabledModel.loadSettings( e, linkModelName );
}
switch( m_port->data_type )
{
case TOGGLED:
m_toggledModel.loadSettings( e, dataModelName );
break;
case INTEGER:
case ENUM:
case FLOATING:
m_knobModel.loadSettings( e, dataModelName );
break;
case TIME:
m_tempoSyncKnobModel.loadSettings( e, dataModelName );
break;
default:
printf("LadspaControl::loadSettings BAD BAD BAD\n");
break;
}
}
}
void LadspaControl::linkControls( LadspaControl * _control )
{
switch( m_port->data_type )
{
case TOGGLED:
BoolModel::linkModels( &m_toggledModel, _control->toggledModel() );
break;
case INTEGER:
case ENUM:
case FLOATING:
FloatModel::linkModels( &m_knobModel, _control->knobModel() );
break;
case TIME:
TempoSyncKnobModel::linkModels( &m_tempoSyncKnobModel,
_control->tempoSyncKnobModel() );
break;
default:
break;
}
}
void LadspaControl::ledChanged()
{
emit changed( m_port->port_id, static_cast<LADSPA_Data>(
m_toggledModel.value() ) );
}
void LadspaControl::knobChanged()
{
emit changed( m_port->port_id, static_cast<LADSPA_Data>(
m_knobModel.value() ) );
}
void LadspaControl::tempoKnobChanged()
{
emit changed( m_port->port_id, static_cast<LADSPA_Data>(
m_tempoSyncKnobModel.value() ) );
}
void LadspaControl::unlinkControls( LadspaControl * _control )
{
switch( m_port->data_type )
{
case TOGGLED:
BoolModel::unlinkModels( &m_toggledModel, _control->toggledModel() );
break;
case INTEGER:
case ENUM:
case FLOATING:
FloatModel::unlinkModels( &m_knobModel, _control->knobModel() );
break;
case TIME:
TempoSyncKnobModel::unlinkModels( &m_tempoSyncKnobModel,
_control->tempoSyncKnobModel() );
break;
default:
break;
}
}
void LadspaControl::linkStateChanged()
{
emit linkChanged( m_port->control_id, m_linkEnabledModel.value() );
}
void LadspaControl::setLink( bool _state )
{
m_linkEnabledModel.setValue( _state );
}