Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
182c319
Encapsulate location and id of tracks in TrackRef
uklotzde Mar 3, 2016
30c302a
Move construction from QFileInfo into a separate factory function
uklotzde Mar 5, 2016
92d1820
Introduce TrackCache for managing Track objects
uklotzde Jun 15, 2017
14f1e1f
Workaround for missing defaulted move ctors/operators in VS 2015
uklotzde Jun 15, 2017
d2ca2ca
Browse view: Modify Track object instead of writing directly into files
uklotzde Dec 27, 2015
b071279
Re-enable export of track metadata into files
uklotzde Jun 22, 2016
ec6c94d
Rename members and reformat code
uklotzde Jan 28, 2017
7e434ac
Safely write tags by using a temporary file
uklotzde Nov 11, 2017
3bf38d5
Explain the purpose of SafelyWritableFile
uklotzde Nov 11, 2017
2dbf1ec
Improve safety when writing tags even more
uklotzde Nov 26, 2017
abaf7ea
Improve temporary file handling when writing tags
uklotzde Nov 26, 2017
ef3d25d
Try to fix tag writing tests on AppVeyor
uklotzde Nov 26, 2017
35ce52b
Improve documentation of TrackRef
uklotzde Dec 1, 2017
2d89416
Rename slots to indicate source/target of metadata import/export
uklotzde Dec 1, 2017
6c92735
Use the terms "evict" and "cache" in conjunction
uklotzde Dec 1, 2017
9a4cc91
Display message box before exporting track metadata
uklotzde Dec 1, 2017
8a1a6d3
Merge branch 'master' into WriteAudioTags
uklotzde Dec 1, 2017
efead4e
Merge branch 'master' into WriteAudioTags
uklotzde Dec 1, 2017
ceae6c2
Inform the user how exporting of track metadata works
uklotzde Dec 1, 2017
f970405
Allow re-import of metadata for tracks with unsaved changes
uklotzde Dec 2, 2017
40ff03f
Simply overwrite unsaved metadata when importing from file
uklotzde Dec 2, 2017
0567e31
Change wording of message box when exporting track metadata
uklotzde Dec 2, 2017
d94d536
Show information about track metadata export only once per session
uklotzde Dec 2, 2017
cd52a1f
Temporarily disable tag writing test on Windows builds
uklotzde Dec 2, 2017
183c8d3
Revert "Temporarily disable tag writing test on Windows builds"
uklotzde Dec 2, 2017
612f691
Close the audio source before releasing the track pointer
uklotzde Dec 2, 2017
b6a24af
Log cause after file operations failed
uklotzde Dec 2, 2017
f1b458d
Don't call function with side effects in DBEUG_ASSERT
uklotzde Dec 2, 2017
1904180
Close temporary file before renaming
uklotzde Dec 2, 2017
ba5cbff
Change wording of informational messages again
uklotzde Dec 2, 2017
69bd2bf
Add a quick hack for avoiding redundant message strings
uklotzde Dec 2, 2017
36e3cf9
Reduce ugliness of the translabtable string hack
uklotzde Dec 2, 2017
6822a60
VorbisComment: Handle "DESCRIPTION"/"COMMENT" fields like TagLib
uklotzde Dec 3, 2017
8f53cc8
VorbisComment: Use MusicBrainz recommendation "BPM" instead of "TEMPO"
uklotzde Dec 3, 2017
9e86472
Fix initialization order of members
uklotzde Dec 3, 2017
d0177a5
Read file modification dates safely
uklotzde Dec 3, 2017
2513d94
Prepare to configure safe/unsafe file access when exporting track met…
uklotzde Dec 3, 2017
f36c7dd
Follow-up of previous commit
uklotzde Dec 3, 2017
56a73e8
VorbisComments: Prefer "COMMENT" (MusicBrainz) over "DESCRIPTION"
uklotzde Dec 3, 2017
6a0b744
Merge branch 'master' into WriteAudioTags
uklotzde Dec 3, 2017
92a7dab
Remove the recent tracks cache from TrackDAO
uklotzde Dec 4, 2017
ef1c20b
Delete unused code from Duration class
uklotzde Dec 5, 2017
8477814
Fix minor oddities in Duration class
uklotzde Dec 5, 2017
e8fc77a
Do not consider audio properties when exporting metadata
uklotzde Dec 5, 2017
029622e
Add QDebug operators
uklotzde Dec 5, 2017
601538a
Merge branch 'master' of https://github.com/mixxxdj/mixxx.git into Wr…
uklotzde Dec 5, 2017
86e14ab
Fix plugin builds
uklotzde Dec 5, 2017
8b01e12
Temporarily disable unused track metadata properties
uklotzde Dec 5, 2017
26de42d
Use TagLib instead of opusfile
uklotzde Dec 5, 2017
6e05e53
Fix normalization of bpm values
uklotzde Dec 5, 2017
0a46bdc
Remove verbose debug output
uklotzde Dec 5, 2017
64489db
Fix typo
uklotzde Dec 6, 2017
1cca670
Defer normalization of floating-point values until exported
uklotzde Dec 6, 2017
db2f063
Re-enable new metadata properties
uklotzde Dec 6, 2017
32c15a1
Update the informational text about exporting track metadata
uklotzde Dec 6, 2017
f270f93
Merge branch 'master' into WriteAudioTags
uklotzde Dec 10, 2017
4f8d24c
Improve comprehensibility of the code and many comments
uklotzde Dec 10, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,7 @@ def sources(self, build):
"library/dlgmissing.cpp",
"library/dlgtagfetcher.cpp",
"library/dlgtrackinfo.cpp",
"library/dlgtrackmetadataexport.cpp",

