Ability to save mixer sends to disk with the mmp

LMMS can load projects with the old mixer and new projects with
the new mixer. By "new mixer", I simply mean not hardcoded to 64
channels.
This commit is contained in:
Andrew Kelley
2009-10-01 02:45:32 -07:00
parent dd28a654b5
commit 333df687e6
8 changed files with 152 additions and 42 deletions

View File

@@ -280,18 +280,6 @@ signals:
inline type maxValue() const \
{ \
return AutomatableModel::maxValue<type>(); \
} \
\
inline void setMinValue(type val) \
{ \
m_minValue = val; \
if( m_value < m_minValue ) m_value = m_minValue; \
} \
\
inline void setMaxValue(type val) \
{ \
m_maxValue = val; \
if( m_value > m_maxValue ) m_value = m_maxValue; \
}
// some typed AutomatableModel-definitions

View File

@@ -5,6 +5,7 @@
#include <QLabel>
#include "knob.h"
#include "lcd_spinbox.h"
#include "SendButtonIndicator.h"
class FxMixerView;
@@ -15,19 +16,21 @@ class FxLine : public QWidget
Q_OBJECT
public:
FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex);
~FxLine();
virtual void paintEvent( QPaintEvent * );
virtual void mousePressEvent( QMouseEvent * );
virtual void mouseDoubleClickEvent( QMouseEvent * );
inline int channelIndex() { return m_channelIndex; }
inline void setChannelIndex(int index) { m_channelIndex = index; }
void setChannelIndex(int index);
knob * m_sendKnob;
SendButtonIndicator * m_sendBtn;
private:
FxMixerView * m_mv;
lcdSpinBox * m_lcd;
int m_channelIndex;

View File

@@ -73,9 +73,6 @@ public:
void prepareMasterMix();
void masterMix( sampleFrame * _buf );
void clear();
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
@@ -112,6 +109,9 @@ public:
// delete a channel from the FX mixer.
void deleteChannel(int index);
// delete all the mixer channels except master and remove all effects
void clear();
// re-arrange channels
void moveChannelLeft(int index);
void moveChannelRight(int index);
@@ -128,6 +128,9 @@ private:
// the fx channels in the mixer. index 0 is always master.
QVector<FxChannel *> m_fxChannels;
void allocateChannelsTo(int num);
friend class mixerWorkerThread;
friend class FxMixerView;

View File

@@ -91,6 +91,10 @@ public:
void moveChannelLeft(int index);
void moveChannelRight(int index);
// make sure the display syncs up with the fx mixer.
// useful for loading projects
void refreshDisplay();
private slots:
void updateFaders();
void addNewChannel();

View File

@@ -442,13 +442,16 @@ void FxMixer::masterMix( sampleFrame * _buf )
void FxMixer::clear()
{
for( int i = 0; i < m_fxChannels.size(); ++i )
while( m_fxChannels.size() > 1 )
{
clearChannel(i);
deleteChannel(1);
}
clearChannel(0);
}
void FxMixer::clearChannel(fx_ch_t index)
{
FxChannel * ch = m_fxChannels[index];
@@ -483,38 +486,94 @@ void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
for( int i = 0; i < m_fxChannels.size(); ++i )
{
FxChannel * ch = m_fxChannels[i];
QDomElement fxch = _doc.createElement( QString( "fxchannel" ) );
_this.appendChild( fxch );
m_fxChannels[i]->m_fxChain.saveState( _doc, fxch );
m_fxChannels[i]->m_volumeModel.saveSettings( _doc, fxch,
"volume" );
m_fxChannels[i]->m_muteModel.saveSettings( _doc, fxch,
"muted" );
ch->m_fxChain.saveState( _doc, fxch );
ch->m_volumeModel.saveSettings( _doc, fxch, "volume" );
ch->m_muteModel.saveSettings( _doc, fxch, "muted" );
fxch.setAttribute( "num", i );
fxch.setAttribute( "name", m_fxChannels[i]->m_name );
fxch.setAttribute( "name", ch->m_name );
// add the channel sends
for( int si = 0; si < ch->m_sends.size(); ++si )
{
QDomElement sendsDom = _doc.createElement( QString( "send" ) );
fxch.appendChild( sendsDom );
sendsDom.setAttribute( "channel", ch->m_sends[si] );
ch->m_sendAmount[si]->saveSettings( _doc, sendsDom, "amount");
}
}
}
void FxMixer::allocateChannelsTo(int num)
{
while( num > m_fxChannels.size() - 1 )
{
createChannel();
// delete the default send to master
deleteChannelSend(m_fxChannels.size()-1, 0);
}
}
void FxMixer::loadSettings( const QDomElement & _this )
{
clear();
QDomNode node = _this.firstChild();
for( int i = 0; i <= 64; ++i ) // TODO make this work
bool thereIsASend = false;
while( ! node.isNull() )
{
QDomElement fxch = node.toElement();
// index of the channel we are about to load
int num = fxch.attribute( "num" ).toInt();
m_fxChannels[num]->m_fxChain.restoreState(
fxch.firstChildElement(
m_fxChannels[num]->m_fxChain.nodeName() ) );
// allocate enough channels
allocateChannelsTo( num );
m_fxChannels[num]->m_volumeModel.loadSettings( fxch, "volume" );
m_fxChannels[num]->m_muteModel.loadSettings( fxch, "muted" );
m_fxChannels[num]->m_name = fxch.attribute( "name" );
m_fxChannels[num]->m_fxChain.restoreState( fxch.firstChildElement(
m_fxChannels[num]->m_fxChain.nodeName() ) );
// mixer sends
QDomNodeList chData = fxch.childNodes();
for( unsigned int i=0; i<chData.length(); ++i )
{
QDomElement chDataItem = chData.at(i).toElement();
if( chDataItem.nodeName() == QString( "send" ) )
{
thereIsASend = true;
int sendTo = chDataItem.attribute( "channel" ).toInt();
allocateChannelsTo( sendTo) ;
float amount = chDataItem.attribute( "amount" ).toFloat();
createChannelSend( num, sendTo, amount );
}
}
node = node.nextSibling();
}
// check for old format. 65 fx channels and no explicit sends.
if( ! thereIsASend && m_fxChannels.size() == 65 ) {
// create a send from every channel into master
for( int i=1; i<m_fxChannels.size(); ++i )
{
createChannelSend(i, 0);
}
}
emit dataChanged();
}

