Merge branch 'stable-1.1'
Conflicts: include/AutomatableModel.h include/FxMixer.h src/core/FxMixer.cpp src/gui/widgets/caption_menu.cpp src/tracks/InstrumentTrack.cpp
This commit is contained in:
@@ -47,6 +47,7 @@ AutomatableModel::AutomatableModel( DataType type,
|
||||
m_step( step ),
|
||||
m_range( max - min ),
|
||||
m_centerValue( m_minValue ),
|
||||
m_valueChanged( false ),
|
||||
m_setValueDepth( 0 ),
|
||||
m_hasStrictStepSize( false ),
|
||||
m_hasLinkedModels( false ),
|
||||
@@ -240,6 +241,7 @@ void AutomatableModel::setValue( const float value )
|
||||
(*it)->setJournalling( journalling );
|
||||
}
|
||||
}
|
||||
m_valueChanged = true;
|
||||
emit dataChanged();
|
||||
}
|
||||
else
|
||||
@@ -334,6 +336,7 @@ void AutomatableModel::setAutomatedValue( const float value )
|
||||
(*it)->setAutomatedValue( value );
|
||||
}
|
||||
}
|
||||
m_valueChanged = true;
|
||||
emit dataChanged();
|
||||
}
|
||||
--m_setValueDepth;
|
||||
@@ -478,6 +481,7 @@ void AutomatableModel::setControllerConnection( ControllerConnection* c )
|
||||
{
|
||||
QObject::connect( m_controllerConnection, SIGNAL( valueChanged() ), this, SIGNAL( dataChanged() ) );
|
||||
QObject::connect( m_controllerConnection, SIGNAL( destroyed() ), this, SLOT( unlinkControllerConnection() ) );
|
||||
m_valueChanged = true;
|
||||
emit dataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ FxChannel::FxChannel( int idx, Model * _parent ) :
|
||||
m_name(),
|
||||
m_lock(),
|
||||
m_channelIndex( idx ),
|
||||
m_queued( false )
|
||||
m_queued( false ),
|
||||
m_dependenciesMet( 0 )
|
||||
{
|
||||
engine::mixer()->clearAudioBuffer( m_buffer,
|
||||
engine::mixer()->framesPerPeriod() );
|
||||
@@ -85,6 +86,27 @@ FxChannel::~FxChannel()
|
||||
}
|
||||
|
||||
|
||||
inline void FxChannel::processed()
|
||||
{
|
||||
foreach( FxRoute * receiverRoute, m_sends )
|
||||
{
|
||||
if( receiverRoute->receiver()->m_muted == false )
|
||||
{
|
||||
receiverRoute->receiver()->incrementDeps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FxChannel::incrementDeps()
|
||||
{
|
||||
m_dependenciesMet.ref();
|
||||
if( m_dependenciesMet >= m_receives.size() )
|
||||
{
|
||||
m_queued = true;
|
||||
MixerWorkerThread::addJob( this );
|
||||
m_dependenciesMet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FxChannel::unmuteForSolo()
|
||||
{
|
||||
@@ -107,25 +129,14 @@ void FxChannel::doProcessing( sampleFrame * _buf )
|
||||
// <tobydox> this improves cache hit rate
|
||||
_buf = m_buffer;
|
||||
|
||||
if( m_muteModel.value() == false )
|
||||
if( m_muted == false )
|
||||
{
|
||||
// OK, we are not muted, so we go recursively through all the channels
|
||||
// which send to us (our children)...
|
||||
foreach( FxRoute * senderRoute, m_receives )
|
||||
{
|
||||
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
|
||||
// thread - otherwise it has been is is being processed by another
|
||||
// thread and we just have to wait for it to finish
|
||||
while( sender->state() != ThreadableJob::Done )
|
||||
{
|
||||
sender->process();
|
||||
}
|
||||
|
||||
if( sender->m_hasInput || sender->m_stillRunning )
|
||||
{
|
||||
// figure out if we're getting sample-exact input
|
||||
@@ -158,20 +169,28 @@ void FxChannel::doProcessing( sampleFrame * _buf )
|
||||
m_hasInput = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const float v = m_volumeModel.value();
|
||||
|
||||
if( m_hasInput )
|
||||
{
|
||||
// only start fxchain when we have input...
|
||||
m_fxChain.startRunning();
|
||||
}
|
||||
|
||||
m_stillRunning = m_fxChain.processAudioBuffer( _buf, fpp, m_hasInput );
|
||||
|
||||
m_peakLeft = qMax( m_peakLeft, engine::mixer()->peakValueLeft( _buf, fpp ) * v );
|
||||
m_peakRight = qMax( m_peakRight, engine::mixer()->peakValueRight( _buf, fpp ) * v );
|
||||
}
|
||||
|
||||
const float v = m_volumeModel.value();
|
||||
|
||||
if( m_hasInput )
|
||||
else
|
||||
{
|
||||
// only start fxchain when we have input...
|
||||
m_fxChain.startRunning();
|
||||
m_peakLeft = m_peakRight = 0.0f;
|
||||
}
|
||||
|
||||
m_stillRunning = m_fxChain.processAudioBuffer( _buf, fpp, m_hasInput );
|
||||
|
||||
m_peakLeft = qMax( m_peakLeft, engine::mixer()->peakValueLeft( _buf, fpp ) * v );
|
||||
m_peakRight = qMax( m_peakRight, engine::mixer()->peakValueRight( _buf, fpp ) * v );
|
||||
// increment dependency counter of all receivers
|
||||
processed();
|
||||
}
|
||||
|
||||
|
||||
@@ -456,11 +475,9 @@ void FxMixer::deleteChannelSend( FxRoute * route )
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -538,42 +555,38 @@ void FxMixer::prepareMasterMix()
|
||||
|
||||
|
||||
|
||||
void FxMixer::addChannelLeaf( FxChannel * ch, sampleFrame * buf )
|
||||
{
|
||||
// if we're muted or this channel is seen already, discount it
|
||||
if( ch->m_queued )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach( FxRoute * senderRoute, ch->m_receives )
|
||||
{
|
||||
addChannelLeaf( senderRoute->sender(), buf );
|
||||
}
|
||||
|
||||
// add this channel to job list
|
||||
ch->m_queued = true;
|
||||
MixerWorkerThread::addJob( ch );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FxMixer::masterMix( sampleFrame * _buf )
|
||||
{
|
||||
const int fpp = engine::mixer()->framesPerPeriod();
|
||||
|
||||
// recursively loop through channel dependency chain
|
||||
// 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();
|
||||
MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic );
|
||||
addChannelLeaf( m_fxChannels[0], _buf );
|
||||
while( m_fxChannels[0]->state() != ThreadableJob::Done )
|
||||
if( m_sendsMutex.tryLock() )
|
||||
{
|
||||
MixerWorkerThread::startAndWaitForJobs();
|
||||
// add the channels that have no dependencies (no incoming senders, ie. no receives)
|
||||
// to the jobqueue. The channels that have receives get added when their senders get processed, which
|
||||
// is detected by dependency counting.
|
||||
// also instantly add all muted channels as they don't need to care about their senders, and can just increment the deps of
|
||||
// their recipients right away.
|
||||
MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic );
|
||||
foreach( FxChannel * ch, m_fxChannels )
|
||||
{
|
||||
ch->m_muted = ch->m_muteModel.value();
|
||||
if( ch->m_muted ) // instantly "process" muted channels
|
||||
{
|
||||
ch->processed();
|
||||
ch->done();
|
||||
}
|
||||
else if( ch->m_receives.size() == 0 )
|
||||
{
|
||||
ch->m_queued = true;
|
||||
MixerWorkerThread::addJob( ch );
|
||||
}
|
||||
}
|
||||
while( m_fxChannels[0]->state() != ThreadableJob::Done )
|
||||
{
|
||||
MixerWorkerThread::startAndWaitForJobs();
|
||||
}
|
||||
m_sendsMutex.unlock();
|
||||
}
|
||||
//m_sendsMutex.unlock();
|
||||
|
||||
// handle sample-exact data in master volume fader
|
||||
ValueBuffer * volBuf = m_fxChannels[0]->m_volumeModel.valueBuffer();
|
||||
|
||||
@@ -1044,7 +1044,7 @@ void trackContentWidget::updateBackground()
|
||||
// draw lines
|
||||
pmp.setPen( QPen( QColor( 0, 0, 0, 160 ), 1 ) );
|
||||
// horizontal line
|
||||
pmp.drawLine( 0, 0, w*2, 0 );
|
||||
pmp.drawLine( 0, h-1, w*2, h-1 );
|
||||
|
||||
// vertical lines
|
||||
for( float x = 0; x < w * 2; x += ppt )
|
||||
|
||||
@@ -176,14 +176,12 @@ void ControllerView::modelChanged()
|
||||
|
||||
void ControllerView::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
QPointer<captionMenu> contextMenu = new captionMenu( model()->displayName() );
|
||||
QPointer<captionMenu> contextMenu = new captionMenu( model()->displayName(), this );
|
||||
contextMenu->addAction( embed::getIconPixmap( "cancel" ),
|
||||
tr( "&Remove this plugin" ),
|
||||
this, SLOT( deleteController() ) );
|
||||
contextMenu->addSeparator();
|
||||
contextMenu->addAction( embed::getIconPixmap( "help" ),
|
||||
tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu->addHelpAction();
|
||||
contextMenu->exec( QCursor::pos() );
|
||||
delete contextMenu;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ void EffectView::closeEffects()
|
||||
|
||||
void EffectView::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
QPointer<captionMenu> contextMenu = new captionMenu( model()->displayName() );
|
||||
QPointer<captionMenu> contextMenu = new captionMenu( model()->displayName(), this );
|
||||
contextMenu->addAction( embed::getIconPixmap( "arp_up" ),
|
||||
tr( "Move &up" ),
|
||||
this, SLOT( moveUp() ) );
|
||||
@@ -257,9 +257,7 @@ void EffectView::contextMenuEvent( QContextMenuEvent * )
|
||||
tr( "&Remove this plugin" ),
|
||||
this, SLOT( deletePlugin() ) );
|
||||
contextMenu->addSeparator();
|
||||
contextMenu->addAction( embed::getIconPixmap( "help" ),
|
||||
tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu->addHelpAction();
|
||||
contextMenu->exec( QCursor::pos() );
|
||||
delete contextMenu;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ void FxLine::mouseDoubleClickEvent( QMouseEvent * )
|
||||
void FxLine::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
FxMixer * mix = engine::fxMixer();
|
||||
QPointer<captionMenu> contextMenu = new captionMenu( mix->effectChannel( m_channelIndex )->m_name );
|
||||
QPointer<captionMenu> contextMenu = new captionMenu( mix->effectChannel( m_channelIndex )->m_name, this );
|
||||
if( m_channelIndex != 0 ) // no move-options in master
|
||||
{
|
||||
contextMenu->addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) );
|
||||
@@ -199,9 +199,7 @@ void FxLine::contextMenuEvent( QContextMenuEvent * )
|
||||
contextMenu->addSeparator();
|
||||
}
|
||||
|
||||
contextMenu->addAction( embed::getIconPixmap( "help" ),
|
||||
tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu->addHelpAction();
|
||||
contextMenu->exec( QCursor::pos() );
|
||||
delete contextMenu;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
|
||||
#include "caption_menu.h"
|
||||
#include "embed.h"
|
||||
|
||||
|
||||
|
||||
@@ -45,6 +46,19 @@ captionMenu::~captionMenu()
|
||||
|
||||
|
||||
|
||||
void captionMenu::addHelpAction()
|
||||
{
|
||||
QWidget* parent = (QWidget*) this->parent();
|
||||
|
||||
if (parent == NULL)
|
||||
return;
|
||||
|
||||
|
||||
if (! parent->whatsThis().isEmpty()) {
|
||||
addAction( embed::getIconPixmap( "help" ), tr( "&Help" ),
|
||||
parent, SLOT( displayHelp() ) );
|
||||
}
|
||||
else {
|
||||
QAction* helpAction = addAction( embed::getIconPixmap("help"), tr("Help (not available)") );
|
||||
helpAction->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,11 +481,10 @@ void knob::contextMenuEvent( QContextMenuEvent * )
|
||||
// an QApplication::restoreOverrideCursor()-call...
|
||||
mouseReleaseEvent( NULL );
|
||||
|
||||
captionMenu contextMenu( model()->displayName() );
|
||||
captionMenu contextMenu( model()->displayName(), this );
|
||||
addDefaultActions( &contextMenu );
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu.addHelpAction();
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ void TempoSyncKnob::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
mouseReleaseEvent( NULL );
|
||||
|
||||
captionMenu contextMenu( model()->displayName() );
|
||||
captionMenu contextMenu( model()->displayName(), this );
|
||||
addDefaultActions( &contextMenu );
|
||||
contextMenu.addSeparator();
|
||||
|
||||
@@ -147,9 +147,7 @@ void TempoSyncKnob::contextMenuEvent( QContextMenuEvent * )
|
||||
|
||||
}
|
||||
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu.addHelpAction();
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
|
||||
delete syncMenu;
|
||||
|
||||
@@ -806,6 +806,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
updatePitchRange();
|
||||
unlock();
|
||||
}
|
||||
|
||||
@@ -1585,10 +1586,3 @@ void InstrumentTrackWindow::loadSettings( const QDomElement& thisElement )
|
||||
m_itv->m_tlb->setChecked( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user