summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUwe Klotz <uwe_klotz@web.de>2016-06-25 00:28:37 +0200
committerUwe Klotz <uwe_klotz@web.de>2016-06-25 10:12:31 +0200
commit8ce8f1f5c7776b596c381feff72cf03ac24be402 (patch)
treef67cb1e4f907f1d8142cb12856a671e086d28e3a /src
parentb0debc788f0c7ae628e67cbba9f29973881b4703 (diff)
Enhance precision of track duration from int to double
Diffstat (limited to 'src')
-rw-r--r--src/library/autodj/autodjprocessor.cpp30
-rw-r--r--src/library/autodj/autodjprocessor.h8
-rw-r--r--src/library/autodj/dlgautodj.cpp2
-rw-r--r--src/library/banshee/bansheeplaylistmodel.cpp2
-rw-r--r--src/library/browse/browsethread.cpp3
-rw-r--r--src/library/dao/trackdao.cpp12
-rw-r--r--src/library/dlgtrackinfo.cpp2
-rw-r--r--src/library/trackcollection.cpp2
-rw-r--r--src/musicbrainz/tagfetcher.cpp2
-rw-r--r--src/sources/soundsourcemodplug.cpp2
-rw-r--r--src/sources/soundsourceopus.cpp2
-rw-r--r--src/track/track.cpp30
-rw-r--r--src/track/track.h40
-rw-r--r--src/track/trackmetadata.cpp15
-rw-r--r--src/track/trackmetadata.h8
-rw-r--r--src/track/trackmetadatataglib.cpp4
16 files changed, 104 insertions, 60 deletions
diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp
index c88a13824b..497e7e4db9 100644
--- a/src/library/autodj/autodjprocessor.cpp
+++ b/src/library/autodj/autodjprocessor.cpp
@@ -9,7 +9,7 @@
#define kConfigKey "[Auto DJ]"
const char* kTransitionPreferenceName = "Transition";
-const int kTransitionPreferenceDefault = 10;
+const double kTransitionPreferenceDefault = 10.0;
static const bool sDebug = false;
@@ -73,7 +73,7 @@ AutoDJProcessor::AutoDJProcessor(QObject* pParent,
m_pPlayerManager(pPlayerManager),
m_pAutoDJTableModel(NULL),
m_eState(ADJ_DISABLED),
- m_iTransitionTime(kTransitionPreferenceDefault),
+ m_transitionTime(kTransitionPreferenceDefault),
m_nextTransitionTime(kTransitionPreferenceDefault) {
m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,
"mixxx.db.model.autodj");
@@ -123,8 +123,8 @@ AutoDJProcessor::AutoDJProcessor(QObject* pParent,
QString str_autoDjTransition = m_pConfig->getValueString(
ConfigKey(kConfigKey, kTransitionPreferenceName));
if (!str_autoDjTransition.isEmpty()) {
- m_iTransitionTime = str_autoDjTransition.toInt();
- m_nextTransitionTime = m_iTransitionTime;
+ m_transitionTime = str_autoDjTransition.toDouble();
+ m_nextTransitionTime = m_transitionTime;
}
}
@@ -707,37 +707,35 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck,
if (fromTrack) {
// TODO(rryan): Duration is super inaccurate! We should be using
// track_samples / track_samplerate instead.
- int fromTrackDuration = fromTrack->getDuration();
+ double fromTrackDuration = fromTrack->getDuration();
qDebug() << fromTrack->getLocation()
<< "fromTrackDuration =" << fromTrackDuration;
// The track might be shorter than the transition period. Use a
// sensible cap.
- m_nextTransitionTime = math_min(m_iTransitionTime,
- fromTrackDuration / 2);
+ m_nextTransitionTime = math_min(m_transitionTime,
+ fromTrackDuration / 2.0);
if (pToDeck) {
TrackPointer toTrack = pToDeck->getLoadedTrack();
if (toTrack) {
// TODO(rryan): Duration is super inaccurate! We should be using
// track_samples / track_samplerate instead.
- int toTrackDuration = toTrack->getDuration();
+ double toTrackDuration = toTrack->getDuration();
qDebug() << toTrack->getLocation()
<< "toTrackDuration = " << toTrackDuration;
m_nextTransitionTime = math_min(m_nextTransitionTime,
- toTrackDuration / 2);
+ toTrackDuration / 2.0);
}
}
- if (fromTrackDuration > 0) {
- pFromDeck->fadeDuration =
- static_cast<double>(m_nextTransitionTime) /
- static_cast<double>(fromTrackDuration);
+ if (fromTrackDuration > 0.0) {
+ pFromDeck->fadeDuration = m_nextTransitionTime / fromTrackDuration;
} else {
- pFromDeck->fadeDuration = 0;
+ pFromDeck->fadeDuration = 0.0;
}
- if (m_nextTransitionTime > 0) {
+ if (m_nextTransitionTime > 0.0) {
pFromDeck->posThreshold = 1.0 - pFromDeck->fadeDuration;
} else {
// in case of pause transition
@@ -826,7 +824,7 @@ void AutoDJProcessor::setTransitionTime(int time) {
// Update the transition time first.
m_pConfig->set(ConfigKey(kConfigKey, kTransitionPreferenceName),
ConfigValue(time));
- m_iTransitionTime = time;
+ m_transitionTime = time;
// Then re-calculate fade thresholds for the decks.
if (m_eState == ADJ_IDLE) {
diff --git a/src/library/autodj/autodjprocessor.h b/src/library/autodj/autodjprocessor.h
index f243e6f313..8a560a50b9 100644
--- a/src/library/autodj/autodjprocessor.h
+++ b/src/library/autodj/autodjprocessor.h
@@ -123,8 +123,8 @@ class AutoDJProcessor : public QObject {
return m_eState;
}
- int getTransitionTime() const {
- return m_iTransitionTime;
+ double getTransitionTime() const {
+ return m_transitionTime;
}
PlaylistTableModel* getTableModel() const {
@@ -197,8 +197,8 @@ class AutoDJProcessor : public QObject {
PlaylistTableModel* m_pAutoDJTableModel;
AutoDJState m_eState;
- int m_iTransitionTime; // the desired value set by the user
- int m_nextTransitionTime; // the tweaked value actually used
+ double m_transitionTime; // the desired value set by the user
+ double m_nextTransitionTime; // the tweaked value actually used
QList<DeckAttributes*> m_decks;
diff --git a/src/library/autodj/dlgautodj.cpp b/src/library/autodj/dlgautodj.cpp
index d00cfb2314..9b2197e422 100644
--- a/src/library/autodj/dlgautodj.cpp
+++ b/src/library/autodj/dlgautodj.cpp
@@ -200,7 +200,7 @@ void DlgAutoDJ::setTrackTableRowHeight(int rowHeight) {
}
void DlgAutoDJ::updateSelectionInfo() {
- int duration = 0;
+ double duration = 0.0;
QModelIndexList indices = m_pTrackTableView->selectionModel()->selectedRows();
diff --git a/src/library/banshee/bansheeplaylistmodel.cpp b/src/library/banshee/bansheeplaylistmodel.cpp
index 49e222ecbe..ec162d478c 100644
--- a/src/library/banshee/bansheeplaylistmodel.cpp
+++ b/src/library/banshee/bansheeplaylistmodel.cpp
@@ -305,7 +305,7 @@ TrackPointer BansheePlaylistModel::getTrack(const QModelIndex& index) const {
if (pTrack && !track_already_in_library) {
pTrack->setArtist(getFieldString(index, CLM_ARTIST));
pTrack->setTitle(getFieldString(index, CLM_TITLE));
- pTrack->setDuration(getFieldString(index, CLM_DURATION).toInt());
+ pTrack->setDuration(getFieldString(index, CLM_DURATION).toDouble());
pTrack->setAlbum(getFieldString(index, CLM_ALBUM));
pTrack->setAlbumArtist(getFieldString(index, CLM_ALBUM_ARTIST));
pTrack->setYear(getFieldString(index, CLM_YEAR));
diff --git a/src/library/browse/browsethread.cpp b/src/library/browse/browsethread.cpp
index 227fe16c13..dddac5399b 100644
--- a/src/library/browse/browsethread.cpp
+++ b/src/library/browse/browsethread.cpp
@@ -10,7 +10,6 @@
#include "library/browse/browsetablemodel.h"
#include "sources/soundsourceproxy.h"
#include "track/trackmetadata.h"
-#include "util/duration.h"
#include "util/trace.h"
@@ -213,7 +212,7 @@ void BrowseThread::populateModel() {
item->setData(item->text(), Qt::UserRole);
row_data.insert(COLUMN_COMMENT, item);
- QString duration = mixxx::Duration::formatSeconds(pTrack->getDuration());
+ QString duration = pTrack->getDurationText(mixxx::Duration::Precision::SECONDS);
item = new QStandardItem(duration);
item->setToolTip(item->text());
item->setData(item->text(), Qt::UserRole);
diff --git a/src/library/dao/trackdao.cpp b/src/library/dao/trackdao.cpp
index 4f44802771..a845760828 100644
--- a/src/library/dao/trackdao.cpp
+++ b/src/library/dao/trackdao.cpp
@@ -390,7 +390,7 @@ void TrackDAO::addTracksPrepare() {
m_pQueryLibraryInsert->prepare("INSERT INTO library "
"("
"artist,title,album,album_artist,year,genre,tracknumber,tracktotal,composer,"
- "grouping,filetype,location,comment,url,duration,rating,key,key_id,"
+ "grouping,filetype,location,comment,url,duration,duration_real,rating,key,key_id,"
"bitrate,samplerate,cuepoint,bpm,replaygain,replaygain_peak,wavesummaryhex,"
"timesplayed,channels,mixxx_deleted,header_parsed,"
"beats_version,beats_sub_version,beats,bpm_lock,"
@@ -398,7 +398,7 @@ void TrackDAO::addTracksPrepare() {
"coverart_source,coverart_type,coverart_location,coverart_hash"
") VALUES ("
":artist,:title,:album,:album_artist,:year,:genre,:tracknumber,:tracktotal,:composer,"
- ":grouping,:filetype,:location,:comment,:url,:duration,:rating,:key,:key_id,"
+ ":grouping,:filetype,:location,:comment,:url,:duration,:duration_real,:rating,:key,:key_id,"
":bitrate,:samplerate,:cuepoint,:bpm,:replaygain,:replaygain_peak,:wavesummaryhex,"
":timesplayed,:channels,:mixxx_deleted,:header_parsed,"
":beats_version,:beats_sub_version,:beats,:bpm_lock,"
@@ -465,7 +465,8 @@ namespace {
pTrackLibraryQuery->bindValue(":filetype", track.getType());
pTrackLibraryQuery->bindValue(":comment", track.getComment());
pTrackLibraryQuery->bindValue(":url", track.getURL());
- pTrackLibraryQuery->bindValue(":duration", track.getDuration());
+ pTrackLibraryQuery->bindValue(":duration", track.getDurationInt());
+ pTrackLibraryQuery->bindValue(":duration_real", track.getDuration());
pTrackLibraryQuery->bindValue(":rating", track.getRating());
pTrackLibraryQuery->bindValue(":bitrate", track.getBitrate());
pTrackLibraryQuery->bindValue(":samplerate", track.getSampleRate());
@@ -1088,7 +1089,7 @@ bool setTrackUrl(const QSqlRecord& record, const int column,
bool setTrackDuration(const QSqlRecord& record, const int column,
TrackPointer pTrack) {
- pTrack->setDuration(record.value(column).toInt());
+ pTrack->setDuration(record.value(column).toDouble());
return false;
}
@@ -1279,7 +1280,7 @@ TrackPointer TrackDAO::getTrackFromDB(TrackId trackId) const {
{ "rating", setTrackRating },
{ "comment", setTrackComment },
{ "url", setTrackUrl },
- { "duration", setTrackDuration },
+ { "duration_real", setTrackDuration },
{ "bitrate", setTrackBitrate },
{ "samplerate", setTrackSampleRate },
{ "cuepoint", setTrackCuePoint },
@@ -1542,6 +1543,7 @@ bool TrackDAO::updateTrack(Track* pTrack) {
"comment=:comment,"
"url=:url,"
"duration=:duration,"
+ "duration_real=:duration_real,"
"rating=:rating,"
"key=:key,"
"key_id=:key_id,"
diff --git a/src/library/dlgtrackinfo.cpp b/src/library/dlgtrackinfo.cpp
index d3998a9648..a83c9321b6 100644
--- a/src/library/dlgtrackinfo.cpp
+++ b/src/library/dlgtrackinfo.cpp
@@ -165,7 +165,7 @@ void DlgTrackInfo::populateFields(const Track& track) {
txtComment->setPlainText(track.getComment());
// Non-editable fields
- txtDuration->setText(track.getDurationText());
+ txtDuration->setText(track.getDurationText(mixxx::Duration::Precision::SECONDS));
txtLocation->setPlainText(track.getLocation());
txtType->setText(track.getType());
txtBitrate->setText(QString(track.getBitrateText()) + (" ") + tr("kbps"));
diff --git a/src/library/trackcollection.cpp b/src/library/trackcollection.cpp
index 5406bfbf8f..1af6d52ebb 100644
--- a/src/library/trackcollection.cpp
+++ b/src/library/trackcollection.cpp
@@ -14,7 +14,7 @@
#include "util/assert.h"
// static
-const int TrackCollection::kRequiredSchemaVersion = 26;
+const int TrackCollection::kRequiredSchemaVersion = 27;
TrackCollection::TrackCollection(UserSettingsPointer pConfig)
: m_pConfig(pConfig),
diff --git a/src/musicbrainz/tagfetcher.cpp b/src/musicbrainz/tagfetcher.cpp
index 516f641571..9a7320f158 100644
--- a/src/musicbrainz/tagfetcher.cpp
+++ b/src/musicbrainz/tagfetcher.cpp
@@ -85,7 +85,7 @@ void TagFetcher::fingerprintFound(int index) {
emit(fetchProgress(tr("Identifying track")));
// qDebug() << "start to look up the MBID";
- m_AcoustidClient.start(index, fingerprint, ptrack->getDuration());
+ m_AcoustidClient.start(index, fingerprint, ptrack->getDurationInt());
}
void TagFetcher::mbidFound(int index, const QString& mbid) {
diff --git a/src/sources/soundsourcemodplug.cpp b/src/sources/soundsourcemodplug.cpp
index 627e230040..bfeaf9cb00 100644
--- a/src/sources/soundsourcemodplug.cpp
+++ b/src/sources/soundsourcemodplug.cpp
@@ -77,7 +77,7 @@ Result SoundSourceModPlug::parseTrackMetadataAndCoverArt(
if (nullptr != pModFile) {
pTrackMetadata->setComment(QString(ModPlug::ModPlug_GetMessage(pModFile)));
pTrackMetadata->setTitle(QString(ModPlug::ModPlug_GetName(pModFile)));
- pTrackMetadata->setDuration(ModPlug::ModPlug_GetLength(pModFile) / 1000);
+ pTrackMetadata->setDuration(ModPlug::ModPlug_GetLength(pModFile) / 1000.0);
pTrackMetadata->setBitrate(8); // not really, but fill in something...
ModPlug::ModPlug_Unload(pModFile);
}
diff --git a/src/sources/soundsourceopus.cpp b/src/sources/soundsourceopus.cpp
index 4a87feea22..9747eb99fa 100644
--- a/src/sources/soundsourceopus.cpp
+++ b/src/sources/soundsourceopus.cpp
@@ -84,7 +84,7 @@ Result SoundSourceOpus::parseTrackMetadataAndCoverArt(
pTrackMetadata->setSampleRate(kSamplingRate);
pTrackMetadata->setBitrate(op_bitrate(l_ptrOpusFile, -1) / 1000);
pTrackMetadata->setDuration(
- op_pcm_total(l_ptrOpusFile, -1) / pTrackMetadata->getSampleRate());
+ double(op_pcm_total(l_ptrOpusFile, -1)) / double(pTrackMetadata->getSampleRate()));
bool hasDate = false;
for (i = 0; i < l_ptrOpusTags->comments; ++i) {
diff --git a/src/track/track.cpp b/src/track/track.cpp
index 88a423ed38..1ed5b11107 100644
--- a/src/track/track.cpp
+++ b/src/track/track.cpp
@@ -11,7 +11,6 @@
#include "track/trackmetadatataglib.h"
#include "util/assert.h"
#include "util/compatibility.h"
-#include "util/duration.h"
namespace {
@@ -373,21 +372,38 @@ void Track::setDateAdded(const QDateTime& dateAdded) {
m_dateAdded = dateAdded;
}
-void Track::setDuration(int iDuration) {
+void Track::setDuration(double duration) {
QMutexLocker lock(&m_qMutex);
- if (m_metadata.getDuration() != iDuration) {
- m_metadata.setDuration(iDuration);
+ if (m_metadata.getDuration() != duration) {
+ m_metadata.setDuration(duration);
markDirtyAndUnlock(&lock);
}
}
-int Track::getDuration() const {
+double Track::getDuration(DurationRounding rounding) const {
QMutexLocker lock(&m_qMutex);
+ switch (rounding) {
+ case DurationRounding::SECONDS:
+ return std::round(m_metadata.getDuration());
+ case DurationRounding::NONE:
+ return m_metadata.getDuration();
+ }
+ // unreachable code / avoid compiler warnings
+ DEBUG_ASSERT(!"unhandled enum value");
return m_metadata.getDuration();
}
-QString Track::getDurationText() const {
- return mixxx::Duration::formatSeconds(getDuration());
+QString Track::getDurationText(mixxx::Duration::Precision precision) const {
+ double duration;
+ if (precision == mixxx::Duration::Precision::SECONDS) {
+ // Round to full seconds before formatting for consistency:
+ // getDurationText() should always display the same number
+ // as getDuration(DurationRounding::SECONDS) = getDurationInt()
+ duration = getDuration(DurationRounding::SECONDS);
+ } else {
+ duration = getDuration(DurationRounding::NONE);
+ }
+ return mixxx::Duration::formatSeconds(duration, precision);
}
QString Track::getTitle() const {
diff --git a/src/track/track.h b/src/track/track.h
index 351a80bfb0..3eda94af8c 100644
--- a/src/track/track.h
+++ b/src/track/track.h
@@ -17,6 +17,7 @@
#include "track/playcounter.h"
#include "track/trackmetadata.h"
#include "util/sandbox.h"
+#include "util/duration.h"
#include "waveform/waveform.h"
class Track;
@@ -59,8 +60,10 @@ class Track : public QObject {
Q_PROPERTY(double bpm READ getBpm WRITE setBpm)
Q_PROPERTY(QString bpmFormatted READ getBpmText STORED false)
Q_PROPERTY(QString key READ getKeyText WRITE setKeyText)
- Q_PROPERTY(int duration READ getDuration WRITE setDuration)
- Q_PROPERTY(QString durationFormatted READ getDurationText STORED false)
+ Q_PROPERTY(double duration READ getDuration WRITE setDuration)
+ Q_PROPERTY(QString durationFormatted READ getDurationTextSeconds STORED false)
+ Q_PROPERTY(QString durationFormattedCentiseconds READ getDurationTextCentiseconds STORED false)
+ Q_PROPERTY(QString durationFormattedMilliseconds READ getDurationTextMilliseconds STORED false)
QFileInfo getFileInfo() const {
// Copying a QFileInfo is thread-safe (implicit sharing), no locking needed.
@@ -114,12 +117,27 @@ class Track : public QObject {
// Returns the bitrate as a string
QString getBitrateText() const;
- // Set duration in seconds
- void setDuration(int);
- // Returns the duration in seconds
- int getDuration() const;
- // Returns the duration as a string: H:MM:SS
- QString getDurationText() const;
+ void setDuration(double duration);
+ double getDuration() const {
+ return getDuration(DurationRounding::NONE);
+ }
+ // Returns the duration rounded to seconds
+ int getDurationInt() const {
+ return static_cast<int>(getDuration(DurationRounding::SECONDS));
+ }
+ // Returns the duration formatted as a string (H:MM:SS or H:MM:SS.cc or H:MM:SS.mmm)
+ QString getDurationText(mixxx::Duration::Precision precision) const;
+
+ // Helper functions for Q_PROPERTYs
+ QString getDurationTextSeconds() const {
+ return getDurationText(mixxx::Duration::Precision::SECONDS);
+ }
+ QString getDurationTextCentiseconds() const {
+ return getDurationText(mixxx::Duration::Precision::CENTISECONDS);
+ }
+ QString getDurationTextMilliseconds() const {
+ return getDurationText(mixxx::Duration::Precision::MILLISECONDS);
+ }
// Set BPM
double setBpm(double);
@@ -324,6 +342,12 @@ class Track : public QObject {
// Only used by TrackDAO!
void setId(TrackId id);
+ enum class DurationRounding {
+ SECONDS, // rounded to full seconds
+ NONE // unmodified
+ };
+ double getDuration(DurationRounding rounding) const;
+
// The file
const QFileInfo m_fileInfo;
diff --git a/src/track/trackmetadata.cpp b/src/track/trackmetadata.cpp
index 77d0f77707..5affb01425 100644
--- a/src/track/trackmetadata.cpp
+++ b/src/track/trackmetadata.cpp
@@ -67,14 +67,19 @@ QString TrackMetadata::reformatYear(QString year) {
}
TrackMetadata::TrackMetadata()
- : m_bitrate(0),
+ : m_duration(0.0),
+ m_bitrate(0),
m_channels(0),
- m_duration(0),
m_sampleRate(0) {
}
bool operator==(const TrackMetadata& lhs, const TrackMetadata& rhs) {
- return (lhs.getArtist() == rhs.getArtist()) &&
+ // Compare the integer and double fields 1st for maximum efficiency
+ return (lhs.getBitrate() == rhs.getBitrate()) &&
+ (lhs.getChannels() == rhs.getChannels()) &&
+ (lhs.getSampleRate() == rhs.getSampleRate()) &&
+ (lhs.getDuration() == rhs.getDuration()) &&
+ (lhs.getArtist() == rhs.getArtist()) &&
(lhs.getTitle() == rhs.getTitle()) &&
(lhs.getAlbum() == rhs.getAlbum()) &&
(lhs.getAlbumArtist() == rhs.getAlbumArtist()) &&
@@ -86,10 +91,6 @@ bool operator==(const TrackMetadata& lhs, const TrackMetadata& rhs) {
(lhs.getComposer() == rhs.getComposer()) &&
(lhs.getGrouping() == rhs.getGrouping()) &&
(lhs.getKey() == rhs.getKey()) &&
- (lhs.getChannels() == rhs.getChannels()) &&
- (lhs.getSampleRate() == rhs.getSampleRate()) &&
- (lhs.getBitrate() == rhs.getBitrate()) &&
- (lhs.getDuration() == rhs.getDuration()) &&
(lhs.getBpm() == rhs.getBpm()) &&
(lhs.getReplayGain() == rhs.getReplayGain());
}
diff --git a/src/track/trackmetadata.h b/src/track/trackmetadata.h
index d80cb0a6b1..58cef6bb85 100644
--- a/src/track/trackmetadata.h
+++ b/src/track/trackmetadata.h
@@ -122,10 +122,10 @@ public:
}
// #seconds
- int getDuration() const {
+ double getDuration() const {
return m_duration;
}
- void setDuration(int duration) {
+ void setDuration(double duration) {
m_duration = duration;
}
@@ -189,10 +189,12 @@ private:
Bpm m_bpm;
ReplayGain m_replayGain;
+ // Floating-point fields (in alphabetical order)
+ double m_duration; // seconds
+
// Integer fields (in alphabetical order)
int m_bitrate; // kbit/s
int m_channels;
- int m_duration; // seconds
int m_sampleRate; // Hz
};
diff --git a/src/track/trackmetadatataglib.cpp b/src/track/trackmetadatataglib.cpp
index 021190727a..6818e1f6c3 100644
--- a/src/track/trackmetadatataglib.cpp
+++ b/src/track/trackmetadatataglib.cpp
@@ -252,8 +252,10 @@ void readAudioProperties(TrackMetadata* pTrackMetadata,
pTrackMetadata->setChannels(audioProperties.channels());
pTrackMetadata->setSampleRate(audioProperties.sampleRate());
- pTrackMetadata->setDuration(audioProperties.length());
pTrackMetadata->setBitrate(audioProperties.bitrate());
+ // Duration will be replaced by the actual length with
+ // sub-second precision later
+ pTrackMetadata->setDuration(audioProperties.length());
}
bool readAudioProperties(TrackMetadata* pTrackMetadata,