save and load effects

effects on sample tracks
no more ladspa knob segfaults


git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@298 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Danny McRae
2006-08-10 01:03:54 +00:00
parent 19e4bfdb5e
commit 4cb0d266a3
20 changed files with 511 additions and 60 deletions

View File

@@ -53,7 +53,7 @@ audioPort::audioPort( const QString & _name, engine * _engine ) :
eng()->getMixer()->addAudioPort( this );
setExtOutputEnabled( TRUE );
#ifdef LADSPA_SUPPORT
m_frames = configManager::inst()->value( "mixer", "framesperaudiobuffer" ).toInt();
m_frames = eng()->getMixer()->framesPerAudioBuffer();
m_effects = new effectChain( eng() );
#endif
}

View File

@@ -44,7 +44,7 @@ effect::effect( const ladspa_key_t & _key, engine * _engine ) :
m_output( NULL ),
m_okay( TRUE ),
m_noRun( FALSE ),
m_running( TRUE ),
m_running( FALSE ),
m_bypass( FALSE ),
m_bufferCount( 0 ),
m_silenceTimeout( 10 ),
@@ -66,7 +66,7 @@ effect::effect( const ladspa_key_t & _key, engine * _engine ) :
m_processors = lmms_chnls / m_effectChannels;
// Categorize the ports, and create the buffers.
m_bufferSize = configManager::inst()->value( "mixer", "framesperaudiobuffer" ).toInt();
m_bufferSize = eng()->getMixer()->framesPerAudioBuffer();
m_portCount = m_ladspa->getPortCount( _key );
for( ch_cnt_t proc = 0; proc < m_processors; proc++ )

View File

@@ -48,6 +48,7 @@
#include "effect_tab_widget.h"
#include "instrument_track.h"
#include "sample_track.h"
#include "group_box.h"
#include "tooltip.h"
#include "embed.h"
@@ -56,22 +57,25 @@
#include "audio_port.h"
effectTabWidget::effectTabWidget( instrumentTrack * _instrument_track ) :
QWidget( _instrument_track->tabWidgetParent() ),
journallingObject( _instrument_track->eng() ),
m_instrumentTrack( _instrument_track )
effectTabWidget::effectTabWidget( instrumentTrack * _track, audioPort * _port ) :
QWidget( _track->tabWidgetParent() ),
journallingObject( _track->eng() ),
m_track( dynamic_cast<track *>( _track ) ),
m_port( _port )
{
m_effectsGroupBox = new groupBox( tr( "EFFECTS CHAIN" ), this, eng(), _instrument_track );
connect( m_effectsGroupBox, SIGNAL( toggled( bool ) ), this, SLOT( setBypass( bool ) ) );
m_effectsGroupBox->setGeometry( 2, 2, 242, 244 );
m_rack = new rackView( m_effectsGroupBox, eng(), _instrument_track );
m_rack->move( 6, 22 );
m_addButton = new QPushButton( m_effectsGroupBox, "Add Effect" );
m_addButton->setText( tr( "Add" ) );
m_addButton->move( 75, 210 );
connect( m_addButton, SIGNAL( clicked( void ) ), this, SLOT( addEffect( void ) ) );
setupWidget();
}
effectTabWidget::effectTabWidget( QWidget * _parent, sampleTrack * _track, audioPort * _port ) :
QWidget( _parent ),
journallingObject( _track->eng() ),
m_track( dynamic_cast<track *>( _track ) ),
m_port( _port )
{
setupWidget();
}
@@ -84,6 +88,24 @@ effectTabWidget::~effectTabWidget()
void effectTabWidget::setupWidget( void )
{
m_effectsGroupBox = new groupBox( tr( "EFFECTS CHAIN" ), this, eng(), m_track );
connect( m_effectsGroupBox, SIGNAL( toggled( bool ) ), this, SLOT( setBypass( bool ) ) );
m_effectsGroupBox->setGeometry( 2, 2, 242, 244 );
m_rack = new rackView( m_effectsGroupBox, eng(), m_track, m_port );
m_rack->move( 6, 22 );
m_addButton = new QPushButton( m_effectsGroupBox, "Add Effect" );
m_addButton->setText( tr( "Add" ) );
m_addButton->move( 75, 210 );
connect( m_addButton, SIGNAL( clicked( void ) ), this, SLOT( addEffect( void ) ) );
}
void effectTabWidget::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
_this.setAttribute( "fxdisabled", !m_effectsGroupBox->isActive() );
@@ -134,9 +156,19 @@ void effectTabWidget::addEffect( void )
void effectTabWidget::setBypass( bool _state )
{
m_instrumentTrack->getAudioPort()->getEffects()->setBypass( !_state );
m_port->getEffects()->setBypass( !_state );
}
void effectTabWidget::closeEvent( QCloseEvent * _ce )
{
_ce->ignore();
emit( closed() );
}
#include "effect_tab_widget.moc"

