summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Klotz <uklotz@mixxx.org>2020-07-13 01:17:57 +0200
committerUwe Klotz <uklotz@mixxx.org>2020-07-13 01:17:57 +0200
commit7d71d75d753a98d9d2abec37818f440470a4248d (patch)
treec3749e50b9b34a57e0d18a48e265b47cadb1383a
parent4d11c82f6e3ba780b1db037dfce92cb48f7668ad (diff)
parentf6210f4d84c13792fdbe022feb5a4d586bf0fa9d (diff)
Merge branch '2.3' of git@github.com:mixxxdj/mixxx.git
-rw-r--r--src/library/dao/trackdao.cpp11
-rw-r--r--src/library/librarycontrol.cpp20
-rw-r--r--src/library/librarycontrol.h4
-rw-r--r--src/track/track.cpp27
-rw-r--r--src/track/track.h5
-rw-r--r--src/widget/wtracktableview.cpp12
-rw-r--r--src/widget/wtracktableview.h4
7 files changed, 71 insertions, 12 deletions
diff --git a/src/library/dao/trackdao.cpp b/src/library/dao/trackdao.cpp
index 86f24fe5ed..25d5a6691f 100644
--- a/src/library/dao/trackdao.cpp
+++ b/src/library/dao/trackdao.cpp
@@ -687,6 +687,10 @@ TrackId TrackDAO::addTracksAddTrack(const TrackPointer& pTrack, bool unremove) {
trackId = TrackId(m_pQueryLibrarySelect->value(m_queryLibraryIdColumn));
DEBUG_ASSERT(trackId.isValid());
}
+ VERIFY_OR_DEBUG_ASSERT(trackId.isValid()) {
+ return TrackId();
+ }
+ pTrack->initId(trackId);
// Track already included in library, but maybe marked as deleted
bool mixxx_deleted = m_pQueryLibrarySelect->value(m_queryLibraryMixxxDeletedColumn).toBool();
if (unremove && mixxx_deleted) {
@@ -741,6 +745,7 @@ TrackId TrackDAO::addTracksAddTrack(const TrackPointer& pTrack, bool unremove) {
VERIFY_OR_DEBUG_ASSERT(trackId.isValid()) {
return TrackId();
}
+ pTrack->initId(trackId);
pTrack->setDateAdded(trackDateAdded);
m_analysisDao.saveTrackAnalyses(
@@ -808,8 +813,12 @@ TrackPointer TrackDAO::addTracksAddFile(const TrackFile& trackFile, bool unremov
// GlobalTrackCache will be unlocked implicitly
return TrackPointer();
}
- cacheResolver.initTrackIdAndUnlockCache(newTrackId);
+ // The track object has already been initialized with the
+ // database id, but the cache is not aware of this yet.
+ // Re-initializing the track object with the same id again
+ // from within the cache scope is allowed.
DEBUG_ASSERT(pTrack->getId() == newTrackId);
+ cacheResolver.initTrackIdAndUnlockCache(newTrackId);
// Only newly inserted tracks must be marked as clean!
// Existing or unremoved tracks have not been added to
// m_tracksAddedSet and will keep their dirty flag unchanged.
diff --git a/src/library/librarycontrol.cpp b/src/library/librarycontrol.cpp
index d1e9d6579f..fb1e5da22a 100644
--- a/src/library/librarycontrol.cpp
+++ b/src/library/librarycontrol.cpp
@@ -156,6 +156,13 @@ LibraryControl::LibraryControl(Library* pLibrary)
this,
&LibraryControl::slotAutoDjAddBottom);
+ m_pAutoDjAddReplace = std::make_unique<ControlPushButton>(
+ ConfigKey("[Library]", "AutoDjAddReplace"));
+ connect(m_pAutoDjAddReplace.get(),
+ &ControlPushButton::valueChanged,
+ this,
+ &LibraryControl::slotAutoDjAddReplace);
+
// Sort controls
m_pSortColumn = std::make_unique<ControlEncoder>(ConfigKey("[Library]", "sort_column"));
m_pSortOrder = std::make_unique<ControlPushButton>(ConfigKey("[Library]", "sort_order"));
@@ -409,6 +416,19 @@ void LibraryControl::slotAutoDjAddBottom(double v) {
}
}
+void LibraryControl::slotAutoDjAddReplace(double v) {
+ if (!m_pLibraryWidget) {
+ return;
+ }
+ if (v > 0) {
+ auto activeView = m_pLibraryWidget->getActiveView();
+ if (!activeView) {
+ return;
+ }
+ activeView->slotAddToAutoDJReplace();
+ }
+}
+
void LibraryControl::slotSelectNextTrack(double v) {
if (v > 0) {
slotSelectTrack(1);
diff --git a/src/library/librarycontrol.h b/src/library/librarycontrol.h
index 6c438942c5..dd8046c89e 100644
--- a/src/library/librarycontrol.h
+++ b/src/library/librarycontrol.h
@@ -85,6 +85,7 @@ class LibraryControl : public QObject {
void slotLoadSelectedIntoFirstStopped(double v);
void slotAutoDjAddTop(double v);
void slotAutoDjAddBottom(double v);
+ void slotAutoDjAddReplace(double v);
void maybeCreateGroupController(const QString& group);
void slotNumDecksChanged(double v);
@@ -129,9 +130,10 @@ class LibraryControl : public QObject {
// Control to choose the currently selected item in focused widget (double click)
std::unique_ptr<ControlObject> m_pGoToItem;
- // Add to Auto-Dj Cueue
+ // Add to Auto-Dj Queue
std::unique_ptr<ControlObject> m_pAutoDjAddTop;
std::unique_ptr<ControlObject> m_pAutoDjAddBottom;
+ std::unique_ptr<ControlObject> m_pAutoDjAddReplace;
// Controls to sort the track view
std::unique_ptr<ControlEncoder> m_pSortColumn;
diff --git a/src/track/track.cpp b/src/track/track.cpp
index 506359209b..16c1459759 100644
--- a/src/track/track.cpp
+++ b/src/track/track.cpp
@@ -681,21 +681,31 @@ TrackId Track::getId() const {
void Track::initId(TrackId id) {
QMutexLocker lock(&m_qMutex);
+ DEBUG_ASSERT(id.isValid());
+ if (m_record.getId() == id) {
+ return;
+ }
// The track's id must be set only once and immediately after
// the object has been created.
- VERIFY_OR_DEBUG_ASSERT(!m_record.getId().isValid() || (m_record.getId() == id)) {
+ VERIFY_OR_DEBUG_ASSERT(!m_record.getId().isValid()) {
kLogger.warning() << "Cannot change id from"
<< m_record.getId() << "to" << id;
return; // abort
}
- m_record.setId(std::move(id));
+ m_record.setId(id);
+ for (const auto pCue : qAsConst(m_cuePoints)) {
+ pCue->setTrackId(id);
+ }
// Changing the Id does not make the track dirty because the Id is always
- // generated by the Database itself.
+ // generated by the database itself.
}
void Track::resetId() {
QMutexLocker lock(&m_qMutex);
m_record.setId(TrackId());
+ for (const auto pCue : qAsConst(m_cuePoints)) {
+ pCue->setTrackId(TrackId());
+ }
}
void Track::setURL(const QString& url) {
@@ -838,16 +848,18 @@ CuePointer Track::findCueById(int id) const {
}
void Track::removeCue(const CuePointer& pCue) {
- if (pCue == nullptr) {
+ if (!pCue) {
return;
}
QMutexLocker lock(&m_qMutex);
+ DEBUG_ASSERT(pCue->getTrackId() == m_record.getId());
disconnect(pCue.get(), 0, this, 0);
m_cuePoints.removeOne(pCue);
if (pCue->getType() == mixxx::CueType::MainCue) {
m_record.setCuePoint(CuePosition());
}
+ pCue->setTrackId(TrackId());
markDirtyAndUnlock(&lock);
emit cuesUpdated();
}
@@ -861,6 +873,7 @@ void Track::removeCuesOfType(mixxx::CueType type) {
// FIXME: Why does this only work for the Hotcue Type?
if (pCue->getType() == type) {
disconnect(pCue.get(), 0, this, 0);
+ pCue->setTrackId(TrackId());
it.remove();
dirty = true;
}
@@ -874,11 +887,6 @@ void Track::removeCuesOfType(mixxx::CueType type) {
}
}
-QList<CuePointer> Track::getCuePoints() const {
- QMutexLocker lock(&m_qMutex);
- return m_cuePoints;
-}
-
void Track::setCuePoints(const QList<CuePointer>& cuePoints) {
// While this method could be called from any thread,
// associated Cue objects should always live on the
@@ -951,6 +959,7 @@ void Track::setCuePointsMarkDirtyAndUnlock(
// disconnect existing cue points
for (const auto& pCue: m_cuePoints) {
disconnect(pCue.get(), 0, this, 0);
+ pCue->setTrackId(TrackId());
}
m_cuePoints = cuePoints;
// connect new cue points
diff --git a/src/track/track.h b/src/track/track.h
index 97d2b95066..56b920fedb 100644
--- a/src/track/track.h
+++ b/src/track/track.h
@@ -268,7 +268,10 @@ class Track : public QObject {
CuePointer findCueById(int id) const;
void removeCue(const CuePointer& pCue);
void removeCuesOfType(mixxx::CueType);
- QList<CuePointer> getCuePoints() const;
+ QList<CuePointer> getCuePoints() const {
+ // Copying implicitly shared collections is thread-safe
+ return m_cuePoints;
+ }
void setCuePoints(const QList<CuePointer>& cuePoints);
diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp
index fdc409ae47..da1f43bfb8 100644
--- a/src/widget/wtracktableview.cpp
+++ b/src/widget/wtracktableview.cpp
@@ -839,6 +839,18 @@ void WTrackTableView::addToAutoDJ(PlaylistDAO::AutoDJSendLoc loc) {
playlistDao.addTracksToAutoDJQueue(trackIds, loc);
}
+void WTrackTableView::slotAddToAutoDJBottom() {
+ addToAutoDJ(PlaylistDAO::AutoDJSendLoc::BOTTOM);
+}
+
+void WTrackTableView::slotAddToAutoDJTop() {
+ addToAutoDJ(PlaylistDAO::AutoDJSendLoc::TOP);
+}
+
+void WTrackTableView::slotAddToAutoDJReplace() {
+ addToAutoDJ(PlaylistDAO::AutoDJSendLoc::REPLACE);
+}
+
void WTrackTableView::doSortByColumn(int headerSection, Qt::SortOrder sortOrder) {
TrackModel* trackModel = getTrackModel();
QAbstractItemModel* itemModel = model();
diff --git a/src/widget/wtracktableview.h b/src/widget/wtracktableview.h
index 2e5af79b43..f00d982ab0 100644
--- a/src/widget/wtracktableview.h
+++ b/src/widget/wtracktableview.h
@@ -56,6 +56,10 @@ class WTrackTableView : public WLibraryTableView {
void slotUnhide();
void slotPurge();
+ void slotAddToAutoDJBottom() override;
+ void slotAddToAutoDJTop() override;
+ void slotAddToAutoDJReplace() override;
+
private slots:
void doSortByColumn(int headerSection, Qt::SortOrder sortOrder);
void applySortingIfVisible();