diff --git a/src/controllers/midi/midicontroller.cpp b/src/controllers/midi/midicontroller.cpp index 6b4829ff4e7..bc735a6cf33 100644 --- a/src/controllers/midi/midicontroller.cpp +++ b/src/controllers/midi/midicontroller.cpp @@ -10,6 +10,7 @@ #include "controllers/scripting/legacy/controllerscriptenginelegacy.h" #include "defs_urls.h" #include "errordialoghandler.h" +#include "mixer/playerinfo.h" #include "mixer/playermanager.h" #include "moc_midicontroller.cpp" #include "util/make_const_iterator.h" @@ -145,7 +146,7 @@ void MidiController::createOutputHandlers() { if (m_logBase().isDebugEnabled()) { failures.append(errorLog); } else if (PlayerManager::isDeckGroup(group, &deckNum)) { - int numDecks = PlayerManager::numDecks(); + int numDecks = PlayerInfo::instance().numDecks(); if (deckNum <= numDecks) { failures.append(errorLog); } diff --git a/src/coreservices.cpp b/src/coreservices.cpp index e1b57089f90..fa7769873db 100644 --- a/src/coreservices.cpp +++ b/src/coreservices.cpp @@ -441,7 +441,9 @@ void CoreServices::initialize(QApplication* pApp) { // Load tracks in args.qlMusicFiles (command line arguments) into player // 1 and 2: const QList& musicFiles = m_cmdlineArgs.getMusicFiles(); - for (int i = 0; i < (int)m_pPlayerManager->numDecks() && i < musicFiles.count(); ++i) { + const int numTracks = std::min(m_pPlayerManager->numberOfDecks(), + static_cast(musicFiles.count())); + for (int i = 0; i < numTracks; ++i) { if (SoundSourceProxy::isFileNameSupported(musicFiles.at(i))) { m_pPlayerManager->slotLoadToDeck(musicFiles.at(i), i + 1); } diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 068efd0329d..8995a2e91de 100644 --- a/src/library/autodj/autodjprocessor.cpp +++ b/src/library/autodj/autodjprocessor.cpp @@ -155,9 +155,8 @@ AutoDJProcessor::AutoDJProcessor( // TODO(rryan) listen to signals from PlayerManager and add/remove as decks // are created. - for (unsigned int i = 0; i < pPlayerManager->numberOfDecks(); ++i) { - QString group = PlayerManager::groupForDeck(i); - BaseTrackPlayer* pPlayer = pPlayerManager->getPlayer(group); + for (int i = 0; i < pPlayerManager->numberOfDecks(); ++i) { + BaseTrackPlayer* pPlayer = pPlayerManager->getDeckBase(i); // Shouldn't be possible. VERIFY_OR_DEBUG_ASSERT(pPlayer) { continue; diff --git a/src/library/banshee/bansheeplaylistmodel.cpp b/src/library/banshee/bansheeplaylistmodel.cpp index 20082a04c11..b585a9c1e4d 100644 --- a/src/library/banshee/bansheeplaylistmodel.cpp +++ b/src/library/banshee/bansheeplaylistmodel.cpp @@ -8,6 +8,7 @@ #include "library/dao/trackschema.h" #include "library/queryutil.h" #include "library/trackcollectionmanager.h" +#include "mixer/playerinfo.h" #include "mixer/playermanager.h" #include "moc_bansheeplaylistmodel.cpp" #include "track/track.h" @@ -363,6 +364,6 @@ QString BansheePlaylistModel::getTrackLocation(const QModelIndex& index) const { bool BansheePlaylistModel::isColumnInternal(int column) { return (column == fieldIndex(ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_TRACKID) || - (PlayerManager::numPreviewDecks() == 0 && + (PlayerInfo::instance().numPreviewDecks() == 0 && column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW))); } diff --git a/src/library/baseexternalplaylistmodel.cpp b/src/library/baseexternalplaylistmodel.cpp index 01169cd9a37..ddcf79921c3 100644 --- a/src/library/baseexternalplaylistmodel.cpp +++ b/src/library/baseexternalplaylistmodel.cpp @@ -4,6 +4,7 @@ #include "library/queryutil.h" #include "library/trackcollection.h" #include "library/trackcollectionmanager.h" +#include "mixer/playerinfo.h" #include "mixer/playermanager.h" #include "moc_baseexternalplaylistmodel.cpp" #include "track/track.h" @@ -82,7 +83,7 @@ TrackId BaseExternalPlaylistModel::getTrackId(const QModelIndex& index) const { bool BaseExternalPlaylistModel::isColumnInternal(int column) { return column == fieldIndex(ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_TRACKID) || - (PlayerManager::numPreviewDecks() == 0 && + (PlayerInfo::instance().numPreviewDecks() == 0 && column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW)); } diff --git a/src/library/baseexternaltrackmodel.cpp b/src/library/baseexternaltrackmodel.cpp index 45f986a5121..e920e7f7f6d 100644 --- a/src/library/baseexternaltrackmodel.cpp +++ b/src/library/baseexternaltrackmodel.cpp @@ -6,6 +6,7 @@ #include "library/dao/trackschema.h" #include "library/queryutil.h" #include "library/trackcollectionmanager.h" +#include "mixer/playerinfo.h" #include "mixer/playermanager.h" #include "moc_baseexternaltrackmodel.cpp" #include "track/track.h" @@ -110,7 +111,7 @@ TrackId BaseExternalTrackModel::doGetTrackId(const TrackPointer& pTrack) const { bool BaseExternalTrackModel::isColumnInternal(int column) { return column == fieldIndex(LIBRARYTABLE_ID) || - (PlayerManager::numPreviewDecks() == 0 && + (PlayerInfo::instance().numPreviewDecks() == 0 && column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW)); } diff --git a/src/library/basetracktablemodel.cpp b/src/library/basetracktablemodel.cpp index 8ce9c7a65a1..5c7b7cd1b07 100644 --- a/src/library/basetracktablemodel.cpp +++ b/src/library/basetracktablemodel.cpp @@ -485,7 +485,7 @@ QAbstractItemDelegate* BaseTrackTableModel::delegateForColumn( return new BPMDelegate(pTableView); } else if (index == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED)) { return new CheckboxDelegate(pTableView, QStringLiteral("LibraryPlayedCheckbox")); - } else if (PlayerManager::numPreviewDecks() > 0 && + } else if (PlayerInfo::instance().numPreviewDecks() > 0 && index == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW)) { return new PreviewButtonDelegate(pTableView, index); } else if (index == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COMMENT)) { diff --git a/src/library/browse/browsetablemodel.cpp b/src/library/browse/browsetablemodel.cpp index 5a618986129..20b1f2fa202 100644 --- a/src/library/browse/browsetablemodel.cpp +++ b/src/library/browse/browsetablemodel.cpp @@ -526,7 +526,7 @@ bool BrowseTableModel::isColumnSortable(int column) const { QAbstractItemDelegate* BrowseTableModel::delegateForColumn(const int i, QObject* pParent) { WLibraryTableView* pTableView = qobject_cast(pParent); DEBUG_ASSERT(pTableView); - if (PlayerManager::numPreviewDecks() > 0 && i == COLUMN_PREVIEW) { + if (PlayerInfo::instance().numPreviewDecks() > 0 && i == COLUMN_PREVIEW) { return new PreviewButtonDelegate(pTableView, i); } return nullptr; diff --git a/src/library/dao/autodjcratesdao.cpp b/src/library/dao/autodjcratesdao.cpp index a5db774f57c..98d9d839345 100644 --- a/src/library/dao/autodjcratesdao.cpp +++ b/src/library/dao/autodjcratesdao.cpp @@ -370,8 +370,8 @@ bool AutoDJCratesDAO::updateAutoDjPlaylistReferences() { // Incorporate all tracks loaded into decks. // Each track has to be done as a separate database query, in case the same // track is loaded into multiple decks. - int iDecks = (int) PlayerManager::numDecks(); - for (int i = 0; i < iDecks; ++i) { + int numDecks = PlayerInfo::instance().numDecks(); + for (int i = 0; i < numDecks; ++i) { QString group = PlayerManager::groupForDeck(i); TrackPointer pTrack = PlayerInfo::instance().getTrackInfo(group); if (pTrack) { @@ -1103,8 +1103,8 @@ void AutoDJCratesDAO::playerInfoTrackLoaded(const QString& group, } // This counts as an auto-DJ reference. The idea is to prevent tracks that // are loaded into a deck from being randomly chosen. - unsigned int numDecks = PlayerManager::numDecks(); - for (unsigned int i = 0; i < numDecks; ++i) { + int numDecks = PlayerInfo::instance().numDecks(); + for (int i = 0; i < numDecks; ++i) { if (group == PlayerManager::groupForDeck(i)) { // Update the number of auto-DJ-playlist references to this track. QSqlQuery oQuery(m_database); @@ -1131,8 +1131,8 @@ void AutoDJCratesDAO::playerInfoTrackUnloaded(const QString& group, } // This counts as an auto-DJ reference. The idea is to prevent tracks that // are loaded into a deck from being randomly chosen. - unsigned int numDecks = PlayerManager::numDecks(); - for (unsigned int i = 0; i < numDecks; ++i) { + int numDecks = PlayerInfo::instance().numDecks(); + for (int i = 0; i < numDecks; ++i) { if (group == PlayerManager::groupForDeck(i)) { // Get rid of the ID of the track in this deck. QSqlQuery oQuery(m_database); diff --git a/src/library/librarytablemodel.cpp b/src/library/librarytablemodel.cpp index aec9a8777d6..bcf483d486f 100644 --- a/src/library/librarytablemodel.cpp +++ b/src/library/librarytablemodel.cpp @@ -4,6 +4,7 @@ #include "library/queryutil.h" #include "library/trackcollection.h" #include "library/trackcollectionmanager.h" +#include "mixer/playerinfo.h" #include "mixer/playermanager.h" #include "moc_librarytablemodel.cpp" @@ -77,7 +78,7 @@ bool LibraryTableModel::isColumnInternal(int column) { column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK) || column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_CHANNELS) || column == fieldIndex(ColumnCache::COLUMN_TRACKLOCATIONSTABLE_FSDELETED) || - (PlayerManager::numPreviewDecks() == 0 && + (PlayerInfo::instance().numPreviewDecks() == 0 && column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW)) || column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_SOURCE) || column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_TYPE) || diff --git a/src/library/trackset/tracksettablemodel.cpp b/src/library/trackset/tracksettablemodel.cpp index 1e53c73ca60..b86356b9639 100644 --- a/src/library/trackset/tracksettablemodel.cpp +++ b/src/library/trackset/tracksettablemodel.cpp @@ -1,6 +1,7 @@ #include "library/trackset/tracksettablemodel.h" #include "library/trackcollectionmanager.h" +#include "mixer/playerinfo.h" #include "mixer/playermanager.h" #include "moc_tracksettablemodel.cpp" @@ -18,7 +19,7 @@ bool TrackSetTableModel::isColumnInternal(int column) { column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK) || column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_KEY_ID) || column == fieldIndex(ColumnCache::COLUMN_TRACKLOCATIONSTABLE_FSDELETED) || - (PlayerManager::numPreviewDecks() == 0 && + (PlayerInfo::instance().numPreviewDecks() == 0 && column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW)) || column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_SOURCE) || column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_TYPE) || diff --git a/src/mixer/playerinfo.cpp b/src/mixer/playerinfo.cpp index 577c45efba9..01fbe5138a6 100644 --- a/src/mixer/playerinfo.cpp +++ b/src/mixer/playerinfo.cpp @@ -14,10 +14,16 @@ constexpr int kPlayingDeckUpdateIntervalMillis = 2000; PlayerInfo* s_pPlayerInfo = nullptr; +const QString kAppGroup = QStringLiteral("[App]"); +const QString kMasterGroup = QStringLiteral("[Master]"); + } // namespace PlayerInfo::PlayerInfo() - : m_pCOxfader(new ControlProxy("[Master]","crossfader", this)), + : m_xfader(kMasterGroup, QStringLiteral("crossfader")), + m_numDecks(kAppGroup, QStringLiteral("num_decks")), + m_numSamplers(kAppGroup, QStringLiteral("num_samplers")), + m_numPreviewDecks(kAppGroup, QStringLiteral("num_preview_decks")), m_currentlyPlayingDeck(-1) { startTimer(kPlayingDeckUpdateIntervalMillis); } @@ -135,7 +141,7 @@ void PlayerInfo::updateCurrentPlayingDeck() { CSAMPLE_GAIN xfl, xfr; // TODO: supply correct parameters to the function. If the hamster style // for the crossfader is enabled, the result is currently wrong. - EngineXfader::getXfadeGains(m_pCOxfader->get(), + EngineXfader::getXfadeGains(m_xfader.get(), 1.0, 0.0, MIXXX_XFADER_ADDITIVE, @@ -143,7 +149,7 @@ void PlayerInfo::updateCurrentPlayingDeck() { &xfl, &xfr); - for (int i = 0; i < (int)PlayerManager::numDecks(); ++i) { + for (int i = 0; i < numDecks(); ++i) { DeckControls* pDc = getDeckControls(i); if (pDc->m_play.get() == 0.0) { @@ -213,3 +219,15 @@ void PlayerInfo::clearControlCache() { } m_deckControlList.clear(); } + +int PlayerInfo::numDecks() const { + return static_cast(m_numDecks.get()); +} + +int PlayerInfo::numPreviewDecks() const { + return static_cast(m_numPreviewDecks.get()); +} + +int PlayerInfo::numSamplers() const { + return static_cast(m_numSamplers.get()); +} diff --git a/src/mixer/playerinfo.h b/src/mixer/playerinfo.h index a345322e52b..3ec22c42da8 100644 --- a/src/mixer/playerinfo.h +++ b/src/mixer/playerinfo.h @@ -6,7 +6,7 @@ #include #include -#include "control/controlproxy.h" +#include "control/pollingcontrolproxy.h" #include "track/track_decl.h" class PlayerInfo : public QObject { @@ -24,6 +24,10 @@ class PlayerInfo : public QObject { bool isTrackLoaded(const TrackPointer& pTrack) const; bool isFileLoaded(const QString& track_location) const; + int numDecks() const; + int numPreviewDecks() const; + int numSamplers() const; + signals: void currentPlayingDeckChanged(int deck); void currentPlayingTrackChanged(TrackPointer pTrack); @@ -39,10 +43,10 @@ class PlayerInfo : public QObject { m_orientation(group, "orientation") { } - ControlProxy m_play; - ControlProxy m_pregain; - ControlProxy m_volume; - ControlProxy m_orientation; + PollingControlProxy m_play; + PollingControlProxy m_pregain; + PollingControlProxy m_volume; + PollingControlProxy m_orientation; }; void clearControlCache(); @@ -54,7 +58,12 @@ class PlayerInfo : public QObject { ~PlayerInfo() override; mutable QMutex m_mutex; - ControlProxy* m_pCOxfader; + + PollingControlProxy m_xfader; + PollingControlProxy m_numDecks; + PollingControlProxy m_numSamplers; + PollingControlProxy m_numPreviewDecks; + // QMap is faster than QHash for small count of elements < 50 QMap m_loadedTrackMap; QAtomicInt m_currentlyPlayingDeck; diff --git a/src/mixer/playermanager.cpp b/src/mixer/playermanager.cpp index 3a2b544ea05..3c765ebc323 100644 --- a/src/mixer/playermanager.cpp +++ b/src/mixer/playermanager.cpp @@ -93,13 +93,6 @@ inline QString getDefaultSamplerPath(UserSettingsPointer pConfig) { } // anonymous namespace -//static -QAtomicPointer PlayerManager::m_pCOPNumDecks; -//static -QAtomicPointer PlayerManager::m_pCOPNumSamplers; -//static -QAtomicPointer PlayerManager::m_pCOPNumPreviewDecks; - PlayerManager::PlayerManager(UserSettingsPointer pConfig, SoundManager* pSoundManager, EffectsManager* pEffectsManager, @@ -159,10 +152,6 @@ PlayerManager::~PlayerManager() { m_microphones.clear(); m_auxiliaries.clear(); - delete m_pCOPNumDecks.fetchAndStoreAcquire(nullptr); - delete m_pCOPNumSamplers.fetchAndStoreAcquire(nullptr); - delete m_pCOPNumPreviewDecks.fetchAndStoreAcquire(nullptr); - if (m_pTrackAnalysisScheduler) { m_pTrackAnalysisScheduler->stop(); m_pTrackAnalysisScheduler.reset(); @@ -243,61 +232,6 @@ bool PlayerManager::isPreviewDeckGroup(const QString& group, int* number) { return extractIntFromRegex(kPreviewDeckRegex, group, number); } -// static -unsigned int PlayerManager::numDecks() { - // We do this to cache the control once it is created so callers don't incur - // a hashtable lookup every time they call this. - ControlProxy* pCOPNumDecks = atomicLoadRelaxed(m_pCOPNumDecks); - if (pCOPNumDecks == nullptr) { - pCOPNumDecks = new ControlProxy(ConfigKey(kAppGroup, QStringLiteral("num_decks"))); - if (!pCOPNumDecks->valid()) { - delete pCOPNumDecks; - pCOPNumDecks = nullptr; - } else { - m_pCOPNumDecks = pCOPNumDecks; - } - } - // m_pCOPNumDecks->get() fails on MacOs - return pCOPNumDecks ? static_cast(pCOPNumDecks->get()) : 0; -} - -// static -unsigned int PlayerManager::numSamplers() { - // We do this to cache the control once it is created so callers don't incur - // a hashtable lookup every time they call this. - ControlProxy* pCOPNumSamplers = atomicLoadRelaxed(m_pCOPNumSamplers); - if (pCOPNumSamplers == nullptr) { - pCOPNumSamplers = new ControlProxy(ConfigKey(kAppGroup, QStringLiteral("num_samplers"))); - if (!pCOPNumSamplers->valid()) { - delete pCOPNumSamplers; - pCOPNumSamplers = nullptr; - } else { - m_pCOPNumSamplers = pCOPNumSamplers; - } - } - // m_pCOPNumSamplers->get() fails on MacOs - return pCOPNumSamplers ? static_cast(pCOPNumSamplers->get()) : 0; -} - -// static -unsigned int PlayerManager::numPreviewDecks() { - // We do this to cache the control once it is created so callers don't incur - // a hashtable lookup every time they call this. - ControlProxy* pCOPNumPreviewDecks = atomicLoadRelaxed(m_pCOPNumPreviewDecks); - if (pCOPNumPreviewDecks == nullptr) { - pCOPNumPreviewDecks = new ControlProxy( - ConfigKey(kAppGroup, QStringLiteral("num_preview_decks"))); - if (!pCOPNumPreviewDecks->valid()) { - delete pCOPNumPreviewDecks; - pCOPNumPreviewDecks = nullptr; - } else { - m_pCOPNumPreviewDecks = pCOPNumPreviewDecks; - } - } - // m_pCOPNumPreviewDecks->get() fails on MacOs - return pCOPNumPreviewDecks ? static_cast(pCOPNumPreviewDecks->get()) : 0; -} - void PlayerManager::slotChangeNumDecks(double v) { const auto locker = lockMutex(&m_mutex); int num = (int)v; @@ -587,33 +521,37 @@ BaseTrackPlayer* PlayerManager::getPlayer(const ChannelHandle& handle) const { return nullptr; } -Deck* PlayerManager::getDeck(unsigned int deck) const { +Deck* PlayerManager::getDeck(int deckIndex) const { const auto locker = lockMutex(&m_mutex); - VERIFY_OR_DEBUG_ASSERT(deck > 0 && deck <= numDecks()) { - qWarning() << "getDeck() called with invalid number:" << deck; + VERIFY_OR_DEBUG_ASSERT(deckIndex >= 0 && deckIndex < m_decks.size()) { + qWarning() << "getDeck() called with invalid index:" << deckIndex; return nullptr; } - return m_decks[deck - 1]; + return m_decks[deckIndex]; +} + +BaseTrackPlayer* PlayerManager::getDeckBase(int deckIndex) const { + return getDeck(deckIndex); } -PreviewDeck* PlayerManager::getPreviewDeck(unsigned int libPreviewPlayer) const { +PreviewDeck* PlayerManager::getPreviewDeck(int previewDeckIndex) const { const auto locker = lockMutex(&m_mutex); - if (libPreviewPlayer < 1 || libPreviewPlayer > numPreviewDecks()) { + VERIFY_OR_DEBUG_ASSERT(previewDeckIndex >= 0 && previewDeckIndex < m_previewDecks.size()) { kLogger.warning() << "Warning getPreviewDeck() called with invalid index: " - << libPreviewPlayer; + << previewDeckIndex; return nullptr; } - return m_previewDecks[libPreviewPlayer - 1]; + return m_previewDecks[previewDeckIndex]; } -Sampler* PlayerManager::getSampler(unsigned int sampler) const { +Sampler* PlayerManager::getSampler(int samplerIndex) const { const auto locker = lockMutex(&m_mutex); - if (sampler < 1 || sampler > numSamplers()) { + VERIFY_OR_DEBUG_ASSERT(samplerIndex >= 0 && samplerIndex < m_samplers.size()) { kLogger.warning() << "Warning getSampler() called with invalid index: " - << sampler; + << samplerIndex; return nullptr; } - return m_samplers[sampler - 1]; + return m_samplers[samplerIndex]; } TrackPointer PlayerManager::getLastEjectedTrack() const { @@ -824,3 +762,15 @@ void PlayerManager::onTrackAnalysisProgress(TrackId trackId, AnalyzerProgress an void PlayerManager::onTrackAnalysisFinished() { emit trackAnalyzerIdle(); } + +int PlayerManager::numberOfDecks() const { + return static_cast(m_pCONumDecks->get()); +} + +int PlayerManager::numberOfPreviewDecks() const { + return static_cast(m_pCONumPreviewDecks->get()); +} + +int PlayerManager::numberOfSamplers() const { + return static_cast(m_pCONumSamplers->get()); +} diff --git a/src/mixer/playermanager.h b/src/mixer/playermanager.h index cbd74d31787..c23f1f5d983 100644 --- a/src/mixer/playermanager.h +++ b/src/mixer/playermanager.h @@ -36,21 +36,21 @@ class PlayerManagerInterface { virtual BaseTrackPlayer* getPlayer(const QString& group) const = 0; virtual BaseTrackPlayer* getPlayer(const ChannelHandle& channelHandle) const = 0; - // Get the deck by its deck number. Decks are numbered starting with 1. - virtual Deck* getDeck(unsigned int player) const = 0; + // Get the deck as BaseTrackPlayer by its deck index + // to allow unit test to return a mocked Deck + virtual BaseTrackPlayer* getDeckBase(int deckIndex) const = 0; - virtual unsigned int numberOfDecks() const = 0; + virtual int numberOfDecks() const = 0; - // Get the preview deck by its deck number. Preview decks are numbered - // starting with 1. - virtual PreviewDeck* getPreviewDeck(unsigned int libPreviewPlayer) const = 0; + // Get the preview deck by its index. + virtual PreviewDeck* getPreviewDeck(int previewPlayerIndex) const = 0; - virtual unsigned int numberOfPreviewDecks() const = 0; + virtual int numberOfPreviewDecks() const = 0; - // Get the sampler by its number. Samplers are numbered starting with 1. - virtual Sampler* getSampler(unsigned int sampler) const = 0; + // Get the sampler by its index + virtual Sampler* getSampler(int samplerIndex) const = 0; - virtual unsigned int numberOfSamplers() const = 0; + virtual int numberOfSamplers() const = 0; }; class PlayerManager : public QObject, public PlayerManagerInterface { @@ -102,28 +102,22 @@ class PlayerManager : public QObject, public PlayerManagerInterface { // Get a BaseTrackPlayer (Deck, Sampler or PreviewDeck) by its handle. BaseTrackPlayer* getPlayer(const ChannelHandle& handle) const override; - // Get the deck by its deck number. Decks are numbered starting with 1. - Deck* getDeck(unsigned int player) const override; + // Get the deck by its index. + Deck* getDeck(int deckIndex) const; + BaseTrackPlayer* getDeckBase(int deckIndex) const override; + // Return the number of players. Thread-safe. - static unsigned int numDecks(); - unsigned int numberOfDecks() const override { - return numDecks(); - } + int numberOfDecks() const override; - PreviewDeck* getPreviewDeck(unsigned int libPreviewPlayer) const override; + // Get the preview deck by its index. + PreviewDeck* getPreviewDeck(int previewDeckIndex) const override; // Return the number of preview decks. Thread-safe. - static unsigned int numPreviewDecks(); - unsigned int numberOfPreviewDecks() const override { - return numPreviewDecks(); - } + int numberOfPreviewDecks() const override; - // Get the sampler by its number. Samplers are numbered starting with 1. - Sampler* getSampler(unsigned int sampler) const override; + // Get the sampler by its index. + Sampler* getSampler(int samplerIndex) const override; // Return the number of samplers. Thread-safe. - static unsigned int numSamplers(); - unsigned int numberOfSamplers() const override { - return numSamplers(); - } + int numberOfSamplers() const override; // Returns the track that was last ejected or unloaded. Can return nullptr or // invalid TrackId in case of error. @@ -179,10 +173,6 @@ class PlayerManager : public QObject, public PlayerManagerInterface { return QStringLiteral("[Auxiliary") + QString::number(i + 1) + ']'; } - static QAtomicPointer m_pCOPNumDecks; - static QAtomicPointer m_pCOPNumSamplers; - static QAtomicPointer m_pCOPNumPreviewDecks; - public slots: // Slots for loading tracks into a Player, which is either a Sampler or a Deck void slotLoadTrackToPlayer(TrackPointer pTrack, const QString& group, bool play); diff --git a/src/mixer/samplerbank.cpp b/src/mixer/samplerbank.cpp index 37545c804fe..866ad57916b 100644 --- a/src/mixer/samplerbank.cpp +++ b/src/mixer/samplerbank.cpp @@ -107,8 +107,8 @@ bool SamplerBank::saveSamplerBankToPath(const QString& samplerBankPath) { QDomElement root = doc.createElement(QStringLiteral("samplerbank")); doc.appendChild(root); - for (unsigned int i = 0; i < m_pPlayerManager->numSamplers(); ++i) { - Sampler* pSampler = m_pPlayerManager->getSampler(i + 1); + for (int i = 0; i < m_pPlayerManager->numberOfSamplers(); ++i) { + Sampler* pSampler = m_pPlayerManager->getSampler(i); if (!pSampler) { continue; } @@ -207,7 +207,7 @@ bool SamplerBank::loadSamplerBankFromPath(const QString& samplerBankPath) { int samplerNum; if (!group.isEmpty() && m_pPlayerManager->isSamplerGroup(group, &samplerNum)) { - if (m_pPlayerManager->numSamplers() < (unsigned)samplerNum) { + if (m_pPlayerManager->numberOfSamplers() < samplerNum) { m_pCONumSamplers->set(samplerNum); } diff --git a/src/mixxxmainwindow.cpp b/src/mixxxmainwindow.cpp index 9cd0271ceeb..c5dab4a1f7b 100644 --- a/src/mixxxmainwindow.cpp +++ b/src/mixxxmainwindow.cpp @@ -1378,16 +1378,16 @@ bool MixxxMainWindow::confirmExit() { bool playing(false); bool playingSampler(false); auto pPlayerManager = m_pCoreServices->getPlayerManager(); - unsigned int deckCount = pPlayerManager->numDecks(); - unsigned int samplerCount = pPlayerManager->numSamplers(); - for (unsigned int i = 0; i < deckCount; ++i) { + int deckCount = pPlayerManager->numberOfDecks(); + int samplerCount = pPlayerManager->numberOfSamplers(); + for (int i = 0; i < deckCount; ++i) { if (ControlObject::toBool( ConfigKey(PlayerManager::groupForDeck(i), "play"))) { playing = true; break; } } - for (unsigned int i = 0; i < samplerCount; ++i) { + for (int i = 0; i < samplerCount; ++i) { if (ControlObject::toBool( ConfigKey(PlayerManager::groupForSampler(i), "play"))) { playingSampler = true; diff --git a/src/test/autodjprocessor_test.cpp b/src/test/autodjprocessor_test.cpp index 8e0178c7b7e..e1fa580ae04 100644 --- a/src/test/autodjprocessor_test.cpp +++ b/src/test/autodjprocessor_test.cpp @@ -138,20 +138,20 @@ class MockPlayerManager : public PlayerManagerInterface { MOCK_CONST_METHOD1(getPlayer, BaseTrackPlayer*(const QString&)); MOCK_CONST_METHOD1(getPlayer, BaseTrackPlayer*(const ChannelHandle&)); - MOCK_CONST_METHOD1(getDeck, Deck*(unsigned int)); - MOCK_CONST_METHOD1(getPreviewDeck, PreviewDeck*(unsigned int)); - MOCK_CONST_METHOD1(getSampler, Sampler*(unsigned int)); + MOCK_CONST_METHOD1(getDeckBase, BaseTrackPlayer*(int)); + MOCK_CONST_METHOD1(getPreviewDeck, PreviewDeck*(int)); + MOCK_CONST_METHOD1(getSampler, Sampler*(int)); - unsigned int numberOfDecks() const { - return static_cast(numDecks.get()); + int numberOfDecks() const { + return static_cast(numDecks.get()); } - unsigned int numberOfSamplers() const { - return static_cast(numSamplers.get()); + int numberOfSamplers() const { + return static_cast(numSamplers.get()); } - unsigned int numberOfPreviewDecks() const { - return static_cast(numPreviewDecks.get()); + int numberOfPreviewDecks() const { + return static_cast(numPreviewDecks.get()); } ControlObject numDecks; @@ -209,20 +209,20 @@ class AutoDJProcessorTest : public LibraryTest { PlayerInfo::create(); // Setup 4 fake decks. - ON_CALL(*pPlayerManager, getPlayer(QString("[Channel1]"))) + ON_CALL(*pPlayerManager, getDeckBase(0)) .WillByDefault(Return(&deck1)); - ON_CALL(*pPlayerManager, getPlayer(QString("[Channel2]"))) + ON_CALL(*pPlayerManager, getDeckBase(1)) .WillByDefault(Return(&deck2)); - ON_CALL(*pPlayerManager, getPlayer(QString("[Channel3]"))) + ON_CALL(*pPlayerManager, getDeckBase(2)) .WillByDefault(Return(&deck3)); - ON_CALL(*pPlayerManager, getPlayer(QString("[Channel4]"))) + ON_CALL(*pPlayerManager, getDeckBase(3)) .WillByDefault(Return(&deck4)); pPlayerManager->numDecks.set(4); - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel1]"))).Times(1); - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel2]"))).Times(1); - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel3]"))).Times(1); - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel4]"))).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(0)).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(1)).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(2)).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(3)).Times(1); pProcessor.reset(new MockAutoDJProcessor(nullptr, config(), @@ -566,10 +566,10 @@ TEST_F(AutoDJProcessorTest, TransitionTimeLoadedFromConfig) { config()->set(ConfigKey("[Auto DJ]", "Transition"), QString("25")); // Creating a new MockAutoDJProcessor will get each player from player // manager. - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel1]"))).Times(1); - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel2]"))).Times(1); - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel3]"))).Times(1); - EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel4]"))).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(0)).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(1)).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(2)).Times(1); + EXPECT_CALL(*pPlayerManager, getDeckBase(3)).Times(1); // We need to call reset *before* constructing a new MockAutoDJProcessor, // because otherwise the new object will try to create COs that already diff --git a/src/test/playermanagertest.cpp b/src/test/playermanagertest.cpp index 3fba2dc3dcc..ff0a71fb959 100644 --- a/src/test/playermanagertest.cpp +++ b/src/test/playermanagertest.cpp @@ -129,7 +129,7 @@ class PlayerManagerTest : public MixxxDbTest, SoundSourceProviderRegistration { TEST_F(PlayerManagerTest, UnEjectTest) { // Ejecting an empty deck with no previously-recorded ejected track has no effect. - auto deck1 = m_pPlayerManager->getDeck(1); + auto deck1 = m_pPlayerManager->getDeck(0); deck1->slotEjectTrack(1.0); ASSERT_EQ(nullptr, deck1->getLoadedTrack()); @@ -154,7 +154,7 @@ TEST_F(PlayerManagerTest, UnEjectTest) { deck1->slotLoadTrack(pTrack2, false); // Ejecting in an empty deck loads the last-ejected track. - auto deck2 = m_pPlayerManager->getDeck(2); + auto deck2 = m_pPlayerManager->getDeck(1); ASSERT_EQ(nullptr, deck2->getLoadedTrack()); // make sure eject does not trigger 'unreplace' QTest::qSleep(kUnreplaceDelay); // millis @@ -166,7 +166,7 @@ TEST_F(PlayerManagerTest, UnEjectTest) { // Loading a new track in a deck causes the old one to be ejected. // That old track can be unejected into a different deck. TEST_F(PlayerManagerTest, UnEjectReplaceTrackTest) { - auto deck1 = m_pPlayerManager->getDeck(1); + auto deck1 = m_pPlayerManager->getDeck(0); // Load a track and the load another one TrackPointer pTrack1 = getOrAddTrackByLocation(getTestDir().filePath(kTrackLocationTest1)); ASSERT_NE(nullptr, pTrack1); @@ -186,7 +186,7 @@ TEST_F(PlayerManagerTest, UnEjectReplaceTrackTest) { waitForTrackToBeLoaded(deck1); // Ejecting in an empty deck loads the last-ejected track. - auto deck2 = m_pPlayerManager->getDeck(2); + auto deck2 = m_pPlayerManager->getDeck(1); ASSERT_EQ(nullptr, deck2->getLoadedTrack()); // make sure eject does not trigger 'unreplace' QTest::qSleep(kUnreplaceDelay); @@ -201,7 +201,7 @@ TEST_F(PlayerManagerTest, UnEjectInvalidTrackIdTest) { getTestDir().filePath(kTrackLocationTest1), TrackId(QVariant(10))); ASSERT_NE(nullptr, pTrack); m_pPlayerManager->slotSaveEjectedTrack(pTrack); - auto deck1 = m_pPlayerManager->getDeck(1); + auto deck1 = m_pPlayerManager->getDeck(0); // Does nothing -- no crash. // make sure eject does not trigger 'unreplace' QTest::qSleep(kUnreplaceDelay); @@ -211,7 +211,7 @@ TEST_F(PlayerManagerTest, UnEjectInvalidTrackIdTest) { TEST_F(PlayerManagerTest, UnReplaceTest) { // Trigger eject twice within 500 ms to undo track replacement - auto deck1 = m_pPlayerManager->getDeck(1); + auto deck1 = m_pPlayerManager->getDeck(0); // Load a track TrackPointer pTrack1 = getOrAddTrackByLocation(getTestDir().filePath(kTrackLocationTest1)); ASSERT_NE(nullptr, pTrack1); diff --git a/src/test/signalpathtest.h b/src/test/signalpathtest.h index 30f5a342f93..3c531933e98 100644 --- a/src/test/signalpathtest.h +++ b/src/test/signalpathtest.h @@ -71,6 +71,10 @@ class BaseSignalPathTest : public MixxxTest, SoundSourceProviderRegistration { m_pChannelHandleFactory = std::make_shared(); m_pNumDecks = new ControlObject(ConfigKey( QStringLiteral("[App]"), QStringLiteral("num_decks"))); + m_pNumSamplers = new ControlObject(ConfigKey( + QStringLiteral("[App]"), QStringLiteral("num_samplers"))); + m_pNumPreviewDecks = new ControlObject(ConfigKey( + QStringLiteral("[App]"), QStringLiteral("num_preview_decks"))); m_pEffectsManager = new EffectsManager(config(), m_pChannelHandleFactory); m_pEngineMixer = new TestEngineMixer(m_pConfig, m_sMainGroup, @@ -139,6 +143,8 @@ class BaseSignalPathTest : public MixxxTest, SoundSourceProviderRegistration { delete m_pEngineMixer; delete m_pEffectsManager; delete m_pNumDecks; + delete m_pNumSamplers; + delete m_pNumPreviewDecks; PlayerInfo::destroy(); } @@ -242,6 +248,8 @@ class BaseSignalPathTest : public MixxxTest, SoundSourceProviderRegistration { ChannelHandleFactoryPointer m_pChannelHandleFactory; ControlObject* m_pNumDecks; + ControlObject* m_pNumSamplers; + ControlObject* m_pNumPreviewDecks; std::unique_ptr m_pControlIndicatorTimer; EffectsManager* m_pEffectsManager; EngineSync* m_pEngineSync;