summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Szmigin <smidge@xsco.net>2023-06-23 23:16:52 +0100
committerAdam Szmigin <smidge@xsco.net>2023-06-23 23:16:52 +0100
commitab66ed6670e62d651ded088015a2cf0a00af1b0c (patch)
treeb5cee833f48d21a29df13481baa22f6f94c4b65b
parentd763be606148a1047522b21a8840d50d882cf1c2 (diff)
Update to libdjinterop 0.19.0enh/djinterop-0.19.0
-rw-r--r--CMakeLists.txt5
-rw-r--r--src/library/export/dlglibraryexport.cpp50
-rw-r--r--src/library/export/engineprimeexportjob.cpp71
-rw-r--r--src/library/export/engineprimeexportrequest.h2
4 files changed, 57 insertions, 71 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 807f63f919..58ff53fd12 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2038,7 +2038,7 @@ endif()
# Denon Engine Prime library export support (using libdjinterop)
option(ENGINEPRIME "Support for library export to Denon Engine Prime" ON)
if(ENGINEPRIME)
- set(LIBDJINTEROP_VERSION 0.16.1)
+ set(LIBDJINTEROP_VERSION 0.19.0)
# Look for an existing installation of libdjinterop and use that if available.
# Otherwise, download and build from GitHub.
# Note: Version 0.17.0 is not yet compatible
@@ -2075,7 +2075,7 @@ if(ENGINEPRIME)
# the configuration.
ExternalProject_Add(libdjinterop
URL "https://github.com/xsco/libdjinterop/archive/refs/tags/${LIBDJINTEROP_VERSION}.tar.gz"
- URL_HASH SHA256=25461f5cc3ea80850d8400872f4fef08ad3730d9f2051719cccf2460f5ac15ad
+ URL_HASH SHA256=0fb8374f0074d4399d29cd3356f5f68969194711f2e36f5db5b34b56e2607c64
DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads"
DOWNLOAD_NAME "libdjinterop-${LIBDJINTEROP_VERSION}.tar.gz"
INSTALL_DIR ${DJINTEROP_INSTALL_DIR}
@@ -2089,6 +2089,7 @@ if(ENGINEPRIME)
-DCMAKE_INSTALL_LIBDIR:PATH=lib
-DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH}
-DSYSTEM_SQLITE=${DJINTEROP_SYSTEM_SQLITE}
+ BUILD_COMMAND ${CMAKE_COMMAND} --build . --target DjInterop
BUILD_BYPRODUCTS <INSTALL_DIR>/${DJINTEROP_LIBRARY}
EXCLUDE_FROM_ALL TRUE
)
diff --git a/src/library/export/dlglibraryexport.cpp b/src/library/export/dlglibraryexport.cpp
index 26fbdf73ae..22bc707c47 100644
--- a/src/library/export/dlglibraryexport.cpp
+++ b/src/library/export/dlglibraryexport.cpp
@@ -17,7 +17,7 @@
#include "library/trackset/crate/crateid.h"
#include "library/trackset/crate/cratestorage.h"
-namespace el = djinterop::enginelibrary;
+namespace el = djinterop::engine;
namespace mixxx {
@@ -198,8 +198,8 @@ void DlgLibraryExport::exportRequested() {
// Work out what version was requested.
// If there is an existing database, the version does not matter.
int versionIndex = m_pVersionCombo->currentData().toInt();
- djinterop::semantic_version exportVersion =
- versionIndex == -1 ? el::version_latest_firmware : el::all_versions[versionIndex];
+ el::engine_version exportVersion =
+ versionIndex == -1 ? el::latest_os : el::all_versions[versionIndex];
// Construct a request to export the library/crates.
auto pRequest = QSharedPointer<EnginePrimeExportRequest>::create();
@@ -231,46 +231,30 @@ void DlgLibraryExport::checkExistingDatabase() {
m_pExistingDatabaseLabel->setText("");
m_pVersionCombo->clear();
m_pVersionCombo->setEnabled(true);
- int versionIndex = 0;
- for (const djinterop::semantic_version& version : el::all_versions) {
+ for (int versionIndex = 0; versionIndex < (int)el::all_versions.size(); ++versionIndex) {
+ el::engine_version version = el::all_versions[versionIndex];
m_pVersionCombo->insertItem(0,
- QString::fromStdString(el::version_name(version)),
+ QString::fromStdString(version.name),
QVariant{versionIndex});
- if (version == el::version_latest_firmware) {
+ if (version == el::latest_os) {
// Latest firmware version is the default selection.
m_pVersionCombo->setCurrentIndex(0);
}
-
- ++versionIndex;
}
return;
}
- // Find out version of the existing database, and set the displayed
- // version widget accordingly. Changing the schema version of existing
- // databases is not currently supported.
+ // Load the existing database, and set the displayed version widget
+ // accordingly. Changing the schema version of existing databases is
+ // not currently supported.
djinterop::database db = el::load_database(databaseDirectory.toStdString());
- const auto version = db.version();
-
- const auto result = std::find(el::all_versions.begin(), el::all_versions.end(), version);
- if (result == el::all_versions.end()) {
- // Unknown database version.
- m_pExistingDatabaseLabel->setText(
- tr("A database already exists in the chosen directory, "
- "but it is of an unsupported version. Export is not "
- "guaranteed to succeed in this situation."));
- m_pVersionCombo->clear();
- m_pVersionCombo->setEnabled(false);
- } else {
- int versionIndex = std::distance(el::all_versions.begin(), result);
- m_pExistingDatabaseLabel->setText(
- tr("A database already exists in the chosen directory. "
- "Exported tracks will be added into this database."));
- m_pVersionCombo->clear();
- m_pVersionCombo->insertItem(
- 0, QString::fromStdString(el::version_name(version)), QVariant{versionIndex});
- m_pVersionCombo->setEnabled(false);
- }
+ m_pExistingDatabaseLabel->setText(
+ tr("A database already exists in the chosen directory. "
+ "Exported tracks will be added into this database."));
+ m_pVersionCombo->clear();
+ m_pVersionCombo->insertItem(
+ 0, QString::fromStdString(db.version_name()), QVariant{-1});
+ m_pVersionCombo->setEnabled(false);
} catch (std::exception& e) {
Q_UNUSED(e);
diff --git a/src/library/export/engineprimeexportjob.cpp b/src/library/export/engineprimeexportjob.cpp
index d5db7057d6..840f4fa32c 100644
--- a/src/library/export/engineprimeexportjob.cpp
+++ b/src/library/export/engineprimeexportjob.cpp
@@ -18,7 +18,7 @@
#include "util/thread_affinity.h"
#include "waveform/waveformfactory.h"
-namespace el = djinterop::enginelibrary;
+namespace el = djinterop::engine;
namespace mixxx {
@@ -168,7 +168,9 @@ bool tryGetBeatgrid(BeatsPointer pBeats,
return true;
}
-void exportMetadata(djinterop::database* pDatabase,
+void exportMetadata(
+ djinterop::database* pDatabase,
+ const el::engine_version& dbVersion,
QHash<TrackId, int64_t>* pMixxxToEnginePrimeTrackIdMap,
TrackPointer pTrack,
const Waveform* pWaveform,
@@ -182,12 +184,11 @@ void exportMetadata(djinterop::database* pDatabase,
: djinterop::track_snapshot{};
snapshot.relative_path = relativePath.toStdString();
- // Note that the Engine Prime format has the scope for recording meta-data
- // about whether track was imported from an external database. However,
- // that meta-data only extends as far as other Engine Prime databases,
- // which Mixxx is not. So we do not set any import information on the
- // exported track.
snapshot.track_number = pTrack->getTrackNumber().toInt();
+ if (snapshot.track_number == 0) {
+ snapshot.track_number = djinterop::stdx::nullopt;
+ }
+
snapshot.duration = std::chrono::milliseconds{
static_cast<int64_t>(1000 * pTrack->getDuration())};
snapshot.bpm = pTrack->getBpm();
@@ -199,24 +200,14 @@ void exportMetadata(djinterop::database* pDatabase,
snapshot.comment = pTrack->getComment().toStdString();
snapshot.composer = pTrack->getComposer().toStdString();
snapshot.key = toDjinteropKey(pTrack->getKey());
- int64_t lastModifiedMillisSinceEpoch = 0;
- const QDateTime fileLastModified = pTrack->getFileInfo().lastModified();
- if (fileLastModified.isValid()) {
- // Only defined if valid
- lastModifiedMillisSinceEpoch = fileLastModified.toMSecsSinceEpoch();
- }
- std::chrono::system_clock::time_point lastModifiedAt{
- std::chrono::milliseconds{lastModifiedMillisSinceEpoch}};
- snapshot.last_modified_at = lastModifiedAt;
- snapshot.last_accessed_at = lastModifiedAt;
snapshot.bitrate = pTrack->getBitrate();
snapshot.rating = pTrack->getRating() * 20; // note rating is in range 0-100
snapshot.file_bytes = pTrack->getFileInfo().sizeInBytes();
// Frames used interchangeably with "samples" here.
const auto frameCount = static_cast<int64_t>(pTrack->getDuration() * pTrack->getSampleRate());
- snapshot.sampling = djinterop::sampling_info{
- static_cast<double>(pTrack->getSampleRate()), frameCount};
+ snapshot.sample_count = frameCount;
+ snapshot.sample_rate = pTrack->getSampleRate();
// Set track loudness.
// Note that the djinterop API method for setting loudness may be revised
@@ -229,16 +220,14 @@ void exportMetadata(djinterop::database* pDatabase,
// Set main cue-point.
mixxx::audio::FramePos cuePlayPos = pTrack->getMainCuePosition();
const auto cuePlayPosValue = cuePlayPos.isValid() ? cuePlayPos.value() : 0;
- snapshot.default_main_cue = cuePlayPosValue;
- snapshot.adjusted_main_cue = cuePlayPosValue;
+ snapshot.main_cue = cuePlayPosValue;
// Fill in beat grid.
BeatsPointer beats = pTrack->getBeats();
if (beats != nullptr) {
std::vector<djinterop::beatgrid_marker> beatgrid;
if (tryGetBeatgrid(beats, cuePlayPos, frameCount, &beatgrid)) {
- snapshot.default_beatgrid = beatgrid;
- snapshot.adjusted_beatgrid = beatgrid;
+ snapshot.beatgrid = beatgrid;
} else {
qWarning() << "Beats data exists but is invalid for track"
<< pTrack->getId() << "("
@@ -252,7 +241,7 @@ void exportMetadata(djinterop::database* pDatabase,
// Note that any existing hot cues on the track are kept in place, if Mixxx
// does not have a hot cue at that location.
const auto cues = pTrack->getCuePoints();
- snapshot.hot_cues.fill(djinterop::stdx::nullopt);
+ snapshot.hot_cues.resize(kMaxHotCues);
for (const CuePointer& pCue : cues) {
// We are only interested in hot cues.
if (pCue->getType() != CueType::HotCue) {
@@ -303,16 +292,15 @@ void exportMetadata(djinterop::database* pDatabase,
// Note also that the loops on any existing track are not modified here.
// Write waveform.
- // Note that writing a single waveform will automatically calculate an
- // overview waveform too.
if (pWaveform) {
- int64_t samplesPerEntry =
- el::required_waveform_samples_per_entry(pTrack->getSampleRate());
- int64_t externalWaveformSize = (frameCount + samplesPerEntry - 1) / samplesPerEntry;
+ djinterop::waveform_extents extents = dbVersion.is_v2_schema()
+ ? el::calculate_overview_waveform_extents(
+ frameCount, pTrack->getSampleRate())
+ : el::calculate_high_resolution_waveform_extents(frameCount, pTrack->getSampleRate());
std::vector<djinterop::waveform_entry> externalWaveform;
- externalWaveform.reserve(externalWaveformSize);
- for (int64_t i = 0; i < externalWaveformSize; ++i) {
- int64_t j = pWaveform->getDataSize() * i / externalWaveformSize;
+ externalWaveform.reserve(extents.size);
+ for (uint64_t i = 0; i < extents.size; ++i) {
+ uint64_t j = pWaveform->getDataSize() * i / extents.size;
externalWaveform.push_back({{pWaveform->getLow(j), kDefaultWaveformOpacity},
{pWaveform->getMid(j), kDefaultWaveformOpacity},
{pWaveform->getHigh(j), kDefaultWaveformOpacity}});
@@ -339,6 +327,7 @@ void exportMetadata(djinterop::database* pDatabase,
void exportTrack(
const QSharedPointer<EnginePrimeExportRequest> pRequest,
djinterop::database* pDatabase,
+ const el::engine_version& dbVersion,
QHash<TrackId, int64_t>* pMixxxToEnginePrimeTrackIdMap,
const TrackPointer pTrack,
const Waveform* pWaveform) {
@@ -355,6 +344,7 @@ void exportTrack(
// Export meta-data.
exportMetadata(pDatabase,
+ dbVersion,
pMixxxToEnginePrimeTrackIdMap,
pTrack,
pWaveform,
@@ -366,8 +356,12 @@ void exportCrate(
const QHash<TrackId, int64_t>& mixxxToEnginePrimeTrackIdMap,
const Crate& crate,
const QList<TrackId>& trackIds) {
- // Create a new crate as a sub-crate of the top-level Mixxx crate.
- auto extCrate = pExtRootCrate->create_sub_crate(crate.getName().toStdString());
+ // Create a new crate as a sub-crate of the top-level Mixxx crate, if one does not already exist.
+ auto crateName = crate.getName().toStdString();
+ const auto optionalExtCrate = pExtRootCrate->sub_crate_by_name(crateName);
+ auto extCrate = optionalExtCrate
+ ? *optionalExtCrate
+ : pExtRootCrate->create_sub_crate(crateName);
// Loop through all track ids in this crate and add.
for (const auto& trackId : trackIds) {
@@ -520,12 +514,18 @@ void EnginePrimeExportJob::run() {
// Ensure that the database exists, creating an empty one if not.
std::unique_ptr<djinterop::database> pDb;
+ el::engine_version dbVersion;
try {
bool created;
pDb = std::make_unique<djinterop::database>(el::create_or_load_database(
m_pRequest->engineLibraryDbDir.path().toStdString(),
m_pRequest->exportVersion,
- created));
+ created,
+ dbVersion));
+
+ if (!created) {
+ dbVersion = m_pRequest->exportVersion;
+ }
} catch (std::exception& e) {
qWarning() << "Failed to create/load database:" << e.what();
m_lastErrorMessage = e.what();
@@ -561,6 +561,7 @@ void EnginePrimeExportJob::run() {
try {
exportTrack(m_pRequest,
pDb.get(),
+ dbVersion,
&mixxxToEnginePrimeTrackIdMap,
m_pLastLoadedTrack,
m_pLastLoadedWaveform.get());
diff --git a/src/library/export/engineprimeexportrequest.h b/src/library/export/engineprimeexportrequest.h
index efd840be83..1f31b2beea 100644
--- a/src/library/export/engineprimeexportrequest.h
+++ b/src/library/export/engineprimeexportrequest.h
@@ -18,7 +18,7 @@ struct EnginePrimeExportRequest {
QDir musicFilesDir;
/// Version of Engine Prime database to use when exporting.
- djinterop::semantic_version exportVersion;
+ djinterop::engine::engine_version exportVersion;
/// Set of crates to export, if `exportSelectedCrates` is set to true.
///