Merge pull request #902 from diizy/fxmixer
FxMixer: rewrite mixer routing
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 1022 B After Width: | Height: | Size: 817 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
data/themes/default/receive_bg_arrow.png
Normal file
BIN
data/themes/default/receive_bg_arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 289 B |
@@ -61,13 +61,14 @@ public:
|
||||
static const int FxLineHeight;
|
||||
|
||||
private:
|
||||
static void drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, bool isActive, bool sendToThis );
|
||||
static void drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, bool isActive, bool sendToThis, bool receiveFromThis );
|
||||
|
||||
FxMixerView * m_mv;
|
||||
LcdWidget* m_lcd;
|
||||
int m_channelIndex;
|
||||
QBrush m_backgroundActive;
|
||||
static QPixmap * s_sendBgArrow;
|
||||
static QPixmap * s_receiveBgArrow;
|
||||
|
||||
private slots:
|
||||
void renameChannel();
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
#include "ThreadableJob.h"
|
||||
|
||||
|
||||
|
||||
class FxRoute;
|
||||
typedef QVector<FxRoute *> FxRouteVector;
|
||||
|
||||
class FxChannel : public ThreadableJob
|
||||
{
|
||||
@@ -58,11 +59,10 @@ class FxChannel : public ThreadableJob
|
||||
bool m_queued; // are we queued up for rendering yet?
|
||||
|
||||
// pointers to other channels that this one sends to
|
||||
QVector<fx_ch_t> m_sends;
|
||||
QVector<FloatModel *> m_sendAmount;
|
||||
FxRouteVector m_sends;
|
||||
|
||||
// pointers to other channels that send to this one
|
||||
QVector<fx_ch_t> m_receives;
|
||||
FxRouteVector m_receives;
|
||||
|
||||
virtual bool requiresProcessing() const { return true; }
|
||||
|
||||
@@ -71,6 +71,45 @@ class FxChannel : public ThreadableJob
|
||||
};
|
||||
|
||||
|
||||
class FxRoute : public QObject
|
||||
{
|
||||
public:
|
||||
FxRoute( FxChannel * from, FxChannel * to, float amount );
|
||||
virtual ~FxRoute();
|
||||
|
||||
fx_ch_t senderIndex() const
|
||||
{
|
||||
return m_from->m_channelIndex;
|
||||
}
|
||||
|
||||
fx_ch_t receiverIndex() const
|
||||
{
|
||||
return m_to->m_channelIndex;
|
||||
}
|
||||
|
||||
FloatModel * amount() const
|
||||
{
|
||||
return m_amount;
|
||||
}
|
||||
|
||||
FxChannel * sender() const
|
||||
{
|
||||
return m_from;
|
||||
}
|
||||
|
||||
FxChannel * receiver() const
|
||||
{
|
||||
return m_to;
|
||||
}
|
||||
|
||||
void updateName();
|
||||
|
||||
private:
|
||||
FxChannel * m_from;
|
||||
FxChannel * m_to;
|
||||
FloatModel * m_amount;
|
||||
};
|
||||
|
||||
|
||||
class EXPORT FxMixer : public JournallingObject, public Model
|
||||
{
|
||||
@@ -100,13 +139,16 @@ public:
|
||||
// it is safe to call even if the send already exists
|
||||
void createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel,
|
||||
float amount = 1.0f);
|
||||
void createRoute( FxChannel * from, FxChannel * to, float amount );
|
||||
|
||||
// delete the connection made by createChannelSend
|
||||
void deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel);
|
||||
void deleteChannelSend( FxRoute * route );
|
||||
|
||||
// determine if adding a send from sendFrom to
|
||||
// sendTo would result in an infinite mixer loop.
|
||||
bool isInfiniteLoop(fx_ch_t fromChannel, fx_ch_t toChannel);
|
||||
bool checkInfiniteLoop( FxChannel * from, FxChannel * to );
|
||||
|
||||
// return the FloatModel of fromChannel sending its output to the input of
|
||||
// toChannel. NULL if there is no send.
|
||||
@@ -129,11 +171,16 @@ public:
|
||||
// reset a channel's name, fx, sends, etc
|
||||
void clearChannel(fx_ch_t channelIndex);
|
||||
|
||||
// rename channels when moving etc. if they still have their original name
|
||||
void validateChannelName( int index, int oldIndex );
|
||||
|
||||
inline fx_ch_t numChannels() const
|
||||
{
|
||||
return m_fxChannels.size();
|
||||
}
|
||||
|
||||
FxRouteVector m_fxRoutes;
|
||||
|
||||
private:
|
||||
// the fx channels in the mixer. index 0 is always master.
|
||||
QVector<FxChannel *> m_fxChannels;
|
||||
@@ -142,7 +189,7 @@ private:
|
||||
void allocateChannelsTo(int num);
|
||||
QMutex m_sendsMutex;
|
||||
|
||||
void addChannelLeaf( int _ch, sampleFrame * _buf );
|
||||
void addChannelLeaf( FxChannel * ch, sampleFrame * buf );
|
||||
|
||||
friend class MixerWorkerThread;
|
||||
friend class FxMixerView;
|
||||
|
||||
@@ -34,6 +34,34 @@
|
||||
#include "bb_track_container.h"
|
||||
|
||||
|
||||
FxRoute::FxRoute( FxChannel * from, FxChannel * to, float amount ) :
|
||||
m_from( from ),
|
||||
m_to( to )
|
||||
{
|
||||
//qDebug( "created: %d to %d", m_from->m_channelIndex, m_to->m_channelIndex );
|
||||
// create send amount model
|
||||
m_amount = new FloatModel( amount, 0, 1, 0.001, NULL,
|
||||
tr( "Amount to send from channel %1 to channel %2" ).arg( m_from->m_channelIndex ).arg( m_to->m_channelIndex ) );
|
||||
}
|
||||
|
||||
|
||||
FxRoute::~FxRoute()
|
||||
{
|
||||
// remove send model
|
||||
delete m_amount;
|
||||
}
|
||||
|
||||
|
||||
void FxRoute::updateName()
|
||||
{
|
||||
if( m_amount)
|
||||
{
|
||||
m_amount->setDisplayName(
|
||||
tr( "Amount to send from channel %1 to channel %2" ).arg( m_from->m_channelIndex ).arg( m_to->m_channelIndex ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FxChannel::FxChannel( int idx, Model * _parent ) :
|
||||
m_fxChain( NULL ),
|
||||
m_hasInput( false ),
|
||||
@@ -65,7 +93,6 @@ FxChannel::~FxChannel()
|
||||
|
||||
void FxChannel::doProcessing( sampleFrame * _buf )
|
||||
{
|
||||
FxMixer * fxm = engine::fxMixer();
|
||||
const fpp_t fpp = engine::mixer()->framesPerPeriod();
|
||||
|
||||
// <tobydox> ignore the passed _buf
|
||||
@@ -77,20 +104,15 @@ void FxChannel::doProcessing( sampleFrame * _buf )
|
||||
// <tobydox> this improves cache hit rate
|
||||
_buf = m_buffer;
|
||||
|
||||
// SMF: OK, due to the fact, that the data from the audio-tracks has been
|
||||
// written into our buffer already, all which needs to be done at this
|
||||
// stage is to process inter-channel sends. I really don't like the idea
|
||||
// of using threads for this -- it just doesn't make any sense and wastes
|
||||
// cpu-cylces... so I just go through every child of this channel and
|
||||
// call the acc. doProcessing() directly.
|
||||
|
||||
if( m_muteModel.value() == false )
|
||||
{
|
||||
// OK, we are not muted, so we go recursively through all the channels
|
||||
// which send to us (our children)...
|
||||
foreach( fx_ch_t senderIndex, m_receives )
|
||||
foreach( FxRoute * senderRoute, m_receives )
|
||||
{
|
||||
FxChannel * sender = fxm->effectChannel( senderIndex );
|
||||
FxChannel * sender = senderRoute->sender();
|
||||
FloatModel * sendModel = senderRoute->amount();
|
||||
if( ! sendModel ) qFatal( "Error: no send model found from %d to %d", senderRoute->senderIndex(), m_channelIndex );
|
||||
|
||||
// wait for the sender job - either it's just been queued yet,
|
||||
// then ThreadableJob::process() will process it now within this
|
||||
@@ -104,8 +126,7 @@ void FxChannel::doProcessing( sampleFrame * _buf )
|
||||
if( sender->m_hasInput || sender->m_stillRunning )
|
||||
{
|
||||
// get the send level...
|
||||
const float amt =
|
||||
fxm->channelSendModel( senderIndex, m_channelIndex )->value();
|
||||
const float amt = sendModel->value();
|
||||
|
||||
// mix it's output with this one's output
|
||||
sampleFrame * ch_buf = sender->m_buffer;
|
||||
@@ -116,7 +137,7 @@ void FxChannel::doProcessing( sampleFrame * _buf )
|
||||
_buf[f][1] += ch_buf[f][1] * v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if sender channel hasInput, then we hasInput too
|
||||
if( sender->m_hasInput ) m_hasInput = true;
|
||||
}
|
||||
@@ -124,10 +145,10 @@ void FxChannel::doProcessing( sampleFrame * _buf )
|
||||
|
||||
const float v = m_volumeModel.value();
|
||||
|
||||
if( m_hasInput )
|
||||
if( m_hasInput )
|
||||
{
|
||||
// only start fxchain when we have input...
|
||||
m_fxChain.startRunning();
|
||||
m_fxChain.startRunning();
|
||||
}
|
||||
if( m_hasInput || m_stillRunning )
|
||||
{
|
||||
@@ -152,12 +173,12 @@ FxMixer::FxMixer() :
|
||||
|
||||
FxMixer::~FxMixer()
|
||||
{
|
||||
while( ! m_fxRoutes.isEmpty() )
|
||||
{
|
||||
deleteChannelSend( m_fxRoutes.first() );
|
||||
}
|
||||
for( int i = 0; i < m_fxChannels.size(); ++i )
|
||||
{
|
||||
for( int j = 0; j < m_fxChannels[i]->m_sendAmount.size(); ++j)
|
||||
{
|
||||
delete m_fxChannels[i]->m_sendAmount[j];
|
||||
}
|
||||
delete m_fxChannels[i];
|
||||
}
|
||||
}
|
||||
@@ -177,10 +198,12 @@ int FxMixer::createChannel()
|
||||
}
|
||||
|
||||
|
||||
void FxMixer::deleteChannel(int index)
|
||||
void FxMixer::deleteChannel( int index )
|
||||
{
|
||||
m_fxChannels[index]->m_lock.lock();
|
||||
|
||||
FxChannel * ch = m_fxChannels[index];
|
||||
|
||||
// go through every instrument and adjust for the channel index change
|
||||
TrackContainer::TrackList tracks;
|
||||
tracks += engine::getSong()->tracks();
|
||||
@@ -207,52 +230,34 @@ void FxMixer::deleteChannel(int index)
|
||||
}
|
||||
|
||||
// delete all of this channel's sends and receives
|
||||
while( ! m_fxChannels[index]->m_sends.isEmpty() )
|
||||
while( ! ch->m_sends.isEmpty() )
|
||||
{
|
||||
deleteChannelSend( index, m_fxChannels[index]->m_sends.first() );
|
||||
deleteChannelSend( ch->m_sends.first() );
|
||||
}
|
||||
while( ! m_fxChannels[index]->m_receives.isEmpty() )
|
||||
while( ! ch->m_receives.isEmpty() )
|
||||
{
|
||||
deleteChannelSend( m_fxChannels[index]->m_receives.first(), index );
|
||||
}
|
||||
|
||||
for(int i=0; i<m_fxChannels.size(); ++i)
|
||||
{
|
||||
// for every send/receive, adjust for the channel index change
|
||||
for(int j=0; j<m_fxChannels[i]->m_sends.size(); ++j)
|
||||
{
|
||||
if( m_fxChannels[i]->m_sends[j] > index )
|
||||
{
|
||||
// subtract 1 to make up for the missing channel
|
||||
--m_fxChannels[i]->m_sends[j];
|
||||
}
|
||||
}
|
||||
for(int j=0; j<m_fxChannels[i]->m_receives.size(); ++j)
|
||||
{
|
||||
if( m_fxChannels[i]->m_receives[j] > index )
|
||||
{
|
||||
// subtract 1 to make up for the missing channel
|
||||
--m_fxChannels[i]->m_receives[j];
|
||||
}
|
||||
}
|
||||
|
||||
deleteChannelSend( ch->m_receives.first() );
|
||||
}
|
||||
|
||||
// actually delete the channel
|
||||
delete m_fxChannels[index];
|
||||
m_fxChannels.remove(index);
|
||||
|
||||
for( int i = index; i < m_fxChannels.size(); ++i )
|
||||
{
|
||||
validateChannelName( i, i + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FxMixer::moveChannelLeft(int index)
|
||||
void FxMixer::moveChannelLeft( int index )
|
||||
{
|
||||
// can't move master or first channel
|
||||
if( index <= 1 || index >= m_fxChannels.size() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_sendsMutex.lock();
|
||||
// channels to swap
|
||||
int a = index - 1, b = index;
|
||||
|
||||
@@ -283,122 +288,132 @@ void FxMixer::moveChannelLeft(int index)
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<m_fxChannels.size(); ++i)
|
||||
{
|
||||
// for every send/receive, adjust for the channel index change
|
||||
for(int j=0; j<m_fxChannels[i]->m_sends.size(); ++j)
|
||||
{
|
||||
if( m_fxChannels[i]->m_sends[j] == a )
|
||||
{
|
||||
m_fxChannels[i]->m_sends[j] = b;
|
||||
}
|
||||
else if( m_fxChannels[i]->m_sends[j] == b )
|
||||
{
|
||||
m_fxChannels[i]->m_sends[j] = a;
|
||||
}
|
||||
}
|
||||
for(int j=0; j<m_fxChannels[i]->m_receives.size(); ++j)
|
||||
{
|
||||
if( m_fxChannels[i]->m_receives[j] == a )
|
||||
{
|
||||
m_fxChannels[i]->m_receives[j] = b;
|
||||
}
|
||||
else if( m_fxChannels[i]->m_receives[j] == b )
|
||||
{
|
||||
m_fxChannels[i]->m_receives[j] = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actually do the swap
|
||||
FxChannel * tmpChannel = m_fxChannels[a];
|
||||
m_fxChannels[a] = m_fxChannels[b];
|
||||
m_fxChannels[b] = tmpChannel;
|
||||
m_sendsMutex.unlock();
|
||||
|
||||
validateChannelName( a, b );
|
||||
validateChannelName( b, a );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FxMixer::moveChannelRight(int index)
|
||||
void FxMixer::moveChannelRight( int index )
|
||||
{
|
||||
moveChannelLeft(index+1);
|
||||
moveChannelLeft( index + 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FxMixer::createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel,
|
||||
float amount)
|
||||
void FxMixer::createChannelSend( fx_ch_t fromChannel, fx_ch_t toChannel,
|
||||
float amount )
|
||||
{
|
||||
// qDebug( "requested: %d to %d", fromChannel, toChannel );
|
||||
// find the existing connection
|
||||
FxChannel * from = m_fxChannels[fromChannel];
|
||||
for(int i=0; i<from->m_sends.size(); ++i){
|
||||
if( from->m_sends[i] == toChannel )
|
||||
FxChannel * to = m_fxChannels[toChannel];
|
||||
|
||||
for( int i=0; i<from->m_sends.size(); ++i )
|
||||
{
|
||||
if( from->m_sends[i]->receiver() == to )
|
||||
{
|
||||
// simply adjust the amount
|
||||
from->m_sendAmount[i]->setValue(amount);
|
||||
from->m_sends[i]->amount()->setValue( amount );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// connection does not exist. create a new one
|
||||
m_sendsMutex.lock();
|
||||
// add to from's sends
|
||||
from->m_sends.push_back(toChannel);
|
||||
from->m_sendAmount.push_back(new FloatModel(amount, 0, 1, 0.001, NULL,
|
||||
tr("Amount to send")));
|
||||
createRoute( from, to, amount );
|
||||
}
|
||||
|
||||
// add to to's receives
|
||||
m_fxChannels[toChannel]->m_receives.push_back(fromChannel);
|
||||
|
||||
void FxMixer::createRoute( FxChannel * from, FxChannel * to, float amount )
|
||||
{
|
||||
if( from == to )
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_sendsMutex.lock();
|
||||
FxRoute * route = new FxRoute( from, to, amount );
|
||||
|
||||
// add us to from's sends
|
||||
from->m_sends.append( route );
|
||||
|
||||
// add us to to's receives
|
||||
to->m_receives.append( route );
|
||||
|
||||
// add us to fxmixer's list
|
||||
engine::fxMixer()->m_fxRoutes.append( route );
|
||||
m_sendsMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// delete the connection made by createChannelSend
|
||||
void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel)
|
||||
void FxMixer::deleteChannelSend( fx_ch_t fromChannel, fx_ch_t toChannel )
|
||||
{
|
||||
// delete the send
|
||||
FxChannel * from = m_fxChannels[fromChannel];
|
||||
FxChannel * to = m_fxChannels[toChannel];
|
||||
m_sendsMutex.lock();
|
||||
// find and delete the send entry
|
||||
for(int i=0; i<from->m_sends.size(); ++i) {
|
||||
if( from->m_sends[i] == toChannel )
|
||||
{
|
||||
// delete this index
|
||||
delete from->m_sendAmount[i];
|
||||
from->m_sendAmount.remove(i);
|
||||
from->m_sends.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// find and delete the receive entry
|
||||
for(int i=0; i<to->m_receives.size(); ++i)
|
||||
// find and delete the send entry
|
||||
for( int i = 0; i < from->m_sends.size(); ++i )
|
||||
{
|
||||
if( to->m_receives[i] == fromChannel )
|
||||
if( from->m_sends[i]->receiver() == to )
|
||||
{
|
||||
// delete this index
|
||||
to->m_receives.remove(i);
|
||||
deleteChannelSend( from->m_sends[i] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FxMixer::deleteChannelSend( FxRoute * route )
|
||||
{
|
||||
m_sendsMutex.lock();
|
||||
// remove us from from's sends
|
||||
route->sender()->m_sends.remove( route->sender()->m_sends.indexOf( route ) );
|
||||
// remove us from to's receives
|
||||
route->receiver()->m_receives.remove( route->receiver()->m_receives.indexOf( route ) );
|
||||
// remove us from fxmixer's list
|
||||
engine::fxMixer()->m_fxRoutes.remove( engine::fxMixer()->m_fxRoutes.indexOf( route ) );
|
||||
delete route;
|
||||
m_sendsMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
bool FxMixer::isInfiniteLoop(fx_ch_t sendFrom, fx_ch_t sendTo) {
|
||||
bool FxMixer::isInfiniteLoop( fx_ch_t sendFrom, fx_ch_t sendTo )
|
||||
{
|
||||
if( sendFrom == sendTo ) return true;
|
||||
//m_sendsMutex.lock();
|
||||
FxChannel * from = m_fxChannels[sendFrom];
|
||||
FxChannel * to = m_fxChannels[sendTo];
|
||||
bool b = checkInfiniteLoop( from, to );
|
||||
//m_sendsMutex.unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
bool FxMixer::checkInfiniteLoop( FxChannel * from, FxChannel * to )
|
||||
{
|
||||
// can't send master to anything
|
||||
if( sendFrom == 0 ) return true;
|
||||
if( from == m_fxChannels[0] )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// can't send channel to itself
|
||||
if( sendFrom == sendTo ) return true;
|
||||
if( from == to )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// follow sendTo's outputs recursively looking for something that sends
|
||||
// to sendFrom
|
||||
for(int i=0; i<m_fxChannels[sendTo]->m_sends.size(); ++i)
|
||||
for( int i=0; i < to->m_sends.size(); ++i )
|
||||
{
|
||||
if( isInfiniteLoop( sendFrom, m_fxChannels[sendTo]->m_sends[i] ) )
|
||||
if( checkInfiniteLoop( from, to->m_sends[i]->receiver() ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -409,13 +424,23 @@ bool FxMixer::isInfiniteLoop(fx_ch_t sendFrom, fx_ch_t sendTo) {
|
||||
|
||||
|
||||
// how much does fromChannel send its output to the input of toChannel?
|
||||
FloatModel * FxMixer::channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel)
|
||||
FloatModel * FxMixer::channelSendModel( fx_ch_t fromChannel, fx_ch_t toChannel )
|
||||
{
|
||||
FxChannel * from = m_fxChannels[fromChannel];
|
||||
for(int i=0; i<from->m_sends.size(); ++i){
|
||||
if( from->m_sends[i] == toChannel )
|
||||
return from->m_sendAmount[i];
|
||||
if( fromChannel == toChannel )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
FxChannel * from = m_fxChannels[fromChannel];
|
||||
FxChannel * to = m_fxChannels[toChannel];
|
||||
|
||||
foreach( FxRoute * route, from->m_sends )
|
||||
{
|
||||
if( route->receiver() == to )
|
||||
{
|
||||
return route->amount();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -423,15 +448,6 @@ FloatModel * FxMixer::channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel)
|
||||
|
||||
void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch )
|
||||
{
|
||||
// SMF: it seems like here the track-channels are mixed in... but from where
|
||||
// is this called and when and why...?!?
|
||||
//
|
||||
// OK, found it (git grep is your friend...): This is the next part,
|
||||
// where there is a mix between push and pull model inside the core, as
|
||||
// the audio-tracks *push* their data into the fx-channels hopefully just
|
||||
// before the Mixer-Channels are processed... Sorry to say this: but this
|
||||
// took me senseless hours to find out and is silly, too...
|
||||
|
||||
if( m_fxChannels[_ch]->m_muteModel.value() == false )
|
||||
{
|
||||
m_fxChannels[_ch]->m_lock.lock();
|
||||
@@ -452,24 +468,22 @@ void FxMixer::prepareMasterMix()
|
||||
|
||||
|
||||
|
||||
void FxMixer::addChannelLeaf( int _ch, sampleFrame * _buf )
|
||||
void FxMixer::addChannelLeaf( FxChannel * ch, sampleFrame * buf )
|
||||
{
|
||||
FxChannel * thisCh = m_fxChannels[_ch];
|
||||
|
||||
// if we're muted or this channel is seen already, discount it
|
||||
if( thisCh->m_queued )
|
||||
if( ch->m_queued )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach( const int senderIndex, thisCh->m_receives )
|
||||
foreach( FxRoute * senderRoute, ch->m_receives )
|
||||
{
|
||||
addChannelLeaf( senderIndex, _buf );
|
||||
addChannelLeaf( senderRoute->sender(), buf );
|
||||
}
|
||||
|
||||
// add this channel to job list
|
||||
thisCh->m_queued = true;
|
||||
MixerWorkerThread::addJob( thisCh );
|
||||
ch->m_queued = true;
|
||||
MixerWorkerThread::addJob( ch );
|
||||
}
|
||||
|
||||
|
||||
@@ -482,15 +496,14 @@ void FxMixer::masterMix( sampleFrame * _buf )
|
||||
// and add all channels to job list that have no dependencies
|
||||
// when the channel completes it will check its parent to see if it needs
|
||||
// to be processed.
|
||||
m_sendsMutex.lock();
|
||||
//m_sendsMutex.lock();
|
||||
MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic );
|
||||
addChannelLeaf( 0, _buf );
|
||||
addChannelLeaf( m_fxChannels[0], _buf );
|
||||
while( m_fxChannels[0]->state() != ThreadableJob::Done )
|
||||
{
|
||||
MixerWorkerThread::startAndWaitForJobs();
|
||||
}
|
||||
//m_fxChannels[0]->doProcessing( NULL );
|
||||
m_sendsMutex.unlock();
|
||||
//m_sendsMutex.unlock();
|
||||
|
||||
const float v = m_fxChannels[0]->m_volumeModel.value();
|
||||
MixHelpers::addMultiplied( _buf, m_fxChannels[0]->m_buffer, v, fpp );
|
||||
@@ -532,7 +545,7 @@ void FxMixer::clearChannel(fx_ch_t index)
|
||||
ch->m_volumeModel.setValue( 1.0f );
|
||||
ch->m_muteModel.setValue( false );
|
||||
ch->m_name = ( index == 0 ) ? tr( "Master" ) : tr( "FX %1" ).arg( index );
|
||||
ch->m_volumeModel.setDisplayName(ch->m_name );
|
||||
ch->m_volumeModel.setDisplayName( ch->m_name );
|
||||
|
||||
// send only to master
|
||||
if( index > 0)
|
||||
@@ -540,17 +553,17 @@ void FxMixer::clearChannel(fx_ch_t index)
|
||||
// delete existing sends
|
||||
while( ! ch->m_sends.isEmpty() )
|
||||
{
|
||||
deleteChannelSend( index, ch->m_sends.first() );
|
||||
deleteChannelSend( ch->m_sends.first() );
|
||||
}
|
||||
|
||||
// add send to master
|
||||
createChannelSend(index, 0);
|
||||
createChannelSend( index, 0 );
|
||||
}
|
||||
|
||||
// delete receives
|
||||
while( ! ch->m_receives.isEmpty() )
|
||||
{
|
||||
deleteChannelSend( ch->m_receives.first(), index );
|
||||
deleteChannelSend( ch->m_receives.first() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,8 +588,8 @@ void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
QDomElement sendsDom = _doc.createElement( QString( "send" ) );
|
||||
fxch.appendChild( sendsDom );
|
||||
|
||||
sendsDom.setAttribute( "channel", ch->m_sends[si] );
|
||||
ch->m_sendAmount[si]->saveSettings( _doc, sendsDom, "amount");
|
||||
sendsDom.setAttribute( "channel", ch->m_sends[si]->receiverIndex() );
|
||||
ch->m_sends[si]->amount()->saveSettings( _doc, sendsDom, "amount" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -589,7 +602,7 @@ void FxMixer::allocateChannelsTo(int num)
|
||||
createChannel();
|
||||
|
||||
// delete the default send to master
|
||||
deleteChannelSend(m_fxChannels.size()-1, 0);
|
||||
deleteChannelSend( m_fxChannels.size()-1, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,7 +639,7 @@ void FxMixer::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
thereIsASend = true;
|
||||
int sendTo = chDataItem.attribute( "channel" ).toInt();
|
||||
allocateChannelsTo( sendTo) ;
|
||||
allocateChannelsTo( sendTo ) ;
|
||||
float amount = chDataItem.attribute( "amount" ).toFloat();
|
||||
createChannelSend( num, sendTo, amount );
|
||||
}
|
||||
@@ -642,10 +655,31 @@ void FxMixer::loadSettings( const QDomElement & _this )
|
||||
// create a send from every channel into master
|
||||
for( int i=1; i<m_fxChannels.size(); ++i )
|
||||
{
|
||||
createChannelSend(i, 0);
|
||||
createChannelSend( i, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
|
||||
void FxMixer::validateChannelName( int index, int oldIndex )
|
||||
{
|
||||
FxChannel * fxc = m_fxChannels[ index ];
|
||||
if( fxc->m_name == tr( "FX %1" ).arg( oldIndex ) )
|
||||
{
|
||||
fxc->m_name = tr( "FX %1" ).arg( index );
|
||||
}
|
||||
// set correct channel index
|
||||
fxc->m_channelIndex = index;
|
||||
|
||||
// now check all routes and update names of the send models
|
||||
foreach( FxRoute * r, fxc->m_sends )
|
||||
{
|
||||
r->updateName();
|
||||
}
|
||||
foreach( FxRoute * r, fxc->m_receives )
|
||||
{
|
||||
r->updateName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
const int FxLine::FxLineHeight = 287;
|
||||
QPixmap * FxLine::s_sendBgArrow = NULL;
|
||||
QPixmap * FxLine::s_receiveBgArrow = NULL;
|
||||
|
||||
FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) :
|
||||
QWidget( _parent ),
|
||||
@@ -51,6 +52,10 @@ FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) :
|
||||
{
|
||||
s_sendBgArrow = new QPixmap( embed::getIconPixmap( "send_bg_arrow", 29, 56 ) );
|
||||
}
|
||||
if( ! s_receiveBgArrow )
|
||||
{
|
||||
s_receiveBgArrow = new QPixmap( embed::getIconPixmap( "receive_bg_arrow", 29, 56 ) );
|
||||
}
|
||||
|
||||
setFixedSize( 33, FxLineHeight );
|
||||
setAttribute( Qt::WA_OpaquePaintEvent, true );
|
||||
@@ -103,7 +108,7 @@ void FxLine::setChannelIndex(int index) {
|
||||
}
|
||||
|
||||
|
||||
void FxLine::drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, bool isActive, bool sendToThis )
|
||||
void FxLine::drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, bool isActive, bool sendToThis, bool receiveFromThis )
|
||||
{
|
||||
int width = fxLine->rect().width();
|
||||
int height = fxLine->rect().height();
|
||||
@@ -126,7 +131,11 @@ void FxLine::drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name,
|
||||
// draw the mixer send background
|
||||
if( sendToThis )
|
||||
{
|
||||
p->drawPixmap( 2, 0, 29, 56, *FxLine::s_sendBgArrow );
|
||||
p->drawPixmap( 2, 0, 29, 56, *s_sendBgArrow );
|
||||
}
|
||||
else if( receiveFromThis )
|
||||
{
|
||||
p->drawPixmap( 2, 0, 29, 56, *s_receiveBgArrow );
|
||||
}
|
||||
|
||||
// draw the channel name
|
||||
@@ -148,11 +157,13 @@ void FxLine::paintEvent( QPaintEvent * )
|
||||
FxMixer * mix = engine::fxMixer();
|
||||
bool sendToThis = mix->channelSendModel(
|
||||
m_mv->currentFxLine()->m_channelIndex, m_channelIndex ) != NULL;
|
||||
bool receiveFromThis = mix->channelSendModel(
|
||||
m_channelIndex, m_mv->currentFxLine()->m_channelIndex ) != NULL;
|
||||
QPainter painter;
|
||||
painter.begin( this );
|
||||
drawFxLine( &painter, this,
|
||||
mix->effectChannel( m_channelIndex )->m_name,
|
||||
m_mv->currentFxLine() == this, sendToThis );
|
||||
m_mv->currentFxLine() == this, sendToThis, receiveFromThis );
|
||||
painter.end();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user