From 239d9175bcf1ceb58dec22f1e508b3c27321b1f7 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sun, 15 May 2022 21:39:02 +0200 Subject: [PATCH 01/25] Automatic FX-mixer strip management #1215 rebasing/resolved conflicts --- include/Mixer.h | 12 + include/MixerLine.h | 3 + include/MixerView.h | 13 +- src/core/Mixer.cpp | 229 +++++++++------ src/core/Song.cpp | 4 +- src/gui/MixerLine.cpp | 74 ++++- src/gui/MixerView.cpp | 245 ++++++++++++---- src/gui/editors/BBEditor.cpp | 343 +++++++++++++++++++++++ src/gui/editors/PatternEditor.cpp | 1 + src/gui/editors/TrackContainerView.cpp | 7 + src/gui/tracks/InstrumentTrackView.cpp | 7 +- src/gui/tracks/SampleTrackView.cpp | 8 +- src/gui/tracks/TrackLabelButton.cpp | 10 +- src/gui/tracks/TrackOperationsWidget.cpp | 5 + 14 files changed, 787 insertions(+), 174 deletions(-) create mode 100644 src/gui/editors/BBEditor.cpp diff --git a/include/Mixer.h b/include/Mixer.h index ecd864ae749..59471cafe78 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -26,6 +26,7 @@ #define MIXER_H #include "Model.h" +#include "Track.h" #include "EffectChain.h" #include "JournallingObject.h" #include "ThreadableJob.h" @@ -66,6 +67,7 @@ class MixerChannel : public ThreadableJob int m_channelIndex; // what channel index are we bool m_queued; // are we queued up for rendering yet? bool m_muted; // are we muted? updated per period so we don't have to call m_muteModel.value() twice + BoolModel m_autoTrackLinkModel; // pointers to other channels that this one sends to MixerRouteVector m_sends; @@ -195,6 +197,16 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject // re-arrange channels void moveChannelLeft(int index); void moveChannelRight(int index); + void swapChannels(int indexA, int indexB); + + void toggleAutoTrackLink(int index); + + // process tracks which have a fx send + void processFxTracks(std::function process); + IntModel * getFxChannelModelByTrack(Track * track); + std::vector getUsedChannelCounts(); + bool isChannelUsed(int index); + bool isAutoTrackLinkToggleAllowed(int index); // reset a channel's name, fx, sends, etc void clearChannel(mix_ch_t channelIndex); diff --git a/include/MixerLine.h b/include/MixerLine.h index decd5f3aa0c..239fb5042ed 100644 --- a/include/MixerLine.h +++ b/include/MixerLine.h @@ -89,6 +89,7 @@ class MixerLine : public QWidget MixerView * m_mv; LcdWidget* m_lcd; int m_channelIndex; + QPalette m_renameEditPalette; QBrush m_backgroundActive; QColor m_strokeOuterActive; QColor m_strokeOuterInactive; @@ -112,6 +113,8 @@ private slots: void removeUnusedChannels(); void moveChannelLeft(); void moveChannelRight(); + void toogleAutoTrackLink(); + void autoTrackLinkChanged(); }; diff --git a/include/MixerView.h b/include/MixerView.h index a7b1b51919d..063acbfc030 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -36,6 +36,7 @@ #include "PixmapButton.h" #include "embed.h" #include "EffectRackView.h" +#include "Track.h" class QButtonGroup; @@ -101,7 +102,6 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, // move the channel to the left or right void moveChannelLeft(int index); - void moveChannelLeft(int index, int focusIndex); void moveChannelRight(int index); void renameChannel(int index); @@ -110,6 +110,15 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, // useful for loading projects void refreshDisplay(); + // Auto track link support + void processAfterTrackAdd(Track * track); + void processAfterTrackStyleModify(Track * track); + void processAfterTrackFxMixerModify(Track * track); + void processAfterTrackMove(Track * track); + void processAfterTrackDelete(Track * track); + void toggleAutoTrackLink(int index); + + public slots: int addNewChannel(); @@ -132,6 +141,8 @@ private slots: QWidget * m_racksWidget; void updateMaxChannelSelector(); + void swapChannels(int indexA, int indexB); + void updateAutoTrackSortOrder(); friend class MixerChannelView; } ; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 96d4fc8b2df..848f75d840e 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -72,6 +72,7 @@ MixerChannel::MixerChannel( int idx, Model * _parent ) : m_lock(), m_channelIndex( idx ), m_queued( false ), + m_autoTrackLinkModel (false, _parent), m_hasColor( false ), m_dependenciesMet(0) { @@ -284,46 +285,25 @@ void Mixer::deleteChannel( int index ) // channel deletion is performed between mixer rounds Engine::audioEngine()->requestChangeInModel(); - // go through every instrument and adjust for the channel index change - TrackContainer::TrackList tracks; - tracks += Engine::getSong()->tracks(); - tracks += Engine::patternStore()->tracks(); - for( Track* t : tracks ) + processFxTracks( [index](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) { - if( t->type() == Track::InstrumentTrack ) + (void) track; + (void) fxChannel; + int curFxIndex = fxChannelModel->value(0); + if( curFxIndex == index ) { - InstrumentTrack* inst = dynamic_cast( t ); - int val = inst->mixerChannelModel()->value(0); - if( val == index ) - { - // we are deleting this track's channel send - // send to master - inst->mixerChannelModel()->setValue(0); - } - else if( val > index ) - { - // subtract 1 to make up for the missing channel - inst->mixerChannelModel()->setValue(val-1); - } + // we are deleting this track's fx send + // send to master + fxChannelModel->setValue(0); } - else if( t->type() == Track::SampleTrack ) + else if ( curFxIndex > index ) { - SampleTrack* strk = dynamic_cast( t ); - int val = strk->mixerChannelModel()->value(0); - if( val == index ) - { - // we are deleting this track's channel send - // send to master - strk->mixerChannelModel()->setValue(0); - } - else if( val > index ) - { - // subtract 1 to make up for the missing channel - strk->mixerChannelModel()->setValue(val-1); - } + // subtract 1 to make up for the missing channel + fxChannelModel->setValue(-1); } - } + }); + MixerChannel * ch = m_mixerChannels[index]; @@ -367,74 +347,143 @@ void Mixer::deleteChannel( int index ) Engine::audioEngine()->doneChangeInModel(); } +void FxMixer::toggleAutoTrackLink(int index) +{ + m_fxChannels[index]->m_autoTrackLinkModel.setValue(! m_fxChannels[index]->m_autoTrackLinkModel.value()); +} + +IntModel * FxMixer::getFxChannelModelByTrack(Track * track) +{ + if( track->type() == Track::InstrumentTrack ) + { + InstrumentTrack * inst = (InstrumentTrack *) track; + return inst->effectChannelModel(); + } + else if( track->type() == Track::SampleTrack ) + { + SampleTrack * strk = (SampleTrack *) track; + return strk->effectChannelModel(); + } + return NULL; +} + +bool FxMixer::isAutoTrackLinkToggleAllowed(int index) +{ + if (effectChannel( index )->m_autoTrackLinkModel.value()) return true; + std::vector used(m_fxChannels.size(), 0); + processFxTracks([&used](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + mutable { + (void) track; + (void) fxChannel; + ++used[fxChannelModel->value()]; + }); -void Mixer::moveChannelLeft( int index ) + return used[index] == 1; +} + + +void FxMixer::processFxTracks(std::function process) { - // can't move master or first channel - if( index <= 1 || index >= m_mixerChannels.size() ) + TrackContainer::TrackList trackList; + trackList += Engine::getSong()->tracks(); + trackList += Engine::getBBTrackContainer()->tracks(); + + for (Track* track: trackList) + { + IntModel * fxChannelModel = getFxChannelModelByTrack(track); + FxChannel * fxChannel = NULL; + if (fxChannelModel != NULL) + { + int channelIndex = fxChannelModel->value(); + if (channelIndex > 0 && channelIndex < m_fxChannels.size() ) + { + fxChannel = effectChannel(channelIndex); + } + process(track,fxChannelModel, fxChannel); + } + } +} + +std::vector FxMixer::getUsedChannelCounts() +{ + std::vector used(m_fxChannels.size(), 0); + processFxTracks([&used](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + mutable { + (void) track; + (void) fxChannel; + ++used[fxChannelModel->value()]; + }); + + return used; +} + +bool FxMixer::isChannelUsed(int index) +{ + bool result = false; + + processFxTracks([&result, index](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + mutable { + (void) track; + (void) fxChannel; + if (fxChannelModel->value() == index) result = true; + }); + return result; +} + + + +void FxMixer::swapChannels(int indexA, int indexB) +{ + // range check - can't move master or first channel + if (( indexA == indexB ) || + ( indexA <= 1 || indexA >= m_fxChannels.size() ) || + ( indexB <= 1 || indexB >= m_fxChannels.size() )) { return; } + // channels to swap - int a = index - 1, b = index; + int a = indexA, b = indexB; // check if m_lastSoloed is one of our swaps if (m_lastSoloed == a) { m_lastSoloed = b; } else if (m_lastSoloed == b) { m_lastSoloed = a; } // go through every instrument and adjust for the channel index change - TrackContainer::TrackList songTrackList = Engine::getSong()->tracks(); - TrackContainer::TrackList patternTrackList = Engine::patternStore()->tracks(); - - TrackContainer::TrackList trackLists[] = {songTrackList, patternTrackList}; - for(int tl=0; tl<2; ++tl) + processFxTracks( [a,b](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) { - TrackContainer::TrackList trackList = trackLists[tl]; - for(int i=0; ivalue(0); + if( curFxIndex == a ) { - if( trackList[i]->type() == Track::InstrumentTrack ) - { - InstrumentTrack * inst = (InstrumentTrack *) trackList[i]; - int val = inst->mixerChannelModel()->value(0); - if( val == a ) - { - inst->mixerChannelModel()->setValue(b); - } - else if( val == b ) - { - inst->mixerChannelModel()->setValue(a); - } - } - else if( trackList[i]->type() == Track::SampleTrack ) - { - SampleTrack * strk = (SampleTrack *) trackList[i]; - int val = strk->mixerChannelModel()->value(0); - if( val == a ) - { - strk->mixerChannelModel()->setValue(b); - } - else if( val == b ) - { - strk->mixerChannelModel()->setValue(a); - } - } + fxChannelModel->setValue(b); } - } + else if ( curFxIndex == b ) + { + fxChannelModel->setValue(a); + } + }); // Swap positions in array - qSwap(m_mixerChannels[index], m_mixerChannels[index - 1]); + qSwap(m_fxChannels[a], m_fxChannels[b]); // Update m_channelIndex of both channels - m_mixerChannels[index]->m_channelIndex = index; - m_mixerChannels[index - 1]->m_channelIndex = index -1; + m_fxChannels[a]->m_channelIndex = a; + m_fxChannels[b]->m_channelIndex = b; } +void FxMixer::moveChannelLeft( int index ) +{ + swapChannels(index - 1, index); +} + void Mixer::moveChannelRight( int index ) { - moveChannelLeft( index + 1 ); + swapChannels(index, index + 1 ); } @@ -735,13 +784,14 @@ void Mixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) QDomElement mixch = _doc.createElement( QString( "mixerchannel" ) ); _this.appendChild( mixch ); - ch->m_fxChain.saveState( _doc, mixch ); - ch->m_volumeModel.saveSettings( _doc, mixch, "volume" ); - ch->m_muteModel.saveSettings( _doc, mixch, "muted" ); - ch->m_soloModel.saveSettings( _doc, mixch, "soloed" ); - mixch.setAttribute( "num", i ); - mixch.setAttribute( "name", ch->m_name ); - if( ch->m_hasColor ) mixch.setAttribute( "color", ch->m_color.name() ); + ch->m_fxChain.saveState( _doc, fxch ); + ch->m_volumeModel.saveSettings( _doc, fxch, "volume" ); + ch->m_muteModel.saveSettings( _doc, fxch, "muted" ); + ch->m_soloModel.saveSettings( _doc, fxch, "soloed" ); + ch->m_autoTrackLinkModel.saveSettings( _doc, fxch, "autoTrackLink" ); + fxch.setAttribute( "num", i ); + fxch.setAttribute( "name", ch->m_name ); + if( ch->m_hasColor ) fxch.setAttribute( "color", ch->m_color.name() ); // add the channel sends for( int si = 0; si < ch->m_sends.size(); ++si ) @@ -783,11 +833,14 @@ void Mixer::loadSettings( const QDomElement & _this ) // allocate enough channels allocateChannelsTo( num ); - m_mixerChannels[num]->m_volumeModel.loadSettings( mixch, "volume" ); - m_mixerChannels[num]->m_muteModel.loadSettings( mixch, "muted" ); - m_mixerChannels[num]->m_soloModel.loadSettings( mixch, "soloed" ); - m_mixerChannels[num]->m_name = mixch.attribute( "name" ); - if( mixch.hasAttribute( "color" ) ) + m_fxChannels[num]->m_volumeModel.loadSettings( fxch, "volume" ); + + m_fxChannels[num]->m_muteModel.loadSettings( fxch, "muted" ); + m_fxChannels[num]->m_soloModel.loadSettings( fxch, "soloed" ); + m_fxChannels[num]->m_autoTrackLinkModel.loadSettings( fxch, "autoTrackLink" ); + + m_fxChannels[num]->m_name = fxch.attribute( "name" ); + if( fxch.hasAttribute( "color" ) ) { m_mixerChannels[num]->m_hasColor = true; m_mixerChannels[num]->m_color.setNamedColor( mixch.attribute( "color" ) ); diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 029683f9449..b19f19c5574 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -818,12 +818,12 @@ void Song::addPatternTrack() void Song::addSampleTrack() { - ( void )Track::create( Track::SampleTrack, this ); + Track* track = Track::create( Track::SampleTrack, this ); + getGUI()->fxMixerView()->processAfterTrackAdd(track); } - void Song::addAutomationTrack() { ( void )Track::create( Track::AutomationTrack, this ); diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 900298496f6..1089d07928f 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -82,6 +82,7 @@ MixerLine::MixerLine( QWidget * _parent, MixerView * _mv, int _channelIndex ) : m_strokeInnerInactive( 0, 0, 0 ), m_inRename( false ) { + if( !s_sendBgArrow ) { s_sendBgArrow = new QPixmap( embed::getIconPixmap( "send_bg_arrow", 29, 56 ) ); @@ -134,8 +135,11 @@ MixerLine::MixerLine( QWidget * _parent, MixerView * _mv, int _channelIndex ) : proxyWidget->setRotation( -90 ); proxyWidget->setPos( 8, 145 ); - connect( m_renameLineEdit, SIGNAL(editingFinished()), this, SLOT(renameFinished())); - connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_muteModel, SIGNAL(dataChanged()), this, SLOT(update())); + autoTrackLinkChanged(); + + connect( m_renameLineEdit, SIGNAL( editingFinished() ), this, SLOT( renameFinished() ) ); + connect( &Engine::fxMixer()->effectChannel( m_channelIndex )->m_muteModel, SIGNAL( dataChanged() ), this, SLOT( update() ) ); + connect( &Engine::fxMixer()->effectChannel( m_channelIndex )->m_autoTrackLinkModel, SIGNAL(dataChanged()),this, SLOT(autoTrackLinkChanged())); } @@ -170,9 +174,8 @@ void MixerLine::drawMixerLine( QPainter* p, const MixerLine *mixerLine, bool isA { m_renameLineEdit->setText( elidedName ); } - - int width = mixerLine->rect().width(); - int height = mixerLine->rect().height(); + int width = fxLine->rect().width(); + int height = fxLine->rect().height(); if( channel->m_hasColor && !muted ) { @@ -183,6 +186,7 @@ void MixerLine::drawMixerLine( QPainter* p, const MixerLine *mixerLine, bool isA p->fillRect( mixerLine->rect(), isActive ? mixerLine->backgroundActive().color() : p->background().color() ); } + // inner border p->setPen( isActive ? mixerLine->strokeInnerActive() : mixerLine->strokeInnerInactive() ); @@ -248,14 +252,31 @@ void MixerLine::mouseDoubleClickEvent( QMouseEvent * ) void MixerLine::contextMenuEvent( QContextMenuEvent * ) { - QPointer contextMenu = new CaptionMenu( Engine::mixer()->mixerChannel( m_channelIndex )->m_name, this ); + FxMixer * mix = Engine::fxMixer(); + QPointer contextMenu = new CaptionMenu( mix->effectChannel( m_channelIndex )->m_name, this ); + bool autoTrackLink = mix->effectChannel( m_channelIndex )->m_autoTrackLinkModel.value(); if( m_channelIndex != 0 ) // no move-options in master { - contextMenu->addAction( tr( "Move &left" ), this, SLOT(moveChannelLeft())); - contextMenu->addAction( tr( "Move &right" ), this, SLOT(moveChannelRight())); + if (!autoTrackLink) + { + contextMenu->addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) ); + bool autoTrackLinkRight = (m_channelIndex +1 < mix->numChannels()) ? mix->effectChannel( m_channelIndex +1 )->m_autoTrackLinkModel.value() : false; + if (!autoTrackLinkRight) + { + contextMenu->addAction( tr( "Move &right" ), this, SLOT( moveChannelRight() ) ); + } + } + if (mix->isAutoTrackLinkToggleAllowed(m_channelIndex)) + { + QString marker = (autoTrackLink ? " *" : ""); + contextMenu->addAction( tr("Auto track link") + marker, this, SLOT( toogleAutoTrackLink() ) ); + } + } + if (!autoTrackLink) + { + contextMenu->addAction( tr( "Rename &channel" ), this, SLOT( renameChannel() ) ); + contextMenu->addSeparator(); } - contextMenu->addAction( tr( "Rename &channel" ), this, SLOT(renameChannel())); - contextMenu->addSeparator(); if( m_channelIndex != 0 ) // no remove-option in master { @@ -266,21 +287,44 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) contextMenu->addSeparator(); QMenu colorMenu(tr("Color"), this); - colorMenu.setIcon(embed::getIconPixmap("colorize")); - colorMenu.addAction(tr("Change"), this, SLOT(selectColor())); - colorMenu.addAction(tr("Reset"), this, SLOT(resetColor())); - colorMenu.addAction(tr("Pick random"), this, SLOT(randomizeColor())); - contextMenu->addMenu(&colorMenu); + if (!autoTrackLink) + { + colorMenu.setIcon(embed::getIconPixmap("colorize")); + colorMenu.addAction(tr("Change"), this, SLOT(selectColor())); + colorMenu.addAction(tr("Reset"), this, SLOT(resetColor())); + colorMenu.addAction(tr("Pick random"), this, SLOT(randomizeColor())); + contextMenu->addMenu(&colorMenu); + } contextMenu->exec( QCursor::pos() ); delete contextMenu; } +void FxLine::toogleAutoTrackLink() +{ + FxMixerView * mix = getGUI()->fxMixerView(); + mix->toggleAutoTrackLink(m_channelIndex); +} +void FxLine::autoTrackLinkChanged() +{ + auto channel = Engine::fxMixer()->effectChannel( m_channelIndex ); + if (channel->m_autoTrackLinkModel.value()) + { + m_renameEditPalette.setColor(QPalette::Text,Qt::green); + } + else + { + m_renameEditPalette.setColor(QPalette::Text,Qt::white); + } + m_renameLineEdit->setPalette(m_renameEditPalette); +} void MixerLine::renameChannel() { + if (Engine::fxMixer()->effectChannel( m_channelIndex )->m_autoTrackLinkModel.value()) return; + m_inRename = true; setToolTip( "" ); m_renameLineEdit->setReadOnly( false ); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 32355edd628..b4109fadaee 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -174,6 +174,93 @@ MixerView::~MixerView() } } +void FxMixerView::processAfterTrackAdd(Track * track) +{ + // TODO: check if an autotrack mode is enabled (still missing) + FxMixer * mix = Engine::fxMixer(); + IntModel * model = mix->getFxChannelModelByTrack(track); + if ( model != NULL) + { + int channelIndex = addNewChannel(); + model->setValue( channelIndex ); + mix->effectChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); + + processAfterTrackStyleModify(track); + + setCurrentFxLine( channelIndex ); + } +} + +void FxMixerView::processAfterTrackStyleModify(Track * track) +{ + FxMixer * mix = Engine::fxMixer(); + IntModel * model = Engine::fxMixer()->getFxChannelModelByTrack(track); + if (model != NULL) + { + int index = model->value(); + FxChannel * channel = mix->effectChannel(index); + if (channel->m_autoTrackLinkModel.value()) + { + channel->m_name = track->name(); + if (track->useColor()) { channel->setColor (track->color()); } + updateFxLine(index); + } + } +} + +void FxMixerView::processAfterTrackFxMixerModify(Track * track) +{ + FxMixer * mix = Engine::fxMixer(); + IntModel * model = Engine::fxMixer()->getFxChannelModelByTrack(track); + if (model != NULL) + { + // check if there are more than one track is pointing to the same mixer channel + // if yes disable the autotracklink + std::vector used(m_fxChannelViews.size(), false); + bool needUpdate = false; + std::vector usedChannelCounts = mix->getUsedChannelCounts(); + for(unsigned long i = 0; i< usedChannelCounts.size();i++) + { + if (usedChannelCounts[i] == 0 || usedChannelCounts[i] > 1) + { + mix->effectChannel(i)->m_autoTrackLinkModel.setValue(false); + needUpdate = true; + } + } + if (needUpdate) updateAutoTrackSortOrder(); + } +} + +void FxMixerView::processAfterTrackMove(Track * track) +{ + FxMixer * mix = Engine::fxMixer(); + IntModel * model = Engine::fxMixer()->getFxChannelModelByTrack(track); + if (model != NULL) + { + FxChannel * channel = mix->effectChannel(model->value()); + if (channel->m_autoTrackLinkModel.value()) + { + updateAutoTrackSortOrder(); + } + } +} + +void FxMixerView::processAfterTrackDelete(Track * track) +{ + FxMixer * mix = Engine::fxMixer(); + IntModel * model = mix->getFxChannelModelByTrack(track); + if ( model != NULL) + { + int channelIndex = mix->getFxChannelModelByTrack(track)->value(); + FxChannel * channel = mix->effectChannel(channelIndex); + if (channel->m_autoTrackLinkModel.value()) + { + deleteChannel(channelIndex); + updateAutoTrackSortOrder(); + } + } +} + int MixerView::addNewChannel() @@ -191,9 +278,60 @@ int MixerView::addNewChannel() updateMaxChannelSelector(); + updateAutoTrackSortOrder(); + return newChannelIndex; } +void FxMixerView::updateAutoTrackSortOrder() +{ + return; + + FxMixer * mix = Engine::fxMixer(); + QList *list = new QList(); + + // add all non auto track first + for( int i = 1; ieffectChannel(i)->m_autoTrackLinkModel.value()) + { + list->append(i); + } + } + + // add auto tracks in the order of the song tracks + mix->processFxTracks([&, list](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + mutable { + (void) track; + if (fxChannel == NULL) return; + if (fxChannel->m_autoTrackLinkModel.value()) + { + list->append(fxChannelModel->value()); + } + }); + + + // bubblesort here because the list is normally almost ordered + int n = list->length(); + bool swapped = false; + do + { + for (int i=0; ivalue(i) > list->value(i+1)) + { + // a (+1) because we didn't include master track in our list + swapChannels(list->value(i+1), list->value(i+2)); + list->swapItemsAt(i,i+1); + } + } + n = n-1; + } while (swapped); + + // TODO: think about focus + // setCurrentFxLine( index - 1 ); +} + void MixerView::refreshDisplay() { @@ -236,29 +374,13 @@ void MixerView::refreshDisplay() // update the and max. channel number for every instrument void MixerView::updateMaxChannelSelector() { - TrackContainer::TrackList songTracks = Engine::getSong()->tracks(); - TrackContainer::TrackList patternStoreTracks = Engine::patternStore()->tracks(); - - TrackContainer::TrackList trackLists[] = {songTracks, patternStoreTracks}; - for(int tl=0; tl<2; ++tl) + FxMixer * mix = Engine::fxMixer(); + mix->processFxTracks([this](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) { - TrackContainer::TrackList trackList = trackLists[tl]; - for(int i=0; itype() == Track::InstrumentTrack ) - { - InstrumentTrack * inst = (InstrumentTrack *) trackList[i]; - inst->mixerChannelModel()->setRange(0, - m_mixerChannelViews.size()-1,1); - } - else if( trackList[i]->type() == Track::SampleTrack ) - { - SampleTrack * strk = (SampleTrack *) trackList[i]; - strk->mixerChannelModel()->setRange(0, - m_mixerChannelViews.size()-1,1); - } - } - } + (void) track; + (void) fxChannel; + fxChannelModel->setRange(0,m_fxChannelViews.size()-1,1); + }); } @@ -431,71 +553,76 @@ void MixerView::deleteChannel(int index) void MixerView::deleteUnusedChannels() { - TrackContainer::TrackList tracks; - tracks += Engine::getSong()->tracks(); - tracks += Engine::patternStore()->tracks(); - - std::vector inUse(m_mixerChannelViews.size(), false); + FxMixer * mix = Engine::fxMixer(); + std::vector inUse = mix->getUsedChannelCounts(); - //Populate inUse by checking the destination channel for every track - for (Track* t: tracks) + //Check all channels except master, delete those with no incoming sends + for(int i = m_fxChannelViews.size()-1; i > 0; --i) { - //The channel that this track sends to. Since master channel is always in use, - //setting this to 0 is a safe default (for tracks that don't sent to the mixer). - int channel = 0; - if (t->type() == Track::InstrumentTrack) + if ((inUse[i]==0) && Engine::fxMixer()->effectChannel(i)->m_receives.isEmpty()) { - InstrumentTrack* inst = dynamic_cast(t); - channel = inst->mixerChannelModel()->value(); + deleteChannel(i); } - else if (t->type() == Track::SampleTrack) + } +} + + +void FxMixerView::toggleAutoTrackLink(int index) +{ + FxMixer * mix = Engine::fxMixer(); + mix->toggleAutoTrackLink(index); + FxChannel * channel = mix->effectChannel(index); + if (!channel->m_autoTrackLinkModel.value()) return; + + Track * trackFound = NULL; + mix->processFxTracks([&trackFound, index](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + mutable { + (void) fxChannel; + if (fxChannelModel->value() == index) { - SampleTrack *strack = dynamic_cast(t); - channel = strack->mixerChannelModel()->value(); + trackFound = track; } - inUse[channel] = true; - } + }); - //Check all channels except master, delete those with no incoming sends - for(int i = m_mixerChannelViews.size()-1; i > 0; --i) + if (trackFound != NULL) { - if (!inUse[i] && Engine::mixer()->mixerChannel(i)->m_receives.isEmpty()) - { deleteChannel(i); } + updateAutoTrackSortOrder(); + processAfterTrackStyleModify(trackFound); } } - -void MixerView::moveChannelLeft(int index, int focusIndex) +void FxMixerView::swapChannels(int indexA, int indexB) { - // can't move master or first channel left or last channel right - if( index <= 1 || index >= m_mixerChannelViews.size() ) return; + if (( indexA == indexB ) || + ( indexA <= 1 || indexA >= m_fxChannelViews.size() ) || + ( indexB <= 1 || indexB >= m_fxChannelViews.size() )) + { + return; + } Mixer *m = Engine::mixer(); - // Move instruments channels - m->moveChannelLeft( index ); + m->swapChannels(indexA,indexB); // Update widgets models - m_mixerChannelViews[index]->setChannelIndex( index ); - m_mixerChannelViews[index - 1]->setChannelIndex( index - 1 ); - - // Focus on new position - setCurrentMixerLine( focusIndex ); + m_fxChannelViews[indexA]->setChannelIndex(indexA); + m_fxChannelViews[indexB]->setChannelIndex(indexB ); } - -void MixerView::moveChannelLeft(int index) +void FxMixerView::moveChannelLeft(int index) { - moveChannelLeft( index, index - 1 ); + swapChannels( index, index - 1); + setCurrentFxLine( index - 1 ); } void MixerView::moveChannelRight(int index) { - moveChannelLeft( index + 1, index + 1 ); + swapChannels( index , index + 1 ); + setCurrentFxLine( index + 1 ); } diff --git a/src/gui/editors/BBEditor.cpp b/src/gui/editors/BBEditor.cpp new file mode 100644 index 00000000000..e5a51699e54 --- /dev/null +++ b/src/gui/editors/BBEditor.cpp @@ -0,0 +1,343 @@ +/* + * BBEditor.cpp - basic main-window for editing of beats and basslines + * + * Copyright (c) 2004-2008 Tobias Doerffel + * + * This file is part of LMMS - https://lmms.io + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "BBEditor.h" + +#include +#include +#include + +#include "ComboBox.h" +#include "BBTrack.h" +#include "BBTrackContainer.h" +#include "DataFile.h" +#include "embed.h" +#include "MainWindow.h" +#include "Song.h" +#include "StringPairDrag.h" + +#include "Pattern.h" +#include "GuiApplication.h" +#include "FxMixerView.h" + + + +BBEditor::BBEditor( BBTrackContainer* tc ) : + Editor(false), + m_trackContainerView( new BBTrackContainerView(tc) ) +{ + setWindowIcon( embed::getIconPixmap( "bb_track_btn" ) ); + setWindowTitle( tr( "Beat+Bassline Editor" ) ); + setCentralWidget(m_trackContainerView); + + setAcceptDrops(true); + m_toolBar->setAcceptDrops(true); + connect(m_toolBar, SIGNAL(dragEntered(QDragEnterEvent*)), m_trackContainerView, SLOT(dragEnterEvent(QDragEnterEvent*))); + connect(m_toolBar, SIGNAL(dropped(QDropEvent*)), m_trackContainerView, SLOT(dropEvent(QDropEvent*))); + + // TODO: Use style sheet + if( ConfigManager::inst()->value( "ui", + "compacttrackbuttons" ).toInt() ) + { + setMinimumWidth( TRACK_OP_WIDTH_COMPACT + DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + + 2 * TCO_BORDER_WIDTH + 384 ); + } + else + { + setMinimumWidth( TRACK_OP_WIDTH + DEFAULT_SETTINGS_WIDGET_WIDTH + + 2 * TCO_BORDER_WIDTH + 384 ); + } + + + m_playAction->setToolTip(tr( "Play/pause current beat/bassline (Space)" )); + m_stopAction->setToolTip(tr( "Stop playback of current beat/bassline (Space)" )); + + + // Beat selector + DropToolBar *beatSelectionToolBar = addDropToolBarToTop(tr("Beat selector")); + + m_bbComboBox = new ComboBox( m_toolBar ); + m_bbComboBox->setFixedSize( 200, ComboBox::DEFAULT_HEIGHT ); + m_bbComboBox->setModel( &tc->m_bbComboBoxModel ); + + beatSelectionToolBar->addWidget( m_bbComboBox ); + + + // Track actions + DropToolBar *trackAndStepActionsToolBar = addDropToolBarToTop(tr("Track and step actions")); + + + trackAndStepActionsToolBar->addAction(embed::getIconPixmap("add_bb_track"), tr("Add beat/bassline"), + Engine::getSong(), SLOT(addBBTrack())); + trackAndStepActionsToolBar->addAction(embed::getIconPixmap("clone_bb_track_pattern"), tr("Clone beat/bassline pattern"), + m_trackContainerView, SLOT(clonePattern())); + trackAndStepActionsToolBar->addAction( + embed::getIconPixmap("add_sample_track"), + tr("Add sample-track"), m_trackContainerView, + SLOT(addSampleTrack())); + trackAndStepActionsToolBar->addAction(embed::getIconPixmap("add_automation"), tr("Add automation-track"), + m_trackContainerView, SLOT(addAutomationTrack())); + + QWidget* stretch = new QWidget(m_toolBar); + stretch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + trackAndStepActionsToolBar->addWidget(stretch); + + + // Step actions + trackAndStepActionsToolBar->addAction(embed::getIconPixmap("step_btn_remove"), tr("Remove steps"), + m_trackContainerView, SLOT(removeSteps())); + trackAndStepActionsToolBar->addAction(embed::getIconPixmap("step_btn_add"), tr("Add steps"), + m_trackContainerView, SLOT( addSteps())); + trackAndStepActionsToolBar->addAction( embed::getIconPixmap( "step_btn_duplicate" ), tr( "Clone Steps" ), + m_trackContainerView, SLOT( cloneSteps() ) ); + + connect( &tc->m_bbComboBoxModel, SIGNAL( dataChanged() ), + m_trackContainerView, SLOT( updatePosition() ) ); + + + QAction* viewNext = new QAction(this); + connect(viewNext, SIGNAL(triggered()), m_bbComboBox, SLOT(selectNext())); + viewNext->setShortcut(Qt::Key_Plus); + addAction(viewNext); + + QAction* viewPrevious = new QAction(this); + connect(viewPrevious, SIGNAL(triggered()), m_bbComboBox, SLOT(selectPrevious())); + viewPrevious->setShortcut(Qt::Key_Minus); + addAction(viewPrevious); +} + + +BBEditor::~BBEditor() +{ +} + + +QSize BBEditor::sizeHint() const +{ + return {minimumWidth()+10, 300}; +} + + +void BBEditor::removeBBView( int bb ) +{ + m_trackContainerView->removeBBView(bb); +} + + +void BBEditor::play() +{ + if( Engine::getSong()->playMode() != Song::Mode_PlayBB ) + { + Engine::getSong()->playBB(); + } + else + { + Engine::getSong()->togglePause(); + } +} + + +void BBEditor::stop() +{ + Engine::getSong()->stop(); +} + + + + +BBTrackContainerView::BBTrackContainerView(BBTrackContainer* tc) : + TrackContainerView(tc), + m_bbtc(tc) +{ + setModel( tc ); +} + + + + +void BBTrackContainerView::addSteps() +{ + makeSteps( false ); +} + +void BBTrackContainerView::cloneSteps() +{ + makeSteps( true ); +} + + + + +void BBTrackContainerView::removeSteps() +{ + TrackContainer::TrackList tl = model()->tracks(); + + for( TrackContainer::TrackList::iterator it = tl.begin(); + it != tl.end(); ++it ) + { + if( ( *it )->type() == Track::InstrumentTrack ) + { + Pattern* p = static_cast( ( *it )->getTCO( m_bbtc->currentBB() ) ); + p->removeSteps(); + } + } +} + + + + +void BBTrackContainerView::addSampleTrack() +{ + Track* track = Track::create( Track::SampleTrack, model() ); + getGUI()->fxMixerView()->processAfterTrackAdd(track); +} + + + + +void BBTrackContainerView::addAutomationTrack() +{ + (void) Track::create( Track::AutomationTrack, model() ); +} + + + + +void BBTrackContainerView::removeBBView(int bb) +{ + for( TrackView* view : trackViews() ) + { + view->getTrackContentWidget()->removeTCOView( bb ); + } +} + + + +void BBTrackContainerView::saveSettings(QDomDocument& doc, QDomElement& element) +{ + MainWindow::saveWidgetState( parentWidget(), element ); +} + +void BBTrackContainerView::loadSettings(const QDomElement& element) +{ + MainWindow::restoreWidgetState(parentWidget(), element); +} + + + + +void BBTrackContainerView::dropEvent(QDropEvent* de) +{ + QString type = StringPairDrag::decodeKey( de ); + QString value = StringPairDrag::decodeValue( de ); + + if( type.left( 6 ) == "track_" ) + { + DataFile dataFile( value.toUtf8() ); + Track * t = Track::create( dataFile.content().firstChild().toElement(), model() ); + + // Ensure BB TCOs exist + bool hasValidBBTCOs = false; + if (t->getTCOs().size() == m_bbtc->numOfBBs()) + { + hasValidBBTCOs = true; + for (int i = 0; i < t->getTCOs().size(); ++i) + { + if (t->getTCOs()[i]->startPosition() != TimePos(i, 0)) + { + hasValidBBTCOs = false; + break; + } + } + } + if (!hasValidBBTCOs) + { + t->deleteTCOs(); + t->createTCOsForBB(m_bbtc->numOfBBs() - 1); + } + m_bbtc->updateAfterTrackAdd(); + + de->accept(); + } + else + { + TrackContainerView::dropEvent( de ); + } +} + + + + +void BBTrackContainerView::updatePosition() +{ + //realignTracks(); + emit positionChanged( m_currentPosition ); +} + + + + +void BBTrackContainerView::makeSteps( bool clone ) +{ + TrackContainer::TrackList tl = model()->tracks(); + + for( TrackContainer::TrackList::iterator it = tl.begin(); + it != tl.end(); ++it ) + { + if( ( *it )->type() == Track::InstrumentTrack ) + { + Pattern* p = static_cast( ( *it )->getTCO( m_bbtc->currentBB() ) ); + if( clone ) + { + p->cloneSteps(); + } else + { + p->addSteps(); + } + } + } +} + +// Creates a clone of the current BB track with the same pattern, but no TCOs in the song editor +// TODO: Avoid repeated code from cloneTrack and clearTrack in TrackOperationsWidget somehow +void BBTrackContainerView::clonePattern() +{ + // Get the current BBTrack id + BBTrackContainer *bbtc = static_cast(model()); + const int cur_bb = bbtc->currentBB(); + + BBTrack *bbt = BBTrack::findBBTrack(cur_bb); + + if( bbt ) + { + // Clone the track + Track *newTrack = bbt->clone(); + bbtc->setCurrentBB( static_cast( newTrack )->index() ); + + // Track still have the TCOs which is undesirable in this case, clear the track + newTrack->lock(); + newTrack->deleteTCOs(); + newTrack->unlock(); + } +} diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 4c00942dbb6..d692d41c2da 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -88,6 +88,7 @@ void PatternEditor::removeSteps() void PatternEditor::addSampleTrack() { (void) Track::create( Track::SampleTrack, model() ); + getGUI()->fxMixerView()->processAfterTrackAdd(track); } diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index e7db85e4331..ad9249cfbd1 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -43,6 +43,7 @@ #include "TrackView.h" #include "GuiApplication.h" #include "PluginFactory.h" +#include "FxMixerView.h" namespace lmms { @@ -166,6 +167,8 @@ void TrackContainerView::removeTrackView( TrackView * _tv ) int index = m_trackViews.indexOf( _tv ); if( index != -1 ) { + Track * t = _tv->getTrack(); + getGUI()->fxMixerView()->processAfterTrackDelete(t); m_trackViews.removeAt( index ); disconnect( _tv ); @@ -203,6 +206,7 @@ void TrackContainerView::moveTrackView( TrackView * trackView, int indexTo ) m_tc->m_tracks.insert( indexTo, track ); m_trackViews.move( indexFrom, indexTo ); + getGUI()->fxMixerView()->processAfterTrackMove(track); realignTracks(); } @@ -402,6 +406,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); + getGUI()->fxMixerView()->processAfterTrackAdd(it); InstrumentLoaderThread *ilt = new InstrumentLoaderThread( this, it, value ); ilt->start(); @@ -415,6 +420,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); + getGUI()->fxMixerView()->processAfterTrackAdd(it); PluginFactory::PluginInfoAndKey piakn = getPluginFactory()->pluginSupportingExtension(FileItem::extension(value)); Instrument * i = it->loadInstrument(piakn.info.name(), &piakn.key); @@ -428,6 +434,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); + getGUI()->fxMixerView()->processAfterTrackAdd(it); it->setSimpleSerializing(); it->loadSettings( dataFile.content().toElement() ); //it->toggledInstrumentTrackButton( true ); diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 5d01c8ae0d9..1d7d461412a 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -241,9 +241,10 @@ void InstrumentTrackView::createMixerLine() /*! \brief Assign a specific mixer Channel for this track */ void InstrumentTrackView::assignMixerLine(int channelIndex) { - model()->mixerChannelModel()->setValue( channelIndex ); - - getGUI()->mixerView()->setCurrentMixerLine( channelIndex ); + model()->effectChannelModel()->setValue( channelIndex ); + FxMixerView* fxMixerView = getGUI()->fxMixerView(); + fxMixerView->processAfterTrackFxMixerModify(getTrack()); + fxMixerView->setCurrentFxLine( channelIndex ); } diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index 83331ad1e49..353767b186f 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -232,10 +232,10 @@ void SampleTrackView::createMixerLine() /*! \brief Assign a specific mixer Channel for this track */ void SampleTrackView::assignMixerLine(int channelIndex) { - model()->mixerChannelModel()->setValue(channelIndex); - - getGUI()->mixerView()->setCurrentMixerLine(channelIndex); + model()->effectChannelModel()->setValue(channelIndex); + FxMixerView* fxMixerView = getGUI()->fxMixerView(); + fxMixerView->processAfterTrackFxMixerModify(getTrack()); + fxMixerView->setCurrentFxLine( channelIndex ); } - } // namespace lmms::gui diff --git a/src/gui/tracks/TrackLabelButton.cpp b/src/gui/tracks/TrackLabelButton.cpp index 4e0b2be358c..74a5744255a 100644 --- a/src/gui/tracks/TrackLabelButton.cpp +++ b/src/gui/tracks/TrackLabelButton.cpp @@ -37,6 +37,8 @@ #include "Song.h" #include "TrackRenameLineEdit.h" #include "TrackView.h" +#include "GuiApplication.h" +#include "MixerView.h" namespace lmms::gui { @@ -84,7 +86,9 @@ void TrackLabelButton::rename() renameDlg.exec(); if( txt != text() ) { - m_trackView->getTrack()->setName( txt ); + Track * track = m_trackView->getTrack(); + track->setName( txt ); + getGUI()->fxMixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } } @@ -111,7 +115,9 @@ void TrackLabelButton::renameFinished() if( m_renameLineEdit->text() != m_trackView->getTrack()->name() ) { setText( elideName( m_renameLineEdit->text() ) ); - m_trackView->getTrack()->setName( m_renameLineEdit->text() ); + Track * track = m_trackView->getTrack(); + track->setName( m_renameLineEdit->text() ); + getGUI()->fxMixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } } diff --git a/src/gui/tracks/TrackOperationsWidget.cpp b/src/gui/tracks/TrackOperationsWidget.cpp index b3c8ac37946..0a44531bda3 100644 --- a/src/gui/tracks/TrackOperationsWidget.cpp +++ b/src/gui/tracks/TrackOperationsWidget.cpp @@ -46,6 +46,8 @@ #include "Track.h" #include "TrackContainerView.h" #include "TrackView.h" +#include "GuiApplication.h" +#include "FxMixerView.h" namespace lmms::gui { @@ -275,6 +277,7 @@ void TrackOperationsWidget::selectTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->setColor(new_color); + getGUI()->fxMixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } @@ -283,6 +286,7 @@ void TrackOperationsWidget::resetTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->resetColor(); + getGUI()->fxMixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } @@ -292,6 +296,7 @@ void TrackOperationsWidget::randomizeTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->setColor(buffer); + getGUI()->fxMixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } From 2fb21b75d4eb49ce1bda51b7343c5f1cfad6336f Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Fri, 20 May 2022 20:26:08 +0200 Subject: [PATCH 02/25] mend --- src/gui/editors/BBEditor.cpp | 343 ----------------------------------- 1 file changed, 343 deletions(-) delete mode 100644 src/gui/editors/BBEditor.cpp diff --git a/src/gui/editors/BBEditor.cpp b/src/gui/editors/BBEditor.cpp deleted file mode 100644 index e5a51699e54..00000000000 --- a/src/gui/editors/BBEditor.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* - * BBEditor.cpp - basic main-window for editing of beats and basslines - * - * Copyright (c) 2004-2008 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include "BBEditor.h" - -#include -#include -#include - -#include "ComboBox.h" -#include "BBTrack.h" -#include "BBTrackContainer.h" -#include "DataFile.h" -#include "embed.h" -#include "MainWindow.h" -#include "Song.h" -#include "StringPairDrag.h" - -#include "Pattern.h" -#include "GuiApplication.h" -#include "FxMixerView.h" - - - -BBEditor::BBEditor( BBTrackContainer* tc ) : - Editor(false), - m_trackContainerView( new BBTrackContainerView(tc) ) -{ - setWindowIcon( embed::getIconPixmap( "bb_track_btn" ) ); - setWindowTitle( tr( "Beat+Bassline Editor" ) ); - setCentralWidget(m_trackContainerView); - - setAcceptDrops(true); - m_toolBar->setAcceptDrops(true); - connect(m_toolBar, SIGNAL(dragEntered(QDragEnterEvent*)), m_trackContainerView, SLOT(dragEnterEvent(QDragEnterEvent*))); - connect(m_toolBar, SIGNAL(dropped(QDropEvent*)), m_trackContainerView, SLOT(dropEvent(QDropEvent*))); - - // TODO: Use style sheet - if( ConfigManager::inst()->value( "ui", - "compacttrackbuttons" ).toInt() ) - { - setMinimumWidth( TRACK_OP_WIDTH_COMPACT + DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT - + 2 * TCO_BORDER_WIDTH + 384 ); - } - else - { - setMinimumWidth( TRACK_OP_WIDTH + DEFAULT_SETTINGS_WIDGET_WIDTH - + 2 * TCO_BORDER_WIDTH + 384 ); - } - - - m_playAction->setToolTip(tr( "Play/pause current beat/bassline (Space)" )); - m_stopAction->setToolTip(tr( "Stop playback of current beat/bassline (Space)" )); - - - // Beat selector - DropToolBar *beatSelectionToolBar = addDropToolBarToTop(tr("Beat selector")); - - m_bbComboBox = new ComboBox( m_toolBar ); - m_bbComboBox->setFixedSize( 200, ComboBox::DEFAULT_HEIGHT ); - m_bbComboBox->setModel( &tc->m_bbComboBoxModel ); - - beatSelectionToolBar->addWidget( m_bbComboBox ); - - - // Track actions - DropToolBar *trackAndStepActionsToolBar = addDropToolBarToTop(tr("Track and step actions")); - - - trackAndStepActionsToolBar->addAction(embed::getIconPixmap("add_bb_track"), tr("Add beat/bassline"), - Engine::getSong(), SLOT(addBBTrack())); - trackAndStepActionsToolBar->addAction(embed::getIconPixmap("clone_bb_track_pattern"), tr("Clone beat/bassline pattern"), - m_trackContainerView, SLOT(clonePattern())); - trackAndStepActionsToolBar->addAction( - embed::getIconPixmap("add_sample_track"), - tr("Add sample-track"), m_trackContainerView, - SLOT(addSampleTrack())); - trackAndStepActionsToolBar->addAction(embed::getIconPixmap("add_automation"), tr("Add automation-track"), - m_trackContainerView, SLOT(addAutomationTrack())); - - QWidget* stretch = new QWidget(m_toolBar); - stretch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - trackAndStepActionsToolBar->addWidget(stretch); - - - // Step actions - trackAndStepActionsToolBar->addAction(embed::getIconPixmap("step_btn_remove"), tr("Remove steps"), - m_trackContainerView, SLOT(removeSteps())); - trackAndStepActionsToolBar->addAction(embed::getIconPixmap("step_btn_add"), tr("Add steps"), - m_trackContainerView, SLOT( addSteps())); - trackAndStepActionsToolBar->addAction( embed::getIconPixmap( "step_btn_duplicate" ), tr( "Clone Steps" ), - m_trackContainerView, SLOT( cloneSteps() ) ); - - connect( &tc->m_bbComboBoxModel, SIGNAL( dataChanged() ), - m_trackContainerView, SLOT( updatePosition() ) ); - - - QAction* viewNext = new QAction(this); - connect(viewNext, SIGNAL(triggered()), m_bbComboBox, SLOT(selectNext())); - viewNext->setShortcut(Qt::Key_Plus); - addAction(viewNext); - - QAction* viewPrevious = new QAction(this); - connect(viewPrevious, SIGNAL(triggered()), m_bbComboBox, SLOT(selectPrevious())); - viewPrevious->setShortcut(Qt::Key_Minus); - addAction(viewPrevious); -} - - -BBEditor::~BBEditor() -{ -} - - -QSize BBEditor::sizeHint() const -{ - return {minimumWidth()+10, 300}; -} - - -void BBEditor::removeBBView( int bb ) -{ - m_trackContainerView->removeBBView(bb); -} - - -void BBEditor::play() -{ - if( Engine::getSong()->playMode() != Song::Mode_PlayBB ) - { - Engine::getSong()->playBB(); - } - else - { - Engine::getSong()->togglePause(); - } -} - - -void BBEditor::stop() -{ - Engine::getSong()->stop(); -} - - - - -BBTrackContainerView::BBTrackContainerView(BBTrackContainer* tc) : - TrackContainerView(tc), - m_bbtc(tc) -{ - setModel( tc ); -} - - - - -void BBTrackContainerView::addSteps() -{ - makeSteps( false ); -} - -void BBTrackContainerView::cloneSteps() -{ - makeSteps( true ); -} - - - - -void BBTrackContainerView::removeSteps() -{ - TrackContainer::TrackList tl = model()->tracks(); - - for( TrackContainer::TrackList::iterator it = tl.begin(); - it != tl.end(); ++it ) - { - if( ( *it )->type() == Track::InstrumentTrack ) - { - Pattern* p = static_cast( ( *it )->getTCO( m_bbtc->currentBB() ) ); - p->removeSteps(); - } - } -} - - - - -void BBTrackContainerView::addSampleTrack() -{ - Track* track = Track::create( Track::SampleTrack, model() ); - getGUI()->fxMixerView()->processAfterTrackAdd(track); -} - - - - -void BBTrackContainerView::addAutomationTrack() -{ - (void) Track::create( Track::AutomationTrack, model() ); -} - - - - -void BBTrackContainerView::removeBBView(int bb) -{ - for( TrackView* view : trackViews() ) - { - view->getTrackContentWidget()->removeTCOView( bb ); - } -} - - - -void BBTrackContainerView::saveSettings(QDomDocument& doc, QDomElement& element) -{ - MainWindow::saveWidgetState( parentWidget(), element ); -} - -void BBTrackContainerView::loadSettings(const QDomElement& element) -{ - MainWindow::restoreWidgetState(parentWidget(), element); -} - - - - -void BBTrackContainerView::dropEvent(QDropEvent* de) -{ - QString type = StringPairDrag::decodeKey( de ); - QString value = StringPairDrag::decodeValue( de ); - - if( type.left( 6 ) == "track_" ) - { - DataFile dataFile( value.toUtf8() ); - Track * t = Track::create( dataFile.content().firstChild().toElement(), model() ); - - // Ensure BB TCOs exist - bool hasValidBBTCOs = false; - if (t->getTCOs().size() == m_bbtc->numOfBBs()) - { - hasValidBBTCOs = true; - for (int i = 0; i < t->getTCOs().size(); ++i) - { - if (t->getTCOs()[i]->startPosition() != TimePos(i, 0)) - { - hasValidBBTCOs = false; - break; - } - } - } - if (!hasValidBBTCOs) - { - t->deleteTCOs(); - t->createTCOsForBB(m_bbtc->numOfBBs() - 1); - } - m_bbtc->updateAfterTrackAdd(); - - de->accept(); - } - else - { - TrackContainerView::dropEvent( de ); - } -} - - - - -void BBTrackContainerView::updatePosition() -{ - //realignTracks(); - emit positionChanged( m_currentPosition ); -} - - - - -void BBTrackContainerView::makeSteps( bool clone ) -{ - TrackContainer::TrackList tl = model()->tracks(); - - for( TrackContainer::TrackList::iterator it = tl.begin(); - it != tl.end(); ++it ) - { - if( ( *it )->type() == Track::InstrumentTrack ) - { - Pattern* p = static_cast( ( *it )->getTCO( m_bbtc->currentBB() ) ); - if( clone ) - { - p->cloneSteps(); - } else - { - p->addSteps(); - } - } - } -} - -// Creates a clone of the current BB track with the same pattern, but no TCOs in the song editor -// TODO: Avoid repeated code from cloneTrack and clearTrack in TrackOperationsWidget somehow -void BBTrackContainerView::clonePattern() -{ - // Get the current BBTrack id - BBTrackContainer *bbtc = static_cast(model()); - const int cur_bb = bbtc->currentBB(); - - BBTrack *bbt = BBTrack::findBBTrack(cur_bb); - - if( bbt ) - { - // Clone the track - Track *newTrack = bbt->clone(); - bbtc->setCurrentBB( static_cast( newTrack )->index() ); - - // Track still have the TCOs which is undesirable in this case, clear the track - newTrack->lock(); - newTrack->deleteTCOs(); - newTrack->unlock(); - } -} From c2bdf8ad3c5f922256989b5304624bb02060ab84 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Fri, 20 May 2022 23:27:05 +0200 Subject: [PATCH 03/25] made buildable --- include/Mixer.h | 2 +- src/core/Mixer.cpp | 84 +++++++++++----------- src/core/Song.cpp | 2 +- src/gui/MixerLine.cpp | 26 +++---- src/gui/MixerView.cpp | 88 ++++++++++++------------ src/gui/editors/PatternEditor.cpp | 8 +-- src/gui/editors/TrackContainerView.cpp | 12 ++-- src/gui/tracks/InstrumentTrackView.cpp | 8 +-- src/gui/tracks/SampleTrackView.cpp | 8 +-- src/gui/tracks/TrackLabelButton.cpp | 6 +- src/gui/tracks/TrackOperationsWidget.cpp | 8 +-- 11 files changed, 126 insertions(+), 126 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 59471cafe78..0c0838ffa8a 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -202,7 +202,7 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject void toggleAutoTrackLink(int index); // process tracks which have a fx send - void processFxTracks(std::function process); + void processFxTracks(std::function process); IntModel * getFxChannelModelByTrack(Track * track); std::vector getUsedChannelCounts(); bool isChannelUsed(int index); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 848f75d840e..31a43500f4c 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -286,7 +286,7 @@ void Mixer::deleteChannel( int index ) Engine::audioEngine()->requestChangeInModel(); - processFxTracks( [index](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + processFxTracks( [index](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) { (void) track; (void) fxChannel; @@ -347,32 +347,32 @@ void Mixer::deleteChannel( int index ) Engine::audioEngine()->doneChangeInModel(); } -void FxMixer::toggleAutoTrackLink(int index) +void Mixer::toggleAutoTrackLink(int index) { - m_fxChannels[index]->m_autoTrackLinkModel.setValue(! m_fxChannels[index]->m_autoTrackLinkModel.value()); + m_mixerChannels[index]->m_autoTrackLinkModel.setValue(! m_mixerChannels[index]->m_autoTrackLinkModel.value()); } -IntModel * FxMixer::getFxChannelModelByTrack(Track * track) +IntModel * Mixer::getFxChannelModelByTrack(Track * track) { if( track->type() == Track::InstrumentTrack ) { InstrumentTrack * inst = (InstrumentTrack *) track; - return inst->effectChannelModel(); + return inst->mixerChannelModel(); } else if( track->type() == Track::SampleTrack ) { SampleTrack * strk = (SampleTrack *) track; - return strk->effectChannelModel(); + return strk->mixerChannelModel(); } return NULL; } -bool FxMixer::isAutoTrackLinkToggleAllowed(int index) +bool Mixer::isAutoTrackLinkToggleAllowed(int index) { - if (effectChannel( index )->m_autoTrackLinkModel.value()) return true; + if (mixerChannel( index )->m_autoTrackLinkModel.value()) return true; - std::vector used(m_fxChannels.size(), 0); - processFxTracks([&used](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + std::vector used(m_mixerChannels.size(), 0); + processFxTracks([&used](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) mutable { (void) track; (void) fxChannel; @@ -383,32 +383,32 @@ bool FxMixer::isAutoTrackLinkToggleAllowed(int index) } -void FxMixer::processFxTracks(std::function process) +void Mixer::processFxTracks(std::function process) { TrackContainer::TrackList trackList; trackList += Engine::getSong()->tracks(); - trackList += Engine::getBBTrackContainer()->tracks(); + trackList += Engine::patternStore()->tracks(); for (Track* track: trackList) { IntModel * fxChannelModel = getFxChannelModelByTrack(track); - FxChannel * fxChannel = NULL; + MixerChannel * fxChannel = NULL; if (fxChannelModel != NULL) { int channelIndex = fxChannelModel->value(); - if (channelIndex > 0 && channelIndex < m_fxChannels.size() ) + if (channelIndex > 0 && channelIndex < m_mixerChannels.size() ) { - fxChannel = effectChannel(channelIndex); + fxChannel = mixerChannel(channelIndex); } process(track,fxChannelModel, fxChannel); } } } -std::vector FxMixer::getUsedChannelCounts() +std::vector Mixer::getUsedChannelCounts() { - std::vector used(m_fxChannels.size(), 0); - processFxTracks([&used](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + std::vector used(m_mixerChannels.size(), 0); + processFxTracks([&used](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) mutable { (void) track; (void) fxChannel; @@ -418,11 +418,11 @@ std::vector FxMixer::getUsedChannelCounts() return used; } -bool FxMixer::isChannelUsed(int index) +bool Mixer::isChannelUsed(int index) { bool result = false; - processFxTracks([&result, index](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + processFxTracks([&result, index](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) mutable { (void) track; (void) fxChannel; @@ -433,12 +433,12 @@ bool FxMixer::isChannelUsed(int index) -void FxMixer::swapChannels(int indexA, int indexB) +void Mixer::swapChannels(int indexA, int indexB) { // range check - can't move master or first channel if (( indexA == indexB ) || - ( indexA <= 1 || indexA >= m_fxChannels.size() ) || - ( indexB <= 1 || indexB >= m_fxChannels.size() )) + ( indexA <= 1 || indexA >= m_mixerChannels.size() ) || + ( indexB <= 1 || indexB >= m_mixerChannels.size() )) { return; } @@ -451,7 +451,7 @@ void FxMixer::swapChannels(int indexA, int indexB) else if (m_lastSoloed == b) { m_lastSoloed = a; } // go through every instrument and adjust for the channel index change - processFxTracks( [a,b](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + processFxTracks( [a,b](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) { (void) track; (void) fxChannel; @@ -467,15 +467,15 @@ void FxMixer::swapChannels(int indexA, int indexB) }); // Swap positions in array - qSwap(m_fxChannels[a], m_fxChannels[b]); + qSwap(m_mixerChannels[a], m_mixerChannels[b]); // Update m_channelIndex of both channels - m_fxChannels[a]->m_channelIndex = a; - m_fxChannels[b]->m_channelIndex = b; + m_mixerChannels[a]->m_channelIndex = a; + m_mixerChannels[b]->m_channelIndex = b; } -void FxMixer::moveChannelLeft( int index ) +void Mixer::moveChannelLeft( int index ) { swapChannels(index - 1, index); } @@ -784,14 +784,14 @@ void Mixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) QDomElement mixch = _doc.createElement( QString( "mixerchannel" ) ); _this.appendChild( mixch ); - ch->m_fxChain.saveState( _doc, fxch ); - ch->m_volumeModel.saveSettings( _doc, fxch, "volume" ); - ch->m_muteModel.saveSettings( _doc, fxch, "muted" ); - ch->m_soloModel.saveSettings( _doc, fxch, "soloed" ); - ch->m_autoTrackLinkModel.saveSettings( _doc, fxch, "autoTrackLink" ); - fxch.setAttribute( "num", i ); - fxch.setAttribute( "name", ch->m_name ); - if( ch->m_hasColor ) fxch.setAttribute( "color", ch->m_color.name() ); + ch->m_fxChain.saveState( _doc, mixch ); + ch->m_volumeModel.saveSettings( _doc, mixch, "volume" ); + ch->m_muteModel.saveSettings( _doc, mixch, "muted" ); + ch->m_soloModel.saveSettings( _doc, mixch, "soloed" ); + ch->m_autoTrackLinkModel.saveSettings( _doc, mixch, "autoTrackLink" ); + mixch.setAttribute( "num", i ); + mixch.setAttribute( "name", ch->m_name ); + if( ch->m_hasColor ) mixch.setAttribute( "color", ch->m_color.name() ); // add the channel sends for( int si = 0; si < ch->m_sends.size(); ++si ) @@ -833,14 +833,14 @@ void Mixer::loadSettings( const QDomElement & _this ) // allocate enough channels allocateChannelsTo( num ); - m_fxChannels[num]->m_volumeModel.loadSettings( fxch, "volume" ); + m_mixerChannels[num]->m_volumeModel.loadSettings( mixch, "volume" ); - m_fxChannels[num]->m_muteModel.loadSettings( fxch, "muted" ); - m_fxChannels[num]->m_soloModel.loadSettings( fxch, "soloed" ); - m_fxChannels[num]->m_autoTrackLinkModel.loadSettings( fxch, "autoTrackLink" ); + m_mixerChannels[num]->m_muteModel.loadSettings( mixch, "muted" ); + m_mixerChannels[num]->m_soloModel.loadSettings( mixch, "soloed" ); + m_mixerChannels[num]->m_autoTrackLinkModel.loadSettings( mixch, "autoTrackLink" ); - m_fxChannels[num]->m_name = fxch.attribute( "name" ); - if( fxch.hasAttribute( "color" ) ) + m_mixerChannels[num]->m_name = mixch.attribute( "name" ); + if( mixch.hasAttribute( "color" ) ) { m_mixerChannels[num]->m_hasColor = true; m_mixerChannels[num]->m_color.setNamedColor( mixch.attribute( "color" ) ); diff --git a/src/core/Song.cpp b/src/core/Song.cpp index b19f19c5574..54422611232 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -819,7 +819,7 @@ void Song::addPatternTrack() void Song::addSampleTrack() { Track* track = Track::create( Track::SampleTrack, this ); - getGUI()->fxMixerView()->processAfterTrackAdd(track); + getGUI()->mixerView()->processAfterTrackAdd(track); } diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 1089d07928f..852d0d5b092 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -138,8 +138,8 @@ MixerLine::MixerLine( QWidget * _parent, MixerView * _mv, int _channelIndex ) : autoTrackLinkChanged(); connect( m_renameLineEdit, SIGNAL( editingFinished() ), this, SLOT( renameFinished() ) ); - connect( &Engine::fxMixer()->effectChannel( m_channelIndex )->m_muteModel, SIGNAL( dataChanged() ), this, SLOT( update() ) ); - connect( &Engine::fxMixer()->effectChannel( m_channelIndex )->m_autoTrackLinkModel, SIGNAL(dataChanged()),this, SLOT(autoTrackLinkChanged())); + connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_muteModel, SIGNAL( dataChanged() ), this, SLOT( update() ) ); + connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_autoTrackLinkModel, SIGNAL(dataChanged()),this, SLOT(autoTrackLinkChanged())); } @@ -174,8 +174,8 @@ void MixerLine::drawMixerLine( QPainter* p, const MixerLine *mixerLine, bool isA { m_renameLineEdit->setText( elidedName ); } - int width = fxLine->rect().width(); - int height = fxLine->rect().height(); + int width = mixerLine->rect().width(); + int height = mixerLine->rect().height(); if( channel->m_hasColor && !muted ) { @@ -252,15 +252,15 @@ void MixerLine::mouseDoubleClickEvent( QMouseEvent * ) void MixerLine::contextMenuEvent( QContextMenuEvent * ) { - FxMixer * mix = Engine::fxMixer(); - QPointer contextMenu = new CaptionMenu( mix->effectChannel( m_channelIndex )->m_name, this ); - bool autoTrackLink = mix->effectChannel( m_channelIndex )->m_autoTrackLinkModel.value(); + Mixer * mix = Engine::mixer(); + QPointer contextMenu = new CaptionMenu( mix->mixerChannel( m_channelIndex )->m_name, this ); + bool autoTrackLink = mix->mixerChannel( m_channelIndex )->m_autoTrackLinkModel.value(); if( m_channelIndex != 0 ) // no move-options in master { if (!autoTrackLink) { contextMenu->addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) ); - bool autoTrackLinkRight = (m_channelIndex +1 < mix->numChannels()) ? mix->effectChannel( m_channelIndex +1 )->m_autoTrackLinkModel.value() : false; + bool autoTrackLinkRight = (m_channelIndex +1 < mix->numChannels()) ? mix->mixerChannel( m_channelIndex +1 )->m_autoTrackLinkModel.value() : false; if (!autoTrackLinkRight) { contextMenu->addAction( tr( "Move &right" ), this, SLOT( moveChannelRight() ) ); @@ -300,15 +300,15 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) delete contextMenu; } -void FxLine::toogleAutoTrackLink() +void MixerLine::toogleAutoTrackLink() { - FxMixerView * mix = getGUI()->fxMixerView(); + MixerView * mix = getGUI()->mixerView(); mix->toggleAutoTrackLink(m_channelIndex); } -void FxLine::autoTrackLinkChanged() +void MixerLine::autoTrackLinkChanged() { - auto channel = Engine::fxMixer()->effectChannel( m_channelIndex ); + auto channel = Engine::mixer()->mixerChannel( m_channelIndex ); if (channel->m_autoTrackLinkModel.value()) { m_renameEditPalette.setColor(QPalette::Text,Qt::green); @@ -323,7 +323,7 @@ void FxLine::autoTrackLinkChanged() void MixerLine::renameChannel() { - if (Engine::fxMixer()->effectChannel( m_channelIndex )->m_autoTrackLinkModel.value()) return; + if (Engine::mixer()->mixerChannel( m_channelIndex )->m_autoTrackLinkModel.value()) return; m_inRename = true; setToolTip( "" ); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index b4109fadaee..f4403662212 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -174,56 +174,56 @@ MixerView::~MixerView() } } -void FxMixerView::processAfterTrackAdd(Track * track) +void MixerView::processAfterTrackAdd(Track * track) { // TODO: check if an autotrack mode is enabled (still missing) - FxMixer * mix = Engine::fxMixer(); + Mixer * mix = Engine::mixer(); IntModel * model = mix->getFxChannelModelByTrack(track); if ( model != NULL) { int channelIndex = addNewChannel(); model->setValue( channelIndex ); - mix->effectChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); + mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); processAfterTrackStyleModify(track); - setCurrentFxLine( channelIndex ); + setCurrentMixerLine( channelIndex ); } } -void FxMixerView::processAfterTrackStyleModify(Track * track) +void MixerView::processAfterTrackStyleModify(Track * track) { - FxMixer * mix = Engine::fxMixer(); - IntModel * model = Engine::fxMixer()->getFxChannelModelByTrack(track); + Mixer * mix = Engine::mixer(); + IntModel * model = mix->getFxChannelModelByTrack(track); if (model != NULL) { int index = model->value(); - FxChannel * channel = mix->effectChannel(index); + MixerChannel * channel = mix->mixerChannel(index); if (channel->m_autoTrackLinkModel.value()) { channel->m_name = track->name(); if (track->useColor()) { channel->setColor (track->color()); } - updateFxLine(index); + setCurrentMixerLine(index); } } } -void FxMixerView::processAfterTrackFxMixerModify(Track * track) +void MixerView::processAfterTrackFxMixerModify(Track * track) { - FxMixer * mix = Engine::fxMixer(); - IntModel * model = Engine::fxMixer()->getFxChannelModelByTrack(track); + Mixer * mix = Engine::mixer(); + IntModel * model = mix->getFxChannelModelByTrack(track); if (model != NULL) { // check if there are more than one track is pointing to the same mixer channel // if yes disable the autotracklink - std::vector used(m_fxChannelViews.size(), false); + std::vector used(m_mixerChannelViews.size(), false); bool needUpdate = false; std::vector usedChannelCounts = mix->getUsedChannelCounts(); for(unsigned long i = 0; i< usedChannelCounts.size();i++) { if (usedChannelCounts[i] == 0 || usedChannelCounts[i] > 1) { - mix->effectChannel(i)->m_autoTrackLinkModel.setValue(false); + mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); needUpdate = true; } } @@ -231,13 +231,13 @@ void FxMixerView::processAfterTrackFxMixerModify(Track * track) } } -void FxMixerView::processAfterTrackMove(Track * track) +void MixerView::processAfterTrackMove(Track * track) { - FxMixer * mix = Engine::fxMixer(); - IntModel * model = Engine::fxMixer()->getFxChannelModelByTrack(track); + Mixer * mix = Engine::mixer(); + IntModel * model = Engine::mixer()->getFxChannelModelByTrack(track); if (model != NULL) { - FxChannel * channel = mix->effectChannel(model->value()); + MixerChannel * channel = mix->mixerChannel(model->value()); if (channel->m_autoTrackLinkModel.value()) { updateAutoTrackSortOrder(); @@ -245,14 +245,14 @@ void FxMixerView::processAfterTrackMove(Track * track) } } -void FxMixerView::processAfterTrackDelete(Track * track) +void MixerView::processAfterTrackDelete(Track * track) { - FxMixer * mix = Engine::fxMixer(); + Mixer * mix = Engine::mixer(); IntModel * model = mix->getFxChannelModelByTrack(track); if ( model != NULL) { int channelIndex = mix->getFxChannelModelByTrack(track)->value(); - FxChannel * channel = mix->effectChannel(channelIndex); + MixerChannel * channel = mix->mixerChannel(channelIndex); if (channel->m_autoTrackLinkModel.value()) { deleteChannel(channelIndex); @@ -283,24 +283,24 @@ int MixerView::addNewChannel() return newChannelIndex; } -void FxMixerView::updateAutoTrackSortOrder() +void MixerView::updateAutoTrackSortOrder() { return; - FxMixer * mix = Engine::fxMixer(); + Mixer * mix = Engine::mixer(); QList *list = new QList(); // add all non auto track first - for( int i = 1; ieffectChannel(i)->m_autoTrackLinkModel.value()) + if (!mix->mixerChannel(i)->m_autoTrackLinkModel.value()) { list->append(i); } } // add auto tracks in the order of the song tracks - mix->processFxTracks([&, list](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + mix->processFxTracks([&, list](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) mutable { (void) track; if (fxChannel == NULL) return; @@ -374,12 +374,12 @@ void MixerView::refreshDisplay() // update the and max. channel number for every instrument void MixerView::updateMaxChannelSelector() { - FxMixer * mix = Engine::fxMixer(); - mix->processFxTracks([this](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + Mixer * mix = Engine::mixer(); + mix->processFxTracks([this](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) { (void) track; (void) fxChannel; - fxChannelModel->setRange(0,m_fxChannelViews.size()-1,1); + fxChannelModel->setRange(0,m_mixerChannelViews.size()-1,1); }); } @@ -553,13 +553,13 @@ void MixerView::deleteChannel(int index) void MixerView::deleteUnusedChannels() { - FxMixer * mix = Engine::fxMixer(); + Mixer * mix = Engine::mixer(); std::vector inUse = mix->getUsedChannelCounts(); //Check all channels except master, delete those with no incoming sends - for(int i = m_fxChannelViews.size()-1; i > 0; --i) + for(int i = m_mixerChannelViews.size()-1; i > 0; --i) { - if ((inUse[i]==0) && Engine::fxMixer()->effectChannel(i)->m_receives.isEmpty()) + if ((inUse[i]==0) && Engine::mixer()->mixerChannel(i)->m_receives.isEmpty()) { deleteChannel(i); } @@ -567,15 +567,15 @@ void MixerView::deleteUnusedChannels() } -void FxMixerView::toggleAutoTrackLink(int index) +void MixerView::toggleAutoTrackLink(int index) { - FxMixer * mix = Engine::fxMixer(); + Mixer * mix = Engine::mixer(); mix->toggleAutoTrackLink(index); - FxChannel * channel = mix->effectChannel(index); + MixerChannel * channel = mix->mixerChannel(index); if (!channel->m_autoTrackLinkModel.value()) return; Track * trackFound = NULL; - mix->processFxTracks([&trackFound, index](Track * track, IntModel * fxChannelModel, FxChannel * fxChannel) + mix->processFxTracks([&trackFound, index](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) mutable { (void) fxChannel; if (fxChannelModel->value() == index) @@ -592,11 +592,11 @@ void FxMixerView::toggleAutoTrackLink(int index) } -void FxMixerView::swapChannels(int indexA, int indexB) +void MixerView::swapChannels(int indexA, int indexB) { if (( indexA == indexB ) || - ( indexA <= 1 || indexA >= m_fxChannelViews.size() ) || - ( indexB <= 1 || indexB >= m_fxChannelViews.size() )) + ( indexA <= 1 || indexA >= m_mixerChannelViews.size() ) || + ( indexB <= 1 || indexB >= m_mixerChannelViews.size() )) { return; } @@ -606,15 +606,15 @@ void FxMixerView::swapChannels(int indexA, int indexB) m->swapChannels(indexA,indexB); // Update widgets models - m_fxChannelViews[indexA]->setChannelIndex(indexA); - m_fxChannelViews[indexB]->setChannelIndex(indexB ); + m_mixerChannelViews[indexA]->setChannelIndex(indexA); + m_mixerChannelViews[indexB]->setChannelIndex(indexB ); } -void FxMixerView::moveChannelLeft(int index) +void MixerView::moveChannelLeft(int index) { swapChannels( index, index - 1); - setCurrentFxLine( index - 1 ); + setCurrentMixerLine( index - 1 ); } @@ -622,7 +622,7 @@ void FxMixerView::moveChannelLeft(int index) void MixerView::moveChannelRight(int index) { swapChannels( index , index + 1 ); - setCurrentFxLine( index + 1 ); + setCurrentMixerLine( index + 1 ); } diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index d692d41c2da..c52ebc2693a 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -36,9 +36,9 @@ #include "Song.h" #include "StringPairDrag.h" #include "TrackView.h" - #include "MidiClip.h" - +#include "GuiApplication.h" +#include "MixerView.h" namespace lmms::gui { @@ -87,8 +87,8 @@ void PatternEditor::removeSteps() void PatternEditor::addSampleTrack() { - (void) Track::create( Track::SampleTrack, model() ); - getGUI()->fxMixerView()->processAfterTrackAdd(track); + Track * track = Track::create( Track::SampleTrack, model() ); + getGUI()->mixerView()->processAfterTrackAdd(track); } diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index ad9249cfbd1..645bc60578b 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -43,7 +43,7 @@ #include "TrackView.h" #include "GuiApplication.h" #include "PluginFactory.h" -#include "FxMixerView.h" +#include "MixerView.h" namespace lmms { @@ -168,7 +168,7 @@ void TrackContainerView::removeTrackView( TrackView * _tv ) if( index != -1 ) { Track * t = _tv->getTrack(); - getGUI()->fxMixerView()->processAfterTrackDelete(t); + getGUI()->mixerView()->processAfterTrackDelete(t); m_trackViews.removeAt( index ); disconnect( _tv ); @@ -206,7 +206,7 @@ void TrackContainerView::moveTrackView( TrackView * trackView, int indexTo ) m_tc->m_tracks.insert( indexTo, track ); m_trackViews.move( indexFrom, indexTo ); - getGUI()->fxMixerView()->processAfterTrackMove(track); + getGUI()->mixerView()->processAfterTrackMove(track); realignTracks(); } @@ -406,7 +406,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->fxMixerView()->processAfterTrackAdd(it); + getGUI()->mixerView()->processAfterTrackAdd(it); InstrumentLoaderThread *ilt = new InstrumentLoaderThread( this, it, value ); ilt->start(); @@ -420,7 +420,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->fxMixerView()->processAfterTrackAdd(it); + getGUI()->mixerView()->processAfterTrackAdd(it); PluginFactory::PluginInfoAndKey piakn = getPluginFactory()->pluginSupportingExtension(FileItem::extension(value)); Instrument * i = it->loadInstrument(piakn.info.name(), &piakn.key); @@ -434,7 +434,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->fxMixerView()->processAfterTrackAdd(it); + getGUI()->mixerView()->processAfterTrackAdd(it); it->setSimpleSerializing(); it->loadSettings( dataFile.content().toElement() ); //it->toggledInstrumentTrackButton( true ); diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 1d7d461412a..9849971bd7b 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -241,10 +241,10 @@ void InstrumentTrackView::createMixerLine() /*! \brief Assign a specific mixer Channel for this track */ void InstrumentTrackView::assignMixerLine(int channelIndex) { - model()->effectChannelModel()->setValue( channelIndex ); - FxMixerView* fxMixerView = getGUI()->fxMixerView(); - fxMixerView->processAfterTrackFxMixerModify(getTrack()); - fxMixerView->setCurrentFxLine( channelIndex ); + model()->mixerChannelModel()->setValue( channelIndex ); + MixerView* mixerView = getGUI()->mixerView(); + mixerView->processAfterTrackFxMixerModify(getTrack()); + mixerView->setCurrentMixerLine(channelIndex ); } diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index 353767b186f..ac5753682e8 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -232,10 +232,10 @@ void SampleTrackView::createMixerLine() /*! \brief Assign a specific mixer Channel for this track */ void SampleTrackView::assignMixerLine(int channelIndex) { - model()->effectChannelModel()->setValue(channelIndex); - FxMixerView* fxMixerView = getGUI()->fxMixerView(); - fxMixerView->processAfterTrackFxMixerModify(getTrack()); - fxMixerView->setCurrentFxLine( channelIndex ); + model()->mixerChannelModel()->setValue(channelIndex); + MixerView* mixerView = getGUI()->mixerView(); + mixerView->processAfterTrackFxMixerModify(getTrack()); + mixerView->setCurrentMixerLine( channelIndex ); } } // namespace lmms::gui diff --git a/src/gui/tracks/TrackLabelButton.cpp b/src/gui/tracks/TrackLabelButton.cpp index 74a5744255a..82771e415ca 100644 --- a/src/gui/tracks/TrackLabelButton.cpp +++ b/src/gui/tracks/TrackLabelButton.cpp @@ -39,6 +39,7 @@ #include "TrackView.h" #include "GuiApplication.h" #include "MixerView.h" +#include "TrackView.h" namespace lmms::gui { @@ -66,7 +67,6 @@ TrackLabelButton::TrackLabelButton( TrackView * _tv, QWidget * _parent ) : m_renameLineEdit->setFixedWidth( width() - 33 ); connect( m_renameLineEdit, SIGNAL(editingFinished()), this, SLOT(renameFinished())); } - setIconSize( QSize( 24, 24 ) ); connect( m_trackView->getTrack(), SIGNAL(dataChanged()), this, SLOT(update())); connect( m_trackView->getTrack(), SIGNAL(nameChanged()), this, SLOT(nameChanged())); @@ -88,7 +88,7 @@ void TrackLabelButton::rename() { Track * track = m_trackView->getTrack(); track->setName( txt ); - getGUI()->fxMixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } } @@ -117,7 +117,7 @@ void TrackLabelButton::renameFinished() setText( elideName( m_renameLineEdit->text() ) ); Track * track = m_trackView->getTrack(); track->setName( m_renameLineEdit->text() ); - getGUI()->fxMixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } } diff --git a/src/gui/tracks/TrackOperationsWidget.cpp b/src/gui/tracks/TrackOperationsWidget.cpp index 0a44531bda3..6486b058d94 100644 --- a/src/gui/tracks/TrackOperationsWidget.cpp +++ b/src/gui/tracks/TrackOperationsWidget.cpp @@ -47,7 +47,7 @@ #include "TrackContainerView.h" #include "TrackView.h" #include "GuiApplication.h" -#include "FxMixerView.h" +#include "MixerView.h" namespace lmms::gui { @@ -277,7 +277,7 @@ void TrackOperationsWidget::selectTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->setColor(new_color); - getGUI()->fxMixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } @@ -286,7 +286,7 @@ void TrackOperationsWidget::resetTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->resetColor(); - getGUI()->fxMixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } @@ -296,7 +296,7 @@ void TrackOperationsWidget::randomizeTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->setColor(buffer); - getGUI()->fxMixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->processAfterTrackStyleModify(track); Engine::getSong()->setModified(); } From 1e27fff608077c2e467a96cff62145e58d233fd1 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Fri, 20 May 2022 23:29:39 +0200 Subject: [PATCH 04/25] solve check issues --- src/gui/MixerLine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 852d0d5b092..4df36edc20f 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -82,7 +82,6 @@ MixerLine::MixerLine( QWidget * _parent, MixerView * _mv, int _channelIndex ) : m_strokeInnerInactive( 0, 0, 0 ), m_inRename( false ) { - if( !s_sendBgArrow ) { s_sendBgArrow = new QPixmap( embed::getIconPixmap( "send_bg_arrow", 29, 56 ) ); From c6b29446021be9e4effdcf920a32f8cd2c527482 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Fri, 20 May 2022 23:48:19 +0200 Subject: [PATCH 05/25] solve check issues --- src/gui/MixerView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index f4403662212..335f647d6ae 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -322,7 +322,7 @@ void MixerView::updateAutoTrackSortOrder() { // a (+1) because we didn't include master track in our list swapChannels(list->value(i+1), list->value(i+2)); - list->swapItemsAt(i,i+1); + list->swap(i,i+1); } } n = n-1; From 90f26ce89ced4484db3a3220b3bcc2afe33416af Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sat, 21 May 2022 14:34:02 +0200 Subject: [PATCH 06/25] refactoring naming, removed unused methods, some optimization --- include/Mixer.h | 5 +- include/MixerView.h | 11 ++-- src/core/Mixer.cpp | 77 +++++++++--------------- src/core/Song.cpp | 2 +- src/gui/MixerView.cpp | 74 +++++++++++++---------- src/gui/editors/PatternEditor.cpp | 2 +- src/gui/editors/TrackContainerView.cpp | 10 +-- src/gui/tracks/InstrumentTrackView.cpp | 2 +- src/gui/tracks/SampleTrackView.cpp | 2 +- src/gui/tracks/TrackLabelButton.cpp | 4 +- src/gui/tracks/TrackOperationsWidget.cpp | 6 +- 11 files changed, 91 insertions(+), 104 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 0c0838ffa8a..4454ff5e303 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -202,10 +202,9 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject void toggleAutoTrackLink(int index); // process tracks which have a fx send - void processFxTracks(std::function process); - IntModel * getFxChannelModelByTrack(Track * track); + void processAssignedTracks(std::function process); + IntModel * getChannelModelByTrack(Track * track); std::vector getUsedChannelCounts(); - bool isChannelUsed(int index); bool isAutoTrackLinkToggleAllowed(int index); // reset a channel's name, fx, sends, etc diff --git a/include/MixerView.h b/include/MixerView.h index 063acbfc030..bd3a64c0204 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -111,11 +111,11 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, void refreshDisplay(); // Auto track link support - void processAfterTrackAdd(Track * track); - void processAfterTrackStyleModify(Track * track); - void processAfterTrackFxMixerModify(Track * track); - void processAfterTrackMove(Track * track); - void processAfterTrackDelete(Track * track); + void updateAfterTrackAdd(Track * track); + void updateAfterTrackStyleModify(Track * track); + void updateAfterTrackMixerLineModify(Track * track); + void updateAfterTrackMove(Track * track); + void updateAfterTrackDelete(Track * track); void toggleAutoTrackLink(int index); @@ -143,6 +143,7 @@ private slots: void updateMaxChannelSelector(); void swapChannels(int indexA, int indexB); void updateAutoTrackSortOrder(); + void deleteChannelInternal(int index); friend class MixerChannelView; } ; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 31a43500f4c..a11d311ddc1 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -286,21 +286,21 @@ void Mixer::deleteChannel( int index ) Engine::audioEngine()->requestChangeInModel(); - processFxTracks( [index](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) + processAssignedTracks( [index](Track * track, IntModel * model, MixerChannel * channel) { (void) track; - (void) fxChannel; - int curFxIndex = fxChannelModel->value(0); - if( curFxIndex == index ) + (void) channel; + int curIndex = model->value(0); + if( curIndex == index ) { - // we are deleting this track's fx send + // we are deleting this track's mixer send // send to master - fxChannelModel->setValue(0); + model->setValue(0); } - else if ( curFxIndex > index ) + else if ( curIndex > index ) { // subtract 1 to make up for the missing channel - fxChannelModel->setValue(-1); + model->setValue(-1); } }); @@ -352,7 +352,7 @@ void Mixer::toggleAutoTrackLink(int index) m_mixerChannels[index]->m_autoTrackLinkModel.setValue(! m_mixerChannels[index]->m_autoTrackLinkModel.value()); } -IntModel * Mixer::getFxChannelModelByTrack(Track * track) +IntModel * Mixer::getChannelModelByTrack(Track * track) { if( track->type() == Track::InstrumentTrack ) { @@ -371,19 +371,12 @@ bool Mixer::isAutoTrackLinkToggleAllowed(int index) { if (mixerChannel( index )->m_autoTrackLinkModel.value()) return true; - std::vector used(m_mixerChannels.size(), 0); - processFxTracks([&used](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) - mutable { - (void) track; - (void) fxChannel; - ++used[fxChannelModel->value()]; - }); - - return used[index] == 1; + std::vector usedChannelCounts = getUsedChannelCounts(); + return usedChannelCounts[index] == 1; } -void Mixer::processFxTracks(std::function process) +void Mixer::processAssignedTracks(std::function process) { TrackContainer::TrackList trackList; trackList += Engine::getSong()->tracks(); @@ -391,16 +384,16 @@ void Mixer::processFxTracks(std::functionvalue(); + int channelIndex = model->value(); if (channelIndex > 0 && channelIndex < m_mixerChannels.size() ) { - fxChannel = mixerChannel(channelIndex); + channel = mixerChannel(channelIndex); } - process(track,fxChannelModel, fxChannel); + process(track,model, channel); } } } @@ -408,30 +401,16 @@ void Mixer::processFxTracks(std::function Mixer::getUsedChannelCounts() { std::vector used(m_mixerChannels.size(), 0); - processFxTracks([&used](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) + processAssignedTracks([&used](Track * track, IntModel * model, MixerChannel * channel) mutable { (void) track; - (void) fxChannel; - ++used[fxChannelModel->value()]; + (void) channel; + ++used[model->value()]; }); return used; } -bool Mixer::isChannelUsed(int index) -{ - bool result = false; - - processFxTracks([&result, index](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) - mutable { - (void) track; - (void) fxChannel; - if (fxChannelModel->value() == index) result = true; - }); - return result; -} - - void Mixer::swapChannels(int indexA, int indexB) { @@ -451,18 +430,18 @@ void Mixer::swapChannels(int indexA, int indexB) else if (m_lastSoloed == b) { m_lastSoloed = a; } // go through every instrument and adjust for the channel index change - processFxTracks( [a,b](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) + processAssignedTracks( [a,b](Track * track, IntModel * model, MixerChannel * channel) { (void) track; - (void) fxChannel; - int curFxIndex = fxChannelModel->value(0); - if( curFxIndex == a ) + (void) channel; + int curIndex = model->value(0); + if( curIndex == a ) { - fxChannelModel->setValue(b); + model->setValue(b); } - else if ( curFxIndex == b ) + else if ( curIndex == b ) { - fxChannelModel->setValue(a); + model->setValue(a); } }); diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 54422611232..fbc691db971 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -819,7 +819,7 @@ void Song::addPatternTrack() void Song::addSampleTrack() { Track* track = Track::create( Track::SampleTrack, this ); - getGUI()->mixerView()->processAfterTrackAdd(track); + getGUI()->mixerView()->updateAfterTrackAdd(track); } diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 335f647d6ae..344d7f5100d 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -174,27 +174,27 @@ MixerView::~MixerView() } } -void MixerView::processAfterTrackAdd(Track * track) +void MixerView::updateAfterTrackAdd(Track * track) { // TODO: check if an autotrack mode is enabled (still missing) Mixer * mix = Engine::mixer(); - IntModel * model = mix->getFxChannelModelByTrack(track); + IntModel * model = mix->getChannelModelByTrack(track); if ( model != NULL) { int channelIndex = addNewChannel(); model->setValue( channelIndex ); mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); - processAfterTrackStyleModify(track); + updateAfterTrackStyleModify(track); setCurrentMixerLine( channelIndex ); } } -void MixerView::processAfterTrackStyleModify(Track * track) +void MixerView::updateAfterTrackStyleModify(Track * track) { Mixer * mix = Engine::mixer(); - IntModel * model = mix->getFxChannelModelByTrack(track); + IntModel * model = mix->getChannelModelByTrack(track); if (model != NULL) { int index = model->value(); @@ -208,13 +208,13 @@ void MixerView::processAfterTrackStyleModify(Track * track) } } -void MixerView::processAfterTrackFxMixerModify(Track * track) +void MixerView::updateAfterTrackMixerLineModify(Track * track) { Mixer * mix = Engine::mixer(); - IntModel * model = mix->getFxChannelModelByTrack(track); + IntModel * model = mix->getChannelModelByTrack(track); if (model != NULL) { - // check if there are more than one track is pointing to the same mixer channel + // check if there are more than one track pointing to the same mixer channel // if yes disable the autotracklink std::vector used(m_mixerChannelViews.size(), false); bool needUpdate = false; @@ -231,10 +231,10 @@ void MixerView::processAfterTrackFxMixerModify(Track * track) } } -void MixerView::processAfterTrackMove(Track * track) +void MixerView::updateAfterTrackMove(Track * track) { Mixer * mix = Engine::mixer(); - IntModel * model = Engine::mixer()->getFxChannelModelByTrack(track); + IntModel * model = Engine::mixer()->getChannelModelByTrack(track); if (model != NULL) { MixerChannel * channel = mix->mixerChannel(model->value()); @@ -245,13 +245,13 @@ void MixerView::processAfterTrackMove(Track * track) } } -void MixerView::processAfterTrackDelete(Track * track) +void MixerView::updateAfterTrackDelete(Track * track) { Mixer * mix = Engine::mixer(); - IntModel * model = mix->getFxChannelModelByTrack(track); + IntModel * model = mix->getChannelModelByTrack(track); if ( model != NULL) { - int channelIndex = mix->getFxChannelModelByTrack(track)->value(); + int channelIndex = mix->getChannelModelByTrack(track)->value(); MixerChannel * channel = mix->mixerChannel(channelIndex); if (channel->m_autoTrackLinkModel.value()) { @@ -276,16 +276,14 @@ int MixerView::addNewChannel() updateMixerLine(newChannelIndex); - updateMaxChannelSelector(); - updateAutoTrackSortOrder(); + updateMaxChannelSelector(); return newChannelIndex; } void MixerView::updateAutoTrackSortOrder() { - return; Mixer * mix = Engine::mixer(); QList *list = new QList(); @@ -300,15 +298,16 @@ void MixerView::updateAutoTrackSortOrder() } // add auto tracks in the order of the song tracks - mix->processFxTracks([&, list](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) + mix->processAssignedTracks([&, list](Track * track, IntModel * model, MixerChannel * channel) mutable { - (void) track; - if (fxChannel == NULL) return; - if (fxChannel->m_autoTrackLinkModel.value()) + (void) track; + if (channel == NULL) return; + if (channel->m_autoTrackLinkModel.value()) { - list->append(fxChannelModel->value()); + list->append(model->value()); } }); + return; // bubblesort here because the list is normally almost ordered @@ -329,7 +328,7 @@ void MixerView::updateAutoTrackSortOrder() } while (swapped); // TODO: think about focus - // setCurrentFxLine( index - 1 ); + // setCurrentMixerLine( index - 1 ); } @@ -375,15 +374,16 @@ void MixerView::refreshDisplay() void MixerView::updateMaxChannelSelector() { Mixer * mix = Engine::mixer(); - mix->processFxTracks([this](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) + mix->processAssignedTracks([this](Track * track, IntModel * model, MixerChannel * channel) { (void) track; - (void) fxChannel; - fxChannelModel->setRange(0,m_mixerChannelViews.size()-1,1); + (void) channel; + model->setRange(0,m_mixerChannelViews.size()-1,1); }); } + void MixerView::saveSettings( QDomDocument & _doc, QDomElement & _this ) { MainWindow::saveWidgetState( this, _this ); @@ -503,8 +503,14 @@ void MixerView::updateMixerLine(int index) thisLine->update(); } - void MixerView::deleteChannel(int index) +{ + deleteChannelInternal(index); + updateMaxChannelSelector(); +} + + +void MixerView::deleteChannelInternal(int index) { // can't delete master if( index == 0 ) return; @@ -545,8 +551,6 @@ void MixerView::deleteChannel(int index) selLine = m_mixerChannelViews.size()-1; } setCurrentMixerLine(selLine); - - updateMaxChannelSelector(); } @@ -556,14 +560,18 @@ void MixerView::deleteUnusedChannels() Mixer * mix = Engine::mixer(); std::vector inUse = mix->getUsedChannelCounts(); + bool needUpdateMax = false; + //Check all channels except master, delete those with no incoming sends for(int i = m_mixerChannelViews.size()-1; i > 0; --i) { if ((inUse[i]==0) && Engine::mixer()->mixerChannel(i)->m_receives.isEmpty()) { - deleteChannel(i); + deleteChannelInternal(i); + needUpdateMax = true; } } + if (needUpdateMax) updateMaxChannelSelector(); } @@ -575,10 +583,10 @@ void MixerView::toggleAutoTrackLink(int index) if (!channel->m_autoTrackLinkModel.value()) return; Track * trackFound = NULL; - mix->processFxTracks([&trackFound, index](Track * track, IntModel * fxChannelModel, MixerChannel * fxChannel) + mix->processAssignedTracks([&trackFound, index](Track * track, IntModel * model, MixerChannel * channel) mutable { - (void) fxChannel; - if (fxChannelModel->value() == index) + (void) channel; + if (model->value() == index) { trackFound = track; } @@ -587,7 +595,7 @@ void MixerView::toggleAutoTrackLink(int index) if (trackFound != NULL) { updateAutoTrackSortOrder(); - processAfterTrackStyleModify(trackFound); + updateAfterTrackStyleModify(trackFound); } } diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index c52ebc2693a..527e55f5609 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -88,7 +88,7 @@ void PatternEditor::removeSteps() void PatternEditor::addSampleTrack() { Track * track = Track::create( Track::SampleTrack, model() ); - getGUI()->mixerView()->processAfterTrackAdd(track); + getGUI()->mixerView()->updateAfterTrackAdd(track); } diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index 645bc60578b..67b5a166839 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -168,7 +168,7 @@ void TrackContainerView::removeTrackView( TrackView * _tv ) if( index != -1 ) { Track * t = _tv->getTrack(); - getGUI()->mixerView()->processAfterTrackDelete(t); + getGUI()->mixerView()->updateAfterTrackDelete(t); m_trackViews.removeAt( index ); disconnect( _tv ); @@ -206,7 +206,7 @@ void TrackContainerView::moveTrackView( TrackView * trackView, int indexTo ) m_tc->m_tracks.insert( indexTo, track ); m_trackViews.move( indexFrom, indexTo ); - getGUI()->mixerView()->processAfterTrackMove(track); + getGUI()->mixerView()->updateAfterTrackMove(track); realignTracks(); } @@ -406,7 +406,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->mixerView()->processAfterTrackAdd(it); + getGUI()->mixerView()->updateAfterTrackAdd(it); InstrumentLoaderThread *ilt = new InstrumentLoaderThread( this, it, value ); ilt->start(); @@ -420,7 +420,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->mixerView()->processAfterTrackAdd(it); + getGUI()->mixerView()->updateAfterTrackAdd(it); PluginFactory::PluginInfoAndKey piakn = getPluginFactory()->pluginSupportingExtension(FileItem::extension(value)); Instrument * i = it->loadInstrument(piakn.info.name(), &piakn.key); @@ -434,7 +434,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->mixerView()->processAfterTrackAdd(it); + getGUI()->mixerView()->updateAfterTrackAdd(it); it->setSimpleSerializing(); it->loadSettings( dataFile.content().toElement() ); //it->toggledInstrumentTrackButton( true ); diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 9849971bd7b..8e2809c26aa 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -243,7 +243,7 @@ void InstrumentTrackView::assignMixerLine(int channelIndex) { model()->mixerChannelModel()->setValue( channelIndex ); MixerView* mixerView = getGUI()->mixerView(); - mixerView->processAfterTrackFxMixerModify(getTrack()); + mixerView->updateAfterTrackMixerLineModify(getTrack()); mixerView->setCurrentMixerLine(channelIndex ); } diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index ac5753682e8..cdfc1123c43 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -234,7 +234,7 @@ void SampleTrackView::assignMixerLine(int channelIndex) { model()->mixerChannelModel()->setValue(channelIndex); MixerView* mixerView = getGUI()->mixerView(); - mixerView->processAfterTrackFxMixerModify(getTrack()); + mixerView->updateAfterTrackMixerLineModify(getTrack()); mixerView->setCurrentMixerLine( channelIndex ); } diff --git a/src/gui/tracks/TrackLabelButton.cpp b/src/gui/tracks/TrackLabelButton.cpp index 82771e415ca..5b7580aaadf 100644 --- a/src/gui/tracks/TrackLabelButton.cpp +++ b/src/gui/tracks/TrackLabelButton.cpp @@ -88,7 +88,7 @@ void TrackLabelButton::rename() { Track * track = m_trackView->getTrack(); track->setName( txt ); - getGUI()->mixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->updateAfterTrackStyleModify(track); Engine::getSong()->setModified(); } } @@ -117,7 +117,7 @@ void TrackLabelButton::renameFinished() setText( elideName( m_renameLineEdit->text() ) ); Track * track = m_trackView->getTrack(); track->setName( m_renameLineEdit->text() ); - getGUI()->mixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->updateAfterTrackStyleModify(track); Engine::getSong()->setModified(); } } diff --git a/src/gui/tracks/TrackOperationsWidget.cpp b/src/gui/tracks/TrackOperationsWidget.cpp index 6486b058d94..b0cbc215a9b 100644 --- a/src/gui/tracks/TrackOperationsWidget.cpp +++ b/src/gui/tracks/TrackOperationsWidget.cpp @@ -277,7 +277,7 @@ void TrackOperationsWidget::selectTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->setColor(new_color); - getGUI()->mixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->updateAfterTrackStyleModify(track); Engine::getSong()->setModified(); } @@ -286,7 +286,7 @@ void TrackOperationsWidget::resetTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->resetColor(); - getGUI()->mixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->updateAfterTrackStyleModify(track); Engine::getSong()->setModified(); } @@ -296,7 +296,7 @@ void TrackOperationsWidget::randomizeTrackColor() auto track = m_trackView->getTrack(); track->addJournalCheckPoint(); track->setColor(buffer); - getGUI()->mixerView()->processAfterTrackStyleModify(track); + getGUI()->mixerView()->updateAfterTrackStyleModify(track); Engine::getSong()->setModified(); } From 2ba49827efdf0826c1ef95778fd444c0099a7dd5 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Tue, 24 May 2022 18:28:30 +0200 Subject: [PATCH 07/25] Automatic mixer strip management #1215 - fix some issues with track naming and track delete --- include/MixerView.h | 4 +- src/core/Mixer.cpp | 2 +- src/gui/MixerView.cpp | 64 ++++++++++++++++---------- src/gui/editors/TrackContainerView.cpp | 6 +-- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/include/MixerView.h b/include/MixerView.h index bd3a64c0204..4a3504ccd14 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -110,8 +110,8 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, // useful for loading projects void refreshDisplay(); - // Auto track link support - void updateAfterTrackAdd(Track * track); + // Auto track link support + void updateAfterTrackAdd(Track * track, QString name = ""); void updateAfterTrackStyleModify(Track * track); void updateAfterTrackMixerLineModify(Track * track); void updateAfterTrackMove(Track * track); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index a11d311ddc1..a19a24e1a6a 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -300,7 +300,7 @@ void Mixer::deleteChannel( int index ) else if ( curIndex > index ) { // subtract 1 to make up for the missing channel - model->setValue(-1); + model->setValue(curIndex-1); } }); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 344d7f5100d..280f9a91a95 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -174,7 +174,7 @@ MixerView::~MixerView() } } -void MixerView::updateAfterTrackAdd(Track * track) +void MixerView::updateAfterTrackAdd(Track * track, QString name) { // TODO: check if an autotrack mode is enabled (still missing) Mixer * mix = Engine::mixer(); @@ -185,6 +185,7 @@ void MixerView::updateAfterTrackAdd(Track * track) model->setValue( channelIndex ); mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); + if (name != "") track->setName(name); updateAfterTrackStyleModify(track); setCurrentMixerLine( channelIndex ); @@ -197,13 +198,16 @@ void MixerView::updateAfterTrackStyleModify(Track * track) IntModel * model = mix->getChannelModelByTrack(track); if (model != NULL) { - int index = model->value(); - MixerChannel * channel = mix->mixerChannel(index); - if (channel->m_autoTrackLinkModel.value()) + int channelIndex = model->value(); + if (channelIndex>0) { - channel->m_name = track->name(); - if (track->useColor()) { channel->setColor (track->color()); } - setCurrentMixerLine(index); + MixerChannel * channel = mix->mixerChannel(channelIndex); + if (channel->m_autoTrackLinkModel.value()) + { + channel->m_name = track->name(); + if (track->useColor()) { channel->setColor (track->color()); } + setCurrentMixerLine(channelIndex); + } } } } @@ -237,10 +241,14 @@ void MixerView::updateAfterTrackMove(Track * track) IntModel * model = Engine::mixer()->getChannelModelByTrack(track); if (model != NULL) { - MixerChannel * channel = mix->mixerChannel(model->value()); - if (channel->m_autoTrackLinkModel.value()) + int channelIndex = model->value(); + if (channelIndex>0) { - updateAutoTrackSortOrder(); + MixerChannel * channel = mix->mixerChannel(channelIndex); + if (channel->m_autoTrackLinkModel.value()) + { + updateAutoTrackSortOrder(); + } } } } @@ -251,12 +259,15 @@ void MixerView::updateAfterTrackDelete(Track * track) IntModel * model = mix->getChannelModelByTrack(track); if ( model != NULL) { - int channelIndex = mix->getChannelModelByTrack(track)->value(); - MixerChannel * channel = mix->mixerChannel(channelIndex); - if (channel->m_autoTrackLinkModel.value()) + int channelIndex = model->value(); + if (channelIndex>0) { - deleteChannel(channelIndex); - updateAutoTrackSortOrder(); + MixerChannel * channel = mix->mixerChannel(channelIndex); + if (channel->m_autoTrackLinkModel.value()) + { + deleteChannel(channelIndex); + updateAutoTrackSortOrder(); + } } } } @@ -284,7 +295,6 @@ int MixerView::addNewChannel() void MixerView::updateAutoTrackSortOrder() { - Mixer * mix = Engine::mixer(); QList *list = new QList(); @@ -505,7 +515,20 @@ void MixerView::updateMixerLine(int index) void MixerView::deleteChannel(int index) { + if( index == 0 ) return; + + // remember selected line + int selLine = m_currentMixerLine->channelIndex(); + deleteChannelInternal(index); + + // select the next channel + if( selLine >= m_mixerChannelViews.size() ) + { + selLine = m_mixerChannelViews.size()-1; + } + setCurrentMixerLine(selLine); + updateMaxChannelSelector(); } @@ -515,9 +538,6 @@ void MixerView::deleteChannelInternal(int index) // can't delete master if( index == 0 ) return; - // remember selected line - int selLine = m_currentMixerLine->channelIndex(); - // in case the deleted channel is soloed or the remaining // channels will be left in a muted state Engine::mixer()->clearChannel(index); @@ -545,12 +565,6 @@ void MixerView::deleteChannelInternal(int index) } m_mixerChannelViews.remove(index); - // select the next channel - if( selLine >= m_mixerChannelViews.size() ) - { - selLine = m_mixerChannelViews.size()-1; - } - setCurrentMixerLine(selLine); } diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index 67b5a166839..0101af23820 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -406,9 +406,9 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->mixerView()->updateAfterTrackAdd(it); InstrumentLoaderThread *ilt = new InstrumentLoaderThread( this, it, value ); + getGUI()->mixerView()->updateAfterTrackAdd(it, value); ilt->start(); //it->toggledInstrumentTrackButton( true ); _de->accept(); @@ -420,10 +420,10 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->mixerView()->updateAfterTrackAdd(it); PluginFactory::PluginInfoAndKey piakn = getPluginFactory()->pluginSupportingExtension(FileItem::extension(value)); Instrument * i = it->loadInstrument(piakn.info.name(), &piakn.key); + getGUI()->mixerView()->updateAfterTrackAdd(it); i->loadFile( value ); //it->toggledInstrumentTrackButton( true ); _de->accept(); @@ -434,9 +434,9 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - getGUI()->mixerView()->updateAfterTrackAdd(it); it->setSimpleSerializing(); it->loadSettings( dataFile.content().toElement() ); + getGUI()->mixerView()->updateAfterTrackAdd(it); //it->toggledInstrumentTrackButton( true ); _de->accept(); } From d1c5c29242e01ac37680f78ba4c6b117c3109415 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Tue, 24 May 2022 20:51:32 +0200 Subject: [PATCH 08/25] Automatic mixer strip management #1215 - applied review recommendations --- src/core/Mixer.cpp | 18 ++++++------------ src/gui/MixerLine.cpp | 2 +- src/gui/MixerView.cpp | 34 +++++++++++++++------------------- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index a19a24e1a6a..6ffe4d1c025 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -286,10 +286,8 @@ void Mixer::deleteChannel( int index ) Engine::audioEngine()->requestChangeInModel(); - processAssignedTracks( [index](Track * track, IntModel * model, MixerChannel * channel) + processAssignedTracks( [index](Track *, IntModel * model, MixerChannel * ) { - (void) track; - (void) channel; int curIndex = model->value(0); if( curIndex == index ) { @@ -364,7 +362,7 @@ IntModel * Mixer::getChannelModelByTrack(Track * track) SampleTrack * strk = (SampleTrack *) track; return strk->mixerChannelModel(); } - return NULL; + return nullptr; } bool Mixer::isAutoTrackLinkToggleAllowed(int index) @@ -385,8 +383,8 @@ void Mixer::processAssignedTracks(std::functionvalue(); if (channelIndex > 0 && channelIndex < m_mixerChannels.size() ) @@ -401,10 +399,8 @@ void Mixer::processAssignedTracks(std::function Mixer::getUsedChannelCounts() { std::vector used(m_mixerChannels.size(), 0); - processAssignedTracks([&used](Track * track, IntModel * model, MixerChannel * channel) + processAssignedTracks([&used](Track *, IntModel * model, MixerChannel *) mutable { - (void) track; - (void) channel; ++used[model->value()]; }); @@ -430,10 +426,8 @@ void Mixer::swapChannels(int indexA, int indexB) else if (m_lastSoloed == b) { m_lastSoloed = a; } // go through every instrument and adjust for the channel index change - processAssignedTracks( [a,b](Track * track, IntModel * model, MixerChannel * channel) + processAssignedTracks( [a,b](Track *, IntModel * model, MixerChannel *) { - (void) track; - (void) channel; int curIndex = model->value(0); if( curIndex == a ) { diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 4df36edc20f..b157189122a 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -252,7 +252,7 @@ void MixerLine::mouseDoubleClickEvent( QMouseEvent * ) void MixerLine::contextMenuEvent( QContextMenuEvent * ) { Mixer * mix = Engine::mixer(); - QPointer contextMenu = new CaptionMenu( mix->mixerChannel( m_channelIndex )->m_name, this ); + CaptionMenu* contextMenu = new CaptionMenu( mix->mixerChannel( m_channelIndex )->m_name, this ); bool autoTrackLink = mix->mixerChannel( m_channelIndex )->m_autoTrackLinkModel.value(); if( m_channelIndex != 0 ) // no move-options in master { diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 280f9a91a95..a4f233a8742 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -179,7 +179,7 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name) // TODO: check if an autotrack mode is enabled (still missing) Mixer * mix = Engine::mixer(); IntModel * model = mix->getChannelModelByTrack(track); - if ( model != NULL) + if ( model != nullptr) { int channelIndex = addNewChannel(); model->setValue( channelIndex ); @@ -196,7 +196,7 @@ void MixerView::updateAfterTrackStyleModify(Track * track) { Mixer * mix = Engine::mixer(); IntModel * model = mix->getChannelModelByTrack(track); - if (model != NULL) + if (model != nullptr) { int channelIndex = model->value(); if (channelIndex>0) @@ -216,14 +216,14 @@ void MixerView::updateAfterTrackMixerLineModify(Track * track) { Mixer * mix = Engine::mixer(); IntModel * model = mix->getChannelModelByTrack(track); - if (model != NULL) + if (model != nullptr) { // check if there are more than one track pointing to the same mixer channel // if yes disable the autotracklink std::vector used(m_mixerChannelViews.size(), false); bool needUpdate = false; std::vector usedChannelCounts = mix->getUsedChannelCounts(); - for(unsigned long i = 0; i< usedChannelCounts.size();i++) + for(unsigned long i = 0; i < usedChannelCounts.size(); i++) { if (usedChannelCounts[i] == 0 || usedChannelCounts[i] > 1) { @@ -238,8 +238,8 @@ void MixerView::updateAfterTrackMixerLineModify(Track * track) void MixerView::updateAfterTrackMove(Track * track) { Mixer * mix = Engine::mixer(); - IntModel * model = Engine::mixer()->getChannelModelByTrack(track); - if (model != NULL) + IntModel * model = mix->getChannelModelByTrack(track); + if (model != nullptr) { int channelIndex = model->value(); if (channelIndex>0) @@ -257,7 +257,7 @@ void MixerView::updateAfterTrackDelete(Track * track) { Mixer * mix = Engine::mixer(); IntModel * model = mix->getChannelModelByTrack(track); - if ( model != NULL) + if ( model != nullptr) { int channelIndex = model->value(); if (channelIndex>0) @@ -308,10 +308,9 @@ void MixerView::updateAutoTrackSortOrder() } // add auto tracks in the order of the song tracks - mix->processAssignedTracks([&, list](Track * track, IntModel * model, MixerChannel * channel) + mix->processAssignedTracks([&, list](Track *, IntModel * model, MixerChannel * channel) mutable { - (void) track; - if (channel == NULL) return; + if (channel == nullptr) return; if (channel->m_autoTrackLinkModel.value()) { list->append(model->value()); @@ -384,10 +383,8 @@ void MixerView::refreshDisplay() void MixerView::updateMaxChannelSelector() { Mixer * mix = Engine::mixer(); - mix->processAssignedTracks([this](Track * track, IntModel * model, MixerChannel * channel) + mix->processAssignedTracks([this](Track *, IntModel * model, MixerChannel *) { - (void) track; - (void) channel; model->setRange(0,m_mixerChannelViews.size()-1,1); }); } @@ -492,7 +489,7 @@ void MixerView::updateMixerLine(int index) // does current channel send to this channel? int selIndex = m_currentMixerLine->channelIndex(); MixerLine * thisLine = m_mixerChannelViews[index]->m_mixerLine; - thisLine->setToolTip( Engine::mixer()->mixerChannel( index )->m_name ); + thisLine->setToolTip( mix->mixerChannel( index )->m_name ); FloatModel * sendModel = mix->channelSendModel(selIndex, index); if( sendModel == nullptr ) @@ -579,7 +576,7 @@ void MixerView::deleteUnusedChannels() //Check all channels except master, delete those with no incoming sends for(int i = m_mixerChannelViews.size()-1; i > 0; --i) { - if ((inUse[i]==0) && Engine::mixer()->mixerChannel(i)->m_receives.isEmpty()) + if ((inUse[i]==0) && mix->mixerChannel(i)->m_receives.isEmpty()) { deleteChannelInternal(i); needUpdateMax = true; @@ -596,17 +593,16 @@ void MixerView::toggleAutoTrackLink(int index) MixerChannel * channel = mix->mixerChannel(index); if (!channel->m_autoTrackLinkModel.value()) return; - Track * trackFound = NULL; - mix->processAssignedTracks([&trackFound, index](Track * track, IntModel * model, MixerChannel * channel) + Track * trackFound = nullptr; + mix->processAssignedTracks([&trackFound, index](Track * track, IntModel * model, MixerChannel *) mutable { - (void) channel; if (model->value() == index) { trackFound = track; } }); - if (trackFound != NULL) + if (trackFound != nullptr) { updateAutoTrackSortOrder(); updateAfterTrackStyleModify(trackFound); From 38cf295037e9a5d0e6e3cd3ac430cab344f76d9d Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Tue, 24 May 2022 21:00:39 +0200 Subject: [PATCH 09/25] Automatic mixer strip management #1215 - bugfix for 'frozen' mixer line color --- src/gui/MixerView.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index a4f233a8742..566b74ddb05 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -205,7 +205,8 @@ void MixerView::updateAfterTrackStyleModify(Track * track) if (channel->m_autoTrackLinkModel.value()) { channel->m_name = track->name(); - if (track->useColor()) { channel->setColor (track->color()); } + channel->setColor (track->color()); + channel->m_hasColor = track->useColor(); setCurrentMixerLine(channelIndex); } } @@ -219,8 +220,7 @@ void MixerView::updateAfterTrackMixerLineModify(Track * track) if (model != nullptr) { // check if there are more than one track pointing to the same mixer channel - // if yes disable the autotracklink - std::vector used(m_mixerChannelViews.size(), false); + // if yes disable the autotracklink bool needUpdate = false; std::vector usedChannelCounts = mix->getUsedChannelCounts(); for(unsigned long i = 0; i < usedChannelCounts.size(); i++) @@ -295,15 +295,16 @@ int MixerView::addNewChannel() void MixerView::updateAutoTrackSortOrder() { - Mixer * mix = Engine::mixer(); - QList *list = new QList(); + Mixer * mix = Engine::mixer(); + std::vector list(m_mixerChannelViews.size(), 0); + int c = 0; // add all non auto track first for( int i = 1; imixerChannel(i)->m_autoTrackLinkModel.value()) { - list->append(i); + list[c++] = i; } } @@ -313,27 +314,30 @@ void MixerView::updateAutoTrackSortOrder() if (channel == nullptr) return; if (channel->m_autoTrackLinkModel.value()) { - list->append(model->value()); + list[c++] = model->value(); } }); return; // bubblesort here because the list is normally almost ordered - int n = list->length(); bool swapped = false; do { - for (int i=0; ivalue(i) > list->value(i+1)) + if (list[i] > list[i+1]) { // a (+1) because we didn't include master track in our list - swapChannels(list->value(i+1), list->value(i+2)); - list->swap(i,i+1); + swapChannels(list[i+1], list[i+2]); + int t = list[i]; + list[i] = list[i+1]; + list[i+1] = t; + swapped = true; } } - n = n-1; + c = c-1; } while (swapped); // TODO: think about focus From 5572288e3e89ebaa8aa6dd291a289bf2db4b39a1 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Tue, 24 May 2022 21:48:00 +0200 Subject: [PATCH 10/25] Automatic mixer strip management #1215 - bugfix for broken mixer move --- include/MixerLine.h | 7 ++++--- src/core/Mixer.cpp | 4 ++-- src/gui/MixerView.cpp | 12 +++++++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/MixerLine.h b/include/MixerLine.h index 239fb5042ed..74cde76f233 100644 --- a/include/MixerLine.h +++ b/include/MixerLine.h @@ -82,6 +82,8 @@ class MixerLine : public QWidget bool eventFilter (QObject *dist, QEvent *event) override; + void autoTrackLinkChanged(); + private: void drawMixerLine( QPainter* p, const MixerLine *mixerLine, bool isActive, bool sendToThis, bool receiveFromThis ); QString elideName( const QString & name ); @@ -105,7 +107,7 @@ public slots: void renameChannel(); void resetColor(); void selectColor(); - void randomizeColor(); + void randomizeColor(); private slots: void renameFinished(); @@ -113,8 +115,7 @@ private slots: void removeUnusedChannels(); void moveChannelLeft(); void moveChannelRight(); - void toogleAutoTrackLink(); - void autoTrackLinkChanged(); + void toogleAutoTrackLink(); }; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 6ffe4d1c025..eb83b5e287e 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -412,8 +412,8 @@ void Mixer::swapChannels(int indexA, int indexB) { // range check - can't move master or first channel if (( indexA == indexB ) || - ( indexA <= 1 || indexA >= m_mixerChannels.size() ) || - ( indexB <= 1 || indexB >= m_mixerChannels.size() )) + ( indexA < 1 || indexA >= m_mixerChannels.size() ) || + ( indexB < 1 || indexB >= m_mixerChannels.size() )) { return; } diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 566b74ddb05..ec0d95083ab 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -184,6 +184,7 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name) int channelIndex = addNewChannel(); model->setValue( channelIndex ); mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); + m_mixerChannelViews[channelIndex]->m_mixerLine->autoTrackLinkChanged(); if (name != "") track->setName(name); updateAfterTrackStyleModify(track); @@ -228,6 +229,7 @@ void MixerView::updateAfterTrackMixerLineModify(Track * track) if (usedChannelCounts[i] == 0 || usedChannelCounts[i] > 1) { mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); + m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); needUpdate = true; } } @@ -563,9 +565,9 @@ void MixerView::deleteChannelInternal(int index) for(int i=index + 1; im_mixerLine->setChannelIndex(i-1); + m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); } m_mixerChannelViews.remove(index); - } @@ -594,6 +596,7 @@ void MixerView::toggleAutoTrackLink(int index) { Mixer * mix = Engine::mixer(); mix->toggleAutoTrackLink(index); + m_mixerChannelViews[index]->m_mixerLine->autoTrackLinkChanged(); MixerChannel * channel = mix->mixerChannel(index); if (!channel->m_autoTrackLinkModel.value()) return; @@ -617,8 +620,8 @@ void MixerView::toggleAutoTrackLink(int index) void MixerView::swapChannels(int indexA, int indexB) { if (( indexA == indexB ) || - ( indexA <= 1 || indexA >= m_mixerChannelViews.size() ) || - ( indexB <= 1 || indexB >= m_mixerChannelViews.size() )) + ( indexA < 1 || indexA >= m_mixerChannelViews.size() ) || + ( indexB < 1 || indexB >= m_mixerChannelViews.size() )) { return; } @@ -630,6 +633,9 @@ void MixerView::swapChannels(int indexA, int indexB) // Update widgets models m_mixerChannelViews[indexA]->setChannelIndex(indexA); m_mixerChannelViews[indexB]->setChannelIndex(indexB ); + + m_mixerChannelViews[indexA]->m_mixerLine->autoTrackLinkChanged(); + m_mixerChannelViews[indexB]->m_mixerLine->autoTrackLinkChanged(); } From f7ed9be76902797e90998eb9fa557991ae333480 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Thu, 2 Jun 2022 21:36:31 +0200 Subject: [PATCH 11/25] make text/color changes work also from the mixer line side --- include/Mixer.h | 5 ++- src/core/Mixer.cpp | 12 ++++++ src/gui/MixerLine.cpp | 85 +++++++++++++++++++++++++++++-------------- 3 files changed, 72 insertions(+), 30 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 4454ff5e303..4eefcac7937 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -201,9 +201,10 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject void toggleAutoTrackLink(int index); - // process tracks which have a fx send + // process tracks which have a mixer channel assigned void processAssignedTracks(std::function process); - IntModel * getChannelModelByTrack(Track * track); + void processChannelTracks(MixerChannel * channel, std::function process); + IntModel * getChannelModelByTrack(Track * track); std::vector getUsedChannelCounts(); bool isAutoTrackLinkToggleAllowed(int index); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index eb83b5e287e..dd4ae040e2e 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -365,6 +365,18 @@ IntModel * Mixer::getChannelModelByTrack(Track * track) return nullptr; } + +void Mixer::processChannelTracks(MixerChannel * channel, std::function process) +{ + processAssignedTracks([channel, process](Track * track, IntModel *, MixerChannel * currentChannel) + { + if (currentChannel != nullptr && currentChannel->m_channelIndex == channel->m_channelIndex) + { + process(track); + } + }); +} + bool Mixer::isAutoTrackLinkToggleAllowed(int index) { if (mixerChannel( index )->m_autoTrackLinkModel.value()) return true; diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index b157189122a..7fc9869041b 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -256,14 +256,11 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) bool autoTrackLink = mix->mixerChannel( m_channelIndex )->m_autoTrackLinkModel.value(); if( m_channelIndex != 0 ) // no move-options in master { - if (!autoTrackLink) + contextMenu->addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) ); + bool autoTrackLinkRight = (m_channelIndex +1 < mix->numChannels()) ? mix->mixerChannel( m_channelIndex +1 )->m_autoTrackLinkModel.value() : false; + if (!autoTrackLinkRight) { - contextMenu->addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) ); - bool autoTrackLinkRight = (m_channelIndex +1 < mix->numChannels()) ? mix->mixerChannel( m_channelIndex +1 )->m_autoTrackLinkModel.value() : false; - if (!autoTrackLinkRight) - { - contextMenu->addAction( tr( "Move &right" ), this, SLOT( moveChannelRight() ) ); - } + contextMenu->addAction( tr( "Move &right" ), this, SLOT( moveChannelRight() ) ); } if (mix->isAutoTrackLinkToggleAllowed(m_channelIndex)) { @@ -271,11 +268,9 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) contextMenu->addAction( tr("Auto track link") + marker, this, SLOT( toogleAutoTrackLink() ) ); } } - if (!autoTrackLink) - { - contextMenu->addAction( tr( "Rename &channel" ), this, SLOT( renameChannel() ) ); - contextMenu->addSeparator(); - } + + contextMenu->addAction( tr( "Rename &channel" ), this, SLOT( renameChannel() ) ); + contextMenu->addSeparator(); if( m_channelIndex != 0 ) // no remove-option in master { @@ -286,14 +281,11 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) contextMenu->addSeparator(); QMenu colorMenu(tr("Color"), this); - if (!autoTrackLink) - { - colorMenu.setIcon(embed::getIconPixmap("colorize")); - colorMenu.addAction(tr("Change"), this, SLOT(selectColor())); - colorMenu.addAction(tr("Reset"), this, SLOT(resetColor())); - colorMenu.addAction(tr("Pick random"), this, SLOT(randomizeColor())); - contextMenu->addMenu(&colorMenu); - } + colorMenu.setIcon(embed::getIconPixmap("colorize")); + colorMenu.addAction(tr("Change"), this, SLOT(selectColor())); + colorMenu.addAction(tr("Reset"), this, SLOT(resetColor())); + colorMenu.addAction(tr("Pick random"), this, SLOT(randomizeColor())); + contextMenu->addMenu(&colorMenu); contextMenu->exec( QCursor::pos() ); delete contextMenu; @@ -322,8 +314,6 @@ void MixerLine::autoTrackLinkChanged() void MixerLine::renameChannel() { - if (Engine::mixer()->mixerChannel( m_channelIndex )->m_autoTrackLinkModel.value()) return; - m_inRename = true; setToolTip( "" ); m_renameLineEdit->setReadOnly( false ); @@ -349,8 +339,18 @@ void MixerLine::renameFinished() setFocus(); if( !newName.isEmpty() && Engine::mixer()->mixerChannel( m_channelIndex )->m_name != newName ) { - Engine::mixer()->mixerChannel( m_channelIndex )->m_name = newName; + auto channel = Engine::mixer()->mixerChannel( m_channelIndex ); + channel->m_name = newName; m_renameLineEdit->setText( elideName( newName ) ); + + if (channel->m_autoTrackLinkModel.value()) + { + Engine::mixer()->processChannelTracks(channel, [newName](Track * track) + { + track->setName(newName); + }); + } + Engine::getSong()->setModified(); } QString name = Engine::mixer()->mixerChannel( m_channelIndex )->m_name; @@ -478,9 +478,18 @@ void MixerLine::setStrokeInnerInactive( const QColor & c ) void MixerLine::selectColor() { auto channel = Engine::mixer()->mixerChannel( m_channelIndex ); - auto new_color = ColorChooser(this).withPalette(ColorChooser::Palette::Mixer)->getColor(channel->m_color); - if(!new_color.isValid()) { return; } - channel->setColor (new_color); + auto newColor = ColorChooser(this).withPalette(ColorChooser::Palette::Mixer)->getColor(channel->m_color); + if(!newColor.isValid()) { return; } + channel->setColor (newColor); + + if (channel->m_autoTrackLinkModel.value()) + { + Engine::mixer()->processChannelTracks(channel, [newColor](Track * track) + { + track->setColor(newColor); + }); + } + Engine::getSong()->setModified(); update(); } @@ -489,7 +498,17 @@ void MixerLine::selectColor() // Disable the usage of color on this mixer line void MixerLine::resetColor() { - Engine::mixer()->mixerChannel( m_channelIndex )->m_hasColor = false; + auto channel = Engine::mixer()->mixerChannel( m_channelIndex ); + channel->m_hasColor = false; + + if (channel->m_autoTrackLinkModel.value()) + { + Engine::mixer()->processChannelTracks(channel, [](Track * track) + { + track->resetColor(); + }); + } + Engine::getSong()->setModified(); update(); } @@ -499,7 +518,17 @@ void MixerLine::resetColor() void MixerLine::randomizeColor() { auto channel = Engine::mixer()->mixerChannel( m_channelIndex ); - channel->setColor (ColorChooser::getPalette(ColorChooser::Palette::Mixer)[rand() % 48]); + auto newColor = ColorChooser::getPalette(ColorChooser::Palette::Mixer)[rand() % 48]; + channel->setColor (newColor); + + if (channel->m_autoTrackLinkModel.value()) + { + Engine::mixer()->processChannelTracks(channel, [newColor](Track * track) + { + track->setColor(newColor); + }); + } + Engine::getSong()->setModified(); update(); } From fc785fdc07012815d62a2a30de0963ba07662bb7 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Fri, 3 Jun 2022 22:42:07 +0200 Subject: [PATCH 12/25] button for enabling/disabling the functionality in the mixer --- include/Mixer.h | 2 ++ include/MixerView.h | 3 +++ src/core/Mixer.cpp | 15 +++++++++++++++ src/gui/MixerLine.cpp | 20 +++++++++----------- src/gui/MixerView.cpp | 40 +++++++++++++++++++++++++++++++++++----- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 4eefcac7937..8ea82b25438 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -207,6 +207,8 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject IntModel * getChannelModelByTrack(Track * track); std::vector getUsedChannelCounts(); bool isAutoTrackLinkToggleAllowed(int index); + bool autoLinkTrackConfigEnabled(); + void autoLinkTrackConfigSet(bool value); // reset a channel's name, fx, sends, etc void clearChannel(mix_ch_t channelIndex); diff --git a/include/MixerView.h b/include/MixerView.h index 4a3504ccd14..96c8282f3e4 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -128,6 +128,7 @@ public slots: private slots: void updateFaders(); void toggledSolo(); + void toogleAutoLinkTrackConfig(); private: QVector m_mixerChannelViews; @@ -139,11 +140,13 @@ private slots: QWidget * m_channelAreaWidget; QStackedLayout * m_racksLayout; QWidget * m_racksWidget; + QPushButton * m_toogleAutoLinkTrackConfigBtn; void updateMaxChannelSelector(); void swapChannels(int indexA, int indexB); void updateAutoTrackSortOrder(); void deleteChannelInternal(int index); + void setAutoLinkTrackConfig(bool value); friend class MixerChannelView; } ; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index dd4ae040e2e..ccacbbe0bac 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -31,6 +31,7 @@ #include "MixHelpers.h" #include "Song.h" +#include "ConfigManager.h" #include "InstrumentTrack.h" #include "PatternStore.h" #include "SampleTrack.h" @@ -350,6 +351,19 @@ void Mixer::toggleAutoTrackLink(int index) m_mixerChannels[index]->m_autoTrackLinkModel.setValue(! m_mixerChannels[index]->m_autoTrackLinkModel.value()); } + +bool Mixer::autoLinkTrackConfigEnabled() +{ + return ConfigManager::inst()->value("ui", "autoLinkTrackConfig").toInt() == 1; +} + +void Mixer::autoLinkTrackConfigSet(bool value) +{ + ConfigManager::inst()->setValue("ui", "autoLinkTrackConfig", QString::number(value)); + ConfigManager::inst()->saveConfigFile(); +} + + IntModel * Mixer::getChannelModelByTrack(Track * track) { if( track->type() == Track::InstrumentTrack ) @@ -379,6 +393,7 @@ void Mixer::processChannelTracks(MixerChannel * channel, std::functionautoLinkTrackConfigEnabled()) return false; if (mixerChannel( index )->m_autoTrackLinkModel.value()) return true; std::vector usedChannelCounts = getUsedChannelCounts(); diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 7fc9869041b..62fa91efdc2 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -256,17 +256,15 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) bool autoTrackLink = mix->mixerChannel( m_channelIndex )->m_autoTrackLinkModel.value(); if( m_channelIndex != 0 ) // no move-options in master { - contextMenu->addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) ); - bool autoTrackLinkRight = (m_channelIndex +1 < mix->numChannels()) ? mix->mixerChannel( m_channelIndex +1 )->m_autoTrackLinkModel.value() : false; - if (!autoTrackLinkRight) - { - contextMenu->addAction( tr( "Move &right" ), this, SLOT( moveChannelRight() ) ); - } - if (mix->isAutoTrackLinkToggleAllowed(m_channelIndex)) - { - QString marker = (autoTrackLink ? " *" : ""); - contextMenu->addAction( tr("Auto track link") + marker, this, SLOT( toogleAutoTrackLink() ) ); - } + QAction * actionMoveleft =contextMenu->addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) ); + QAction * actionMoveRight =contextMenu->addAction( tr( "Move &right" ), this, SLOT( moveChannelRight() ) ); + + QString marker = (autoTrackLink ? " *" : ""); + QAction * actionToggleAutoTrackLink = contextMenu->addAction( tr("Auto track link") + marker, this, SLOT( toogleAutoTrackLink() ) ); + + actionMoveleft->setEnabled(m_channelIndex > 1); + actionMoveRight->setEnabled((m_channelIndex +1) < mix->numChannels()); + actionToggleAutoTrackLink->setEnabled(mix->autoLinkTrackConfigEnabled() && mix->isAutoTrackLinkToggleAllowed(m_channelIndex)); } contextMenu->addAction( tr( "Rename &channel" ), this, SLOT( renameChannel() ) ); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index ec0d95083ab..9f02c841e72 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -130,13 +130,24 @@ MixerView::MixerView() : style()->pixelMetric( QStyle::PM_ScrollBarExtent ) ); ml->addWidget( channelArea, 1, Qt::AlignTop ); + QWidget * buttonAreaWidget = new QWidget; + buttonAreaWidget->setFixedSize(mixerLineSize); + QVBoxLayout * bl = new QVBoxLayout( buttonAreaWidget ); + bl->setSizeConstraint( QLayout::SetMinimumSize ); + bl->setSpacing( 0 ); + bl->setMargin( 0 ); + ml->addWidget(buttonAreaWidget); + // show the add new mixer channel button QPushButton * newChannelBtn = new QPushButton( embed::getIconPixmap( "new_channel" ), QString(), this ); newChannelBtn->setObjectName( "newChannelBtn" ); - newChannelBtn->setFixedSize( mixerLineSize ); - connect( newChannelBtn, SIGNAL(clicked()), this, SLOT(addNewChannel())); - ml->addWidget( newChannelBtn, 0, Qt::AlignTop ); + connect( newChannelBtn, SIGNAL( clicked() ), this, SLOT( addNewChannel() ) ); + bl->addWidget(newChannelBtn, 0, Qt::AlignTop ); + m_toogleAutoLinkTrackConfigBtn = new QPushButton( embed::getIconPixmap( "exp_wave_inactive" ), QString(), this ); + connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL( clicked() ), this, SLOT(toogleAutoLinkTrackConfig())); + setAutoLinkTrackConfig(Engine::mixer()->autoLinkTrackConfigEnabled()); + bl->addWidget(m_toogleAutoLinkTrackConfigBtn, 0, Qt::AlignTop ); // add the stacked layout for the effect racks of mixer channels ml->addWidget( m_racksWidget, 0, Qt::AlignTop | Qt::AlignRight ); @@ -175,9 +186,9 @@ MixerView::~MixerView() } void MixerView::updateAfterTrackAdd(Track * track, QString name) -{ - // TODO: check if an autotrack mode is enabled (still missing) +{ Mixer * mix = Engine::mixer(); + if (!mix->autoLinkTrackConfigEnabled()) return; IntModel * model = mix->getChannelModelByTrack(track); if ( model != nullptr) { @@ -196,6 +207,7 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name) void MixerView::updateAfterTrackStyleModify(Track * track) { Mixer * mix = Engine::mixer(); + if (!mix->autoLinkTrackConfigEnabled()) return; IntModel * model = mix->getChannelModelByTrack(track); if (model != nullptr) { @@ -217,6 +229,7 @@ void MixerView::updateAfterTrackStyleModify(Track * track) void MixerView::updateAfterTrackMixerLineModify(Track * track) { Mixer * mix = Engine::mixer(); + if (!mix->autoLinkTrackConfigEnabled()) return; IntModel * model = mix->getChannelModelByTrack(track); if (model != nullptr) { @@ -240,6 +253,7 @@ void MixerView::updateAfterTrackMixerLineModify(Track * track) void MixerView::updateAfterTrackMove(Track * track) { Mixer * mix = Engine::mixer(); + if (!mix->autoLinkTrackConfigEnabled()) return; IntModel * model = mix->getChannelModelByTrack(track); if (model != nullptr) { @@ -258,6 +272,7 @@ void MixerView::updateAfterTrackMove(Track * track) void MixerView::updateAfterTrackDelete(Track * track) { Mixer * mix = Engine::mixer(); + if (!mix->autoLinkTrackConfigEnabled()) return; IntModel * model = mix->getChannelModelByTrack(track); if ( model != nullptr) { @@ -275,6 +290,20 @@ void MixerView::updateAfterTrackDelete(Track * track) } +void MixerView::setAutoLinkTrackConfig(bool value) +{ + Engine::mixer()->autoLinkTrackConfigSet(value); + m_toogleAutoLinkTrackConfigBtn->setIcon(value ? embed::getIconPixmap( "exp_wave_active" ) : embed::getIconPixmap( "exp_wave_inactive" )); +} + +void MixerView::toogleAutoLinkTrackConfig() +{ + bool cur = Engine::mixer()->autoLinkTrackConfigEnabled(); + setAutoLinkTrackConfig(!cur); +} + + + int MixerView::addNewChannel() { @@ -595,6 +624,7 @@ void MixerView::deleteUnusedChannels() void MixerView::toggleAutoTrackLink(int index) { Mixer * mix = Engine::mixer(); + if (!mix->autoLinkTrackConfigEnabled()) return; mix->toggleAutoTrackLink(index); m_mixerChannelViews[index]->m_mixerLine->autoTrackLinkChanged(); MixerChannel * channel = mix->mixerChannel(index); From a7d0f6822681f5dd6a222881d2277a429f736398 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Fri, 10 Jun 2022 19:15:47 +0200 Subject: [PATCH 13/25] Provide two-way linking, Prepared additional settings --- include/Mixer.h | 53 ++++++++++++++++++- include/MixerView.h | 3 +- src/core/Mixer.cpp | 52 ++++++++++++++---- src/gui/MixerLine.cpp | 2 +- src/gui/MixerView.cpp | 120 +++++++++++++++++++++++++++--------------- 5 files changed, 174 insertions(+), 56 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 8ea82b25438..7ca33df2f10 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -142,8 +142,53 @@ class MixerRoute : public QObject class LMMS_EXPORT Mixer : public Model, public JournallingObject { + Q_OBJECT public: + + struct autoTrackLinkSettings + { + enum class AutoSort + { + Disabled, /* automatic sorting is disabled */ + LinkedPattern, /* linked tracks first, pattern editor afterwards */ + PatternLinked /* pattern editor first, linked tracks afterwards */ + }; + + enum class LinkPatternEditor + { + Disabled, /* do not link pattern editor tracks */ + Default, /* one channel for each pattern editor track */ + UseFirstTrackOnly, /* use always the first channel in the pattern editor for new tracks*/ + }; + + bool enabled; + bool linkColor; + bool linkName; + bool autoAdd; + bool autoDelete; + AutoSort sort; + LinkPatternEditor linkPatternEditor; + + bool linkStyles() + { + return linkColor || linkName; + } + + autoTrackLinkSettings() + { + enabled = false; + linkColor = true; + linkName = true; + autoAdd = true; + autoDelete = true; + linkPatternEditor = LinkPatternEditor::Default; + sort = AutoSort::Disabled; + } + }; + + + Mixer(); ~Mixer() override; @@ -203,12 +248,15 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject // process tracks which have a mixer channel assigned void processAssignedTracks(std::function process); + // process tracks assigned to a specific channel void processChannelTracks(MixerChannel * channel, std::function process); IntModel * getChannelModelByTrack(Track * track); std::vector getUsedChannelCounts(); bool isAutoTrackLinkToggleAllowed(int index); - bool autoLinkTrackConfigEnabled(); - void autoLinkTrackConfigSet(bool value); + //bool autoLinkTrackConfigEnabled(); + + autoTrackLinkSettings getAutoLinkTrackSettings(); + void saveAutoLinkTrackSettings(autoTrackLinkSettings settings); // reset a channel's name, fx, sends, etc void clearChannel(mix_ch_t channelIndex); @@ -228,6 +276,7 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject MixerRouteVector m_mixerRoutes; private: + static inline QString const AUTOTRACK_CONFIGPREFIX = "autoTrackLinkSettings"; // the mixer channels in the mixer. index 0 is always master. QVector m_mixerChannels; diff --git a/include/MixerView.h b/include/MixerView.h index 96c8282f3e4..042833b84cd 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -146,7 +146,8 @@ private slots: void swapChannels(int indexA, int indexB); void updateAutoTrackSortOrder(); void deleteChannelInternal(int index); - void setAutoLinkTrackConfig(bool value); + void setAutoLinkTrackConfig(bool enabled); + void setAutoTrackConstraints(); friend class MixerChannelView; } ; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index ccacbbe0bac..b1569e8376f 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -352,15 +352,35 @@ void Mixer::toggleAutoTrackLink(int index) } -bool Mixer::autoLinkTrackConfigEnabled() +Mixer::autoTrackLinkSettings Mixer::getAutoLinkTrackSettings() { - return ConfigManager::inst()->value("ui", "autoLinkTrackConfig").toInt() == 1; + autoTrackLinkSettings settings; + auto cfg = ConfigManager::inst(); + auto enabledAsString = cfg->value("ui", AUTOTRACK_CONFIGPREFIX); + if (enabledAsString != "") + { + settings.enabled = enabledAsString.toInt() == 1; + settings.linkName = (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_linkName").toInt() == 1); + settings.linkColor = (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_linkColor").toInt() == 1); + settings.autoAdd = (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_autoAdd").toInt() == 1); + settings.autoDelete = (cfg->value("ui",AUTOTRACK_CONFIGPREFIX+"_autoDelete").toInt() == 1); + settings.linkPatternEditor = (autoTrackLinkSettings::LinkPatternEditor) (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_linkPatternEditor").toInt()); + settings.sort = (autoTrackLinkSettings::AutoSort) (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_sort").toInt()); + } + return settings; } -void Mixer::autoLinkTrackConfigSet(bool value) +void Mixer::saveAutoLinkTrackSettings(autoTrackLinkSettings settings) { - ConfigManager::inst()->setValue("ui", "autoLinkTrackConfig", QString::number(value)); - ConfigManager::inst()->saveConfigFile(); + auto cfg = ConfigManager::inst(); + cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX, QString::number(settings.enabled)); + cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_linkName", QString::number(settings.linkName)); + cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_linkColor", QString::number(settings.linkColor)); + cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_autoAdd", QString::number(settings.autoAdd)); + cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_autoDelete", QString::number(settings.autoDelete)); + cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_linkPatternEditor", QString::number((int)settings.linkPatternEditor)); + cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_sort", QString::number((int)settings.sort)); + cfg->saveConfigFile(); } @@ -391,14 +411,28 @@ void Mixer::processChannelTracks(MixerChannel * channel, std::functionautoLinkTrackConfigEnabled()) return false; - if (mixerChannel( index )->m_autoTrackLinkModel.value()) return true; + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled) return false; + if (mixerChannel( index )->m_autoTrackLinkModel.value()) return true; + if (settings.linkName) + { + std::vector usedChannelCounts = getUsedChannelCounts(); + return usedChannelCounts[index] == 1; + } + return true; +} - std::vector usedChannelCounts = getUsedChannelCounts(); - return usedChannelCounts[index] == 1; +/* +bool Mixer::autoLinkTrackConfigEnabled() +{ + auto settings =mix->getAutoLinkTrackSettings(); } +*/ + void Mixer::processAssignedTracks(std::function process) diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 62fa91efdc2..de82aead8e0 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -264,7 +264,7 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) actionMoveleft->setEnabled(m_channelIndex > 1); actionMoveRight->setEnabled((m_channelIndex +1) < mix->numChannels()); - actionToggleAutoTrackLink->setEnabled(mix->autoLinkTrackConfigEnabled() && mix->isAutoTrackLinkToggleAllowed(m_channelIndex)); + actionToggleAutoTrackLink->setEnabled(mix->isAutoTrackLinkToggleAllowed(m_channelIndex)); } contextMenu->addAction( tr( "Rename &channel" ), this, SLOT( renameChannel() ) ); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 9f02c841e72..3a8dc1d8197 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -144,9 +144,9 @@ MixerView::MixerView() : connect( newChannelBtn, SIGNAL( clicked() ), this, SLOT( addNewChannel() ) ); bl->addWidget(newChannelBtn, 0, Qt::AlignTop ); - m_toogleAutoLinkTrackConfigBtn = new QPushButton( embed::getIconPixmap( "exp_wave_inactive" ), QString(), this ); + m_toogleAutoLinkTrackConfigBtn = new QPushButton(QString(), this ); connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL( clicked() ), this, SLOT(toogleAutoLinkTrackConfig())); - setAutoLinkTrackConfig(Engine::mixer()->autoLinkTrackConfigEnabled()); + setAutoLinkTrackConfig(Engine::mixer()->getAutoLinkTrackSettings().enabled); bl->addWidget(m_toogleAutoLinkTrackConfigBtn, 0, Qt::AlignTop ); // add the stacked layout for the effect racks of mixer channels @@ -186,9 +186,10 @@ MixerView::~MixerView() } void MixerView::updateAfterTrackAdd(Track * track, QString name) -{ - Mixer * mix = Engine::mixer(); - if (!mix->autoLinkTrackConfigEnabled()) return; +{ + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled || !settings.autoAdd) return; IntModel * model = mix->getChannelModelByTrack(track); if ( model != nullptr) { @@ -197,6 +198,7 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name) mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); m_mixerChannelViews[channelIndex]->m_mixerLine->autoTrackLinkChanged(); + // it may be that the track name is not available yet because of async loading if (name != "") track->setName(name); updateAfterTrackStyleModify(track); @@ -206,8 +208,9 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name) void MixerView::updateAfterTrackStyleModify(Track * track) { - Mixer * mix = Engine::mixer(); - if (!mix->autoLinkTrackConfigEnabled()) return; + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled || !settings.linkStyles()) return; IntModel * model = mix->getChannelModelByTrack(track); if (model != nullptr) { @@ -217,9 +220,15 @@ void MixerView::updateAfterTrackStyleModify(Track * track) MixerChannel * channel = mix->mixerChannel(channelIndex); if (channel->m_autoTrackLinkModel.value()) { - channel->m_name = track->name(); - channel->setColor (track->color()); - channel->m_hasColor = track->useColor(); + if (settings.linkName) + { + channel->m_name = track->name(); + } + if (settings.linkColor) + { + channel->setColor (track->color()); + channel->m_hasColor = track->useColor(); + } setCurrentMixerLine(channelIndex); } } @@ -228,32 +237,41 @@ void MixerView::updateAfterTrackStyleModify(Track * track) void MixerView::updateAfterTrackMixerLineModify(Track * track) { - Mixer * mix = Engine::mixer(); - if (!mix->autoLinkTrackConfigEnabled()) return; + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled) return; IntModel * model = mix->getChannelModelByTrack(track); if (model != nullptr) { - // check if there are more than one track pointing to the same mixer channel - // if yes disable the autotracklink - bool needUpdate = false; - std::vector usedChannelCounts = mix->getUsedChannelCounts(); - for(unsigned long i = 0; i < usedChannelCounts.size(); i++) + setAutoTrackConstraints(); + } +} + +void MixerView::setAutoTrackConstraints() +{ + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled) return; + std::vector usedChannelCounts = mix->getUsedChannelCounts(); + bool wasModified = false; + for(unsigned long i = 0; i < usedChannelCounts.size(); i++) + { + // no more linked tracks or too many linked tracks (if name linking is enabled) + if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && settings.linkName)) { - if (usedChannelCounts[i] == 0 || usedChannelCounts[i] > 1) - { - mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); - m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); - needUpdate = true; - } + mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); + m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); + wasModified = true; } - if (needUpdate) updateAutoTrackSortOrder(); } + if (wasModified) updateAutoTrackSortOrder(); } void MixerView::updateAfterTrackMove(Track * track) { - Mixer * mix = Engine::mixer(); - if (!mix->autoLinkTrackConfigEnabled()) return; + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled || settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; IntModel * model = mix->getChannelModelByTrack(track); if (model != nullptr) { @@ -271,8 +289,9 @@ void MixerView::updateAfterTrackMove(Track * track) void MixerView::updateAfterTrackDelete(Track * track) { - Mixer * mix = Engine::mixer(); - if (!mix->autoLinkTrackConfigEnabled()) return; + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled) return; IntModel * model = mix->getChannelModelByTrack(track); if ( model != nullptr) { @@ -282,29 +301,40 @@ void MixerView::updateAfterTrackDelete(Track * track) MixerChannel * channel = mix->mixerChannel(channelIndex); if (channel->m_autoTrackLinkModel.value()) { - deleteChannel(channelIndex); - updateAutoTrackSortOrder(); + bool shouldDelete = true; + if (!settings.linkName) + { + // if we don't have a 1.1 name link we make sure that no track is left. + std::vector usedChannelCounts = mix->getUsedChannelCounts(); + shouldDelete = usedChannelCounts[channelIndex] == 0; + } + if (shouldDelete) + { + deleteChannel(channelIndex); + updateAutoTrackSortOrder(); + } } } } } - -void MixerView::setAutoLinkTrackConfig(bool value) +void MixerView::setAutoLinkTrackConfig(bool enabled) { - Engine::mixer()->autoLinkTrackConfigSet(value); - m_toogleAutoLinkTrackConfigBtn->setIcon(value ? embed::getIconPixmap( "exp_wave_active" ) : embed::getIconPixmap( "exp_wave_inactive" )); + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + settings.enabled = enabled; + mix->saveAutoLinkTrackSettings(settings); + m_toogleAutoLinkTrackConfigBtn->setIcon(enabled ? embed::getIconPixmap( "exp_wave_active" ) : embed::getIconPixmap( "exp_wave_inactive" )); + setAutoTrackConstraints(); } void MixerView::toogleAutoLinkTrackConfig() { - bool cur = Engine::mixer()->autoLinkTrackConfigEnabled(); - setAutoLinkTrackConfig(!cur); + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + setAutoLinkTrackConfig(!settings.enabled); } - - - int MixerView::addNewChannel() { // add new mixer channel and redraw the form. @@ -326,7 +356,10 @@ int MixerView::addNewChannel() void MixerView::updateAutoTrackSortOrder() { - Mixer * mix = Engine::mixer(); + Mixer * mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled || settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; + std::vector list(m_mixerChannelViews.size(), 0); int c = 0; @@ -348,7 +381,7 @@ void MixerView::updateAutoTrackSortOrder() list[c++] = model->value(); } }); - return; + return; // ignore for now // bubblesort here because the list is normally almost ordered @@ -623,8 +656,9 @@ void MixerView::deleteUnusedChannels() void MixerView::toggleAutoTrackLink(int index) { - Mixer * mix = Engine::mixer(); - if (!mix->autoLinkTrackConfigEnabled()) return; + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (!settings.enabled) return; mix->toggleAutoTrackLink(index); m_mixerChannelViews[index]->m_mixerLine->autoTrackLinkChanged(); MixerChannel * channel = mix->mixerChannel(index); From 76b0f50d104096ae4f0a4fff4b4325933ec6bf79 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sat, 11 Jun 2022 13:01:14 +0200 Subject: [PATCH 14/25] Improved settings menu and added icons --- data/themes/default/auto_link_active.png | Bin 0 -> 1001 bytes data/themes/default/auto_link_inactive.png | Bin 0 -> 820 bytes include/Mixer.h | 12 +- include/MixerView.h | 8 +- src/gui/MixerLine.cpp | 11 +- src/gui/MixerView.cpp | 150 +++++++++++++++++++-- src/gui/editors/PatternEditor.cpp | 2 +- 7 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 data/themes/default/auto_link_active.png create mode 100644 data/themes/default/auto_link_inactive.png diff --git a/data/themes/default/auto_link_active.png b/data/themes/default/auto_link_active.png new file mode 100644 index 0000000000000000000000000000000000000000..fd765509dac83d2fe6de2d82d72fb10c9671666d GIT binary patch literal 1001 zcmV500009a7bBm000}7 z000}70dwn0!vFvP8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H119nM7 zK~z|U#n{hp8$}er@$VbEi1-IBg+`nTZKaahu@IyY3Wur}g46?2)i_(426F0=KL`Xp z&{TD-@|!0G{{e1zA&c4LAlI@tw9*%jn5SF&!Wk6=v$0 zxi8y^l$)PWy#s zv>?sUHBaN<6Jv}@5_l#&1lT>1H=Y>tFf;d^2xov=7)Z*^PXMoYQj3vI;8c0?l(o_b z0!b`8qawNh?DwRn`&NN_K<0r1p7fnsMn~eIM!I=Ao){c_U*IAz0z3y)fs(?NdgH)n zoc!ofNXSMEoj{7)fuBtJUj9|P&GqhUjk;=MGxglH(qoXa^M9iCy!URpzWwYE0s|^~sh%m`Xm=ba=g%6I%j~WrT_Jm7 zfDx{$6AtCMf+ltmYof8JLxziMXu?hkSRL}xq)LTQ2q+BQe zG$1XET=gat{lpJSEl-|n?OFQ^I;intPSQzGIO?niydJUFX<8MsER! z0-O_gtqB_jppq-B#;uG2OFjDEiJ@=y0|Ndngyv((vN;dh{?arE`~j3euKK?;MIHYF XYaaFSbNRtv00000NkvXXu0mjf$xG7x literal 0 HcmV?d00001 diff --git a/data/themes/default/auto_link_inactive.png b/data/themes/default/auto_link_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..355edce5f990be95a735c0d7783b5b60154de3b4 GIT binary patch literal 820 zcmV-41Izr0P)500009a7bBm000}7 z000}70dwn0!vFvP8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10>Mc{ zK~z|U#h5)$R6!JmpINXmh!E`%F_2(lQ0(aa4ycP73-Je78h?k0t%+791}Xt9tgs`o zq2OzmVB!a$oftr4OoY4^Gb_XFdhcAgiznG+?#wxx=bo8)&)hN8(IhnjH-IA03$y^= zfEi#6cx8;)s`#5af^-5;f$jvi5^&ELvs5=2NvDBfY$nod6(|~GmU4%2AS1xxU}zaw z0!{$!!B`0x$Q?w|yrdQHSC(`+@Eee{5cmz|mYIKKWCIv7#>~|4zY09|y58ghlNH2^ zdkY+MkE@0M1>$VkYq#tf1~>>D*aZl{aj(6W0}Dv%le8$QB&jztW*}I=&+=TreZa4n zj5y#C;E>mSzitYg0x}FVd);NAzcJ$e{W6y1lVp=kLeQyG&&Q z>8bHXW&e#NHMvYoNje|IUvd7KK&lq7q#o=V@#pwER^q2Uzem7r&*u}c0(7ub<^k4$ zJI0u~XqXHjUBCnp8vv^#LunuYe+y+S2!PuyMXatQ*#h=RnF<0fGw$&GlIrc3b{?rH z@*q}`o3T?ei#`31`ltU?lhhz-B5Bv`mld$zH7C8k%G5+vUstX3F-gyZtXztWtLVsL zZa{&aOlAbB#N`51U}rgBi2addAction( tr( "Move &left" ), this, SLOT( moveChannelLeft() ) ); QAction * actionMoveRight =contextMenu->addAction( tr( "Move &right" ), this, SLOT( moveChannelRight() ) ); - QString marker = (autoTrackLink ? " *" : ""); - QAction * actionToggleAutoTrackLink = contextMenu->addAction( tr("Auto track link") + marker, this, SLOT( toogleAutoTrackLink() ) ); + auto settings =mix->getAutoLinkTrackSettings(); + if (settings.enabled) + { + // we don't show the menu entry if the auto link functionality is completely disabled + QString marker = (autoTrackLink ? " *" : ""); + QAction * actionToggleAutoTrackLink = contextMenu->addAction( tr("Auto track link") + marker, this, [this](){ toogleAutoTrackLink(); } ); + actionToggleAutoTrackLink->setEnabled(mix->isAutoTrackLinkToggleAllowed(m_channelIndex)); + } actionMoveleft->setEnabled(m_channelIndex > 1); actionMoveRight->setEnabled((m_channelIndex +1) < mix->numChannels()); - actionToggleAutoTrackLink->setEnabled(mix->isAutoTrackLinkToggleAllowed(m_channelIndex)); } contextMenu->addAction( tr( "Rename &channel" ), this, SLOT( renameChannel() ) ); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 3a8dc1d8197..bf214db8d5a 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -22,7 +22,7 @@ * */ - +#include #include #include #include @@ -45,6 +45,7 @@ #include "Song.h" #include "SubWindow.h" #include "TrackContainer.h" // For TrackContainer::TrackList typedef +#include "gui_templates.h" namespace lmms::gui { @@ -141,14 +142,27 @@ MixerView::MixerView() : // show the add new mixer channel button QPushButton * newChannelBtn = new QPushButton( embed::getIconPixmap( "new_channel" ), QString(), this ); newChannelBtn->setObjectName( "newChannelBtn" ); - connect( newChannelBtn, SIGNAL( clicked() ), this, SLOT( addNewChannel() ) ); + connect( newChannelBtn, SIGNAL(clicked()), this, SLOT(addNewChannel())); + //ml->addWidget( newChannelBtn, 0, Qt::AlignTop ); bl->addWidget(newChannelBtn, 0, Qt::AlignTop ); - m_toogleAutoLinkTrackConfigBtn = new QPushButton(QString(), this ); - connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL( clicked() ), this, SLOT(toogleAutoLinkTrackConfig())); + QMenu * toMenu = new QMenu(this ); + toMenu->setFont( pointSize<9>( toMenu->font() ) ); + connect( toMenu, SIGNAL( aboutToShow() ), this, SLOT( updateMenu() ) ); + + m_autoLinkTrackSettingsBtn = new QPushButton(embed::getIconPixmap( "trackop" ),QString(), this); + m_autoLinkTrackSettingsBtn->move( 12, 1 ); + m_autoLinkTrackSettingsBtn->setFocusPolicy( Qt::NoFocus ); + m_autoLinkTrackSettingsBtn->setMenu( toMenu ); + m_autoLinkTrackSettingsBtn->setToolTip(tr("Auto track link settings")); + bl->addWidget(m_autoLinkTrackSettingsBtn, 0, Qt::AlignTop ); + + m_toogleAutoLinkTrackConfigBtn = new QPushButton(this); + connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL(clicked()), this, SLOT(toogleAutoLinkTrackConfig())); setAutoLinkTrackConfig(Engine::mixer()->getAutoLinkTrackSettings().enabled); bl->addWidget(m_toogleAutoLinkTrackConfigBtn, 0, Qt::AlignTop ); + // add the stacked layout for the effect racks of mixer channels ml->addWidget( m_racksWidget, 0, Qt::AlignTop | Qt::AlignRight ); @@ -185,7 +199,101 @@ MixerView::~MixerView() } } -void MixerView::updateAfterTrackAdd(Track * track, QString name) + +void MixerView::updateMenu() +{ + QMenu* toMenu = m_autoLinkTrackSettingsBtn->menu(); + toMenu->clear(); + + // no widget but same approach as for CaptionMenu + + QAction * captionMain = toMenu->addAction( "Auto track linking" ); + captionMain->setEnabled( false ); + QMenu* sortMenu = toMenu->addMenu(tr("Sort")); + + QMenu* settingsMenu = toMenu->addMenu(tr("Settings")); + QMenu* linkTypeMenu = settingsMenu->addMenu(tr("Link type")); + QMenu* sortAutoMenu = settingsMenu->addMenu(tr("Automatic sorting")); + QMenu* patternEditorMenu = settingsMenu->addMenu(tr("Pattern Editor")); + + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + + linkTypeMenu->addAction( tr("Name and color") + + (settings.linkNameAndColor() ? " *" :""), + this, [&settings, &mix]() + { + settings.linkName = true; + settings.linkColor = true; + mix->saveAutoLinkTrackSettings(settings); + }); + linkTypeMenu->addAction( tr("Color only") + + (settings.linkColorOnly() ? " *" :""), + this, [&settings, &mix]() + { + settings.linkName = false; + settings.linkColor = true; + mix->saveAutoLinkTrackSettings(settings); + }); + + sortMenu->addAction( tr("Song Editor -> Pattern Editor"), this, [this]() + { + updateAutoTrackSortOrder(false); + }); + sortMenu->addAction( tr("Pattern Editor -> Song Editor"), this, [this]() + { + updateAutoTrackSortOrder(false); + }); + + sortAutoMenu->addAction( + tr("Disabled") +(settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled ? " *" :""), + this, [&settings, &mix]() + { + settings.sort = Mixer::autoTrackLinkSettings::AutoSort::Disabled; + mix->saveAutoLinkTrackSettings(settings); + }); + sortAutoMenu->addAction( tr("Song Editor -> Pattern Editor") + + (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern ? " *" :""), + this, [this, &settings, &mix]() + { + settings.sort = Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern; + mix->saveAutoLinkTrackSettings(settings); + updateAutoTrackSortOrder(); + }); + sortAutoMenu->addAction( tr("Pattern Editor - > Song Editor") + + (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::PatternLinked ? " *" :""), + this, [this, &settings, &mix]() + { + settings.sort = Mixer::autoTrackLinkSettings::AutoSort::PatternLinked; + mix->saveAutoLinkTrackSettings(settings); + updateAutoTrackSortOrder(); + }); + + patternEditorMenu->addAction( tr("Disabled") + + (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::Disabled ? " *" :""), + this, [&settings, &mix]() + { + settings.linkPatternEditor = Mixer::autoTrackLinkSettings::LinkPatternEditor::Disabled; + mix->saveAutoLinkTrackSettings(settings); + }); + patternEditorMenu->addAction( tr("Each separate") + + (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::Default ? " *" :""), + this, [&settings, &mix]() + { + settings.linkPatternEditor = Mixer::autoTrackLinkSettings::LinkPatternEditor::Default; + mix->saveAutoLinkTrackSettings(settings); + }); + patternEditorMenu->addAction( tr("Use first track channel") + + (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::UseFirstTrackOnly ? " *" :""), + this, [&settings, &mix]() + { + settings.linkPatternEditor = Mixer::autoTrackLinkSettings::LinkPatternEditor::UseFirstTrackOnly; + mix->saveAutoLinkTrackSettings(settings); + }); + +} + +void MixerView::updateAfterTrackAdd(Track * track, QString name, bool isPatternEditor) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); @@ -193,6 +301,26 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name) IntModel * model = mix->getChannelModelByTrack(track); if ( model != nullptr) { + + if (isPatternEditor) + { + if (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::Disabled) return; + + if (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::UseFirstTrackOnly) + { + auto trackList = Engine::patternStore()->tracks(); + if (!trackList.empty()) + { + IntModel * firstTrackModel = mix->getChannelModelByTrack(trackList.first()); + if ( firstTrackModel != nullptr) + { + model->setValue(firstTrackModel->value()); + } + } + return; + } + } + int channelIndex = addNewChannel(); model->setValue( channelIndex ); mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); @@ -263,6 +391,7 @@ void MixerView::setAutoTrackConstraints() m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); wasModified = true; } + m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); } if (wasModified) updateAutoTrackSortOrder(); } @@ -324,7 +453,7 @@ void MixerView::setAutoLinkTrackConfig(bool enabled) auto settings =mix->getAutoLinkTrackSettings(); settings.enabled = enabled; mix->saveAutoLinkTrackSettings(settings); - m_toogleAutoLinkTrackConfigBtn->setIcon(enabled ? embed::getIconPixmap( "exp_wave_active" ) : embed::getIconPixmap( "exp_wave_inactive" )); + m_toogleAutoLinkTrackConfigBtn->setIcon(enabled ? embed::getIconPixmap( "auto_link_active" ) : embed::getIconPixmap( "auto_link_inactive" )); setAutoTrackConstraints(); } @@ -354,11 +483,12 @@ int MixerView::addNewChannel() return newChannelIndex; } -void MixerView::updateAutoTrackSortOrder() +void MixerView::updateAutoTrackSortOrder(bool autoSort) { - Mixer * mix = Engine::mixer(); + Mixer * mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (!settings.enabled || settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; + if (!settings.enabled) return; + if (autoSort && settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; std::vector list(m_mixerChannelViews.size(), 0); @@ -381,8 +511,6 @@ void MixerView::updateAutoTrackSortOrder() list[c++] = model->value(); } }); - return; // ignore for now - // bubblesort here because the list is normally almost ordered bool swapped = false; diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 527e55f5609..477dad0329f 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -88,7 +88,7 @@ void PatternEditor::removeSteps() void PatternEditor::addSampleTrack() { Track * track = Track::create( Track::SampleTrack, model() ); - getGUI()->mixerView()->updateAfterTrackAdd(track); + getGUI()->mixerView()->updateAfterTrackAdd(track, "", true); } From dd139bf0e73b88c3f9d3cbdbefc115d06770d185 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sat, 11 Jun 2022 18:37:08 +0200 Subject: [PATCH 15/25] Refactored setttings - set inactive alpha --- data/themes/default/auto_link_inactive.png | Bin 820 -> 771 bytes include/Mixer.h | 34 +++- include/MixerView.h | 3 + src/core/Mixer.cpp | 61 ++++-- src/gui/MixerLine.cpp | 6 +- src/gui/MixerView.cpp | 222 ++++++++++++++------- 6 files changed, 226 insertions(+), 100 deletions(-) diff --git a/data/themes/default/auto_link_inactive.png b/data/themes/default/auto_link_inactive.png index 355edce5f990be95a735c0d7783b5b60154de3b4..83208784996ba3f01e2c960c5ecfa3e826d784f4 100644 GIT binary patch delta 689 zcmV;i0#5z327?BWUVo5DL_t(og}s+$T&J7bFlnwbgM0=mEkPz8p- zG0+40k}UGq0zsOa9sq%CviPkIw~`P?*rF4K{~)|ZmJ33ptREV z5t?d2j)fp6K!3jwjPEs%as8&_Z#d$n*YqTfbAZH?eP5F0J|;730lQ@Pnp2#>CFx2V zcQkR3JxNE9vo{s&HDlntq_ZL*;L37VkaL`9)q!TP-kSwvDojSNIgs=t@OuDk1Al?9 zvw%RxG38NKGg}8PB@NB22CPXs&AUHtiIMS7loXM@0Doi^cmdoovoDekakB|#_7Hf= zWcf}N#9NU`3GK+==qT{p0iFatQ4Tejl=)mB5Q|I!kQPpBLTfUa$b~>4h)iCPz`uh# ziY(nZ!3o;=G?4!=et3RE!7;$hD!2%3;ik2!-xn&frEI?q<0bwblTTP=3@FW_CksKM zqsi5MeSfzu4W=7gOYAL4Ah_~>Sr$+Q_of%wAe`cJfK+i6Sqe~vNnyH3b4&q=Y>b=q z=7zZn{@2qSGeAm9_6n{HBWw8gnWck7FumB?b{xnL&q>|4)bfvX<}Gk9cI^*v2DE^? zv1<#_p-6!nI0dfd*t0M}40}@pH{-T5{0sG(nJQsCkZ>Z{#ZCWfz$Grp`^3I9m2Lk3 XC$n6Y34<+v00000NkvXXu0mjf&uupg delta 738 zcmV<80v-K>2DAo{UVp(!L_t(og~gaXPgFq^hM!rmF^CZD5HXNoVo>bp{SK&$8Vm6U zSQ>waiLHrNCI%`2Ev&F3v7z8=mtf)tpq&^%V@!m+7Befu?0WB9xQi#*WbVv4o9CXH zdC%N2)X^k00ylsn& z7&6Ap)bPIwJodWY=_0)2prf22*7c#y_N$DNa~Zc zD5)f=H!@}*SbxCJ@?5}uz^|B$IN%ZBkk@^`ZVH?NG7L0(-DRM^G2b_0@X3AN^8;CD{alz*g2NliigTo7N9bT%3y0c3}c zNa~i<>e{W6y1lVp=kLeQyG&&Q>8bHXW&e#NHMvYoNje|IUvd7KK&lq7q#o=V@#pwE zR^q2Uzem7r&*u}c0(7ub<^k4$JI0u~XqXHjUBCnp8vv^#LunuYe+y+S2!PuyMXatQ z*#h=RnSTlbE;H`%{F3VJmv$bhDDogyk(;qoGK)R^kNT(oRFl*oX(DOY?3Wd=-!&(_ zzRJ`@RbN-F^D#-!gRESNjH~F#Vs1czo=j#0sl??1RA6U0Ux@*s`WWyV_?ZXHy7%0% z3y>&5i-qwuq}_eb>^n#WW<2P77y?P^#|mQIKwAKeqz2$Ma4H!40(`)pRoa5F+(BSl zfjh7Yd?X?!y4Ga10)V?8DPnH}lB^6|s|N^FSM3JiI@>o*M}e={S~E^?)0DUU0kDx} Uk+~%~X#fBK07*qoM6N<$g8ocZmjD0& diff --git a/include/Mixer.h b/include/Mixer.h index a54f555ad35..ce7d07e82f1 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -153,20 +153,33 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject PatternLinked /* pattern editor first, linked tracks afterwards */ }; - enum class LinkPatternEditor + enum class AutoAdd { - Disabled, /* do not link pattern editor tracks */ - Default, /* one channel for each pattern editor track */ - UseFirstTrackOnly, /* use always the first channel in the pattern editor for new tracks*/ + Disabled, /* do not link tracks after add */ + Separate, /* one channel for each track after add*/ + UseFirstTrackOnly, /* use always the first channel in the editor for new tracks*/ }; + enum class LinkMode + { + OneToOne, /* do not link song editor tracks */ + OneToMany, /* one channel for each song editor track */ + }; + + bool enabled; bool linkColor; bool linkName; - bool autoAdd; bool autoDelete; + LinkMode linkMode; AutoSort sort; - LinkPatternEditor linkPatternEditor; + AutoAdd autoAddPatternEditor; + AutoAdd autoAddSongEditor; + + bool autoAdd() + { + return autoAddSongEditor != AutoAdd::Disabled || autoAddPatternEditor != AutoAdd::Disabled; + } bool linkStyles() { @@ -188,9 +201,10 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject enabled = false; linkColor = true; linkName = true; - autoAdd = true; autoDelete = true; - linkPatternEditor = LinkPatternEditor::Default; + linkMode = LinkMode::OneToOne; + autoAddPatternEditor = AutoAdd::Separate; + autoAddSongEditor = AutoAdd::Separate; sort = AutoSort::Disabled; } }; @@ -259,6 +273,7 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject // process tracks assigned to a specific channel void processChannelTracks(MixerChannel * channel, std::function process); IntModel * getChannelModelByTrack(Track * track); + MixerChannel * getCustomChannelByTrack(Track * track); std::vector getUsedChannelCounts(); bool isAutoTrackLinkToggleAllowed(int index); //bool autoLinkTrackConfigEnabled(); @@ -284,7 +299,8 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject MixerRouteVector m_mixerRoutes; private: - static inline QString const AUTOTRACK_CONFIGPREFIX = "autoTrackLinkSettings"; + static inline QString const AUTOTRACK_CONFIGPREFIX = "settings"; + static inline QString const AUTOTRACK_CONFIGID = "AutoTrackLink"; // the mixer channels in the mixer. index 0 is always master. QVector m_mixerChannels; diff --git a/include/MixerView.h b/include/MixerView.h index e87901bdf5e..e2c43444a04 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -31,6 +31,7 @@ #include #include "ModelView.h" +#include "Mixer.h" #include "Engine.h" #include "Fader.h" #include "PixmapButton.h" @@ -150,6 +151,8 @@ private slots: void deleteChannelInternal(int index); void setAutoLinkTrackConfig(bool enabled); void setAutoTrackConstraints(); + void trackStyleToChannel(Track * track, MixerChannel * channel); + void channelStyleToTrack(MixerChannel * channel, Track * track); friend class MixerChannelView; } ; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index b1569e8376f..710b93a6b89 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -352,20 +352,33 @@ void Mixer::toggleAutoTrackLink(int index) } +//enabled = false; +//linkColor = true; +//linkName = true; +//autoDelete = true; +//linkMode = LinkMode::OneToOne; +//autoAddPatternEditor = AutoAddPatternEditor::Separate; +//autoAddSongEditor = AutoAddPatternEditor::Separate; +//sort = AutoSort::Disabled; + Mixer::autoTrackLinkSettings Mixer::getAutoLinkTrackSettings() { autoTrackLinkSettings settings; auto cfg = ConfigManager::inst(); - auto enabledAsString = cfg->value("ui", AUTOTRACK_CONFIGPREFIX); - if (enabledAsString != "") - { - settings.enabled = enabledAsString.toInt() == 1; - settings.linkName = (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_linkName").toInt() == 1); - settings.linkColor = (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_linkColor").toInt() == 1); - settings.autoAdd = (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_autoAdd").toInt() == 1); - settings.autoDelete = (cfg->value("ui",AUTOTRACK_CONFIGPREFIX+"_autoDelete").toInt() == 1); - settings.linkPatternEditor = (autoTrackLinkSettings::LinkPatternEditor) (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_linkPatternEditor").toInt()); - settings.sort = (autoTrackLinkSettings::AutoSort) (cfg->value("ui", AUTOTRACK_CONFIGPREFIX+"_sort").toInt()); + auto enabledAsString = cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX); + if (!enabledAsString.isEmpty()) + { + settings.enabled = enabledAsString.toInt(); + settings.linkColor = cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkColor").toInt(); + settings.linkName = cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkName").toInt(); + settings.autoDelete = cfg->value(AUTOTRACK_CONFIGID,AUTOTRACK_CONFIGPREFIX+"_autoDelete").toInt(); + settings.linkMode = (autoTrackLinkSettings::LinkMode) + (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkMode").toInt()); + settings.autoAddPatternEditor = (autoTrackLinkSettings::AutoAdd) + (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddPatternEditor").toInt()); + settings.autoAddSongEditor = (autoTrackLinkSettings::AutoAdd) + (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddSongEditor").toInt()); + settings.sort = (autoTrackLinkSettings::AutoSort) (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_sort").toInt()); } return settings; } @@ -373,13 +386,14 @@ Mixer::autoTrackLinkSettings Mixer::getAutoLinkTrackSettings() void Mixer::saveAutoLinkTrackSettings(autoTrackLinkSettings settings) { auto cfg = ConfigManager::inst(); - cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX, QString::number(settings.enabled)); - cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_linkName", QString::number(settings.linkName)); - cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_linkColor", QString::number(settings.linkColor)); - cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_autoAdd", QString::number(settings.autoAdd)); - cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_autoDelete", QString::number(settings.autoDelete)); - cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_linkPatternEditor", QString::number((int)settings.linkPatternEditor)); - cfg->setValue("ui", AUTOTRACK_CONFIGPREFIX+"_sort", QString::number((int)settings.sort)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX, QString::number(settings.enabled)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkColor", QString::number(settings.linkColor)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkName", QString::number(settings.linkName)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoDelete", QString::number(settings.autoDelete)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkMode", QString::number((int)settings.linkMode)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddPatternEditor", QString::number((int)settings.autoAddPatternEditor)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddSongEditor", QString::number((int)settings.autoAddSongEditor)); + cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_sort", QString::number((int)settings.sort)); cfg->saveConfigFile(); } @@ -399,6 +413,19 @@ IntModel * Mixer::getChannelModelByTrack(Track * track) return nullptr; } +MixerChannel * Mixer::getCustomChannelByTrack(Track * track) +{ + IntModel * model = getChannelModelByTrack(track); + if (model != nullptr) + { + int channelIndex = model->value(); + if (channelIndex>0) + { + return mixerChannel(channelIndex); + } + } + return nullptr; +} void Mixer::processChannelTracks(MixerChannel * channel, std::function process) { diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 69d7c235770..d681f5b1f50 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -302,8 +302,10 @@ void MixerLine::toogleAutoTrackLink() void MixerLine::autoTrackLinkChanged() { - auto channel = Engine::mixer()->mixerChannel( m_channelIndex ); - if (channel->m_autoTrackLinkModel.value()) + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + auto channel = mix->mixerChannel( m_channelIndex ); + if (settings.enabled && channel->m_autoTrackLinkModel.value()) { m_renameEditPalette.setColor(QPalette::Text,Qt::green); } diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index bf214db8d5a..90788213ef0 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -158,6 +158,7 @@ MixerView::MixerView() : bl->addWidget(m_autoLinkTrackSettingsBtn, 0, Qt::AlignTop ); m_toogleAutoLinkTrackConfigBtn = new QPushButton(this); + m_toogleAutoLinkTrackConfigBtn->setToolTip(tr("Enable/Disable auto track link")); connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL(clicked()), this, SLOT(toogleAutoLinkTrackConfig())); setAutoLinkTrackConfig(Engine::mixer()->getAutoLinkTrackSettings().enabled); bl->addWidget(m_toogleAutoLinkTrackConfigBtn, 0, Qt::AlignTop ); @@ -212,14 +213,17 @@ void MixerView::updateMenu() QMenu* sortMenu = toMenu->addMenu(tr("Sort")); QMenu* settingsMenu = toMenu->addMenu(tr("Settings")); - QMenu* linkTypeMenu = settingsMenu->addMenu(tr("Link type")); + QMenu* linkModeMenu = settingsMenu->addMenu(tr("Link mode")); + QMenu* linkStyleMenu = settingsMenu->addMenu(tr("Link style type")); QMenu* sortAutoMenu = settingsMenu->addMenu(tr("Automatic sorting")); - QMenu* patternEditorMenu = settingsMenu->addMenu(tr("Pattern Editor")); + QMenu* addAutoMenu = settingsMenu->addMenu(tr("Automatic add")); + QMenu* deleteAutoMenu = settingsMenu->addMenu(tr("Automatic delete")); + //QMenu* patternEditorMenu = settingsMenu->addMenu(tr("Pattern Editor")); auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - linkTypeMenu->addAction( tr("Name and color") + + linkStyleMenu->addAction( tr("Name and color") + (settings.linkNameAndColor() ? " *" :""), this, [&settings, &mix]() { @@ -227,7 +231,7 @@ void MixerView::updateMenu() settings.linkColor = true; mix->saveAutoLinkTrackSettings(settings); }); - linkTypeMenu->addAction( tr("Color only") + + linkStyleMenu->addAction( tr("Color only") + (settings.linkColorOnly() ? " *" :""), this, [&settings, &mix]() { @@ -236,6 +240,24 @@ void MixerView::updateMenu() mix->saveAutoLinkTrackSettings(settings); }); + linkModeMenu->addAction( tr("One track to one channel") + + (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne ? " *" :""), + this, [this, &settings, &mix]() + { + settings.linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToOne; + mix->saveAutoLinkTrackSettings(settings); + setAutoTrackConstraints(); + }); + linkModeMenu->addAction( tr("Multiple tracks to one channel") + + (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToMany ? " *" :""), + this, [this,&settings, &mix]() + { + settings.linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToMany; + mix->saveAutoLinkTrackSettings(settings); + setAutoTrackConstraints(); + }); + + sortMenu->addAction( tr("Song Editor -> Pattern Editor"), this, [this]() { updateAutoTrackSortOrder(false); @@ -245,8 +267,8 @@ void MixerView::updateMenu() updateAutoTrackSortOrder(false); }); - sortAutoMenu->addAction( - tr("Disabled") +(settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled ? " *" :""), + sortAutoMenu->addAction(tr("Disabled") + + (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled ? " *" :""), this, [&settings, &mix]() { settings.sort = Mixer::autoTrackLinkSettings::AutoSort::Disabled; @@ -269,25 +291,61 @@ void MixerView::updateMenu() updateAutoTrackSortOrder(); }); - patternEditorMenu->addAction( tr("Disabled") + - (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::Disabled ? " *" :""), + QAction * captionPatternEditor = addAutoMenu->addAction( "Pattern Editor" ); + captionPatternEditor->setEnabled( false ); + + addAutoMenu->addAction( tr("Disabled") + + (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled ? " *" :""), + this, [&settings, &mix]() + { + settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::Disabled; + mix->saveAutoLinkTrackSettings(settings); + }); + addAutoMenu->addAction( tr("Each separate") + + (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Separate ? " *" :""), + this, [&settings, &mix]() + { + settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::Separate; + mix->saveAutoLinkTrackSettings(settings); + }); + addAutoMenu->addAction( tr("Use first track's channel") + + (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly ? " *" :""), + this, [&settings, &mix]() + { + settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly; + mix->saveAutoLinkTrackSettings(settings); + }); + + QAction * captionSongEditor = addAutoMenu->addAction( "Song Editor" ); + captionSongEditor->setEnabled( false ); + + addAutoMenu->addAction( tr("Disabled") + + (settings.autoAddSongEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled ? " *" :""), this, [&settings, &mix]() { - settings.linkPatternEditor = Mixer::autoTrackLinkSettings::LinkPatternEditor::Disabled; + settings.autoAddSongEditor = Mixer::autoTrackLinkSettings::AutoAdd::Disabled; mix->saveAutoLinkTrackSettings(settings); }); - patternEditorMenu->addAction( tr("Each separate") + - (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::Default ? " *" :""), + addAutoMenu->addAction( tr("Each separate") + + (settings.autoAddSongEditor == Mixer::autoTrackLinkSettings::AutoAdd::Separate ? " *" :""), this, [&settings, &mix]() { - settings.linkPatternEditor = Mixer::autoTrackLinkSettings::LinkPatternEditor::Default; + settings.autoAddSongEditor = Mixer::autoTrackLinkSettings::AutoAdd::Separate; mix->saveAutoLinkTrackSettings(settings); }); - patternEditorMenu->addAction( tr("Use first track channel") + - (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::UseFirstTrackOnly ? " *" :""), + + deleteAutoMenu->addAction( tr("Disabled") + + (!settings.autoDelete ? " *" :""), this, [&settings, &mix]() { - settings.linkPatternEditor = Mixer::autoTrackLinkSettings::LinkPatternEditor::UseFirstTrackOnly; + settings.autoDelete = false; + mix->saveAutoLinkTrackSettings(settings); + }); + deleteAutoMenu->addAction( tr("Enabled") + + (settings.autoDelete ? " *" :""), + this, [&settings, &mix]() + { + settings.autoDelete = true; mix->saveAutoLinkTrackSettings(settings); }); @@ -297,24 +355,24 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name, bool isPatternE { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (!settings.enabled || !settings.autoAdd) return; + if (!settings.enabled || !settings.autoAdd()) return; IntModel * model = mix->getChannelModelByTrack(track); if ( model != nullptr) { if (isPatternEditor) { - if (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::Disabled) return; + if (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled) return; - if (settings.linkPatternEditor == Mixer::autoTrackLinkSettings::LinkPatternEditor::UseFirstTrackOnly) + if (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly) { auto trackList = Engine::patternStore()->tracks(); if (!trackList.empty()) { - IntModel * firstTrackModel = mix->getChannelModelByTrack(trackList.first()); - if ( firstTrackModel != nullptr) + auto channel = mix->getCustomChannelByTrack(trackList.first()); + if (channel != nullptr) { - model->setValue(firstTrackModel->value()); + model->setValue(channel->m_channelIndex); } } return; @@ -334,32 +392,53 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name, bool isPatternE } } +void MixerView::trackStyleToChannel(Track * track, MixerChannel * channel) +{ + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (settings.linkName) + { + channel->m_name = track->name(); + } + if (settings.linkColor) + { + channel->setColor (track->color()); + channel->m_hasColor = track->useColor(); + } +} + +void MixerView::channelStyleToTrack(MixerChannel * channel, Track * track) +{ + auto mix = Engine::mixer(); + auto settings =mix->getAutoLinkTrackSettings(); + if (settings.linkName) + { + track->setName(channel->m_name); + } + if (settings.linkColor) + { + track->setColor(channel->m_color); + if (!channel->m_hasColor) track->resetColor(); + } +} + void MixerView::updateAfterTrackStyleModify(Track * track) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); if (!settings.enabled || !settings.linkStyles()) return; - IntModel * model = mix->getChannelModelByTrack(track); - if (model != nullptr) + auto channel = mix->getCustomChannelByTrack(track); + if (channel != nullptr && channel->m_autoTrackLinkModel.value()) { - int channelIndex = model->value(); - if (channelIndex>0) - { - MixerChannel * channel = mix->mixerChannel(channelIndex); - if (channel->m_autoTrackLinkModel.value()) + trackStyleToChannel(track, channel); + mix->processAssignedTracks([this, channel](Track * otherTrack, IntModel * model, MixerChannel *) + mutable { + if (model->value() == channel->m_channelIndex) { - if (settings.linkName) - { - channel->m_name = track->name(); - } - if (settings.linkColor) - { - channel->setColor (track->color()); - channel->m_hasColor = track->useColor(); - } - setCurrentMixerLine(channelIndex); + channelStyleToTrack(channel, otherTrack); } - } + }); + setCurrentMixerLine(channel->m_channelIndex); } } @@ -384,8 +463,9 @@ void MixerView::setAutoTrackConstraints() bool wasModified = false; for(unsigned long i = 0; i < usedChannelCounts.size(); i++) { - // no more linked tracks or too many linked tracks (if name linking is enabled) - if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && settings.linkName)) + // no more linked tracks or too many linked tracks + if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && + settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne)) { mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); @@ -393,6 +473,16 @@ void MixerView::setAutoTrackConstraints() } m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); } + mix->processAssignedTracks([this](Track * track, IntModel *, MixerChannel * channel) + mutable { + if (channel != nullptr) + { + if (channel->m_autoTrackLinkModel.value()) + { + channelStyleToTrack(channel, track); + } + } + }); if (wasModified) updateAutoTrackSortOrder(); } @@ -401,18 +491,10 @@ void MixerView::updateAfterTrackMove(Track * track) auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); if (!settings.enabled || settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; - IntModel * model = mix->getChannelModelByTrack(track); - if (model != nullptr) + auto channel = mix->getCustomChannelByTrack(track); + if (channel != nullptr && channel->m_autoTrackLinkModel.value()) { - int channelIndex = model->value(); - if (channelIndex>0) - { - MixerChannel * channel = mix->mixerChannel(channelIndex); - if (channel->m_autoTrackLinkModel.value()) - { - updateAutoTrackSortOrder(); - } - } + updateAutoTrackSortOrder(); } } @@ -421,28 +503,24 @@ void MixerView::updateAfterTrackDelete(Track * track) auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); if (!settings.enabled) return; - IntModel * model = mix->getChannelModelByTrack(track); - if ( model != nullptr) + if (!settings.autoDelete) + { + setAutoTrackConstraints(); + return; + } + auto channel = mix->getCustomChannelByTrack(track); + if (channel != nullptr && channel->m_autoTrackLinkModel.value()) { - int channelIndex = model->value(); - if (channelIndex>0) + bool shouldDelete = true; + if (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToMany) { - MixerChannel * channel = mix->mixerChannel(channelIndex); - if (channel->m_autoTrackLinkModel.value()) - { - bool shouldDelete = true; - if (!settings.linkName) - { - // if we don't have a 1.1 name link we make sure that no track is left. - std::vector usedChannelCounts = mix->getUsedChannelCounts(); - shouldDelete = usedChannelCounts[channelIndex] == 0; - } - if (shouldDelete) - { - deleteChannel(channelIndex); - updateAutoTrackSortOrder(); - } - } + std::vector usedChannelCounts = mix->getUsedChannelCounts(); + shouldDelete = usedChannelCounts[channel->m_channelIndex] == 0; + } + if (shouldDelete) + { + deleteChannel(channel->m_channelIndex); + updateAutoTrackSortOrder(); } } } From e2c49caaee3959097a31bbba1601ec3d387ece26 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sun, 12 Jun 2022 12:19:30 +0200 Subject: [PATCH 16/25] fixed settings menu - lambda capture for settings behaves strange --- include/Mixer.h | 35 ++++++++++++++++++++ include/MixerView.h | 1 + src/core/Mixer.cpp | 29 ++++++++++------- src/gui/MixerView.cpp | 76 +++++++++++++++++++++++++++++-------------- 4 files changed, 105 insertions(+), 36 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index ce7d07e82f1..275108d509e 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -196,6 +196,31 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject return linkColor && !linkName; } + bool getAsBoolOrDefault(const QString & text, bool defaultValue) + { + return (bool)getIntInRangeOrDefault(text, 0,1,defaultValue); + } + + LinkMode getAsLinkModeOrCurrent(const QString & text) + { + return (LinkMode) getIntInRangeOrDefault(text,(int)LinkMode::OneToOne, (int)LinkMode::OneToMany,(int)linkMode); + } + + AutoSort getAsAutoSortOrCurrent(const QString & text) + { + return (AutoSort) getIntInRangeOrDefault(text,(int)AutoSort::Disabled, (int)AutoSort::PatternLinked,(int)sort); + } + + AutoAdd getAsAutoAddPatternEditorOrCurrent(const QString & text) + { + return (AutoAdd) getIntInRangeOrDefault(text,(int)AutoAdd::Disabled, (int)AutoAdd::UseFirstTrackOnly,(int)autoAddPatternEditor); + } + + AutoAdd getAsAutoAddSongEditorOrCurrent(const QString & text) + { + return (AutoAdd) getIntInRangeOrDefault(text,(int)AutoAdd::Disabled, (int)AutoAdd::Separate,(int)autoAddSongEditor); + } + autoTrackLinkSettings() { enabled = false; @@ -207,6 +232,16 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject autoAddSongEditor = AutoAdd::Separate; sort = AutoSort::Disabled; } + + private: + int getIntInRangeOrDefault(const QString & text, int lower, int upper, int defaultValue) + { + if (text == nullptr || text.isEmpty()) return defaultValue; + auto asInt = text.toInt(); + if (asInt < lower || asInt >upper) return defaultValue; + return asInt; + } + }; diff --git a/include/MixerView.h b/include/MixerView.h index e2c43444a04..c285ad61349 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -150,6 +150,7 @@ private slots: void updateAutoTrackSortOrder(bool autoSort = true); void deleteChannelInternal(int index); void setAutoLinkTrackConfig(bool enabled); + void updateAutoLinkTrackConfigBtn(bool enabled); void setAutoTrackConstraints(); void trackStyleToChannel(Track * track, MixerChannel * channel); void channelStyleToTrack(MixerChannel * channel, Track * track); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 710b93a6b89..07809bb9c12 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -363,22 +363,27 @@ void Mixer::toggleAutoTrackLink(int index) Mixer::autoTrackLinkSettings Mixer::getAutoLinkTrackSettings() { - autoTrackLinkSettings settings; + autoTrackLinkSettings settings = autoTrackLinkSettings(); auto cfg = ConfigManager::inst(); auto enabledAsString = cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX); if (!enabledAsString.isEmpty()) { - settings.enabled = enabledAsString.toInt(); - settings.linkColor = cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkColor").toInt(); - settings.linkName = cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkName").toInt(); - settings.autoDelete = cfg->value(AUTOTRACK_CONFIGID,AUTOTRACK_CONFIGPREFIX+"_autoDelete").toInt(); - settings.linkMode = (autoTrackLinkSettings::LinkMode) - (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkMode").toInt()); - settings.autoAddPatternEditor = (autoTrackLinkSettings::AutoAdd) - (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddPatternEditor").toInt()); - settings.autoAddSongEditor = (autoTrackLinkSettings::AutoAdd) - (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddSongEditor").toInt()); - settings.sort = (autoTrackLinkSettings::AutoSort) (cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_sort").toInt()); + settings.enabled = settings.getAsBoolOrDefault( + enabledAsString, settings.enabled); + settings.linkColor =settings.getAsBoolOrDefault( + cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkColor"),settings.linkColor); + settings.linkName = settings.getAsBoolOrDefault( + cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkName"),settings.linkName); + settings.autoDelete = settings.getAsBoolOrDefault( + cfg->value(AUTOTRACK_CONFIGID,AUTOTRACK_CONFIGPREFIX+"_autoDelete"),settings.autoDelete); + settings.linkMode = settings.getAsLinkModeOrCurrent( + cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkMode")); + settings.autoAddPatternEditor = settings.getAsAutoAddPatternEditorOrCurrent( + cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddPatternEditor")); + settings.autoAddSongEditor = settings.getAsAutoAddSongEditorOrCurrent( + cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddSongEditor")); + settings.sort = settings.getAsAutoSortOrCurrent( + cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_sort")); } return settings; } diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 90788213ef0..c5209353a85 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -160,7 +160,7 @@ MixerView::MixerView() : m_toogleAutoLinkTrackConfigBtn = new QPushButton(this); m_toogleAutoLinkTrackConfigBtn->setToolTip(tr("Enable/Disable auto track link")); connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL(clicked()), this, SLOT(toogleAutoLinkTrackConfig())); - setAutoLinkTrackConfig(Engine::mixer()->getAutoLinkTrackSettings().enabled); + updateAutoLinkTrackConfigBtn(Engine::mixer()->getAutoLinkTrackSettings().enabled); bl->addWidget(m_toogleAutoLinkTrackConfigBtn, 0, Qt::AlignTop ); @@ -190,6 +190,8 @@ MixerView::MixerView() : // we want to receive dataChanged-signals in order to update setModel( m ); + + setAutoTrackConstraints(); } MixerView::~MixerView() @@ -221,20 +223,23 @@ void MixerView::updateMenu() //QMenu* patternEditorMenu = settingsMenu->addMenu(tr("Pattern Editor")); auto mix = Engine::mixer(); - auto settings =mix->getAutoLinkTrackSettings(); + // remark: capturing "settings" (also as pointer) does not work as expected + auto settings = mix->getAutoLinkTrackSettings(); linkStyleMenu->addAction( tr("Name and color") + (settings.linkNameAndColor() ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.linkName = true; settings.linkColor = true; mix->saveAutoLinkTrackSettings(settings); }); linkStyleMenu->addAction( tr("Color only") + (settings.linkColorOnly() ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.linkName = false; settings.linkColor = true; mix->saveAutoLinkTrackSettings(settings); @@ -242,16 +247,18 @@ void MixerView::updateMenu() linkModeMenu->addAction( tr("One track to one channel") + (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne ? " *" :""), - this, [this, &settings, &mix]() + this, [this, mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToOne; mix->saveAutoLinkTrackSettings(settings); setAutoTrackConstraints(); }); linkModeMenu->addAction( tr("Multiple tracks to one channel") + (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToMany ? " *" :""), - this, [this,&settings, &mix]() + this, [this, mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToMany; mix->saveAutoLinkTrackSettings(settings); setAutoTrackConstraints(); @@ -269,23 +276,26 @@ void MixerView::updateMenu() sortAutoMenu->addAction(tr("Disabled") + (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.sort = Mixer::autoTrackLinkSettings::AutoSort::Disabled; mix->saveAutoLinkTrackSettings(settings); }); sortAutoMenu->addAction( tr("Song Editor -> Pattern Editor") + (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern ? " *" :""), - this, [this, &settings, &mix]() + this, [this, mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.sort = Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern; mix->saveAutoLinkTrackSettings(settings); updateAutoTrackSortOrder(); }); sortAutoMenu->addAction( tr("Pattern Editor - > Song Editor") + (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::PatternLinked ? " *" :""), - this, [this, &settings, &mix]() + this, [this, mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.sort = Mixer::autoTrackLinkSettings::AutoSort::PatternLinked; mix->saveAutoLinkTrackSettings(settings); updateAutoTrackSortOrder(); @@ -296,22 +306,25 @@ void MixerView::updateMenu() addAutoMenu->addAction( tr("Disabled") + (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::Disabled; mix->saveAutoLinkTrackSettings(settings); }); addAutoMenu->addAction( tr("Each separate") + (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Separate ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::Separate; mix->saveAutoLinkTrackSettings(settings); }); addAutoMenu->addAction( tr("Use first track's channel") + (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly; mix->saveAutoLinkTrackSettings(settings); }); @@ -321,30 +334,34 @@ void MixerView::updateMenu() addAutoMenu->addAction( tr("Disabled") + (settings.autoAddSongEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.autoAddSongEditor = Mixer::autoTrackLinkSettings::AutoAdd::Disabled; mix->saveAutoLinkTrackSettings(settings); }); addAutoMenu->addAction( tr("Each separate") + (settings.autoAddSongEditor == Mixer::autoTrackLinkSettings::AutoAdd::Separate ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.autoAddSongEditor = Mixer::autoTrackLinkSettings::AutoAdd::Separate; mix->saveAutoLinkTrackSettings(settings); }); deleteAutoMenu->addAction( tr("Disabled") + (!settings.autoDelete ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.autoDelete = false; mix->saveAutoLinkTrackSettings(settings); }); deleteAutoMenu->addAction( tr("Enabled") + (settings.autoDelete ? " *" :""), - this, [&settings, &mix]() + this, [mix]() { + auto settings = mix->getAutoLinkTrackSettings(); settings.autoDelete = true; mix->saveAutoLinkTrackSettings(settings); }); @@ -458,21 +475,27 @@ void MixerView::setAutoTrackConstraints() { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (!settings.enabled) return; std::vector usedChannelCounts = mix->getUsedChannelCounts(); bool wasModified = false; for(unsigned long i = 0; i < usedChannelCounts.size(); i++) { - // no more linked tracks or too many linked tracks - if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && - settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne)) + if (settings.enabled) { - mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); - m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); - wasModified = true; + // no more linked tracks or too many linked tracks + if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && + settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne)) + { + mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); + m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); + wasModified = true; + } } + // update mixer lines in both cases (enabling/disabling) m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); } + if (!settings.enabled) return; + + // make sure that the tracks are updated according to the auto link settings mix->processAssignedTracks([this](Track * track, IntModel *, MixerChannel * channel) mutable { if (channel != nullptr) @@ -529,12 +552,17 @@ void MixerView::setAutoLinkTrackConfig(bool enabled) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); + updateAutoLinkTrackConfigBtn(enabled); settings.enabled = enabled; mix->saveAutoLinkTrackSettings(settings); - m_toogleAutoLinkTrackConfigBtn->setIcon(enabled ? embed::getIconPixmap( "auto_link_active" ) : embed::getIconPixmap( "auto_link_inactive" )); setAutoTrackConstraints(); } +void MixerView::updateAutoLinkTrackConfigBtn(bool enabled) +{ + m_toogleAutoLinkTrackConfigBtn->setIcon(enabled ? embed::getIconPixmap( "auto_link_active" ) : embed::getIconPixmap( "auto_link_inactive" )); +} + void MixerView::toogleAutoLinkTrackConfig() { auto mix = Engine::mixer(); From f8cec55fe095bb4a033d6f0e6c49c1275cd90cd9 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sun, 12 Jun 2022 17:35:47 +0200 Subject: [PATCH 17/25] refactored settings menu - reduced redundancy --- include/Mixer.h | 100 +++++++---- include/MixerView.h | 24 ++- src/core/Mixer.cpp | 88 ++++------ src/gui/MixerView.cpp | 265 ++++++++++++++---------------- src/gui/editors/PatternEditor.cpp | 2 +- 5 files changed, 243 insertions(+), 236 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 275108d509e..f2002af6447 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -25,6 +25,7 @@ #ifndef MIXER_H #define MIXER_H +#include "ConfigManager.h" #include "Model.h" #include "Track.h" #include "EffectChain.h" @@ -146,11 +147,12 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject public: struct autoTrackLinkSettings { - enum class AutoSort + // Remark: take care of the enum order as it is used for range checking during reading the values from config + enum class LinkStyle { - Disabled, /* automatic sorting is disabled */ - LinkedPattern, /* linked tracks first, pattern editor afterwards */ - PatternLinked /* pattern editor first, linked tracks afterwards */ + Disabled, /* don't link any styles */ + LinkNameAndColor, /* link namd and color */ + LinkColorOnly, /* link only color */ }; enum class AutoAdd @@ -166,71 +168,92 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject OneToMany, /* one channel for each song editor track */ }; + enum class AutoSort + { + Disabled, /* automatic sorting is disabled */ + LinkedPattern, /* linked tracks first, pattern editor afterwards */ + PatternLinked /* pattern editor first, linked tracks afterwards */ + }; + + + struct editorSettings + { + LinkStyle linkStyle; + AutoAdd autoAdd; + + editorSettings() + { + linkStyle = LinkStyle::LinkNameAndColor; + autoAdd = AutoAdd::Separate; + } + }; + bool enabled; - bool linkColor; - bool linkName; bool autoDelete; LinkMode linkMode; - AutoSort sort; - AutoAdd autoAddPatternEditor; - AutoAdd autoAddSongEditor; + AutoSort autoSort; + editorSettings songEditor; + editorSettings patternEditor; - bool autoAdd() + bool getAsBoolOrDefault(const QString & text, bool defaultValue) { - return autoAddSongEditor != AutoAdd::Disabled || autoAddPatternEditor != AutoAdd::Disabled; + return (bool)getIntInRangeOrDefault(text, 0,1,defaultValue); } - bool linkStyles() + + AutoAdd getAsAutoAddOrDefault(const QString & text, AutoAdd defaultValue) { - return linkColor || linkName; + return (AutoAdd) getIntInRangeOrDefault(text,(int)AutoAdd::Disabled, (int)AutoAdd::UseFirstTrackOnly,(int)defaultValue); } - bool linkNameAndColor() + LinkStyle getAsLinkStyleOrDefault(const QString & text, LinkStyle defaultValue) { - return linkColor && linkName; + return (LinkStyle) getIntInRangeOrDefault(text,(int)LinkStyle::Disabled, (int)LinkStyle::LinkColorOnly,(int)defaultValue); } - bool linkColorOnly() + AutoSort getAsAutoSortOrDefault(const QString & text, AutoSort defaultValue) { - return linkColor && !linkName; + return (AutoSort) getIntInRangeOrDefault(text,(int)AutoSort::Disabled, (int)AutoSort::PatternLinked,(int)defaultValue); } - bool getAsBoolOrDefault(const QString & text, bool defaultValue) + + LinkMode getAsLinkModeOrDefault(const QString & text, LinkMode defaultValue) { - return (bool)getIntInRangeOrDefault(text, 0,1,defaultValue); + return (LinkMode) getIntInRangeOrDefault(text,(int)LinkMode::OneToOne, (int)LinkMode::OneToMany,(int)defaultValue); } - LinkMode getAsLinkModeOrCurrent(const QString & text) + bool autoAdd() { - return (LinkMode) getIntInRangeOrDefault(text,(int)LinkMode::OneToOne, (int)LinkMode::OneToMany,(int)linkMode); + return songEditor.autoAdd != AutoAdd::Disabled || patternEditor.autoAdd != AutoAdd::Disabled; } - AutoSort getAsAutoSortOrCurrent(const QString & text) + + bool linkName(bool isPatternEditor) { - return (AutoSort) getIntInRangeOrDefault(text,(int)AutoSort::Disabled, (int)AutoSort::PatternLinked,(int)sort); + return isPatternEditor ? + patternEditor.linkStyle == LinkStyle::LinkNameAndColor : + songEditor.linkStyle == LinkStyle::LinkNameAndColor; } - AutoAdd getAsAutoAddPatternEditorOrCurrent(const QString & text) + bool linkColor(bool isPatternEditor) { - return (AutoAdd) getIntInRangeOrDefault(text,(int)AutoAdd::Disabled, (int)AutoAdd::UseFirstTrackOnly,(int)autoAddPatternEditor); + return isPatternEditor ? + (patternEditor.linkStyle == LinkStyle::LinkNameAndColor) || (patternEditor.linkStyle == LinkStyle::LinkColorOnly) : + (songEditor.linkStyle == LinkStyle::LinkNameAndColor) || (songEditor.linkStyle == LinkStyle::LinkColorOnly); } - AutoAdd getAsAutoAddSongEditorOrCurrent(const QString & text) + bool linkAnyStyles() { - return (AutoAdd) getIntInRangeOrDefault(text,(int)AutoAdd::Disabled, (int)AutoAdd::Separate,(int)autoAddSongEditor); + return patternEditor.linkStyle != LinkStyle::Disabled || songEditor.linkStyle != LinkStyle::Disabled; } autoTrackLinkSettings() { enabled = false; - linkColor = true; - linkName = true; autoDelete = true; linkMode = LinkMode::OneToOne; - autoAddPatternEditor = AutoAdd::Separate; - autoAddSongEditor = AutoAdd::Separate; - sort = AutoSort::Disabled; + autoSort = AutoSort::Disabled; } private: @@ -334,8 +357,17 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject MixerRouteVector m_mixerRoutes; private: - static inline QString const AUTOTRACK_CONFIGPREFIX = "settings"; - static inline QString const AUTOTRACK_CONFIGID = "AutoTrackLink"; + + inline const QString & getAutoTrackCfg(ConfigManager * cfg, const QString & postFix) + { + return cfg->value("AutoTrackLink", "settings_"+postFix); + } + + inline void setAutoTrackCfg(ConfigManager * cfg, const QString & postFix, int value) + { + cfg->setValue("AutoTrackLink", "settings_"+postFix, QString::number(value)); + } + // the mixer channels in the mixer. index 0 is always master. QVector m_mixerChannels; diff --git a/include/MixerView.h b/include/MixerView.h index c285ad61349..216a9670cfe 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -25,6 +25,7 @@ #ifndef MIXER_VIEW_H #define MIXER_VIEW_H +#include #include #include #include @@ -112,7 +113,7 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, void refreshDisplay(); // Auto track link support - void updateAfterTrackAdd(Track * track, QString name = "", bool isPatternEditor = false); + void updateAfterTrackAdd(Track * track, QString name = ""); void updateAfterTrackStyleModify(Track * track); void updateAfterTrackMixerLineModify(Track * track); void updateAfterTrackMove(Track * track); @@ -129,10 +130,26 @@ public slots: private slots: void updateFaders(); void toggledSolo(); - void updateMenu(); + void updateAutoTrackLinkMenu(); void toogleAutoLinkTrackConfig(); private: + + + +// inline const QString autoTrackMenuText(const QString text, bool enabled) +// { +// return text + (enabled ? " *" :""); +// } + +// inline void setAutoTrackLinkValue(Mixer * mix, std::function setValue) +// { +// auto settings = mix->getAutoLinkTrackSettings(); +// setValue(settings); +// mix->saveAutoLinkTrackSettings(settings); +// } + + QVector m_mixerChannelViews; MixerLine * m_currentMixerLine; @@ -154,6 +171,9 @@ private slots: void setAutoTrackConstraints(); void trackStyleToChannel(Track * track, MixerChannel * channel); void channelStyleToTrack(MixerChannel * channel, Track * track); + void addAutoLinkTrackMenuEntry(QMenu* menu, const QString &text, bool state, + std::function setValue, + std::function after = nullptr); friend class MixerChannelView; } ; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 07809bb9c12..d93a3699aff 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -352,55 +352,6 @@ void Mixer::toggleAutoTrackLink(int index) } -//enabled = false; -//linkColor = true; -//linkName = true; -//autoDelete = true; -//linkMode = LinkMode::OneToOne; -//autoAddPatternEditor = AutoAddPatternEditor::Separate; -//autoAddSongEditor = AutoAddPatternEditor::Separate; -//sort = AutoSort::Disabled; - -Mixer::autoTrackLinkSettings Mixer::getAutoLinkTrackSettings() -{ - autoTrackLinkSettings settings = autoTrackLinkSettings(); - auto cfg = ConfigManager::inst(); - auto enabledAsString = cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX); - if (!enabledAsString.isEmpty()) - { - settings.enabled = settings.getAsBoolOrDefault( - enabledAsString, settings.enabled); - settings.linkColor =settings.getAsBoolOrDefault( - cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkColor"),settings.linkColor); - settings.linkName = settings.getAsBoolOrDefault( - cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkName"),settings.linkName); - settings.autoDelete = settings.getAsBoolOrDefault( - cfg->value(AUTOTRACK_CONFIGID,AUTOTRACK_CONFIGPREFIX+"_autoDelete"),settings.autoDelete); - settings.linkMode = settings.getAsLinkModeOrCurrent( - cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkMode")); - settings.autoAddPatternEditor = settings.getAsAutoAddPatternEditorOrCurrent( - cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddPatternEditor")); - settings.autoAddSongEditor = settings.getAsAutoAddSongEditorOrCurrent( - cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddSongEditor")); - settings.sort = settings.getAsAutoSortOrCurrent( - cfg->value(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_sort")); - } - return settings; -} - -void Mixer::saveAutoLinkTrackSettings(autoTrackLinkSettings settings) -{ - auto cfg = ConfigManager::inst(); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX, QString::number(settings.enabled)); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkColor", QString::number(settings.linkColor)); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkName", QString::number(settings.linkName)); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoDelete", QString::number(settings.autoDelete)); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_linkMode", QString::number((int)settings.linkMode)); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddPatternEditor", QString::number((int)settings.autoAddPatternEditor)); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_autoAddSongEditor", QString::number((int)settings.autoAddSongEditor)); - cfg->setValue(AUTOTRACK_CONFIGID, AUTOTRACK_CONFIGPREFIX+"_sort", QString::number((int)settings.sort)); - cfg->saveConfigFile(); -} IntModel * Mixer::getChannelModelByTrack(Track * track) @@ -450,11 +401,10 @@ bool Mixer::isAutoTrackLinkToggleAllowed(int index) auto settings =mix->getAutoLinkTrackSettings(); if (!settings.enabled) return false; if (mixerChannel( index )->m_autoTrackLinkModel.value()) return true; - if (settings.linkName) - { - std::vector usedChannelCounts = getUsedChannelCounts(); - return usedChannelCounts[index] == 1; - } + std::vector usedChannelCounts = getUsedChannelCounts(); + return settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne ? + usedChannelCounts[index] == 1 : + usedChannelCounts[index] >= 1; return true; } @@ -840,6 +790,36 @@ void Mixer::clearChannel(mix_ch_t index) } } +Mixer::autoTrackLinkSettings Mixer::getAutoLinkTrackSettings() +{ + autoTrackLinkSettings settings = autoTrackLinkSettings(); + auto cfg = ConfigManager::inst(); + settings.enabled = settings.getAsBoolOrDefault(Mixer::getAutoTrackCfg(cfg,""), settings.enabled); + settings.autoDelete = settings.getAsBoolOrDefault(Mixer::getAutoTrackCfg(cfg,"autoDelete"), settings.autoDelete); + settings.autoSort = settings.getAsAutoSortOrDefault(Mixer::getAutoTrackCfg(cfg,"autoSort"), settings.autoSort); + settings.linkMode = settings.getAsLinkModeOrDefault(Mixer::getAutoTrackCfg(cfg,"linkMode"), settings.linkMode); + settings.patternEditor.autoAdd = settings.getAsAutoAddOrDefault(Mixer::getAutoTrackCfg(cfg,"pe_autoAdd"), settings.patternEditor.autoAdd); + settings.patternEditor.linkStyle = settings.getAsLinkStyleOrDefault(Mixer::getAutoTrackCfg(cfg,"pe_linkStyle"), settings.patternEditor.linkStyle); + settings.songEditor.autoAdd = settings.getAsAutoAddOrDefault(Mixer::getAutoTrackCfg(cfg,"se_autoAdd"), settings.songEditor.autoAdd); + settings.songEditor.linkStyle = settings.getAsLinkStyleOrDefault(Mixer::getAutoTrackCfg(cfg,"se_linkStyle"), settings.songEditor.linkStyle); + return settings; +} + +void Mixer::saveAutoLinkTrackSettings(autoTrackLinkSettings settings) +{ + auto cfg = ConfigManager::inst(); + Mixer::setAutoTrackCfg(cfg,"", settings.enabled); + Mixer::setAutoTrackCfg(cfg,"autoDelete", settings.autoDelete); + Mixer::setAutoTrackCfg(cfg,"autoSort", (int)settings.autoSort); + Mixer::setAutoTrackCfg(cfg,"linkMode", (int)settings.linkMode); + Mixer::setAutoTrackCfg(cfg,"pe_autoAdd", (int)settings.patternEditor.autoAdd); + Mixer::setAutoTrackCfg(cfg,"pe_linkStyle", (int)settings.patternEditor.linkStyle); + Mixer::setAutoTrackCfg(cfg,"se_autoAdd", (int)settings.songEditor.autoAdd); + Mixer::setAutoTrackCfg(cfg,"se_linkStyle", (int)settings.songEditor.linkStyle); + cfg->saveConfigFile(); +} + + void Mixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) { // save channels diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index c5209353a85..213f8a40d05 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -148,7 +148,7 @@ MixerView::MixerView() : QMenu * toMenu = new QMenu(this ); toMenu->setFont( pointSize<9>( toMenu->font() ) ); - connect( toMenu, SIGNAL( aboutToShow() ), this, SLOT( updateMenu() ) ); + connect( toMenu, SIGNAL( aboutToShow() ), this, SLOT( updateAutoTrackLinkMenu() ) ); m_autoLinkTrackSettingsBtn = new QPushButton(embed::getIconPixmap( "trackop" ),QString(), this); m_autoLinkTrackSettingsBtn->move( 12, 1 ); @@ -158,7 +158,7 @@ MixerView::MixerView() : bl->addWidget(m_autoLinkTrackSettingsBtn, 0, Qt::AlignTop ); m_toogleAutoLinkTrackConfigBtn = new QPushButton(this); - m_toogleAutoLinkTrackConfigBtn->setToolTip(tr("Enable/Disable auto track link")); + m_toogleAutoLinkTrackConfigBtn->setToolTip(tr("Enable/Disable auto track linking")); connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL(clicked()), this, SLOT(toogleAutoLinkTrackConfig())); updateAutoLinkTrackConfigBtn(Engine::mixer()->getAutoLinkTrackSettings().enabled); bl->addWidget(m_toogleAutoLinkTrackConfigBtn, 0, Qt::AlignTop ); @@ -202,8 +202,23 @@ MixerView::~MixerView() } } +void MixerView::addAutoLinkTrackMenuEntry(QMenu* menu, + const QString &text, bool state, std::function setValue, std::function after) +{ + menu->addAction( text + + (state ? " *" :""), + this, [setValue, after]() + { + auto mix = Engine::mixer(); + auto settings = mix->getAutoLinkTrackSettings(); + setValue(&settings); + mix->saveAutoLinkTrackSettings(settings); + if (after != nullptr) after(); + }); +} + -void MixerView::updateMenu() +void MixerView::updateAutoTrackLinkMenu() { QMenu* toMenu = m_autoLinkTrackSettingsBtn->menu(); toMenu->clear(); @@ -212,7 +227,7 @@ void MixerView::updateMenu() QAction * captionMain = toMenu->addAction( "Auto track linking" ); captionMain->setEnabled( false ); - QMenu* sortMenu = toMenu->addMenu(tr("Sort")); + QMenu* sortMenu = toMenu->addMenu(tr("Sort linked channels")); QMenu* settingsMenu = toMenu->addMenu(tr("Settings")); QMenu* linkModeMenu = settingsMenu->addMenu(tr("Link mode")); @@ -226,45 +241,7 @@ void MixerView::updateMenu() // remark: capturing "settings" (also as pointer) does not work as expected auto settings = mix->getAutoLinkTrackSettings(); - linkStyleMenu->addAction( tr("Name and color") + - (settings.linkNameAndColor() ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.linkName = true; - settings.linkColor = true; - mix->saveAutoLinkTrackSettings(settings); - }); - linkStyleMenu->addAction( tr("Color only") + - (settings.linkColorOnly() ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.linkName = false; - settings.linkColor = true; - mix->saveAutoLinkTrackSettings(settings); - }); - - linkModeMenu->addAction( tr("One track to one channel") + - (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne ? " *" :""), - this, [this, mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToOne; - mix->saveAutoLinkTrackSettings(settings); - setAutoTrackConstraints(); - }); - linkModeMenu->addAction( tr("Multiple tracks to one channel") + - (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToMany ? " *" :""), - this, [this, mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToMany; - mix->saveAutoLinkTrackSettings(settings); - setAutoTrackConstraints(); - }); - - + // immediate sort action menu sortMenu->addAction( tr("Song Editor -> Pattern Editor"), this, [this]() { updateAutoTrackSortOrder(false); @@ -274,101 +251,92 @@ void MixerView::updateMenu() updateAutoTrackSortOrder(false); }); - sortAutoMenu->addAction(tr("Disabled") + - (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.sort = Mixer::autoTrackLinkSettings::AutoSort::Disabled; - mix->saveAutoLinkTrackSettings(settings); - }); - sortAutoMenu->addAction( tr("Song Editor -> Pattern Editor") + - (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern ? " *" :""), - this, [this, mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.sort = Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern; - mix->saveAutoLinkTrackSettings(settings); - updateAutoTrackSortOrder(); - }); - sortAutoMenu->addAction( tr("Pattern Editor - > Song Editor") + - (settings.sort == Mixer::autoTrackLinkSettings::AutoSort::PatternLinked ? " *" :""), - this, [this, mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.sort = Mixer::autoTrackLinkSettings::AutoSort::PatternLinked; - mix->saveAutoLinkTrackSettings(settings); - updateAutoTrackSortOrder(); - }); - - QAction * captionPatternEditor = addAutoMenu->addAction( "Pattern Editor" ); - captionPatternEditor->setEnabled( false ); - - addAutoMenu->addAction( tr("Disabled") + - (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::Disabled; - mix->saveAutoLinkTrackSettings(settings); - }); - addAutoMenu->addAction( tr("Each separate") + - (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Separate ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::Separate; - mix->saveAutoLinkTrackSettings(settings); - }); - addAutoMenu->addAction( tr("Use first track's channel") + - (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.autoAddPatternEditor = Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly; - mix->saveAutoLinkTrackSettings(settings); - }); - - QAction * captionSongEditor = addAutoMenu->addAction( "Song Editor" ); - captionSongEditor->setEnabled( false ); - - addAutoMenu->addAction( tr("Disabled") + - (settings.autoAddSongEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.autoAddSongEditor = Mixer::autoTrackLinkSettings::AutoAdd::Disabled; - mix->saveAutoLinkTrackSettings(settings); - }); - addAutoMenu->addAction( tr("Each separate") + - (settings.autoAddSongEditor == Mixer::autoTrackLinkSettings::AutoAdd::Separate ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.autoAddSongEditor = Mixer::autoTrackLinkSettings::AutoAdd::Separate; - mix->saveAutoLinkTrackSettings(settings); - }); - - deleteAutoMenu->addAction( tr("Disabled") + - (!settings.autoDelete ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.autoDelete = false; - mix->saveAutoLinkTrackSettings(settings); - }); - deleteAutoMenu->addAction( tr("Enabled") + - (settings.autoDelete ? " *" :""), - this, [mix]() - { - auto settings = mix->getAutoLinkTrackSettings(); - settings.autoDelete = true; - mix->saveAutoLinkTrackSettings(settings); - }); + // settings - link mode menu + addAutoLinkTrackMenuEntry(linkModeMenu, tr("One track to one channel"), + settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne, + [](Mixer::autoTrackLinkSettings* s) { s->linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToOne;}, + [this]() { setAutoTrackConstraints(); }); + addAutoLinkTrackMenuEntry(linkModeMenu, tr("Multiple tracks to one channel"), + settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToMany, + [](Mixer::autoTrackLinkSettings* s) { s->linkMode = Mixer::autoTrackLinkSettings::LinkMode::OneToMany;}, + [this]() { setAutoTrackConstraints(); }); + + // settings - link style menu + QAction * captionSongEditorLinkStyle = linkStyleMenu->addAction( "Song Editor" ); + captionSongEditorLinkStyle->setEnabled( false ); + + addAutoLinkTrackMenuEntry(linkStyleMenu,tr("Name and color"), + settings.songEditor.linkStyle == Mixer::autoTrackLinkSettings::LinkStyle::LinkNameAndColor, + [](Mixer::autoTrackLinkSettings* s) { s->songEditor.linkStyle = Mixer::autoTrackLinkSettings::LinkStyle::LinkNameAndColor;}); + addAutoLinkTrackMenuEntry(linkStyleMenu,tr("Color only"), + settings.songEditor.linkStyle == Mixer::autoTrackLinkSettings::LinkStyle::LinkColorOnly, + [](Mixer::autoTrackLinkSettings* s) { s->songEditor.linkStyle = Mixer::autoTrackLinkSettings::LinkStyle::LinkColorOnly;}); + addAutoLinkTrackMenuEntry(linkStyleMenu,tr("Disabled"), + settings.songEditor.linkStyle == Mixer::autoTrackLinkSettings::LinkStyle::Disabled, + [](Mixer::autoTrackLinkSettings* s) { s->songEditor.linkStyle = Mixer::autoTrackLinkSettings::LinkStyle::Disabled;}); + + QAction * captionPatternEditorLinkStyle = linkStyleMenu->addAction( "Pattern Editor" ); + captionPatternEditorLinkStyle->setEnabled( false ); + + addAutoLinkTrackMenuEntry(linkStyleMenu,tr("Name and color"), + settings.patternEditor.linkStyle == Mixer::autoTrackLinkSettings::LinkStyle::LinkNameAndColor, + [](Mixer::autoTrackLinkSettings* s) { s->patternEditor.linkStyle = Mixer::autoTrackLinkSettings::LinkStyle::LinkNameAndColor;}); + addAutoLinkTrackMenuEntry(linkStyleMenu,tr("Color only"), + settings.patternEditor.linkStyle == Mixer::autoTrackLinkSettings::LinkStyle::LinkColorOnly, + [](Mixer::autoTrackLinkSettings* s) { s->patternEditor.linkStyle = Mixer::autoTrackLinkSettings::LinkStyle::LinkColorOnly;}); + addAutoLinkTrackMenuEntry(linkStyleMenu,tr("Disabled"), + settings.patternEditor.linkStyle == Mixer::autoTrackLinkSettings::LinkStyle::Disabled, + [](Mixer::autoTrackLinkSettings* s) { s->patternEditor.linkStyle = Mixer::autoTrackLinkSettings::LinkStyle::Disabled;}); + + // settings - automatic sort menu + + addAutoLinkTrackMenuEntry(sortAutoMenu, tr("Song Editor -> Pattern Editor"), + settings.autoSort == Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern, + [](Mixer::autoTrackLinkSettings* s) { s->autoSort = Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern;}, + [this]() { setAutoTrackConstraints(); }); + addAutoLinkTrackMenuEntry(sortAutoMenu, tr("Pattern Editor - > Song Editor"), + settings.autoSort == Mixer::autoTrackLinkSettings::AutoSort::PatternLinked, + [](Mixer::autoTrackLinkSettings* s) { s->autoSort = Mixer::autoTrackLinkSettings::AutoSort::PatternLinked;}, + [this]() { setAutoTrackConstraints(); }); + addAutoLinkTrackMenuEntry(sortAutoMenu,tr("Disabled"), + settings.autoSort == Mixer::autoTrackLinkSettings::AutoSort::Disabled, + [](Mixer::autoTrackLinkSettings* s) { s->autoSort = Mixer::autoTrackLinkSettings::AutoSort::Disabled;}); + + // settings - automatic add menu + QAction * captionSongEditorAddAuto = addAutoMenu->addAction( "Song Editor" ); + captionSongEditorAddAuto->setEnabled( false ); + + addAutoLinkTrackMenuEntry(addAutoMenu,tr("Create new channel") , + settings.songEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::CreateNew, + [](Mixer::autoTrackLinkSettings* s) { s->songEditor.autoAdd = Mixer::autoTrackLinkSettings::AutoAdd::CreateNew;}); + addAutoLinkTrackMenuEntry(addAutoMenu,tr("Disabled"), + settings.songEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::Disabled, + [](Mixer::autoTrackLinkSettings* s) { s->songEditor.autoAdd = Mixer::autoTrackLinkSettings::AutoAdd::Disabled;}); + + QAction * captionPatternEditorAddAuto = addAutoMenu->addAction( "Pattern Editor" ); + captionPatternEditorAddAuto->setEnabled( false ); + + addAutoLinkTrackMenuEntry(addAutoMenu,tr("Create new channel") , + settings.patternEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::CreateNew, + [](Mixer::autoTrackLinkSettings* s) { s->patternEditor.autoAdd = Mixer::autoTrackLinkSettings::AutoAdd::CreateNew;}); + addAutoLinkTrackMenuEntry(addAutoMenu,tr("Use first track's channel") , + settings.patternEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly, + [](Mixer::autoTrackLinkSettings* s) { s->patternEditor.autoAdd = Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly;}); + addAutoLinkTrackMenuEntry(addAutoMenu,tr("Disabled"), + settings.patternEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::Disabled, + [](Mixer::autoTrackLinkSettings* s) { s->patternEditor.autoAdd = Mixer::autoTrackLinkSettings::AutoAdd::Disabled;}); + + // settings - delete menu + addAutoLinkTrackMenuEntry(deleteAutoMenu,tr("Enabled") , + settings.autoDelete == true, + [](Mixer::autoTrackLinkSettings* s) { s->autoDelete =true;}); + addAutoLinkTrackMenuEntry(deleteAutoMenu,tr("Disabled") , + settings.autoDelete == false, + [](Mixer::autoTrackLinkSettings* s) { s->autoDelete =false;}); } -void MixerView::updateAfterTrackAdd(Track * track, QString name, bool isPatternEditor) +void MixerView::updateAfterTrackAdd(Track * track, QString name) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); @@ -376,12 +344,12 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name, bool isPatternE IntModel * model = mix->getChannelModelByTrack(track); if ( model != nullptr) { - + auto isPatternEditor = track->trackContainer()->type() == TrackContainer::TrackContainerTypes::PatternContainer; if (isPatternEditor) { - if (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::Disabled) return; + if (settings.patternEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::Disabled) return; - if (settings.autoAddPatternEditor == Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly) + if (settings.patternEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::UseFirstTrackOnly) { auto trackList = Engine::patternStore()->tracks(); if (!trackList.empty()) @@ -395,7 +363,12 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name, bool isPatternE return; } } + else + { + if (settings.songEditor.autoAdd == Mixer::autoTrackLinkSettings::AutoAdd::Disabled) return; + } + // all other cases can only be "add new channel" because "UseFirstTrackOnly" is not supported by song editor int channelIndex = addNewChannel(); model->setValue( channelIndex ); mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); @@ -413,11 +386,12 @@ void MixerView::trackStyleToChannel(Track * track, MixerChannel * channel) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (settings.linkName) + auto isPatternEditor = track->trackContainer()->type() == TrackContainer::TrackContainerTypes::PatternContainer; + if (settings.linkName(isPatternEditor)) { channel->m_name = track->name(); } - if (settings.linkColor) + if (settings.linkColor(isPatternEditor)) { channel->setColor (track->color()); channel->m_hasColor = track->useColor(); @@ -428,11 +402,12 @@ void MixerView::channelStyleToTrack(MixerChannel * channel, Track * track) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (settings.linkName) + auto isPatternEditor = track->trackContainer()->type() == TrackContainer::TrackContainerTypes::PatternContainer; + if (settings.linkName(isPatternEditor)) { track->setName(channel->m_name); } - if (settings.linkColor) + if (settings.linkColor(isPatternEditor)) { track->setColor(channel->m_color); if (!channel->m_hasColor) track->resetColor(); @@ -443,7 +418,7 @@ void MixerView::updateAfterTrackStyleModify(Track * track) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (!settings.enabled || !settings.linkStyles()) return; + if (!settings.enabled || !settings.linkAnyStyles()) return; auto channel = mix->getCustomChannelByTrack(track); if (channel != nullptr && channel->m_autoTrackLinkModel.value()) { @@ -513,7 +488,7 @@ void MixerView::updateAfterTrackMove(Track * track) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (!settings.enabled || settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; + if (!settings.enabled || settings.autoSort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; auto channel = mix->getCustomChannelByTrack(track); if (channel != nullptr && channel->m_autoTrackLinkModel.value()) { @@ -594,7 +569,7 @@ void MixerView::updateAutoTrackSortOrder(bool autoSort) Mixer * mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); if (!settings.enabled) return; - if (autoSort && settings.sort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; + if (autoSort && settings.autoSort == Mixer::autoTrackLinkSettings::AutoSort::Disabled) return; std::vector list(m_mixerChannelViews.size(), 0); diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 477dad0329f..527e55f5609 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -88,7 +88,7 @@ void PatternEditor::removeSteps() void PatternEditor::addSampleTrack() { Track * track = Track::create( Track::SampleTrack, model() ); - getGUI()->mixerView()->updateAfterTrackAdd(track, "", true); + getGUI()->mixerView()->updateAfterTrackAdd(track); } From 98b48ffab3bc52ae64808e171c4530d598b16f66 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sun, 12 Jun 2022 17:45:02 +0200 Subject: [PATCH 18/25] check also for channel send before deletion --- include/Mixer.h | 9 ++------- include/MixerView.h | 16 ---------------- src/gui/MixerView.cpp | 5 ++++- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index f2002af6447..003389b59aa 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -158,7 +158,7 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject enum class AutoAdd { Disabled, /* do not link tracks after add */ - Separate, /* one channel for each track after add*/ + CreateNew, /* one channel for each track after add*/ UseFirstTrackOnly, /* use always the first channel in the editor for new tracks*/ }; @@ -175,7 +175,6 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject PatternLinked /* pattern editor first, linked tracks afterwards */ }; - struct editorSettings { LinkStyle linkStyle; @@ -184,11 +183,10 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject editorSettings() { linkStyle = LinkStyle::LinkNameAndColor; - autoAdd = AutoAdd::Separate; + autoAdd = AutoAdd::CreateNew; } }; - bool enabled; bool autoDelete; LinkMode linkMode; @@ -264,11 +262,9 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject if (asInt < lower || asInt >upper) return defaultValue; return asInt; } - }; - Mixer(); ~Mixer() override; @@ -357,7 +353,6 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject MixerRouteVector m_mixerRoutes; private: - inline const QString & getAutoTrackCfg(ConfigManager * cfg, const QString & postFix) { return cfg->value("AutoTrackLink", "settings_"+postFix); diff --git a/include/MixerView.h b/include/MixerView.h index 216a9670cfe..7e02a5c8d7b 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -134,22 +134,6 @@ private slots: void toogleAutoLinkTrackConfig(); private: - - - -// inline const QString autoTrackMenuText(const QString text, bool enabled) -// { -// return text + (enabled ? " *" :""); -// } - -// inline void setAutoTrackLinkValue(Mixer * mix, std::function setValue) -// { -// auto settings = mix->getAutoLinkTrackSettings(); -// setValue(settings); -// mix->saveAutoLinkTrackSettings(settings); -// } - - QVector m_mixerChannelViews; MixerLine * m_currentMixerLine; diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 213f8a40d05..ffdde57d640 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -517,7 +517,10 @@ void MixerView::updateAfterTrackDelete(Track * track) } if (shouldDelete) { - deleteChannel(channel->m_channelIndex); + // we disable autolink if it gets not deleted because of a channel send. + channel->m_autoTrackLinkModel.setValue(false); + m_mixerChannelViews[channel->m_channelIndex]->m_mixerLine->autoTrackLinkChanged(); + if (channel->m_receives.isEmpty()) deleteChannel(channel->m_channelIndex); updateAutoTrackSortOrder(); } } From c2c2acd7bcfe5bf6fcdcaa9e35b73aa114f83cb2 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Mon, 13 Jun 2022 21:03:43 +0200 Subject: [PATCH 19/25] auto link text style update is now working correctly (was no SLOT) --- include/MixerLine.h | 4 +-- include/MixerView.h | 2 +- src/core/Mixer.cpp | 2 -- src/gui/MixerLine.cpp | 29 ++++++++++----------- src/gui/MixerView.cpp | 35 +++++++++----------------- src/gui/editors/TrackContainerView.cpp | 2 +- 6 files changed, 29 insertions(+), 45 deletions(-) diff --git a/include/MixerLine.h b/include/MixerLine.h index 74cde76f233..8966fd7bb13 100644 --- a/include/MixerLine.h +++ b/include/MixerLine.h @@ -82,7 +82,6 @@ class MixerLine : public QWidget bool eventFilter (QObject *dist, QEvent *event) override; - void autoTrackLinkChanged(); private: void drawMixerLine( QPainter* p, const MixerLine *mixerLine, bool isActive, bool sendToThis, bool receiveFromThis ); @@ -115,7 +114,8 @@ private slots: void removeUnusedChannels(); void moveChannelLeft(); void moveChannelRight(); - void toogleAutoTrackLink(); + void toogleAutoTrackLink(); + void autoTrackLinkChanged(); }; diff --git a/include/MixerView.h b/include/MixerView.h index 7e02a5c8d7b..5d317644285 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -117,7 +117,7 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, void updateAfterTrackStyleModify(Track * track); void updateAfterTrackMixerLineModify(Track * track); void updateAfterTrackMove(Track * track); - void updateAfterTrackDelete(Track * track); + void updateBeforeTrackDelete(Track * track); void toggleAutoTrackLink(int index); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index d93a3699aff..382b8c5cb87 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -352,8 +352,6 @@ void Mixer::toggleAutoTrackLink(int index) } - - IntModel * Mixer::getChannelModelByTrack(Track * track) { if( track->type() == Track::InstrumentTrack ) diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index d681f5b1f50..048e8dfdaea 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -134,16 +134,12 @@ MixerLine::MixerLine( QWidget * _parent, MixerView * _mv, int _channelIndex ) : proxyWidget->setRotation( -90 ); proxyWidget->setPos( 8, 145 ); - autoTrackLinkChanged(); - - connect( m_renameLineEdit, SIGNAL( editingFinished() ), this, SLOT( renameFinished() ) ); + connect( m_renameLineEdit, SIGNAL( editingFinished() ), this, SLOT( renameFinished() ) ); connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_muteModel, SIGNAL( dataChanged() ), this, SLOT( update() ) ); - connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_autoTrackLinkModel, SIGNAL(dataChanged()),this, SLOT(autoTrackLinkChanged())); + connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_autoTrackLinkModel, SIGNAL( dataChanged() ), this, SLOT( autoTrackLinkChanged() ) ); } - - MixerLine::~MixerLine() { delete m_sendKnob; @@ -159,6 +155,7 @@ void MixerLine::setChannelIndex( int index ) m_channelIndex = index; m_lcd->setValue( m_channelIndex ); m_lcd->update(); + autoTrackLinkChanged(); } @@ -296,8 +293,8 @@ void MixerLine::contextMenuEvent( QContextMenuEvent * ) void MixerLine::toogleAutoTrackLink() { - MixerView * mix = getGUI()->mixerView(); - mix->toggleAutoTrackLink(m_channelIndex); + MixerView * mixView = getGUI()->mixerView(); + mixView->toggleAutoTrackLink(m_channelIndex); } void MixerLine::autoTrackLinkChanged() @@ -367,8 +364,8 @@ void MixerLine::renameFinished() void MixerLine::removeChannel() { - MixerView * mix = getGUI()->mixerView(); - mix->deleteChannel( m_channelIndex ); + MixerView * mixView = getGUI()->mixerView(); + mixView->deleteChannel( m_channelIndex ); } @@ -376,8 +373,8 @@ void MixerLine::removeChannel() void MixerLine::removeUnusedChannels() { - MixerView * mix = getGUI()->mixerView(); - mix->deleteUnusedChannels(); + MixerView * mixView = getGUI()->mixerView(); + mixView->deleteUnusedChannels(); } @@ -385,8 +382,8 @@ void MixerLine::removeUnusedChannels() void MixerLine::moveChannelLeft() { - MixerView * mix = getGUI()->mixerView(); - mix->moveChannelLeft( m_channelIndex ); + MixerView * mixView = getGUI()->mixerView(); + mixView->moveChannelLeft( m_channelIndex ); } @@ -394,8 +391,8 @@ void MixerLine::moveChannelLeft() void MixerLine::moveChannelRight() { - MixerView * mix = getGUI()->mixerView(); - mix->moveChannelRight( m_channelIndex ); + MixerView * mixView = getGUI()->mixerView(); + mixView->moveChannelRight( m_channelIndex ); } diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index ffdde57d640..3a7c8ac8d18 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -223,8 +223,6 @@ void MixerView::updateAutoTrackLinkMenu() QMenu* toMenu = m_autoLinkTrackSettingsBtn->menu(); toMenu->clear(); - // no widget but same approach as for CaptionMenu - QAction * captionMain = toMenu->addAction( "Auto track linking" ); captionMain->setEnabled( false ); QMenu* sortMenu = toMenu->addMenu(tr("Sort linked channels")); @@ -289,7 +287,6 @@ void MixerView::updateAutoTrackLinkMenu() [](Mixer::autoTrackLinkSettings* s) { s->patternEditor.linkStyle = Mixer::autoTrackLinkSettings::LinkStyle::Disabled;}); // settings - automatic sort menu - addAutoLinkTrackMenuEntry(sortAutoMenu, tr("Song Editor -> Pattern Editor"), settings.autoSort == Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern, [](Mixer::autoTrackLinkSettings* s) { s->autoSort = Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern;}, @@ -372,7 +369,6 @@ void MixerView::updateAfterTrackAdd(Track * track, QString name) int channelIndex = addNewChannel(); model->setValue( channelIndex ); mix->mixerChannel(channelIndex)->m_autoTrackLinkModel.setValue(true); - m_mixerChannelViews[channelIndex]->m_mixerLine->autoTrackLinkChanged(); // it may be that the track name is not available yet because of async loading if (name != "") track->setName(name); @@ -454,19 +450,16 @@ void MixerView::setAutoTrackConstraints() bool wasModified = false; for(unsigned long i = 0; i < usedChannelCounts.size(); i++) { - if (settings.enabled) + if (settings.enabled && mix->mixerChannel(i)->m_autoTrackLinkModel.value()) { // no more linked tracks or too many linked tracks if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne)) { mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); - m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); wasModified = true; } } - // update mixer lines in both cases (enabling/disabling) - m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); } if (!settings.enabled) return; @@ -496,16 +489,11 @@ void MixerView::updateAfterTrackMove(Track * track) } } -void MixerView::updateAfterTrackDelete(Track * track) +void MixerView::updateBeforeTrackDelete(Track * track) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); if (!settings.enabled) return; - if (!settings.autoDelete) - { - setAutoTrackConstraints(); - return; - } auto channel = mix->getCustomChannelByTrack(track); if (channel != nullptr && channel->m_autoTrackLinkModel.value()) { @@ -513,14 +501,17 @@ void MixerView::updateAfterTrackDelete(Track * track) if (settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToMany) { std::vector usedChannelCounts = mix->getUsedChannelCounts(); - shouldDelete = usedChannelCounts[channel->m_channelIndex] == 0; + // why "1" - because the track is not yet deleted + shouldDelete = usedChannelCounts[channel->m_channelIndex] == 1; } if (shouldDelete) { - // we disable autolink if it gets not deleted because of a channel send. channel->m_autoTrackLinkModel.setValue(false); - m_mixerChannelViews[channel->m_channelIndex]->m_mixerLine->autoTrackLinkChanged(); - if (channel->m_receives.isEmpty()) deleteChannel(channel->m_channelIndex); + if (settings.autoDelete && channel->m_receives.isEmpty()) + { + // we only delete if the setting allows and the channel does not receive another channel + deleteChannel(channel->m_channelIndex); + } updateAutoTrackSortOrder(); } } @@ -839,7 +830,6 @@ void MixerView::deleteChannelInternal(int index) for(int i=index + 1; im_mixerLine->setChannelIndex(i-1); - m_mixerChannelViews[i]->m_mixerLine->autoTrackLinkChanged(); } m_mixerChannelViews.remove(index); } @@ -872,7 +862,6 @@ void MixerView::toggleAutoTrackLink(int index) auto settings =mix->getAutoLinkTrackSettings(); if (!settings.enabled) return; mix->toggleAutoTrackLink(index); - m_mixerChannelViews[index]->m_mixerLine->autoTrackLinkChanged(); MixerChannel * channel = mix->mixerChannel(index); if (!channel->m_autoTrackLinkModel.value()) return; @@ -887,8 +876,8 @@ void MixerView::toggleAutoTrackLink(int index) if (trackFound != nullptr) { - updateAutoTrackSortOrder(); updateAfterTrackStyleModify(trackFound); + updateAutoTrackSortOrder(); } } @@ -910,8 +899,8 @@ void MixerView::swapChannels(int indexA, int indexB) m_mixerChannelViews[indexA]->setChannelIndex(indexA); m_mixerChannelViews[indexB]->setChannelIndex(indexB ); - m_mixerChannelViews[indexA]->m_mixerLine->autoTrackLinkChanged(); - m_mixerChannelViews[indexB]->m_mixerLine->autoTrackLinkChanged(); + m_mixerChannelViews[indexA]->m_mixerLine->setChannelIndex(indexA); + m_mixerChannelViews[indexB]->m_mixerLine->setChannelIndex(indexB); } diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index 0101af23820..1ed0f04cc58 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -168,7 +168,7 @@ void TrackContainerView::removeTrackView( TrackView * _tv ) if( index != -1 ) { Track * t = _tv->getTrack(); - getGUI()->mixerView()->updateAfterTrackDelete(t); + getGUI()->mixerView()->updateBeforeTrackDelete(t); m_trackViews.removeAt( index ); disconnect( _tv ); From 14044eda354fa8b1020a420389f0d96b8ad5bb9b Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Thu, 23 Jun 2022 21:00:46 +0200 Subject: [PATCH 20/25] made buildable --- src/core/Song.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/Song.cpp b/src/core/Song.cpp index fbc691db971..f97591d1f47 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -819,7 +819,7 @@ void Song::addPatternTrack() void Song::addSampleTrack() { Track* track = Track::create( Track::SampleTrack, this ); - getGUI()->mixerView()->updateAfterTrackAdd(track); + gui::getGUI()->mixerView()->updateAfterTrackAdd(track); } @@ -873,17 +873,17 @@ void Song::clearProject() Engine::audioEngine()->requestChangeInModel(); - if( getGUI() != nullptr && getGUI()->patternEditor() ) + if( getGUI() != nullptr && getGUI()->patternEditor() ) { getGUI()->patternEditor()->m_editor->clearAllTracks(); } - if( getGUI() != nullptr && getGUI()->songEditor() ) + if( getGUI() != nullptr && getGUI()->songEditor() ) { - getGUI()->songEditor()->m_editor->clearAllTracks(); + getGUI()->songEditor()->m_editor->clearAllTracks(); } - if( getGUI() != nullptr && getGUI()->mixerView() ) + if( getGUI() != nullptr && getGUI()->mixerView() ) { - getGUI()->mixerView()->clear(); + getGUI()->mixerView()->clear(); } QCoreApplication::sendPostedEvents(); Engine::patternStore()->clearAllTracks(); From 8db4113d38d8115e8820e017c4bb5f66fef82cb3 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sun, 10 Jul 2022 18:01:34 +0200 Subject: [PATCH 21/25] enable auto track linking when assigning new channel to track --- include/MixerView.h | 3 +- src/gui/MixerView.cpp | 41 ++++++++++++++++++++++---- src/gui/tracks/InstrumentTrackView.cpp | 18 ++--------- src/gui/tracks/SampleTrackView.cpp | 18 ++--------- 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/include/MixerView.h b/include/MixerView.h index 5d317644285..a634d039b0f 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -115,7 +115,8 @@ class LMMS_EXPORT MixerView : public QWidget, public ModelView, // Auto track link support void updateAfterTrackAdd(Track * track, QString name = ""); void updateAfterTrackStyleModify(Track * track); - void updateAfterTrackMixerLineModify(Track * track); + void trackMixerLineCreate(Track * track); + void trackMixerLineAssign(Track * track, int channelIndex); void updateAfterTrackMove(Track * track); void updateBeforeTrackDelete(Track * track); void toggleAutoTrackLink(int index); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 3a7c8ac8d18..eaa43657e1e 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -144,7 +144,6 @@ MixerView::MixerView() : newChannelBtn->setObjectName( "newChannelBtn" ); connect( newChannelBtn, SIGNAL(clicked()), this, SLOT(addNewChannel())); //ml->addWidget( newChannelBtn, 0, Qt::AlignTop ); - bl->addWidget(newChannelBtn, 0, Qt::AlignTop ); QMenu * toMenu = new QMenu(this ); toMenu->setFont( pointSize<9>( toMenu->font() ) ); @@ -155,12 +154,18 @@ MixerView::MixerView() : m_autoLinkTrackSettingsBtn->setFocusPolicy( Qt::NoFocus ); m_autoLinkTrackSettingsBtn->setMenu( toMenu ); m_autoLinkTrackSettingsBtn->setToolTip(tr("Auto track link settings")); - bl->addWidget(m_autoLinkTrackSettingsBtn, 0, Qt::AlignTop ); m_toogleAutoLinkTrackConfigBtn = new QPushButton(this); m_toogleAutoLinkTrackConfigBtn->setToolTip(tr("Enable/Disable auto track linking")); connect( m_toogleAutoLinkTrackConfigBtn, SIGNAL(clicked()), this, SLOT(toogleAutoLinkTrackConfig())); updateAutoLinkTrackConfigBtn(Engine::mixer()->getAutoLinkTrackSettings().enabled); + + m_autoLinkTrackSettingsBtn->setFixedSize(mixerLineSize.width(), 34); + m_toogleAutoLinkTrackConfigBtn->setFixedSize(mixerLineSize.width(), 34); + newChannelBtn->setFixedSize(mixerLineSize.width(), mixerLineSize.height()-34*2); + + bl->addWidget(newChannelBtn, 0, Qt::AlignTop ); + bl->addWidget(m_autoLinkTrackSettingsBtn, 0, Qt::AlignTop ); bl->addWidget(m_toogleAutoLinkTrackConfigBtn, 0, Qt::AlignTop ); @@ -430,18 +435,42 @@ void MixerView::updateAfterTrackStyleModify(Track * track) } } -void MixerView::updateAfterTrackMixerLineModify(Track * track) +void MixerView::trackMixerLineAssign(Track * track, int channelIndex) { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); - if (!settings.enabled) return; + IntModel * model = mix->getChannelModelByTrack(track); - if (model != nullptr) + model->setValue( channelIndex ); + + if (settings.enabled) { - setAutoTrackConstraints(); + IntModel * model = mix->getChannelModelByTrack(track); + if (model != nullptr) + { + setAutoTrackConstraints(); + } } + setCurrentMixerLine(channelIndex); } +void MixerView::trackMixerLineCreate(Track * track) +{ + int channelIndex = addNewChannel(); + auto channel = Engine::mixer()->mixerChannel(channelIndex); + + channel->m_name = track->name(); + if (track->useColor()) { channel->setColor (track->color()); } + + IntModel * model = Engine::mixer()->getChannelModelByTrack(track); + model->setValue( channelIndex ); + + toggleAutoTrackLink(channelIndex); + + setCurrentMixerLine(channelIndex); +} + + void MixerView::setAutoTrackConstraints() { auto mix = Engine::mixer(); diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 8e2809c26aa..7b0a5f2972a 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -221,34 +221,20 @@ InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow() } - - /*! \brief Create and assign a new mixer Channel for this track */ void InstrumentTrackView::createMixerLine() { - int channelIndex = getGUI()->mixerView()->addNewChannel(); - auto channel = Engine::mixer()->mixerChannel(channelIndex); - - channel->m_name = getTrack()->name(); - if (getTrack()->useColor()) { channel->setColor (getTrack()->color()); } - - assignMixerLine(channelIndex); + getGUI()->mixerView()->trackMixerLineCreate(getTrack()); } - - /*! \brief Assign a specific mixer Channel for this track */ void InstrumentTrackView::assignMixerLine(int channelIndex) { - model()->mixerChannelModel()->setValue( channelIndex ); - MixerView* mixerView = getGUI()->mixerView(); - mixerView->updateAfterTrackMixerLineModify(getTrack()); - mixerView->setCurrentMixerLine(channelIndex ); + getGUI()->mixerView()->trackMixerLineAssign(getTrack(), channelIndex); } - InstrumentTrackWindow * InstrumentTrackView::getInstrumentTrackWindow() { if (!m_window) diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index cdfc1123c43..f67038320b6 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -212,30 +212,18 @@ void SampleTrackView::dropEvent(QDropEvent *de) } - - /*! \brief Create and assign a new mixer Channel for this track */ void SampleTrackView::createMixerLine() { - int channelIndex = getGUI()->mixerView()->addNewChannel(); - auto channel = Engine::mixer()->mixerChannel(channelIndex); - - channel->m_name = getTrack()->name(); - if (getTrack()->useColor()) { channel->setColor (getTrack()->color()); } - - assignMixerLine(channelIndex); + getGUI()->mixerView()->trackMixerLineCreate(getTrack()); } - - /*! \brief Assign a specific mixer Channel for this track */ void SampleTrackView::assignMixerLine(int channelIndex) { - model()->mixerChannelModel()->setValue(channelIndex); - MixerView* mixerView = getGUI()->mixerView(); - mixerView->updateAfterTrackMixerLineModify(getTrack()); - mixerView->setCurrentMixerLine( channelIndex ); + getGUI()->mixerView()->trackMixerLineAssign(getTrack(), channelIndex); } + } // namespace lmms::gui From b6e6e7ac9e56449e43152845864fbdbf0e10e7a6 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sun, 10 Jul 2022 21:09:47 +0200 Subject: [PATCH 22/25] update mixer line style after auto link is disabled --- include/MixerLine.h | 4 ++-- src/gui/MixerLine.cpp | 6 +++--- src/gui/MixerView.cpp | 19 +++++++++++++------ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/MixerLine.h b/include/MixerLine.h index 8966fd7bb13..3cce45276b9 100644 --- a/include/MixerLine.h +++ b/include/MixerLine.h @@ -106,7 +106,8 @@ public slots: void renameChannel(); void resetColor(); void selectColor(); - void randomizeColor(); + void randomizeColor(); + void refreshAutoTrackLinkStyle(); private slots: void renameFinished(); @@ -115,7 +116,6 @@ private slots: void moveChannelLeft(); void moveChannelRight(); void toogleAutoTrackLink(); - void autoTrackLinkChanged(); }; diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 048e8dfdaea..c796a961449 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -136,7 +136,7 @@ MixerLine::MixerLine( QWidget * _parent, MixerView * _mv, int _channelIndex ) : connect( m_renameLineEdit, SIGNAL( editingFinished() ), this, SLOT( renameFinished() ) ); connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_muteModel, SIGNAL( dataChanged() ), this, SLOT( update() ) ); - connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_autoTrackLinkModel, SIGNAL( dataChanged() ), this, SLOT( autoTrackLinkChanged() ) ); + connect( &Engine::mixer()->mixerChannel( m_channelIndex )->m_autoTrackLinkModel, SIGNAL( dataChanged() ), this, SLOT( refreshAutoTrackLinkStyle() ) ); } @@ -155,7 +155,7 @@ void MixerLine::setChannelIndex( int index ) m_channelIndex = index; m_lcd->setValue( m_channelIndex ); m_lcd->update(); - autoTrackLinkChanged(); + refreshAutoTrackLinkStyle(); } @@ -297,7 +297,7 @@ void MixerLine::toogleAutoTrackLink() mixView->toggleAutoTrackLink(m_channelIndex); } -void MixerLine::autoTrackLinkChanged() +void MixerLine::refreshAutoTrackLinkStyle() { auto mix = Engine::mixer(); auto settings =mix->getAutoLinkTrackSettings(); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index eaa43657e1e..2ce4208034b 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -479,14 +479,21 @@ void MixerView::setAutoTrackConstraints() bool wasModified = false; for(unsigned long i = 0; i < usedChannelCounts.size(); i++) { - if (settings.enabled && mix->mixerChannel(i)->m_autoTrackLinkModel.value()) + if (mix->mixerChannel(i)->m_autoTrackLinkModel.value()) { - // no more linked tracks or too many linked tracks - if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && - settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne)) + if (settings.enabled) { - mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); - wasModified = true; + // no more linked tracks or too many linked tracks + if (usedChannelCounts[i] == 0 || (usedChannelCounts[i] > 1 && + settings.linkMode == Mixer::autoTrackLinkSettings::LinkMode::OneToOne)) + { + mix->mixerChannel(i)->m_autoTrackLinkModel.setValue(false); + wasModified = true; + } + } + else + { + m_mixerChannelViews[newChannelIndex]->m_mixerLine->refreshAutoTrackLinkStyle(); } } } From 5e4d20aa06585f06f67d7a6e8c10dbceea9d4ea6 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sat, 16 Jul 2022 12:50:57 +0200 Subject: [PATCH 23/25] made buildable --- src/gui/MixerView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 2ce4208034b..8f7b11d3efd 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -493,7 +493,7 @@ void MixerView::setAutoTrackConstraints() } else { - m_mixerChannelViews[newChannelIndex]->m_mixerLine->refreshAutoTrackLinkStyle(); + m_mixerChannelViews[i]->m_mixerLine->refreshAutoTrackLinkStyle(); } } } From e2e7f8bca2992ebef3b935b4e2602590f1a4e007 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sat, 16 Jul 2022 13:04:55 +0200 Subject: [PATCH 24/25] update mixerline style after autotrack link global enable/disable --- src/gui/MixerView.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 8f7b11d3efd..04a9c05ea4f 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -491,10 +491,8 @@ void MixerView::setAutoTrackConstraints() wasModified = true; } } - else - { - m_mixerChannelViews[i]->m_mixerLine->refreshAutoTrackLinkStyle(); - } + // needed when global enabled is switched + m_mixerChannelViews[i]->m_mixerLine->refreshAutoTrackLinkStyle(); } } if (!settings.enabled) return; From 477a4337f4dd0f45fc611a5dd53119e3506ca034 Mon Sep 17 00:00:00 2001 From: Spechtstatt <93736385+spechtstatt@users.noreply.github.com> Date: Sun, 17 Jul 2022 14:07:58 +0200 Subject: [PATCH 25/25] auto sorting seems to work now but more testing needed --- include/Mixer.h | 7 ++++++- src/core/Mixer.cpp | 17 +++++++++++++---- src/gui/MixerLine.cpp | 1 + src/gui/MixerView.cpp | 23 +++++++++++++++-------- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 003389b59aa..d157763f7ee 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -264,6 +264,11 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject } }; + enum class ProcessSortOrder + { + SongPattern, + PatternSong + }; Mixer(); ~Mixer() override; @@ -323,7 +328,7 @@ class LMMS_EXPORT Mixer : public Model, public JournallingObject void toggleAutoTrackLink(int index); // process tracks which have a mixer channel assigned - void processAssignedTracks(std::function process); + void processAssignedTracks(std::function process, ProcessSortOrder sortOrder = ProcessSortOrder::SongPattern); // process tracks assigned to a specific channel void processChannelTracks(MixerChannel * channel, std::function process); IntModel * getChannelModelByTrack(Track * track); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 382b8c5cb87..072bebac70a 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -1,4 +1,4 @@ -/* +/* * Mixer.cpp - effect mixer for LMMS * * Copyright (c) 2008-2011 Tobias Doerffel @@ -415,11 +415,20 @@ bool Mixer::autoLinkTrackConfigEnabled() -void Mixer::processAssignedTracks(std::function process) +void Mixer::processAssignedTracks(std::function process, + ProcessSortOrder sortOrder) { TrackContainer::TrackList trackList; - trackList += Engine::getSong()->tracks(); - trackList += Engine::patternStore()->tracks(); + if (sortOrder == ProcessSortOrder::SongPattern) + { + trackList += Engine::getSong()->tracks(); + trackList += Engine::patternStore()->tracks(); + } + else + { + trackList += Engine::patternStore()->tracks(); + trackList += Engine::getSong()->tracks(); + } for (Track* track: trackList) { diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index c796a961449..38fc7190e80 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -311,6 +311,7 @@ void MixerLine::refreshAutoTrackLinkStyle() m_renameEditPalette.setColor(QPalette::Text,Qt::white); } m_renameLineEdit->setPalette(m_renameEditPalette); + update(); } diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 04a9c05ea4f..22281071691 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -601,8 +601,8 @@ void MixerView::updateAutoTrackSortOrder(bool autoSort) std::vector list(m_mixerChannelViews.size(), 0); - int c = 0; - // add all non auto track first + int c = 1; + // add all non auto tracks first for( int i = 1; imixerChannel(i)->m_autoTrackLinkModel.value()) @@ -611,17 +611,23 @@ void MixerView::updateAutoTrackSortOrder(bool autoSort) } } - // add auto tracks in the order of the song tracks - mix->processAssignedTracks([&, list](Track *, IntModel * model, MixerChannel * channel) + // add auto linked and assigned tracks in song/patter order + auto sortOrder = settings.autoSort == Mixer::autoTrackLinkSettings::AutoSort::LinkedPattern + ? Mixer::ProcessSortOrder::SongPattern + : Mixer::ProcessSortOrder::PatternSong; + mix->processAssignedTracks([&list,&c](Track *, IntModel * model, MixerChannel * channel) mutable { if (channel == nullptr) return; if (channel->m_autoTrackLinkModel.value()) { list[c++] = model->value(); } - }); + }, sortOrder); - // bubblesort here because the list is normally almost ordered + // bubblesort here because: + // - list is normally almost ordered + // - stable sort and + // - "distance" between swapped items is normally small bool swapped = false; do { @@ -630,12 +636,12 @@ void MixerView::updateAutoTrackSortOrder(bool autoSort) { if (list[i] > list[i+1]) { - // a (+1) because we didn't include master track in our list - swapChannels(list[i+1], list[i+2]); + swapChannels(list[i], list[i+1]); int t = list[i]; list[i] = list[i+1]; list[i+1] = t; swapped = true; + } } c = c-1; @@ -812,6 +818,7 @@ void MixerView::updateMixerLine(int index) // disable the send button if it would cause an infinite loop thisLine->m_sendBtn->setVisible(! mix->isInfiniteLoop(selIndex, index)); thisLine->m_sendBtn->updateLightStatus(); + thisLine->refreshAutoTrackLinkStyle(); thisLine->update(); }