View File

@@ -56,7 +56,6 @@ ladspaPortDialog::ladspaPortDialog( const ladspa_key_t & _key,
setWindowIcon( embed::getIconPixmap( "ports" ) );
setWindowTitle( "Ports" );
setModal( TRUE );
// setFixedSize( 500, 500 );
QVBoxLayout * vlayout = new QVBoxLayout( this );
vlayout->setSpacing( 0 );

View File

@@ -102,4 +102,5 @@
#include "src/widgets/rack_plugin.cpp"
#include "src/widgets/rack_view.cpp"
#include "src/widgets/ladspa_control.cpp"
#include "src/widgets/effect_label.cpp"
#endif

View File

@@ -47,6 +47,7 @@
#include <QtGui/QLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QMenu>
#include <QtGui/QMessageBox>
#else
@@ -61,6 +62,7 @@
#include <qlabel.h>
#include <qpopupmenu.h>
#include <qwhatsthis.h>
#include <qmessagebox.h>
#endif
@@ -309,7 +311,7 @@ instrumentTrack::instrumentTrack( trackContainer * _tc ) :
m_arpWidget = new arpAndChordsTabWidget( this );
m_midiWidget = new midiTabWidget( this, m_midiPort );
#ifdef LADSPA_SUPPORT
m_effWidget = new effectTabWidget( this );
m_effWidget = new effectTabWidget( this, m_audioPort );
#endif
m_tabWidget->addTab( m_envWidget, tr( "ENV/LFO/FILTER" ), 1 );
m_tabWidget->addTab( m_arpWidget, tr( "ARP/CHORD" ), 2 );
@@ -1134,6 +1136,21 @@ void instrumentTrack::loadTrackSpecificSettings( const QDomElement & _this )
{
m_effWidget->restoreState( node.toElement() );
}
#else
else if( node.nodeName() == "fx" )
{
// A song saved using ladspa will segfault when
// a version of lmms compiled without ladspa tries
// to instantiate a plugin from "libfx.so", so
// we catch it here.
QMessageBox::information( 0,
tr( "No LADSPA Support" ),
tr( "This instrument uses "
"features that aren't "
"available in this "
"version of LMMS." ),
QMessageBox::Ok );
}
#endif
else if( automationPattern::classNodeName()
!= node.nodeName() )

View File

@@ -44,10 +44,15 @@
#endif
#include "ladspa_manager.h"
#ifdef LADSPA_SUPPORT
#include "effect_label.h"
#else
#include "name_label.h"
#endif
#include "sample_track.h"
#include "song_editor.h"
#include "name_label.h"
#include "embed.h"
#include "templates.h"
#include "buffer_allocator.h"
@@ -377,9 +382,14 @@ sampleTrack::sampleTrack( trackContainer * _tc ) :
{
getTrackWidget()->setFixedHeight( 32 );
#ifdef LADSPA_SUPPORT
m_trackLabel = new effectLabel( tr( "Sample track" ),
getTrackSettingsWidget(), eng(), this );
#else
m_trackLabel = new nameLabel( tr( "Sample track" ),
getTrackSettingsWidget(), eng() );
m_trackLabel->setPixmap( embed::getIconPixmap( "sample_track" ) );
#endif
m_trackLabel->setGeometry( 26, 1, DEFAULT_SETTINGS_WIDGET_WIDTH-2, 29 );
m_trackLabel->show();
@@ -453,6 +463,7 @@ bool FASTCALL sampleTrack::play( const midiTime & _start,
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( _frames );
volumeVector v = { m_volume, m_volume
#ifndef DISABLE_SURROUND
, m_volume, m_volume
@@ -460,6 +471,9 @@ bool FASTCALL sampleTrack::play( const midiTime & _start,
} ;
float fpt64th = eng()->framesPerTact64th();
#ifdef LADSPA_SUPPORT
m_audioPort->getEffects()->setRunning();
#endif
for( vlist<trackContentObject *>::iterator it = tcos.begin();
it != tcos.end(); ++it )
{
@@ -496,7 +510,11 @@ void sampleTrack::saveTrackSpecificSettings( QDomDocument & _doc,
QDomElement & _this )
{
_this.setAttribute( "name", m_trackLabel->text() );
#ifdef LADSPA_SUPPORT
m_trackLabel->saveState( _doc, _this );
#else
_this.setAttribute( "icon", m_trackLabel->pixmapFile() );
#endif
m_volumeKnob->saveSettings( _doc, _this, "vol" );
}
@@ -506,10 +524,25 @@ void sampleTrack::saveTrackSpecificSettings( QDomDocument & _doc,
void sampleTrack::loadTrackSpecificSettings( const QDomElement & _this )
{
m_trackLabel->setText( _this.attribute( "name" ) );
#ifdef LADSPA_SUPPORT
QDomNode node = _this.firstChild();
while( !node.isNull() )
{
if( node.isElement() )
{
if( m_trackLabel->nodeName() == node.nodeName() )
{
m_trackLabel->restoreState( node.toElement() );
}
}
node = node.nextSibling();
}
#else
if( _this.attribute( "icon" ) != "" )
{
m_trackLabel->setPixmapFile( _this.attribute( "icon" ) );
}
#endif
if( _this.attribute( "vol" ) != "" )
{
m_volume = _this.attribute( "vol" ).toFloat();

View File

@@ -0,0 +1,185 @@
#ifndef SINGLE_SOURCE_COMPILE
/*
* effect_label.cpp - a label which is renamable by double-clicking it and
* offers access to an effect rack
*
* Copyright (c) 2006 Danny McRae <khjklujn/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#include "ladspa_manager.h"
#ifdef LADSPA_SUPPORT
#include "effect_label.h"
#include "sample_track.h"
#include "embed.h"
#include "gui_templates.h"
#include "rename_dialog.h"
effectLabel::effectLabel( const QString & _initial_name, QWidget * _parent, engine * _engine, sampleTrack * _track ) :
QWidget( _parent ),
journallingObject( _engine ),
m_track( _track ),
m_show( TRUE )
{
m_effectBtn = new QPushButton( embed::getIconPixmap( "setup_audio" ), "", this );
m_effectBtn->setGeometry( 6, 1, 28, 28 );
connect( m_effectBtn, SIGNAL( clicked() ), this, SLOT( showEffects() ) );
m_label = new QLabel( this );
m_label->setText( _initial_name );
QFont f = m_label->font();
m_label->setFont( pointSize<8>( f ) );
m_label->setGeometry( 38, 1, 200, 28 );
m_effWidget = new effectTabWidget( NULL, m_track, m_track->getAudioPort() );
m_effWidget->setFixedSize( 240, 242 );
m_effWidget->hide();
connect( m_effWidget, SIGNAL( closed() ), this, SLOT( closeEffects() ) );
}
effectLabel::~effectLabel()
{
}
void FASTCALL effectLabel::setText( const QString & _text )
{
m_label->setText( _text );
}
void effectLabel::showEffects( void )
{
if( m_show )
{
m_effWidget->show();
m_effWidget->raise();
m_show = FALSE;
}
else
{
m_effWidget->hide();
m_show = TRUE;
}
}
void effectLabel::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
// _this.setAttribute( "name", m_label->text() );
m_effWidget->saveState( _doc, _this );
}
void effectLabel::loadSettings( const QDomElement & _this )
{
// m_label->setText( _this.attribute( "name" ) );
QDomNode node = _this.firstChild();
while( !node.isNull() )
{
if( node.isElement() )
{
if( m_effWidget->nodeName() == node.nodeName() )
{
m_effWidget->restoreState( node.toElement() );
}
}
node = node.nextSibling();
}
}
void effectLabel::closeEffects( void )
{
m_effWidget->hide();
m_show = TRUE;
}
void effectLabel::rename( void )
{
QString txt = text();
renameDialog rename_dlg( txt );
rename_dlg.exec();
if( txt != text() )
{
setText( txt );
emit nameChanged( txt );
emit nameChanged();
}
}
void effectLabel::mousePressEvent( QMouseEvent * _me )
{
if( _me->button() == Qt::RightButton )
{
if( _me->x() > 29 )
{
rename();
}
}
else
{
emit clicked();
}
}
void effectLabel::mouseDoubleClickEvent( QMouseEvent * _me )
{
if( _me->x() > 29 )
{
rename();
}
}
#include "effect_label.moc"
#endif
#endif

View File

@@ -33,17 +33,18 @@
#include "effect.h"
ladspaControl::ladspaControl( QWidget * _parent, port_desc_t * _port, engine * _engine, instrumentTrack * _track ) :
ladspaControl::ladspaControl( QWidget * _parent, port_desc_t * _port, engine * _engine, track * _track ) :
QWidget( _parent, "ladspaControl" ),
journallingObject( _engine ),
m_port( _port ),
m_track( _track ),
m_toggle( NULL ),
m_knob( NULL )
{
switch( m_port->data_type )
{
case TOGGLED:
m_toggle = new ledCheckBox( m_port->name, this, "", eng(), _track );
m_toggle = new ledCheckBox( m_port->name, this, "", eng(), m_track );
setFixedSize( m_toggle->width(), m_toggle->height() );
if( m_port->def == 1.0f )
{
@@ -51,7 +52,7 @@ ladspaControl::ladspaControl( QWidget * _parent, port_desc_t * _port, engine * _
}
break;
case INTEGER:
m_knob = new knob( knobBright_26, this, m_port->name, eng(), _track);
m_knob = new knob( knobBright_26, this, m_port->name, eng(), m_track);
m_knob->setLabel( m_port->name );
m_knob->setRange( m_port->max, m_port->min, 1 + static_cast<int>( m_port->max - m_port->min ) / 500 );
m_knob->setInitValue( m_port->def );
@@ -65,7 +66,7 @@ ladspaControl::ladspaControl( QWidget * _parent, port_desc_t * _port, engine * _
tr( "Sorry, no help available." ) );
break;
case FLOAT:
m_knob = new knob( knobBright_26, this, m_port->name, eng(), _track);
m_knob = new knob( knobBright_26, this, m_port->name, eng(), m_track);
m_knob->setLabel( m_port->name );
if( ( m_port->max - m_port->min ) < 500.0f )
{

View File

@@ -53,22 +53,25 @@
#include "rack_plugin.h"
#include "knob.h"
#include "tempo_sync_knob.h"
#include "tooltip.h"
#include "ladspa_2_lmms.h"
#include "ladspa_control_dialog.h"
#include "audio_port.h"
#include "embed.h"
#include "gui_templates.h"
rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack * _track, engine * _engine ) :
rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, track * _track, engine * _engine, audioPort * _port ) :
QWidget( _parent, "rackPlugin" ),
journallingObject( _engine ),
m_track( _track ),
m_port( _port ),
m_contextMenu( NULL ),
m_key( _key )
m_key( _key ),
m_show( TRUE )
{
m_effect = new effect( _key, eng() );
_track->getAudioPort()->getEffects()->appendEffect( m_effect );
m_port->getEffects()->appendEffect( m_effect );
m_name = m_effect->getName();
@@ -78,7 +81,7 @@ rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack *
m_grouper = new QGroupBox( 1, Qt::Vertical, "", this );
m_grouper->setFixedSize( 210, 58 );
m_bypass = new ledCheckBox( "", this, tr( "Turn the effect off" ), eng(), _track );
m_bypass = new ledCheckBox( "", this, tr( "Turn the effect off" ), eng(), m_track );
connect( m_bypass, SIGNAL( toggled( bool ) ), this, SLOT( bypassed( bool ) ) );
toolTip::add( m_bypass, tr( "On/Off" ) );
m_bypass->setChecked( TRUE );
@@ -91,7 +94,7 @@ rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack *
tr(
"Toggles the effect on or off." ) );
m_wetDry = new knob( knobBright_26, this, tr( "Wet/Dry mix" ), eng(), _track );
m_wetDry = new knob( knobBright_26, this, tr( "Wet/Dry mix" ), eng(), m_track );
connect( m_wetDry, SIGNAL( valueChanged( float ) ), this, SLOT( setWetDry( float ) ) );
m_wetDry->setLabel( tr( "W/D" ) );
m_wetDry->setRange( 0.0f, 1.0f, 0.01f );
@@ -106,13 +109,13 @@ rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack *
tr(
"The Wet/Dry knob sets the ratio between the input signal and the effect that shows up in the output." ) );
m_autoQuit = new knob( knobBright_26, this, tr( "Decay" ), eng(), _track );
m_autoQuit = new tempoSyncKnob( knobBright_26, this, tr( "Decay" ), eng(), m_track );
connect( m_autoQuit, SIGNAL( valueChanged( float ) ), this, SLOT( setAutoQuit( float ) ) );
m_autoQuit->setLabel( tr( "Decay" ) );
m_autoQuit->setRange( 1, 100, 1 );
m_autoQuit->setRange( 1.0f, 8000.0f, 100.0f );
m_autoQuit->setInitValue( 1 );
m_autoQuit->move( 60, 3 );
m_autoQuit->setHintText( tr( "Buffers:" ) + " ", "" );
m_autoQuit->setHintText( tr( "Time:" ) + " ", "ms" );
#ifdef QT4
m_autoQuit->setWhatsThis(
#else
@@ -122,7 +125,7 @@ rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack *
"The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values "
"will reduce the CPU overhead but run the risk of clipping the tail on delay effects." ) );
m_gate = new knob( knobBright_26, this, tr( "Decay" ), eng(), _track );
m_gate = new knob( knobBright_26, this, tr( "Gate" ), eng(), m_track );
connect( m_wetDry, SIGNAL( valueChanged( float ) ), this, SLOT( setGate( float ) ) );
m_gate->setLabel( tr( "Gate" ) );
m_gate->setRange( 0.0f, 1.0f, 0.01f );
@@ -140,18 +143,22 @@ rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack *
m_editButton = new QPushButton( this, "Controls" );
m_editButton->setText( tr( "Controls" ) );
QFont f = m_editButton->font();
m_editButton->setFont( pointSize<7>( f ) );
m_editButton->setGeometry( 140, 19, 50, 20 );
connect( m_editButton, SIGNAL( clicked() ), this, SLOT( editControls() ) );
QString name = eng()->getLADSPAManager()->getShortName( _key );
m_label = new QLabel( this );
m_label->setText( name );
QFont f = m_label->font();
f = m_label->font();
f.setBold( TRUE );
m_label->setFont( pointSize<7>( f ) );
m_label->setGeometry( 5, 38, 200, 20 );
m_controlView = new ladspaControlDialog( this, m_effect, eng(), _track );
m_controlView = new ladspaControlDialog( NULL, m_effect, eng(), m_track );
connect( m_controlView, SIGNAL( closed() ), this, SLOT( closeEffects() ) );
m_controlView->hide();
#ifdef QT4
this->setWhatsThis(
@@ -199,8 +206,17 @@ rackPlugin::~rackPlugin()
void rackPlugin::editControls( void )
{
m_controlView->show();
m_controlView->raise();
if( m_show)
{
m_controlView->show();
m_controlView->raise();
m_show = FALSE;
}
else
{
m_controlView->hide();
m_show = TRUE;
}
}
@@ -223,7 +239,9 @@ void rackPlugin::setWetDry( float _value )
void rackPlugin::setAutoQuit( float _value )
{
m_effect->setTimeout( static_cast<Uint32>( _value ) );
float samples = eng()->getMixer()->sampleRate() * _value / 1000.0f;
Uint32 buffers = 1 + ( static_cast<Uint32>( samples ) / eng()->getMixer()->framesPerAudioBuffer() );
m_effect->setTimeout( buffers );
}
@@ -349,6 +367,15 @@ void FASTCALL rackPlugin::loadSettings( const QDomElement & _this )
void rackPlugin::closeEffects( void )
{
m_controlView->hide();
m_show = TRUE;
}
#include "rack_plugin.moc"
#endif

View File

@@ -30,13 +30,13 @@
#include <qmessagebox.h>
#include "rack_view.h"
#include "audio_port.h"
rackView::rackView( QWidget * _parent, engine * _engine, instrumentTrack * _track ):
rackView::rackView( QWidget * _parent, engine * _engine, track * _track, audioPort * _port ):
QWidget( _parent, "rackView" ),
journallingObject( _engine ),
m_instrumentTrack( _track ),
m_track( _track ),
m_port( _port ),
m_ladspa( eng()->getLADSPAManager() )
{
setFixedSize( 230, 180 );
@@ -61,7 +61,7 @@ rackView::~rackView()
void rackView::addPlugin( ladspa_key_t _key )
{
rackPlugin * plugin = new rackPlugin( m_scrollView->viewport(), _key, m_instrumentTrack, eng() );
rackPlugin * plugin = new rackPlugin( m_scrollView->viewport(), _key, m_track, eng(), m_port );
connect( plugin, SIGNAL( moveUp( rackPlugin * ) ), this, SLOT( moveUp( rackPlugin * ) ) );
connect( plugin, SIGNAL( moveDown( rackPlugin * ) ), this, SLOT( moveDown( rackPlugin * ) ) );
connect( plugin, SIGNAL( deletePlugin( rackPlugin * ) ), this, SLOT( deletePlugin( rackPlugin * ) ) );
@@ -103,7 +103,7 @@ void rackView::moveUp( rackPlugin * _plugin )
void rackView::moveDown( rackPlugin * _plugin )
{
m_instrumentTrack->getAudioPort()->getEffects()->moveDown( _plugin->getEffect() );
m_port->getEffects()->moveDown( _plugin->getEffect() );
if( _plugin != m_rackInserts.last() )
{
int i = 0;
@@ -129,7 +129,7 @@ void rackView::moveDown( rackPlugin * _plugin )
void rackView::deletePlugin( rackPlugin * _plugin )
{
m_instrumentTrack->getAudioPort()->getEffects()->deleteEffect( _plugin->getEffect() );
m_port->getEffects()->deleteEffect( _plugin->getEffect() );
m_scrollView->removeChild( _plugin );