From 77903a5ecd9a3dd09a05148ba9e857748a257353 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Mon, 8 Apr 2019 23:00:07 +0200 Subject: [PATCH] Improve handling of song source --- src/collection/collection.cpp | 5 ++- src/collection/collectionplaylistitem.cpp | 9 ++-- src/collection/collectionplaylistitem.h | 3 +- src/collection/collectionwatcher.cpp | 11 ++--- src/collection/collectionwatcher.h | 3 +- src/core/song.cpp | 15 +++---- src/core/song.h | 54 +++++++++++------------ src/core/songloader.cpp | 5 ++- src/device/filesystemdevice.cpp | 7 ++- src/playlist/playlistbackend.cpp | 5 ++- src/playlist/playlistitem.cpp | 4 +- src/playlist/songplaylistitem.cpp | 4 +- src/playlistparsers/parserbase.cpp | 3 +- 13 files changed, 67 insertions(+), 61 deletions(-) diff --git a/src/collection/collection.cpp b/src/collection/collection.cpp index e386442de..4d6c854ea 100644 --- a/src/collection/collection.cpp +++ b/src/collection/collection.cpp @@ -32,6 +32,7 @@ #include "core/tagreaderclient.h" #include "core/thread.h" #include "core/utilities.h" +#include "core/song.h" #include "collection.h" #include "collectionwatcher.h" #include "collectionbackend.h" @@ -51,7 +52,7 @@ SCollection::SCollection(Application *app, QObject *parent) watcher_(nullptr), watcher_thread_(nullptr) { - backend_ = new CollectionBackend; + backend_ = new CollectionBackend(); backend()->moveToThread(app->database()->thread()); backend_->Init(app->database(), kSongsTable, kDirsTable, kSubdirsTable, kFtsTable); @@ -71,7 +72,7 @@ SCollection::~SCollection() { void SCollection::Init() { - watcher_ = new CollectionWatcher; + watcher_ = new CollectionWatcher(Song::Source_Collection); watcher_thread_ = new Thread(this); watcher_thread_->SetIoPriority(Utilities::IOPRIO_CLASS_IDLE); diff --git a/src/collection/collectionplaylistitem.cpp b/src/collection/collectionplaylistitem.cpp index 74d2ef24a..651aa15b1 100644 --- a/src/collection/collectionplaylistitem.cpp +++ b/src/collection/collectionplaylistitem.cpp @@ -29,11 +29,11 @@ class SqlRow; -CollectionPlaylistItem::CollectionPlaylistItem(const Song::Source &source) - : PlaylistItem(source) {} +CollectionPlaylistItem::CollectionPlaylistItem() : PlaylistItem(Song::Source_Collection) { + song_.set_source(Song::Source_Collection); +} -CollectionPlaylistItem::CollectionPlaylistItem(const Song &song) - : PlaylistItem(Song::Source_Collection), song_(song) { +CollectionPlaylistItem::CollectionPlaylistItem(const Song &song) : PlaylistItem(Song::Source_Collection), song_(song) { song_.set_source(Song::Source_Collection); } @@ -46,6 +46,7 @@ void CollectionPlaylistItem::Reload() { bool CollectionPlaylistItem::InitFromQuery(const SqlRow &query) { // Rows from the songs tables come first song_.InitFromQuery(query, true); + song_.set_source(Song::Source_Collection); return song_.is_valid(); } diff --git a/src/collection/collectionplaylistitem.h b/src/collection/collectionplaylistitem.h index 0af69afec..01a0f6ef9 100644 --- a/src/collection/collectionplaylistitem.h +++ b/src/collection/collectionplaylistitem.h @@ -36,7 +36,7 @@ class SqlRow; class CollectionPlaylistItem : public PlaylistItem { public: - CollectionPlaylistItem(const Song::Source &source); + CollectionPlaylistItem(); CollectionPlaylistItem(const Song &song); bool InitFromQuery(const SqlRow &query); @@ -51,6 +51,7 @@ class CollectionPlaylistItem : public PlaylistItem { protected: QVariant DatabaseValue(DatabaseColumn column) const; + Song DatabaseSongMetadata() const { return Song(Song::Source_Collection); } protected: Song song_; diff --git a/src/collection/collectionwatcher.cpp b/src/collection/collectionwatcher.cpp index 110ef372b..90701ce0f 100644 --- a/src/collection/collectionwatcher.cpp +++ b/src/collection/collectionwatcher.cpp @@ -59,13 +59,14 @@ namespace { static const char *kNoMediaFile = ".nomedia"; -static const char *kNoMusicFile = ".nomusic"; +static const char *kNoMusicFile = ".nomusic"; } QStringList CollectionWatcher::sValidImages; -CollectionWatcher::CollectionWatcher(QObject *parent) +CollectionWatcher::CollectionWatcher(Song::Source source, QObject *parent) : QObject(parent), + source_(source), backend_(nullptr), task_manager_(nullptr), fs_watcher_(FileSystemWatcherInterface::Create(this)), @@ -387,7 +388,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory QString image = ImageForSong(file, album_art); for (Song song : song_list) { - song.set_source(Song::Source_Collection); + song.set_source(source_); song.set_directory_id(t->dir()); if (song.art_automatic().isEmpty()) song.set_art_automatic(image); t->new_songs << song; @@ -441,7 +442,7 @@ void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file, const QStr // Update every song that's in the cue and collection for (Song cue_song : cue_parser_->Load(&cue, matching_cue, path)) { - cue_song.set_source(Song::Source_Collection); + cue_song.set_source(source_); cue_song.set_directory_id(t->dir()); Song matching = sections_map[cue_song.beginning_nanosec()]; @@ -477,7 +478,7 @@ void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file, const So } Song song_on_disk; - song_on_disk.set_source(Song::Source_Collection); + song_on_disk.set_source(source_); song_on_disk.set_directory_id(t->dir()); TagReaderClient::Instance()->ReadFileBlocking(file, &song_on_disk); diff --git a/src/collection/collectionwatcher.h b/src/collection/collectionwatcher.h index 5a53f940b..fdbc4cd30 100644 --- a/src/collection/collectionwatcher.h +++ b/src/collection/collectionwatcher.h @@ -46,7 +46,7 @@ class CollectionWatcher : public QObject { Q_OBJECT public: - CollectionWatcher(QObject *parent = nullptr); + CollectionWatcher(Song::Source source, QObject *parent = nullptr); void set_backend(CollectionBackend *backend) { backend_ = backend; } void set_task_manager(TaskManager *task_manager) { task_manager_ = task_manager; } @@ -162,6 +162,7 @@ signals: SongList ScanNewFile(const QString &file, const QString &path, const QString &matching_cue, QSet *cues_processed); private: + Song::Source source_; CollectionBackend *backend_; TaskManager *task_manager_; QString device_name_; diff --git a/src/core/song.cpp b/src/core/song.cpp index f04622a9c..dcb20fcee 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -148,7 +148,7 @@ const QRegExp Song::kTitleRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|Live|Remaster struct Song::Private : public QSharedData { - Private(); + Private(Source source = Source_Unknown); bool valid_; int id_; @@ -207,7 +207,7 @@ struct Song::Private : public QSharedData { }; -Song::Private::Private() +Song::Private::Private(Song::Source source) : valid_(false), id_(-1), album_id_(-1), @@ -223,7 +223,7 @@ Song::Private::Private() samplerate_(-1), bitdepth_(-1), - source_(Source_Unknown), + source_(source), directory_id_(-1), filetype_(FileType_Unknown), filesize_(-1), @@ -244,10 +244,8 @@ Song::Private::Private() {} -Song::Song() : d(new Private) {} - +Song::Song(Song::Source source) : d(new Private(source)) {} Song::Song(const Song &other) : d(other.d) {} - Song::~Song() {} Song &Song::operator=(const Song &other) { @@ -590,6 +588,8 @@ QString Song::Decode(const QString &tag, const QTextCodec *codec) { void Song::InitFromProtobuf(const pb::tagreader::SongMetadata &pb) { + if (d->source_ == Source_Unknown) d->source_ = Source_LocalFile; + d->init_from_file_ = true; d->valid_ = pb.valid(); d->title_ = QStringFromStdString(pb.title()); @@ -611,7 +611,6 @@ void Song::InitFromProtobuf(const pb::tagreader::SongMetadata &pb) { d->bitrate_ = pb.bitrate(); d->samplerate_ = pb.samplerate(); d->bitdepth_ = pb.bitdepth(); - d->source_ = Source_LocalFile; set_url(QUrl::fromEncoded(QByteArray(pb.url().data(), pb.url().size()))); d->basefilename_ = QStringFromStdString(pb.basefilename()); d->filetype_ = static_cast(pb.filetype()); @@ -678,7 +677,6 @@ void Song::ToProtobuf(pb::tagreader::SongMetadata *pb) const { void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) { - //qLog(Debug) << __PRETTY_FUNCTION__; //qLog(Debug) << "Song::kColumns.size():" << Song::kColumns.size() << "q.columns_.size():" << q.columns_.size() << "col:" << col; int x = col; @@ -691,6 +689,7 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) { qLog(Error) << "Skipping" << Song::kColumns.value(i); break; } + //qLog(Debug) << "Index:" << i << x << Song::kColumns.value(i) << q.value(x).toString(); if (Song::kColumns.value(i) == "title") { diff --git a/src/core/song.h b/src/core/song.h index 4cfae6b7e..d787ce57a 100644 --- a/src/core/song.h +++ b/src/core/song.h @@ -66,33 +66,6 @@ class Song { public: - Song(); - Song(const Song &other); - ~Song(); - - static const QStringList kColumns; - static const QString kColumnSpec; - static const QString kBindSpec; - static const QString kUpdateSpec; - - static const QStringList kFtsColumns; - static const QString kFtsColumnSpec; - static const QString kFtsBindSpec; - static const QString kFtsUpdateSpec; - - static const QString kManuallyUnsetCover; - static const QString kEmbeddedCover; - - static const QRegExp kAlbumRemoveDisc; - static const QRegExp kAlbumRemoveMisc; - static const QRegExp kTitleRemoveMisc; - static const QRegExp kFilenameRemoveNonFatChars; - - static QString JoinSpec(const QString &table); - - // Don't change these values - they're stored in the database, and defined in the tag reader protobuf. - // If a new lossless file is added, also add it to IsFileLossless(). - enum Source { Source_Unknown = 0, Source_LocalFile = 1, @@ -103,6 +76,9 @@ class Song { Source_Tidal = 6, }; + // Don't change these values - they're stored in the database, and defined in the tag reader protobuf. + // If a new lossless file is added, also add it to IsFileLossless(). + enum FileType { FileType_Unknown = 0, FileType_WAV = 1, @@ -126,6 +102,30 @@ class Song { FileType_Stream = 91, }; + Song(Song::Source source = Song::Source_Unknown); + Song(const Song &other); + ~Song(); + + static const QStringList kColumns; + static const QString kColumnSpec; + static const QString kBindSpec; + static const QString kUpdateSpec; + + static const QStringList kFtsColumns; + static const QString kFtsColumnSpec; + static const QString kFtsBindSpec; + static const QString kFtsUpdateSpec; + + static const QString kManuallyUnsetCover; + static const QString kEmbeddedCover; + + static const QRegExp kAlbumRemoveDisc; + static const QRegExp kAlbumRemoveMisc; + static const QRegExp kTitleRemoveMisc; + static const QRegExp kFilenameRemoveNonFatChars; + + static QString JoinSpec(const QString &table); + static Source SourceFromURL(const QUrl &url); static QString TextForSource(Source source); static QIcon IconForSource(Source source); diff --git a/src/core/songloader.cpp b/src/core/songloader.cpp index 1d6edef19..576f7ea59 100644 --- a/src/core/songloader.cpp +++ b/src/core/songloader.cpp @@ -213,7 +213,8 @@ SongLoader::Result SongLoader::LoadLocal(const QString &filename) { if (song.is_valid()) { songs_ << song; } - } while (query.Next()); + } + while (query.Next()); return Success; } @@ -337,7 +338,7 @@ void SongLoader::LoadLocalDirectory(const QString &filename) { } void SongLoader::AddAsRawStream() { - Song song; + Song song(Song::Source_Stream); song.set_valid(true); song.set_filetype(Song::FileType_Stream); song.set_url(url_); diff --git a/src/device/filesystemdevice.cpp b/src/device/filesystemdevice.cpp index 301005774..52b658029 100644 --- a/src/device/filesystemdevice.cpp +++ b/src/device/filesystemdevice.cpp @@ -27,6 +27,7 @@ #include "core/application.h" #include "core/logging.h" +#include "core/song.h" #include "collection/collectionbackend.h" #include "collection/collectionmodel.h" @@ -38,8 +39,10 @@ class DeviceLister; FilesystemDevice::FilesystemDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, DeviceManager *manager, Application *app, int database_id, bool first_time) - : FilesystemMusicStorage(url.toLocalFile()), ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time), watcher_(new CollectionWatcher), watcher_thread_(new QThread(this)) -{ + : FilesystemMusicStorage(url.toLocalFile()), + ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time), + watcher_(new CollectionWatcher(Song::Source_Device)), watcher_thread_(new QThread(this)) + { watcher_->moveToThread(watcher_thread_); watcher_thread_->start(QThread::IdlePriority); diff --git a/src/playlist/playlistbackend.cpp b/src/playlist/playlistbackend.cpp index 1346b1234..6eea815a4 100644 --- a/src/playlist/playlistbackend.cpp +++ b/src/playlist/playlistbackend.cpp @@ -245,12 +245,13 @@ PlaylistItemPtr PlaylistBackend::RestoreCueData(PlaylistItemPtr item, std::share song_list = cue_parser.Load(&cue, cue_path, QDir(cue_path.section('/', 0, -2))); state->cached_cues_[cue_path] = song_list; - } else { + } + else { song_list = state->cached_cues_[cue_path]; } } - for (const Song& from_list : song_list) { + for (const Song &from_list : song_list) { if (from_list.url().toEncoded() == song.url().toEncoded() && from_list.beginning_nanosec() == song.beginning_nanosec()) { // we found a matching section; replace the input item with a new one containing CUE metadata return PlaylistItemPtr(new SongPlaylistItem(from_list)); diff --git a/src/playlist/playlistitem.cpp b/src/playlist/playlistitem.cpp index 749472a8d..977da22c0 100644 --- a/src/playlist/playlistitem.cpp +++ b/src/playlist/playlistitem.cpp @@ -45,7 +45,7 @@ PlaylistItem::~PlaylistItem() {} PlaylistItem *PlaylistItem::NewFromSource(const Song::Source &source) { switch (source) { - case Song::Source_Collection: return new CollectionPlaylistItem(source); + case Song::Source_Collection: return new CollectionPlaylistItem(); case Song::Source_Tidal: case Song::Source_Stream: return new InternetPlaylistItem(source); default: return new SongPlaylistItem(source); @@ -65,7 +65,7 @@ PlaylistItem *PlaylistItem::NewFromSongsTable(const QString &table, const Song & void PlaylistItem::BindToQuery(QSqlQuery *query) const { - query->bindValue(":type", source()); + query->bindValue(":type", source_); query->bindValue(":collection_id", DatabaseValue(Column_CollectionId)); DatabaseSongMetadata().BindToQuery(query); diff --git a/src/playlist/songplaylistitem.cpp b/src/playlist/songplaylistitem.cpp index 252f50ac3..116ebbcbc 100644 --- a/src/playlist/songplaylistitem.cpp +++ b/src/playlist/songplaylistitem.cpp @@ -30,9 +30,7 @@ #include "songplaylistitem.h" SongPlaylistItem::SongPlaylistItem(const Song::Source &source) : PlaylistItem(source) {} - -SongPlaylistItem::SongPlaylistItem(const Song &song) - : PlaylistItem(Song::Source_LocalFile), song_(song) {} +SongPlaylistItem::SongPlaylistItem(const Song &song) : PlaylistItem(song.source()), song_(song) {} bool SongPlaylistItem::InitFromQuery(const SqlRow &query) { song_.InitFromQuery(query, false, (Song::kColumns.count()+1)); diff --git a/src/playlistparsers/parserbase.cpp b/src/playlistparsers/parserbase.cpp index e7f8b8611..f95cf24f8 100644 --- a/src/playlistparsers/parserbase.cpp +++ b/src/playlistparsers/parserbase.cpp @@ -76,8 +76,7 @@ void ParserBase::LoadSong(const QString &filename_or_url, qint64 beginning, cons const QUrl url = QUrl::fromLocalFile(filename); // Search in the collection - Song collection_song; - collection_song.set_source(Song::Source_Collection); + Song collection_song(Song::Source_Collection); if (collection_) { collection_song = collection_->GetSongByUrl(url, beginning); }