View File

@@ -904,6 +904,23 @@ void song::loadProject( const QString & _file_name )
firstChildElement( "track" ) );
}
QDomNode node = mmp.content().firstChild();
// walk through and fix up the mixer
while( !node.isNull() )
{
if( node.nodeName() == engine::fxMixer()->nodeName() )
{
engine::fxMixer()->restoreState( node.toElement() );
// refresh FxMixerView
engine::fxMixerView()->refreshDisplay();
}
node = node.nextSibling();
}
node = mmp.content().firstChild();
while( !node.isNull() )
{
if( node.isElement() )
@@ -917,10 +934,6 @@ void song::loadProject( const QString & _file_name )
{
restoreControllerStates( node.toElement() );
}
else if( node.nodeName() == engine::fxMixer()->nodeName() )
{
engine::fxMixer()->restoreState( node.toElement() );
}
else if( engine::hasGUI() )
{
if( node.nodeName() ==
@@ -973,7 +986,6 @@ void song::loadProject( const QString & _file_name )
// resolve all IDs so that autoModels are automated
automationPattern::resolveAllIDs();
engine::getMixer()->unlock();
configManager::inst()->addRecentlyOpenedProject( _file_name );

View File

@@ -9,7 +9,6 @@
#include "FxMixerView.h"
#include "embed.h"
#include "engine.h"
#include "lcd_spinbox.h"
#include "SendButtonIndicator.h"
FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) :
@@ -32,11 +31,27 @@ FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) :
m_sendBtn->move(4,4);
// channel number
lcdSpinBox * l = new lcdSpinBox( 2, this );
l->model()->setRange( m_channelIndex, m_channelIndex );
l->model()->setValue( m_channelIndex );
l->move( 2, 58 );
l->setMarginWidth( 1 );
m_lcd = new lcdSpinBox( 2, this );
m_lcd->model()->setRange( m_channelIndex, m_channelIndex );
m_lcd->model()->setValue( m_channelIndex );
m_lcd->move( 2, 58 );
m_lcd->setMarginWidth( 1 );
}
FxLine::~FxLine()
{
delete m_sendKnob;
delete m_sendBtn;
delete m_lcd;
}
void FxLine::setChannelIndex(int index) {
m_channelIndex = index;
m_lcd->model()->setRange( m_channelIndex, m_channelIndex );
m_lcd->model()->setValue( m_channelIndex );
m_lcd->update();
}

View File

@@ -91,8 +91,8 @@ FxMixerView::FxMixerView() :
m_fxChannelViews[i] = new FxChannelView(m_channelAreaWidget, this, i);
chLayout->addWidget(m_fxChannelViews[i]->m_fxLine);
}
// add the scrolling section to the main layout
// add the scrolling section to the main layout
// class solely for scroll area to pass key presses down
class ChannelArea : public QScrollArea
{
@@ -175,6 +175,32 @@ void FxMixerView::addNewChannel()
}
void FxMixerView::refreshDisplay()
{
// delete all views and re-add them
for( int i = 1; i<m_fxChannelViews.size(); ++i )
{
chLayout->removeWidget(m_fxChannelViews[i]->m_fxLine);
delete m_fxChannelViews[i]->m_fader;
delete m_fxChannelViews[i]->m_muteBtn;
delete m_fxChannelViews[i]->m_fxLine;
delete m_fxChannelViews[i];
}
m_channelAreaWidget->adjustSize();
// re-add the views
m_fxChannelViews.resize(engine::fxMixer()->numChannels());
for( int i = 1; i < m_fxChannelViews.size(); ++i )
{
m_fxChannelViews[i] = new FxChannelView(m_channelAreaWidget, this, i);
chLayout->addWidget(m_fxChannelViews[i]->m_fxLine);
}
// fix master
//TODO
}
void FxMixerView::updateMaxChannelSelector()
{
// update the and max. channel number for every instrument
@@ -190,8 +216,8 @@ void FxMixerView::updateMaxChannelSelector()
if( trackList[i]->type() == track::InstrumentTrack )
{
InstrumentTrack * inst = (InstrumentTrack *) trackList[i];
inst->effectChannelModel()->setMaxValue(
m_fxChannelViews.size()-1);
inst->effectChannelModel()->setRange(0,
m_fxChannelViews.size()-1,1);
}
}
}