summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUwe Klotz <uklotz@mixxx.org>2020-12-07 15:06:42 +0100
committerUwe Klotz <uklotz@mixxx.org>2020-12-07 16:16:29 +0100
commitc60ec145af33e51a750a7301285027f5d40d8af0 (patch)
treefb4bab026bfafa133c72d6fa826e4fb65fdba054 /src
parent11c9e64e8e38dd428efc9758f26de3945daea98d (diff)
Reuse StreamInfo for TrackMetadata
Replace individual properties in TrackMetadata with a single StreamInfo property.
Diffstat (limited to 'src')
-rw-r--r--src/sources/soundsourcemodplug.cpp13
-rw-r--r--src/sources/soundsourceopus.cpp17
-rw-r--r--src/sources/soundsourceproxy.cpp2
-rw-r--r--src/test/trackmetadata_test.cpp31
-rw-r--r--src/track/taglib/trackmetadata_file.cpp26
-rw-r--r--src/track/track.cpp127
-rw-r--r--src/track/track.h18
-rw-r--r--src/track/trackmetadata.cpp71
-rw-r--r--src/track/trackmetadata.h23
9 files changed, 177 insertions, 151 deletions
diff --git a/src/sources/soundsourcemodplug.cpp b/src/sources/soundsourcemodplug.cpp
index 4d1520e5b0..9fd98a767a 100644
--- a/src/sources/soundsourcemodplug.cpp
+++ b/src/sources/soundsourcemodplug.cpp
@@ -108,11 +108,14 @@ SoundSourceModPlug::importTrackMetadataAndCoverImage(
pTrackMetadata->refTrackInfo().setComment(QString(ModPlug::ModPlug_GetMessage(pModFile)));
pTrackMetadata->refTrackInfo().setTitle(QString(ModPlug::ModPlug_GetName(pModFile)));
- pTrackMetadata->setChannelCount(audio::ChannelCount(kChannelCount));
- pTrackMetadata->setSampleRate(audio::SampleRate(kSampleRate));
- pTrackMetadata->setBitrate(audio::Bitrate(8));
- pTrackMetadata->setDuration(Duration::fromMillis(ModPlug::ModPlug_GetLength(pModFile)));
- ModPlug::ModPlug_Unload(pModFile);
+ pTrackMetadata->setStreamInfo(audio::StreamInfo{
+ audio::SignalInfo{
+ audio::ChannelCount(kChannelCount),
+ audio::SampleRate(kSampleRate),
+ },
+ audio::Bitrate(8),
+ Duration::fromMillis(ModPlug::ModPlug_GetLength(pModFile)),
+ });
return std::make_pair(ImportResult::Succeeded, QFileInfo(modFile).lastModified());
}
diff --git a/src/sources/soundsourceopus.cpp b/src/sources/soundsourceopus.cpp
index c5ade89860..9cf9eaad10 100644
--- a/src/sources/soundsourceopus.cpp
+++ b/src/sources/soundsourceopus.cpp
@@ -138,17 +138,18 @@ SoundSourceOpus::importTrackMetadataAndCoverImage(
return imported;
}
- pTrackMetadata->setChannelCount(
- audio::ChannelCount(op_channel_count(pOggOpusFile, -1)));
- pTrackMetadata->setSampleRate(
- kSampleRate);
- pTrackMetadata->setBitrate(
- audio::Bitrate(op_bitrate(pOggOpusFile, -1) / 1000));
// Cast to double is required for duration with sub-second precision
const double dTotalFrames = op_pcm_total(pOggOpusFile, -1);
const auto duration = Duration::fromMicros(
- static_cast<qint64>(1000000 * dTotalFrames / pTrackMetadata->getSampleRate()));
- pTrackMetadata->setDuration(duration);
+ static_cast<qint64>(1000000 * dTotalFrames / kSampleRate));
+ pTrackMetadata->setStreamInfo(audio::StreamInfo{
+ audio::SignalInfo{
+ audio::ChannelCount(op_channel_count(pOggOpusFile, -1)),
+ kSampleRate,
+ },
+ audio::Bitrate(op_bitrate(pOggOpusFile, -1) / 1000),
+ duration,
+ });
#ifndef TAGLIB_HAS_OPUSFILE
const OpusTags* l_ptrOpusTags = op_tags(pOggOpusFile, -1);
diff --git a/src/sources/soundsourceproxy.cpp b/src/sources/soundsourceproxy.cpp
index 1347579439..5fb2f6b1ed 100644
--- a/src/sources/soundsourceproxy.cpp
+++ b/src/sources/soundsourceproxy.cpp
@@ -682,7 +682,7 @@ mixxx::AudioSourcePointer SoundSourceProxy::openAudioSource(
DEBUG_ASSERT(m_pAudioSource);
// Overwrite metadata with actual audio properties
if (m_pTrack) {
- m_pTrack->updateAudioPropertiesFromStream(
+ m_pTrack->updateStreamInfoFromSource(
m_pAudioSource->getStreamInfo());
}
return m_pAudioSource;
diff --git a/src/test/trackmetadata_test.cpp b/src/test/trackmetadata_test.cpp
index aec136ab0c..af16af07fe 100644
--- a/src/test/trackmetadata_test.cpp
+++ b/src/test/trackmetadata_test.cpp
@@ -66,10 +66,15 @@ TEST_F(TrackMetadataTest, mergeImportedMetadata) {
// Existing track metadata (stored in the database) without extra properties
mixxx::TrackRecord oldTrackRecord;
mixxx::TrackMetadata* pOldTrackMetadata = oldTrackRecord.ptrMetadata();
- pOldTrackMetadata->setBitrate(mixxx::audio::Bitrate(100));
- pOldTrackMetadata->setChannelCount(mixxx::audio::ChannelCount(1));
- pOldTrackMetadata->setDuration(mixxx::Duration::fromSeconds(60));
- pOldTrackMetadata->setSampleRate(mixxx::audio::SampleRate(10000));
+ pOldTrackMetadata->setStreamInfo(
+ mixxx::audio::StreamInfo{
+ mixxx::audio::SignalInfo{
+ mixxx::audio::ChannelCount(1),
+ mixxx::audio::SampleRate(10000),
+ },
+ mixxx::audio::Bitrate(100),
+ mixxx::Duration::fromSeconds(60),
+ });
mixxx::TrackInfo* pOldTrackInfo = pOldTrackMetadata->ptrTrackInfo();
pOldTrackInfo->setArtist("old artist");
pOldTrackInfo->setBpm(mixxx::Bpm(100));
@@ -89,10 +94,15 @@ TEST_F(TrackMetadataTest, mergeImportedMetadata) {
// Imported track metadata (from file tags) with extra properties
mixxx::TrackMetadata newTrackMetadata;
- newTrackMetadata.setBitrate(mixxx::audio::Bitrate(200));
- newTrackMetadata.setChannelCount(mixxx::audio::ChannelCount(2));
- newTrackMetadata.setDuration(mixxx::Duration::fromSeconds(120));
- newTrackMetadata.setSampleRate(mixxx::audio::SampleRate(20000));
+ newTrackMetadata.setStreamInfo(
+ mixxx::audio::StreamInfo{
+ mixxx::audio::SignalInfo{
+ mixxx::audio::ChannelCount(2),
+ mixxx::audio::SampleRate(20000),
+ },
+ mixxx::audio::Bitrate(200),
+ mixxx::Duration::fromSeconds(120),
+ });
mixxx::TrackInfo* pNewTrackInfo = newTrackMetadata.ptrTrackInfo();
pNewTrackInfo->setArtist("new artist");
pNewTrackInfo->setBpm(mixxx::Bpm(200));
@@ -149,10 +159,7 @@ TEST_F(TrackMetadataTest, mergeImportedMetadata) {
mergedTrackRecord.mergeImportedMetadata(newTrackMetadata);
mixxx::TrackMetadata* pMergedTrackMetadata = mergedTrackRecord.ptrMetadata();
- EXPECT_EQ(pOldTrackMetadata->getBitrate(), pMergedTrackMetadata->getBitrate());
- EXPECT_EQ(pOldTrackMetadata->getChannelCount(), pMergedTrackMetadata->getChannelCount());
- EXPECT_EQ(pOldTrackMetadata->getDuration(), pMergedTrackMetadata->getDuration());
- EXPECT_EQ(pOldTrackMetadata->getSampleRate(), pMergedTrackMetadata->getSampleRate());
+ EXPECT_EQ(pOldTrackMetadata->getStreamInfo(), pMergedTrackMetadata->getStreamInfo());
mixxx::TrackInfo* pMergedTrackInfo = pMergedTrackMetadata->ptrTrackInfo();
EXPECT_EQ(pOldTrackInfo->getArtist(), pMergedTrackInfo->getArtist());
EXPECT_EQ(pOldTrackInfo->getBpm(), pMergedTrackInfo->getBpm());
diff --git a/src/track/taglib/trackmetadata_file.cpp b/src/track/taglib/trackmetadata_file.cpp
index d9e95a6b66..f3b1ee7ff0 100644
--- a/src/track/taglib/trackmetadata_file.cpp
+++ b/src/track/taglib/trackmetadata_file.cpp
@@ -25,22 +25,22 @@ void readAudioProperties(
DEBUG_ASSERT(pTrackMetadata);
// NOTE(uklotzde): All audio properties will be updated
- // with the actual (and more precise) values when reading
- // the audio data for this track. Often those properties
- // stored in tags don't match with the corresponding
- // audio data in the file.
- pTrackMetadata->setChannelCount(
- audio::ChannelCount(audioProperties.channels()));
- pTrackMetadata->setSampleRate(
- audio::SampleRate(audioProperties.sampleRate()));
- pTrackMetadata->setBitrate(
- audio::Bitrate(audioProperties.bitrate()));
+ // with the actual (and more precise) values when opening
+ // the audio source for this track. Often those properties
+ // stored in tags are imprecise and don't match the actual
+ // audio data of the stream.
+ pTrackMetadata->setStreamInfo(audio::StreamInfo {
+ audio::SignalInfo{
+ audio::ChannelCount(audioProperties.channels()),
+ audio::SampleRate(audioProperties.sampleRate()),
+ },
+ audio::Bitrate(audioProperties.bitrate()),
#if (TAGLIB_HAS_LENGTH_IN_MILLISECONDS)
- const auto duration = Duration::fromMillis(audioProperties.lengthInMilliseconds());
+ Duration::fromMillis(audioProperties.lengthInMilliseconds()),
#else
- const auto duration = Duration::fromSeconds(audioProperties.length());
+ Duration::fromSeconds(audioProperties.length()),
#endif
- pTrackMetadata->setDuration(duration);
+ });
}
} // anonymous namespace
diff --git a/src/track/track.cpp b/src/track/track.cpp
index 237a88e9a6..2763661b2c 100644
--- a/src/track/track.cpp
+++ b/src/track/track.cpp
@@ -1,7 +1,6 @@
#include "track/track.h"
#include <QDirIterator>
-#include <QMutexLocker>
#include <atomic>
#include "engine/engine.h"
@@ -419,18 +418,18 @@ void Track::setDateAdded(const QDateTime& dateAdded) {
void Track::setDuration(mixxx::Duration duration) {
QMutexLocker lock(&m_qMutex);
- VERIFY_OR_DEBUG_ASSERT(!m_streamInfo ||
- m_streamInfo->getDuration() <= mixxx::Duration::empty() ||
- m_streamInfo->getDuration() == duration) {
+ VERIFY_OR_DEBUG_ASSERT(!m_streamInfoFromSource ||
+ m_streamInfoFromSource->getDuration() <= mixxx::Duration::empty() ||
+ m_streamInfoFromSource->getDuration() == duration) {
kLogger.warning()
<< "Cannot override stream duration:"
- << m_streamInfo->getDuration()
+ << m_streamInfoFromSource->getDuration()
<< "->"
<< duration;
return;
}
if (compareAndSet(
- m_record.refMetadata().ptrDuration(),
+ m_record.refMetadata().refStreamInfo().ptrDuration(),
duration)) {
markDirtyAndUnlock(&lock);
}
@@ -442,25 +441,19 @@ void Track::setDuration(double duration) {
double Track::getDuration(DurationRounding rounding) const {
QMutexLocker lock(&m_qMutex);
+ const auto durationSeconds =
+ m_record.getMetadata().getStreamInfo().getDuration().toDoubleSeconds();
switch (rounding) {
case DurationRounding::SECONDS:
- return std::round(m_record.getMetadata().getDuration().toDoubleSeconds());
+ return std::round(durationSeconds);
default:
- return m_record.getMetadata().getDuration().toDoubleSeconds();
+ return durationSeconds;
}
}
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::formatTime(duration, precision);
+ QMutexLocker lock(&m_qMutex);
+ return m_record.getMetadata().getDurationText(precision);
}
QString Track::getTitle() const {
@@ -653,38 +646,39 @@ void Track::setType(const QString& sType) {
int Track::getSampleRate() const {
QMutexLocker lock(&m_qMutex);
- return m_record.getMetadata().getSampleRate();
+ return m_record.getMetadata().getStreamInfo().getSignalInfo().getSampleRate();
}
int Track::getChannels() const {
QMutexLocker lock(&m_qMutex);
- return m_record.getMetadata().getChannelCount();
+ return m_record.getMetadata().getStreamInfo().getSignalInfo().getChannelCount();
}
int Track::getBitrate() const {
QMutexLocker lock(&m_qMutex);
- return m_record.getMetadata().getBitrate();
+ return m_record.getMetadata().getStreamInfo().getBitrate();
}
QString Track::getBitrateText() const {
- return QString("%1").arg(getBitrate());
+ QMutexLocker lock(&m_qMutex);
+ return m_record.getMetadata().getBitrateText();
}
void Track::setBitrate(int iBitrate) {
QMutexLocker lock(&m_qMutex);
const mixxx::audio::Bitrate bitrate(iBitrate);
- VERIFY_OR_DEBUG_ASSERT(!m_streamInfo ||
- !m_streamInfo->getBitrate().isValid() ||
- m_streamInfo->getBitrate() == bitrate) {
+ VERIFY_OR_DEBUG_ASSERT(!m_streamInfoFromSource ||
+ !m_streamInfoFromSource->getBitrate().isValid() ||
+ m_streamInfoFromSource->getBitrate() == bitrate) {
kLogger.warning()
<< "Cannot override stream bitrate:"
- << m_streamInfo->getBitrate()
+ << m_streamInfoFromSource->getBitrate()
<< "->"
<< bitrate;
return;
}
if (compareAndSet(
- m_record.refMetadata().ptrBitrate(),
+ m_record.refMetadata().refStreamInfo().ptrBitrate(),
bitrate)) {
markDirtyAndUnlock(&lock);
}
@@ -795,10 +789,10 @@ void Track::setCuePoint(CuePosition cue) {
void Track::shiftCuePositionsMillis(double milliseconds) {
QMutexLocker lock(&m_qMutex);
- VERIFY_OR_DEBUG_ASSERT(m_streamInfo) {
+ VERIFY_OR_DEBUG_ASSERT(m_streamInfoFromSource) {
return;
}
- double frames = m_streamInfo->getSignalInfo().millis2frames(milliseconds);
+ double frames = m_streamInfoFromSource->getSignalInfo().millis2frames(milliseconds);
for (const CuePointer& pCue : qAsConst(m_cuePoints)) {
pCue->shiftPositionFrames(frames);
}
@@ -929,7 +923,7 @@ Track::ImportStatus Track::importBeats(
// existing cue points.
m_pBeatsImporterPending.reset();
return ImportStatus::Complete;
- } else if (m_streamInfo) {
+ } else if (m_streamInfoFromSource) {
// Replace existing cue points with imported cue
// points immediately
importPendingBeatsMarkDirtyAndUnlock(&lock);
@@ -963,14 +957,14 @@ bool Track::importPendingBeatsWhileLocked() {
}
// The sample rate can only be trusted after the audio
// stream has been opened.
- DEBUG_ASSERT(m_streamInfo);
+ DEBUG_ASSERT(m_streamInfoFromSource);
// The sample rate is supposed to be consistent
- DEBUG_ASSERT(m_streamInfo->getSignalInfo().getSampleRate() ==
- m_record.getMetadata().getSampleRate());
+ DEBUG_ASSERT(m_streamInfoFromSource->getSignalInfo().getSampleRate() ==
+ m_record.getMetadata().getStreamInfo().getSignalInfo().getSampleRate());
mixxx::BeatsPointer pBeats(new mixxx::BeatMap(*this,
- static_cast<SINT>(m_streamInfo->getSignalInfo().getSampleRate()),
+ static_cast<SINT>(m_streamInfoFromSource->getSignalInfo().getSampleRate()),
m_pBeatsImporterPending->importBeatsAndApplyTimingOffset(
- getLocation(), *m_streamInfo)));
+ getLocation(), *m_streamInfoFromSource)));
DEBUG_ASSERT(m_pBeatsImporterPending->isEmpty());
m_pBeatsImporterPending.reset();
return setBeatsWhileLocked(pBeats);
@@ -1004,7 +998,7 @@ Track::ImportStatus Track::importCueInfos(
// existing cue points.
m_pCueInfoImporterPending.reset();
return ImportStatus::Complete;
- } else if (m_streamInfo) {
+ } else if (m_streamInfoFromSource) {
// Replace existing cue points with imported cue
// points immediately
importPendingCueInfosMarkDirtyAndUnlock(&lock);
@@ -1091,18 +1085,18 @@ bool Track::importPendingCueInfosWhileLocked() {
}
// The sample rate can only be trusted after the audio
// stream has been opened.
- DEBUG_ASSERT(m_streamInfo);
+ DEBUG_ASSERT(m_streamInfoFromSource);
const auto sampleRate =
- m_streamInfo->getSignalInfo().getSampleRate();
+ m_streamInfoFromSource->getSignalInfo().getSampleRate();
// The sample rate is supposed to be consistent
DEBUG_ASSERT(sampleRate ==
- m_record.getMetadata().getSampleRate());
+ m_record.getMetadata().getStreamInfo().getSignalInfo().getSampleRate());
const auto trackId = m_record.getId();
QList<CuePointer> cuePoints;
cuePoints.reserve(m_pCueInfoImporterPending->size());
const auto cueInfos =
m_pCueInfoImporterPending->importCueInfosAndApplyTimingOffset(
- getLocation(), m_streamInfo->getSignalInfo());
+ getLocation(), m_streamInfoFromSource->getSignalInfo());
for (const auto& cueInfo : cueInfos) {
CuePointer pCue(new Cue(cueInfo, sampleRate, true));
// While this method could be called from any thread,
@@ -1452,48 +1446,45 @@ void Track::setAudioProperties(
mixxx::audio::SampleRate sampleRate,
mixxx::audio::Bitrate bitrate,
mixxx::Duration duration) {
+ setAudioProperties(mixxx::audio::StreamInfo{
+ mixxx::audio::SignalInfo{
+ channelCount,
+ sampleRate,
+ },
+ bitrate,
+ duration,
+ });
+}
+
+void Track::setAudioProperties(
+ const mixxx::audio::StreamInfo& streamInfo) {
QMutexLocker lock(&m_qMutex);
- DEBUG_ASSERT(!m_streamInfo);
- bool dirty = false;
- if (compareAndSet(
- m_record.refMetadata().ptrChannelCount(),
- channelCount)) {
- dirty = true;
- }
+ // These properties are stored separately in the database
+ // and are also imported from file tags. They will be
+ // overriden by the actual properties from the audio
+ // source later.
+ DEBUG_ASSERT(!m_streamInfoFromSource);
if (compareAndSet(
- m_record.refMetadata().ptrSampleRate(),
- sampleRate)) {
- dirty = true;
- }
- if (compareAndSet(
- m_record.refMetadata().ptrBitrate(),
- bitrate)) {
- dirty = true;
- }
- if (compareAndSet(
- m_record.refMetadata().ptrDuration(),
- duration)) {
- dirty = true;
- }
- if (dirty) {
+ m_record.refMetadata().ptrStreamInfo(),
+ streamInfo)) {
markDirtyAndUnlock(&lock);
}
}
-void Track::updateAudioPropertiesFromStream(
+void Track::updateStreamInfoFromSource(
mixxx::audio::StreamInfo&& streamInfo) {
QMutexLocker lock(&m_qMutex);
- VERIFY_OR_DEBUG_ASSERT(!m_streamInfo ||
- *m_streamInfo == streamInfo) {
+ VERIFY_OR_DEBUG_ASSERT(!m_streamInfoFromSource ||
+ *m_streamInfoFromSource == streamInfo) {
kLogger.warning()
<< "Varying stream properties:"
- << *m_streamInfo
+ << *m_streamInfoFromSource
<< "->"
<< streamInfo;
}
- bool updated = m_record.refMetadata().updateAudioPropertiesFromStream(
+ bool updated = m_record.refMetadata().updateStreamInfoFromSource(
streamInfo);
- m_streamInfo = std::make_optional(std::move(streamInfo));
+ m_streamInfoFromSource = std::make_optional(std::move(streamInfo));
bool importBeats = m_pBeatsImporterPending && !m_pBeatsImporterPending->isEmpty();
bool importCueInfos = m_pCueInfoImporterPending && !m_pCueInfoImporterPending->isEmpty();
diff --git a/src/track/track.h b/src/track/track.h
index 84da9037ee..a229852c5c 100644
--- a/src/track/track.h
+++ b/src/track/track.h
@@ -2,6 +2,7 @@
#include <QList>
#include <QMutex>
+#include <QMutexLocker>
#include <QObject>
#include <QUrl>
@@ -348,6 +349,8 @@ class Track : public QObject {
mixxx::audio::SampleRate sampleRate,
mixxx::audio::Bitrate bitrate,
mixxx::Duration duration);
+ void setAudioProperties(
+ const mixxx::audio::StreamInfo& streamInfo);
signals:
void waveformUpdated();
@@ -430,10 +433,15 @@ class Track : public QObject {
mixxx::MetadataSourcePointer pMetadataSource);
// Information about the actual properties of the
- // audio stream is only available after opening it.
- // On this occasion the audio properties of the track
- // need to be updated to reflect these values.
- void updateAudioPropertiesFromStream(
+ // audio stream is only available after opening the
+ // source at least once. On this occasion the metadata
+ // stream info of the track need to be updated to reflect
+ // these values.
+ bool hasStreamInfoFromSource() const {
+ QMutexLocker lock(&m_qMutex);
+ return static_cast<bool>(m_streamInfoFromSource);
+ }
+ void updateStreamInfoFromSource(
mixxx::audio::StreamInfo&& streamInfo);
// Mutex protecting access to object
@@ -457,7 +465,7 @@ class Track : public QObject {
// Reliable information about the PCM audio stream
// that only becomes available when opening the
// corresponding file.
- std::optional<mixxx::audio::StreamInfo> m_streamInfo;
+ std::optional<mixxx::audio::StreamInfo> m_streamInfoFromSource;
// The list of cue points for the track
QList<CuePointer> m_cuePoints;
diff --git a/src/track/trackmetadata.cpp b/src/track/trackmetadata.cpp
index 692326ea0b..b36c00fb38 100644
--- a/src/track/trackmetadata.cpp
+++ b/src/track/trackmetadata.cpp
@@ -13,68 +13,91 @@ const Logger kLogger("TrackMetadata");
/*static*/ constexpr int TrackMetadata::kCalendarYearInvalid;
-bool TrackMetadata::updateAudioPropertiesFromStream(
+bool TrackMetadata::updateStreamInfoFromSource(
const audio::StreamInfo& streamInfo) {
bool changed = false;
const auto streamChannelCount =
streamInfo.getSignalInfo().getChannelCount();
if (streamChannelCount.isValid() &&
- streamChannelCount != getChannelCount()) {
- if (getChannelCount().isValid()) {
+ streamChannelCount != getStreamInfo().getSignalInfo().getChannelCount()) {
+ if (getStreamInfo().getSignalInfo().getChannelCount().isValid()) {
kLogger.debug()
<< "Modifying channel count:"
- << getChannelCount()
+ << getStreamInfo().getSignalInfo().getChannelCount()
<< "->"
<< streamChannelCount;
}
- setChannelCount(streamChannelCount);
+ refStreamInfo().refSignalInfo().setChannelCount(streamChannelCount);
changed = true;
}
const auto streamSampleRate =
streamInfo.getSignalInfo().getSampleRate();
if (streamSampleRate.isValid() &&
- streamSampleRate != getSampleRate()) {
- if (getSampleRate().isValid()) {
+ streamSampleRate != getStreamInfo().getSignalInfo().getSampleRate()) {
+ if (getStreamInfo().getSignalInfo().getSampleRate().isValid()) {
kLogger.debug()
<< "Modifying sample rate:"
- << getSampleRate()
+ << getStreamInfo().getSignalInfo().getSampleRate()
<< "->"
<< streamSampleRate;
}
- setSampleRate(streamSampleRate);
+ refStreamInfo().refSignalInfo().setSampleRate(streamSampleRate);
changed = true;
}
const auto streamBitrate =
streamInfo.getBitrate();
if (streamBitrate.isValid() &&
- streamBitrate != getBitrate()) {
- if (getBitrate().isValid()) {
+ streamBitrate != getStreamInfo().getBitrate()) {
+ if (getStreamInfo().getSignalInfo().isValid()) {
kLogger.debug()
<< "Modifying bitrate:"
- << getBitrate()
+ << getStreamInfo().getSignalInfo()
<< "->"
<< streamBitrate;
}
- setBitrate(streamBitrate);
+ refStreamInfo().setBitrate(streamBitrate);
changed = true;
}
const auto streamDuration =
streamInfo.getDuration();
if (streamDuration > Duration::empty() &&
- streamDuration != getDuration()) {
- if (getDuration() > Duration::empty()) {
+ streamDuration != getStreamInfo().getDuration()) {
+ if (getStreamInfo().getDuration() > Duration::empty()) {
kLogger.debug()
<< "Modifying duration:"
- << getDuration()
+ << getStreamInfo().getDuration()
<< "->"
<< streamDuration;
}
- setDuration(streamDuration);
+ refStreamInfo().setDuration(streamDuration);
changed = true;
}
return changed;
}
+QString TrackMetadata::getBitrateText() const {
+ if (!getStreamInfo().getBitrate().isValid()) {
+ return QString();
+ }
+ return QString::number(getStreamInfo().getBitrate()) +
+ QChar(' ') +
+ audio::Bitrate::unit();
+}
+
+QString TrackMetadata::getDurationText(
+ Duration::Precision precision) const {
+ double durationSeconds;
+ if (precision == Duration::Precision::SECONDS) {
+ // Round to full seconds before formatting for consistency
+ // getDurationText() should always display the same number
+ // as getDurationSecondsRounded()
+ durationSeconds = getDurationSecondsRounded();
+ } else {
+ durationSeconds = getStreamInfo().getDuration().toDoubleSeconds();
+ }
+ return Duration::formatTime(durationSeconds, precision);
+}
+
int TrackMetadata::parseCalendarYear(const QString& year, bool* pValid) {
const QDateTime dateTime(parseDateTime(year));
if (0 < dateTime.date().year()) {
@@ -154,22 +177,16 @@ bool TrackMetadata::anyFileTagsModified(
}
bool operator==(const TrackMetadata& lhs, const TrackMetadata& rhs) {
- return lhs.getAlbumInfo() == rhs.getAlbumInfo() &&
- lhs.getTrackInfo() == rhs.getTrackInfo() &&
- lhs.getChannelCount() == rhs.getChannelCount() &&
- lhs.getSampleRate() == rhs.getSampleRate() &&
- lhs.getBitrate() == rhs.getBitrate() &&
- lhs.getDuration() == rhs.getDuration();
+ return lhs.getStreamInfo() == rhs.getStreamInfo() &&
+ lhs.getAlbumInfo() == rhs.getAlbumInfo() &&
+ lhs.getTrackInfo() == rhs.getTrackInfo();
}
QDebug operator<<(QDebug dbg, const TrackMetadata& arg) {
dbg << "TrackMetadata{";
+ arg.dbgStreamInfo(dbg);
arg.dbgTrackInfo(dbg);
arg.dbgAlbumInfo(dbg);
- arg.dbgBitrate(dbg);
- arg.dbgChannelCount(dbg);
- arg.dbgDuration(dbg);
- arg.dbgSampleRate(dbg);
dbg << '}';
return dbg;
}
diff --git a/src/track/trackmetadata.h b/src/track/trackmetadata.h
index bae8ee188e..e01dc1b9cd 100644
--- a/src/track/trackmetadata.h
+++ b/src/track/trackmetadata.h
@@ -2,27 +2,18 @@
#include <QDateTime>
-#include "audio/types.h"
+#include "audio/streaminfo.h"
#include "track/albuminfo.h"
#include "track/trackinfo.h"
namespace mixxx {
-namespace audio {
-
-class StreamInfo;
-
-} // namespace audio
-
class TrackMetadata final {
// Audio properties
// - read-only
// - stored in file tags
// - adjusted when opening the audio stream (if available)
- MIXXX_DECL_PROPERTY(audio::ChannelCount, channels, ChannelCount)
- MIXXX_DECL_PROPERTY(audio::SampleRate, sampleRate, SampleRate)
- MIXXX_DECL_PROPERTY(audio::Bitrate, bitrate, Bitrate)
- MIXXX_DECL_PROPERTY(Duration, duration, Duration)
+ MIXXX_DECL_PROPERTY(audio::StreamInfo, streamInfo, StreamInfo)
// Track properties
// - read-write
@@ -39,7 +30,7 @@ class TrackMetadata final {
TrackMetadata& operator=(TrackMetadata&&) = default;
TrackMetadata& operator=(const TrackMetadata&) = default;
- bool updateAudioPropertiesFromStream(
+ bool updateStreamInfoFromSource(
const audio::StreamInfo& streamInfo);
// Adjusts floating-point values to match their string representation
@@ -57,6 +48,14 @@ class TrackMetadata final {
const TrackMetadata& importedFromFile,
Bpm::Comparison cmpBpm = Bpm::Comparison::Default) const;
+ QString getBitrateText() const;
+
+ double getDurationSecondsRounded() const {
+ return std::round(getStreamInfo().getDuration().toDoubleSeconds());
+ }
+ QString getDurationText(
+ Duration::Precision precision) const;
+
// Parse an format date/time values according to ISO 8601
static QDate parseDate(const QString& str) {
return QDate::fromString(str.trimmed().replace(" ", ""), Qt::ISODate);