"library/browse/browsetablemodel.cpp",
"library/browse/browsethread.cpp",
Expand Down Expand Up @@ -1081,12 +1082,14 @@ def sources(self, build):
"track/playcounter.cpp",
"track/replaygain.cpp",
"track/track.cpp",
"track/trackcache.cpp",
"track/trackmetadata.cpp",
"track/trackmetadatataglib.cpp",
"track/tracknumbers.cpp",
"track/albuminfo.cpp",
"track/trackinfo.cpp",
"track/trackrecord.cpp",
"track/trackref.cpp",

"mixer/auxiliary.cpp",
"mixer/baseplayer.cpp",
Expand Down
2 changes: 2 additions & 0 deletions plugins/soundsourcem4a/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ m4a_sources = [
"util/sample.cpp",
"util/logger.cpp",
"util/indexrange.cpp",
"track/albuminfo.cpp",
"track/trackinfo.cpp",
"track/trackmetadata.cpp",
"track/trackmetadatataglib.cpp",
"track/tracknumbers.cpp",
Expand Down
2 changes: 2 additions & 0 deletions plugins/soundsourcemediafoundation/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ if int(build.flags['mediafoundation']):
'util/sample.cpp',
'util/logger.cpp',
'util/indexrange.cpp',
'track/albuminfo.cpp',
'track/trackinfo.cpp',
'track/trackmetadata.cpp',
'track/trackmetadatataglib.cpp',
'track/tracknumbers.cpp',
Expand Down
2 changes: 2 additions & 0 deletions plugins/soundsourcewv/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ wv_sources = [
"util/sample.cpp",
"util/logger.cpp",
"util/indexrange.cpp",
"track/albuminfo.cpp",
"track/trackinfo.cpp",
"track/trackmetadata.cpp",
"track/trackmetadatataglib.cpp",
"track/tracknumbers.cpp",
Expand Down
15 changes: 10 additions & 5 deletions src/library/basetrackcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "library/searchqueryparser.h"
#include "library/queryutil.h"
#include "track/keyutils.h"
#include "track/trackcache.h"
#include "util/performancetimer.h"

namespace {
Expand Down Expand Up @@ -144,12 +145,16 @@ void BaseTrackCache::setSearchColumns(const QStringList& columns) {
}

TrackPointer BaseTrackCache::lookupCachedTrack(TrackId trackId) const {
// Only get the track from the TrackDAO if it's in the cache and marked as
// dirty.
if (m_bIsCaching && m_dirtyTracks.contains(trackId)) {
return m_trackDAO.getTrack(trackId, true);
TrackCacheLocker cacheLocker(
TrackCache::instance().lookupById(trackId));
auto pTrack = cacheLocker.getTrack();
if (pTrack && pTrack->isDirty()) {
m_dirtyTracks.insert(trackId);
return pTrack;
} else {
m_dirtyTracks.remove(trackId);
return TrackPointer();
}
return TrackPointer();
}

bool BaseTrackCache::updateIndexWithTrackpointer(TrackPointer pTrack) {
Expand Down
6 changes: 5 additions & 1 deletion src/library/basetrackcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,11 @@ class BaseTrackCache : public QObject {

QVector<TrackId> m_trackOrder;

QSet<TrackId> m_dirtyTracks;
// This set is updated by signals from the Track object. It might contain
// false positives, i.e. track ids of tracks that are neither cached nor
// dirty. Each invocation of lookupCachedTrack() will take care of
// updating this set by inserting and removing entries as required.
mutable QSet<TrackId> m_dirtyTracks;

bool m_bIndexBuilt;
bool m_bIsCaching;
Expand Down
173 changes: 81 additions & 92 deletions src/library/browse/browsetablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "mixer/playerinfo.h"
#include "control/controlobject.h"
#include "library/dao/trackdao.h"
#include "sources/metadatasourcetaglib.h"
#include "util/dnd.h"

BrowseTableModel::BrowseTableModel(QObject* parent,
Expand Down Expand Up @@ -109,6 +108,14 @@ TrackPointer BrowseTableModel::getTrack(const QModelIndex& index) const {
+ "\n" +track_location);
return TrackPointer();
}
// NOTE(uklotzde, 2015-12-08): Accessing tracks from the browse view
// will implicitly add them to the library. Is this really what we
// want here??
// NOTE(rryan, 2015-12-27): This was intentional at the time since
// some people use Browse instead of the library and we want to let
// them edit the tracks in a way that persists across sessions
// and we didn't want to edit the files on disk by default
// unless the user opts in to that.
return m_pTrackCollection->getTrackDAO()
.getOrAddTrack(track_location, true, NULL);
}
Expand Down Expand Up @@ -233,108 +240,93 @@ Qt::ItemFlags BrowseTableModel::flags(const QModelIndex &index) const {
QString track_location = getTrackLocation(index);
int column = index.column();

if (isTrackInUse(track_location) ||
column == COLUMN_FILENAME ||
column == COLUMN_BITRATE ||
column == COLUMN_DURATION ||
column == COLUMN_TYPE ||
column == COLUMN_FILE_MODIFIED_TIME ||
column == COLUMN_FILE_CREATION_TIME ||
column == COLUMN_REPLAYGAIN) {
switch (column) {
case COLUMN_FILENAME:
case COLUMN_BITRATE:
case COLUMN_DURATION:
case COLUMN_TYPE:
case COLUMN_FILE_MODIFIED_TIME:
case COLUMN_FILE_CREATION_TIME:
case COLUMN_REPLAYGAIN:
// read-only
return defaultFlags;
} else {
default:
// editable
return defaultFlags | Qt::ItemIsEditable;
}
}

bool BrowseTableModel::isTrackInUse(const QString& track_location) const {
if (PlayerInfo::instance().isFileLoaded(track_location)) {
return true;
}

if (m_pRecordingManager->getRecordingLocation() == track_location) {
return true;
}

return false;
}

bool BrowseTableModel::setData(const QModelIndex &index, const QVariant &value,
int role) {
bool BrowseTableModel::setData(
const QModelIndex& index,
const QVariant& value,
int role) {
Q_UNUSED(role);

if (!index.isValid()) {
QStandardItem* item = itemFromIndex(index);
DEBUG_ASSERT(nullptr != item);

TrackPointer pTrack(getTrack(index));
if (!pTrack) {
qWarning() << "BrowseTableModel::setData():"
<< "Failed to resolve track"
<< getTrackLocation(index);
// restore previous item content
item->setText(index.data().toString());
item->setToolTip(item->text());
return false;
}
qDebug() << "BrowseTableModel::setData(" << index.data() << ")";
int row = index.row();
int col = index.column();

mixxx::TrackMetadata trackMetadata;

// set tagger information
trackMetadata.refAlbumInfo().setTitle(this->index(row, COLUMN_ALBUM).data().toString());
trackMetadata.refAlbumInfo().setArtist(this->index(row, COLUMN_ALBUMARTIST).data().toString());

trackMetadata.refTrackInfo().setArtist(this->index(row, COLUMN_ARTIST).data().toString());
trackMetadata.refTrackInfo().setTitle(this->index(row, COLUMN_TITLE).data().toString());
trackMetadata.refTrackInfo().setKey(this->index(row, COLUMN_KEY).data().toString());
trackMetadata.refTrackInfo().setBpm(mixxx::Bpm(this->index(row, COLUMN_BPM).data().toDouble()));
trackMetadata.refTrackInfo().setComment(this->index(row, COLUMN_COMMENT).data().toString());
trackMetadata.refTrackInfo().setTrackNumber(this->index(row, COLUMN_TRACK_NUMBER).data().toString());
trackMetadata.refTrackInfo().setYear(this->index(row, COLUMN_YEAR).data().toString());
trackMetadata.refTrackInfo().setGenre(this->index(row, COLUMN_GENRE).data().toString());
trackMetadata.refTrackInfo().setComposer(this->index(row, COLUMN_COMPOSER).data().toString());
trackMetadata.refTrackInfo().setGrouping(this->index(row, COLUMN_GROUPING).data().toString());

// check if one the item were edited
if (col == COLUMN_ARTIST) {
trackMetadata.refTrackInfo().setArtist(value.toString());
} else if (col == COLUMN_TITLE) {
trackMetadata.refTrackInfo().setTitle(value.toString());
} else if (col == COLUMN_ALBUM) {
trackMetadata.refAlbumInfo().setTitle(value.toString());
} else if (col == COLUMN_BPM) {
trackMetadata.refTrackInfo().setBpm(mixxx::Bpm(value.toDouble()));
} else if (col == COLUMN_KEY) {
trackMetadata.refTrackInfo().setKey(value.toString());
} else if (col == COLUMN_TRACK_NUMBER) {
trackMetadata.refTrackInfo().setTrackNumber(value.toString());
} else if (col == COLUMN_COMMENT) {
trackMetadata.refTrackInfo().setComment(value.toString());
} else if (col == COLUMN_GENRE) {
trackMetadata.refTrackInfo().setGenre(value.toString());
} else if (col == COLUMN_COMPOSER) {
trackMetadata.refTrackInfo().setComposer(value.toString());
} else if (col == COLUMN_YEAR) {
trackMetadata.refTrackInfo().setYear(value.toString());
} else if (col == COLUMN_ALBUMARTIST) {
trackMetadata.refAlbumInfo().setArtist(value.toString());
} else if (col == COLUMN_GROUPING) {
trackMetadata.refTrackInfo().setGrouping(value.toString());
} else {
qWarning() << "BrowseTableModel::setData(): no tagger column";
return false;
}

QStandardItem* item = itemFromIndex(index);
QString track_location(getTrackLocation(index));
if (mixxx::MetadataSource::ExportResult::Succeeded ==
mixxx::MetadataSourceTagLib(track_location).exportTrackMetadata(trackMetadata).first) {
// Modify underlying interalPointer object
item->setText(value.toString());
item->setToolTip(item->text());
return true;
} else {
// reset to old value in error
int col = index.column();
switch (col) {
case COLUMN_ARTIST:
pTrack->setArtist(value.toString());
break;
case COLUMN_TITLE:
pTrack->setTitle(value.toString());
break;
case COLUMN_ALBUM:
pTrack->setAlbum(value.toString());
break;
case COLUMN_BPM:
pTrack->setBpm(value.toDouble());
break;
case COLUMN_KEY:
pTrack->setKeyText(value.toString());
break;
case COLUMN_TRACK_NUMBER:
pTrack->setTrackNumber(value.toString());
break;
case COLUMN_COMMENT:
pTrack->setComment(value.toString());
break;
case COLUMN_GENRE:
pTrack->setGenre(value.toString());
break;
case COLUMN_COMPOSER:
pTrack->setComposer(value.toString());
break;
case COLUMN_YEAR:
pTrack->setYear(value.toString());
break;
case COLUMN_ALBUMARTIST:
pTrack->setAlbumArtist(value.toString());
break;
case COLUMN_GROUPING:
pTrack->setGrouping(value.toString());
break;
default:
qWarning() << "BrowseTableModel::setData():"
<< "No tagger column";
// restore previous item context
item->setText(index.data().toString());
item->setToolTip(item->text());
QMessageBox::critical(
0, tr("Mixxx Library"),
tr("Could not update file metadata.")
+ "\n" +track_location);
return false;
}

item->setText(value.toString());
item->setToolTip(item->text());
return true;
}

void BrowseTableModel::trackLoaded(QString group, TrackPointer pTrack) {
Expand All @@ -361,10 +353,7 @@ void BrowseTableModel::trackLoaded(QString group, TrackPointer pTrack) {
}

bool BrowseTableModel::isColumnSortable(int column) {
if (COLUMN_PREVIEW == column) {
return false;
}
return true;
return COLUMN_PREVIEW != column;
}

QAbstractItemDelegate* BrowseTableModel::delegateForColumn(const int i, QObject* pParent) {
Expand Down
6 changes: 5 additions & 1 deletion src/library/browse/browsetablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const int COLUMN_REPLAYGAIN = 20;
// The BrowseTable models displays tracks
// of given directory on the HDD.
// Usage: Recording and Browse feature.
//
// TODO(XXX): Editing track metadata outside of the table view
// (e.g. in the property dialog) does not update the table view!
// Editing single fields in the table view works as expected.
class BrowseTableModel : public QStandardItemModel, public virtual TrackModel {
Q_OBJECT

Expand Down Expand Up @@ -73,7 +77,7 @@ class BrowseTableModel : public QStandardItemModel, public virtual TrackModel {

private:
void addSearchColumn(int index);
bool isTrackInUse(const QString& file) const;

QList<int> m_searchColumns;
MDir m_current_directory;
TrackCollection* m_pTrackCollection;
Expand Down
Loading