From 333df687e6e21a838cd1145b269cf522fe5109dd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 1 Oct 2009 02:45:32 -0700 Subject: [PATCH] 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. --- include/AutomatableModel.h | 12 ------ include/FxLine.h | 5 ++- include/FxMixer.h | 9 +++-- include/FxMixerView.h | 4 ++ src/core/FxMixer.cpp | 83 ++++++++++++++++++++++++++++++++------ src/core/song.cpp | 22 +++++++--- src/gui/FxLine.cpp | 27 ++++++++++--- src/gui/FxMixerView.cpp | 32 +++++++++++++-- 8 files changed, 152 insertions(+), 42 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 6bd68187a..0f9308975 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -280,18 +280,6 @@ signals: inline type maxValue() const \ { \ return AutomatableModel::maxValue(); \ - } \ - \ - 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 diff --git a/include/FxLine.h b/include/FxLine.h index 70def8637..89e0321f3 100644 --- a/include/FxLine.h +++ b/include/FxLine.h @@ -5,6 +5,7 @@ #include #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; diff --git a/include/FxMixer.h b/include/FxMixer.h index 19caa1479..b9f11ca3e 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -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 m_fxChannels; + + void allocateChannelsTo(int num); + friend class mixerWorkerThread; friend class FxMixerView; diff --git a/include/FxMixerView.h b/include/FxMixerView.h index cff856659..1dc08a6e5 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -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(); diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 488fb09d9..e28deda3b 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -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; inodeName() ) + { + 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 ); diff --git a/src/gui/FxLine.cpp b/src/gui/FxLine.cpp index 5d57a6b0f..172d30b17 100644 --- a/src/gui/FxLine.cpp +++ b/src/gui/FxLine.cpp @@ -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(); } diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 70832c71b..ad844ec4f 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -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; iremoveWidget(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); } } }