1
0
mirror of https://github.com/strawberrymusicplayer/strawberry synced 2025-02-10 08:40:43 +01:00

Application: Use shared pointers

Fixes #1239
This commit is contained in:
Jonas Kvinge 2023-07-21 05:55:24 +02:00
parent d6b53f78ab
commit 2e61235403
316 changed files with 2170 additions and 1643 deletions

View File

@ -269,6 +269,7 @@ set(SOURCES
radios/radioparadiseservice.cpp
scrobbler/audioscrobbler.cpp
scrobbler/scrobblersettings.cpp
scrobbler/scrobblerservice.cpp
scrobbler/scrobblercache.cpp
scrobbler/scrobblercacheitem.cpp
@ -502,6 +503,7 @@ set(HEADERS
radios/radioparadiseservice.h
scrobbler/audioscrobbler.h
scrobbler/scrobblersettings.h
scrobbler/scrobblerservice.h
scrobbler/scrobblercache.h
scrobbler/scrobblingapi20.h

View File

@ -24,9 +24,9 @@
#include "analyzerbase.h"
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <cmath>
#include <algorithm>
#include <QWidget>
#include <QVector>

View File

@ -38,6 +38,7 @@
#include <QString>
#include <QPainter>
#include "core/shared_ptr.h"
#include "analyzer/fht.h"
#include "engine/enginebase.h"
@ -54,7 +55,7 @@ class AnalyzerBase : public QWidget {
int timeout() const { return timeout_; }
void set_engine(EngineBase *engine) { engine_ = engine; }
void set_engine(SharedPtr<EngineBase> engine) { engine_ = engine; }
void ChangeTimeout(const int timeout);
@ -82,7 +83,7 @@ class AnalyzerBase : public QWidget {
protected:
QBasicTimer timer_;
FHT *fht_;
EngineBase *engine_;
SharedPtr<EngineBase> engine_;
Scope lastscope_;
bool new_frame_;

View File

@ -43,6 +43,7 @@
#include "sonogram.h"
#include "core/logging.h"
#include "core/shared_ptr.h"
#include "engine/enginebase.h"
using namespace std::chrono_literals;
@ -125,7 +126,7 @@ void AnalyzerContainer::wheelEvent(QWheelEvent *e) {
emit WheelEvent(e->angleDelta().y());
}
void AnalyzerContainer::SetEngine(EngineBase *engine) {
void AnalyzerContainer::SetEngine(SharedPtr<EngineBase> engine) {
if (current_analyzer_) current_analyzer_->set_engine(engine);
engine_ = engine;

View File

@ -30,6 +30,7 @@
#include <QAction>
#include <QActionGroup>
#include "core/shared_ptr.h"
#include "engine/enginebase.h"
class QTimer;
@ -44,7 +45,7 @@ class AnalyzerContainer : public QWidget {
public:
explicit AnalyzerContainer(QWidget *parent);
void SetEngine(EngineBase *engine);
void SetEngine(SharedPtr<EngineBase> engine);
void SetActions(QAction *visualisation);
static const char *kSettingsGroup;
@ -93,7 +94,7 @@ class AnalyzerContainer : public QWidget {
bool ignore_next_click_;
AnalyzerBase *current_analyzer_;
EngineBase *engine_;
SharedPtr<EngineBase> engine_;
};
template<typename T>

View File

@ -21,6 +21,8 @@
#include "config.h"
#include <memory>
#include <QtGlobal>
#include <QObject>
#include <QThread>
@ -43,6 +45,9 @@
#include "scrobbler/lastfmimport.h"
#include "settings/collectionsettingspage.h"
using std::make_unique;
using std::make_shared;
const char *SCollection::kSongsTable = "songs";
const char *SCollection::kFtsTable = "songs_fts";
const char *SCollection::kDirsTable = "directories";
@ -61,9 +66,9 @@ SCollection::SCollection(Application *app, QObject *parent)
original_thread_ = thread();
backend_ = new CollectionBackend();
backend_ = make_shared<CollectionBackend>();
backend()->moveToThread(app->database()->thread());
qLog(Debug) << backend_ << "moved to thread" << app->database()->thread();
qLog(Debug) << &*backend_ << "moved to thread" << app->database()->thread();
backend_->Init(app->database(), app->task_manager(), Song::Source::Collection, kSongsTable, kFtsTable, kDirsTable, kSubdirsTable);
@ -83,44 +88,43 @@ SCollection::~SCollection() {
watcher_thread_->exit();
watcher_thread_->wait(5000);
}
backend_->deleteLater();
}
void SCollection::Init() {
watcher_ = new CollectionWatcher(Song::Source::Collection);
watcher_ = make_unique<CollectionWatcher>(Song::Source::Collection);
watcher_thread_ = new Thread(this);
watcher_thread_->SetIoPriority(Utilities::IoPriority::IOPRIO_CLASS_IDLE);
watcher_->moveToThread(watcher_thread_);
qLog(Debug) << watcher_ << "moved to thread" << watcher_thread_;
qLog(Debug) << &*watcher_ << "moved to thread" << watcher_thread_;
watcher_thread_->start(QThread::IdlePriority);
watcher_->set_backend(backend_);
watcher_->set_task_manager(app_->task_manager());
QObject::connect(backend_, &CollectionBackend::Error, this, &SCollection::Error);
QObject::connect(backend_, &CollectionBackend::DirectoryDiscovered, watcher_, &CollectionWatcher::AddDirectory);
QObject::connect(backend_, &CollectionBackend::DirectoryDeleted, watcher_, &CollectionWatcher::RemoveDirectory);
QObject::connect(backend_, &CollectionBackend::SongsRatingChanged, this, &SCollection::SongsRatingChanged);
QObject::connect(backend_, &CollectionBackend::SongsStatisticsChanged, this, &SCollection::SongsPlaycountChanged);
QObject::connect(&*backend_, &CollectionBackend::Error, this, &SCollection::Error);
QObject::connect(&*backend_, &CollectionBackend::DirectoryDiscovered, &*watcher_, &CollectionWatcher::AddDirectory);
QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, &*watcher_, &CollectionWatcher::RemoveDirectory);
QObject::connect(&*backend_, &CollectionBackend::SongsRatingChanged, this, &SCollection::SongsRatingChanged);
QObject::connect(&*backend_, &CollectionBackend::SongsStatisticsChanged, this, &SCollection::SongsPlaycountChanged);
QObject::connect(watcher_, &CollectionWatcher::NewOrUpdatedSongs, backend_, &CollectionBackend::AddOrUpdateSongs);
QObject::connect(watcher_, &CollectionWatcher::SongsMTimeUpdated, backend_, &CollectionBackend::UpdateMTimesOnly);
QObject::connect(watcher_, &CollectionWatcher::SongsDeleted, backend_, &CollectionBackend::DeleteSongs);
QObject::connect(watcher_, &CollectionWatcher::SongsUnavailable, backend_, &CollectionBackend::MarkSongsUnavailable);
QObject::connect(watcher_, &CollectionWatcher::SongsReadded, backend_, &CollectionBackend::MarkSongsUnavailable);
QObject::connect(watcher_, &CollectionWatcher::SubdirsDiscovered, backend_, &CollectionBackend::AddOrUpdateSubdirs);
QObject::connect(watcher_, &CollectionWatcher::SubdirsMTimeUpdated, backend_, &CollectionBackend::AddOrUpdateSubdirs);
QObject::connect(watcher_, &CollectionWatcher::CompilationsNeedUpdating, backend_, &CollectionBackend::CompilationsNeedUpdating);
QObject::connect(watcher_, &CollectionWatcher::UpdateLastSeen, backend_, &CollectionBackend::UpdateLastSeen);
QObject::connect(&*watcher_, &CollectionWatcher::NewOrUpdatedSongs, &*backend_, &CollectionBackend::AddOrUpdateSongs);
QObject::connect(&*watcher_, &CollectionWatcher::SongsMTimeUpdated, &*backend_, &CollectionBackend::UpdateMTimesOnly);
QObject::connect(&*watcher_, &CollectionWatcher::SongsDeleted, &*backend_, &CollectionBackend::DeleteSongs);
QObject::connect(&*watcher_, &CollectionWatcher::SongsUnavailable, &*backend_, &CollectionBackend::MarkSongsUnavailable);
QObject::connect(&*watcher_, &CollectionWatcher::SongsReadded, &*backend_, &CollectionBackend::MarkSongsUnavailable);
QObject::connect(&*watcher_, &CollectionWatcher::SubdirsDiscovered, &*backend_, &CollectionBackend::AddOrUpdateSubdirs);
QObject::connect(&*watcher_, &CollectionWatcher::SubdirsMTimeUpdated, &*backend_, &CollectionBackend::AddOrUpdateSubdirs);
QObject::connect(&*watcher_, &CollectionWatcher::CompilationsNeedUpdating, &*backend_, &CollectionBackend::CompilationsNeedUpdating);
QObject::connect(&*watcher_, &CollectionWatcher::UpdateLastSeen, &*backend_, &CollectionBackend::UpdateLastSeen);
QObject::connect(app_->lastfm_import(), &LastFMImport::UpdateLastPlayed, backend_, &CollectionBackend::UpdateLastPlayed);
QObject::connect(app_->lastfm_import(), &LastFMImport::UpdatePlayCount, backend_, &CollectionBackend::UpdatePlayCount);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateLastPlayed, &*backend_, &CollectionBackend::UpdateLastPlayed);
QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdatePlayCount, &*backend_, &CollectionBackend::UpdatePlayCount);
// This will start the watcher checking for updates
backend_->LoadDirectoriesAsync();
@ -129,13 +133,13 @@ void SCollection::Init() {
void SCollection::Exit() {
wait_for_exit_ << backend_ << watcher_;
wait_for_exit_ << &*backend_ << &*watcher_;
QObject::disconnect(backend_, nullptr, watcher_, nullptr);
QObject::disconnect(watcher_, nullptr, backend_, nullptr);
QObject::disconnect(&*backend_, nullptr, &*watcher_, nullptr);
QObject::disconnect(&*watcher_, nullptr, &*backend_, nullptr);
QObject::connect(backend_, &CollectionBackend::ExitFinished, this, &SCollection::ExitReceived);
QObject::connect(watcher_, &CollectionWatcher::ExitFinished, this, &SCollection::ExitReceived);
QObject::connect(&*backend_, &CollectionBackend::ExitFinished, this, &SCollection::ExitReceived);
QObject::connect(&*watcher_, &CollectionWatcher::ExitFinished, this, &SCollection::ExitReceived);
backend_->ExitAsync();
watcher_->Abort();
watcher_->ExitAsync();

View File

@ -29,6 +29,8 @@
#include <QHash>
#include <QString>
#include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/song.h"
class QThread;
@ -42,7 +44,7 @@ class SCollection : public QObject {
Q_OBJECT
public:
explicit SCollection(Application *app, QObject *parent);
explicit SCollection(Application *app, QObject *parent = nullptr);
~SCollection() override;
static const char *kSongsTable;
@ -53,7 +55,7 @@ class SCollection : public QObject {
void Init();
void Exit();
CollectionBackend *backend() const { return backend_; }
SharedPtr<CollectionBackend> backend() const { return backend_; }
CollectionModel *model() const { return model_; }
QString full_rescan_reason(int schema_version) const { return full_rescan_revisions_.value(schema_version, QString()); }
@ -86,10 +88,10 @@ class SCollection : public QObject {
private:
Application *app_;
CollectionBackend *backend_;
SharedPtr<CollectionBackend> backend_;
CollectionModel *model_;
CollectionWatcher *watcher_;
ScopedPtr<CollectionWatcher> watcher_;
Thread *watcher_thread_;
QThread *original_thread_;

View File

@ -43,6 +43,7 @@
#include <QSqlQuery>
#include <QSqlError>
#include "core/shared_ptr.h"
#include "core/logging.h"
#include "core/database.h"
#include "core/scopedtransaction.h"
@ -67,7 +68,13 @@ CollectionBackend::CollectionBackend(QObject *parent)
}
void CollectionBackend::Init(Database *db, TaskManager *task_manager, const Song::Source source, const QString &songs_table, const QString &fts_table, const QString &dirs_table, const QString &subdirs_table) {
CollectionBackend::~CollectionBackend() {
qLog(Debug) << "Collection backend" << this << "for" << Song::TextForSource(source_) << "deleted";
}
void CollectionBackend::Init(SharedPtr<Database> db, SharedPtr<TaskManager> task_manager, const Song::Source source, const QString &songs_table, const QString &fts_table, const QString &dirs_table, const QString &subdirs_table) {
db_ = db;
task_manager_ = task_manager;

View File

@ -25,6 +25,7 @@
#include "config.h"
#include <optional>
#include <memory>
#include <QtGlobal>
#include <QObject>
@ -35,6 +36,7 @@
#include <QUrl>
#include <QSqlDatabase>
#include "core/shared_ptr.h"
#include "core/song.h"
#include "collectionfilteroptions.h"
#include "collectionquery.h"
@ -82,7 +84,7 @@ class CollectionBackendInterface : public QObject {
virtual Song::Source source() const = 0;
virtual Database *db() const = 0;
virtual SharedPtr<Database> db() const = 0;
// Get a list of directories in the collection. Emits DirectoriesDiscovered.
virtual void LoadDirectoriesAsync() = 0;
@ -140,7 +142,9 @@ class CollectionBackend : public CollectionBackendInterface {
Q_INVOKABLE explicit CollectionBackend(QObject *parent = nullptr);
void Init(Database *db, TaskManager *task_manager, const Song::Source source, const QString &songs_table, const QString &fts_table, const QString &dirs_table = QString(), const QString &subdirs_table = QString());
~CollectionBackend();
void Init(SharedPtr<Database> db, SharedPtr<TaskManager> task_manager, const Song::Source source, const QString &songs_table, const QString &fts_table, const QString &dirs_table = QString(), const QString &subdirs_table = QString());
void Close();
void ExitAsync();
@ -149,7 +153,7 @@ class CollectionBackend : public CollectionBackendInterface {
Song::Source source() const override { return source_; }
Database *db() const override { return db_; }
SharedPtr<Database> db() const override { return db_; }
QString songs_table() const override { return songs_table_; }
QString fts_table() const override { return fts_table_; }
@ -305,8 +309,8 @@ class CollectionBackend : public CollectionBackendInterface {
SongList GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db);
private:
Database *db_;
TaskManager *task_manager_;
SharedPtr<Database> db_;
SharedPtr<TaskManager> task_manager_;
Song::Source source_;
QString songs_table_;
QString dirs_table_;

View File

@ -20,12 +20,15 @@
#include "config.h"
#include <memory>
#include <QObject>
#include <QStandardItemModel>
#include <QAbstractItemModel>
#include <QVariant>
#include <QString>
#include "core/shared_ptr.h"
#include "core/filesystemmusicstorage.h"
#include "core/iconloader.h"
#include "core/musicstorage.h"
@ -34,24 +37,24 @@
#include "collectionbackend.h"
#include "collectiondirectorymodel.h"
CollectionDirectoryModel::CollectionDirectoryModel(CollectionBackend *backend, QObject *parent)
using std::make_shared;
CollectionDirectoryModel::CollectionDirectoryModel(SharedPtr<CollectionBackend> backend, QObject *parent)
: QStandardItemModel(parent),
dir_icon_(IconLoader::Load("document-open-folder")),
backend_(backend) {
QObject::connect(backend_, &CollectionBackend::DirectoryDiscovered, this, &CollectionDirectoryModel::DirectoryDiscovered);
QObject::connect(backend_, &CollectionBackend::DirectoryDeleted, this, &CollectionDirectoryModel::DirectoryDeleted);
QObject::connect(&*backend_, &CollectionBackend::DirectoryDiscovered, this, &CollectionDirectoryModel::DirectoryDiscovered);
QObject::connect(&*backend_, &CollectionBackend::DirectoryDeleted, this, &CollectionDirectoryModel::DirectoryDeleted);
}
CollectionDirectoryModel::~CollectionDirectoryModel() = default;
void CollectionDirectoryModel::DirectoryDiscovered(const CollectionDirectory &dir) {
QStandardItem *item = new QStandardItem(dir.path);
item->setData(dir.id, kIdRole);
item->setIcon(dir_icon_);
storage_ << std::make_shared<FilesystemMusicStorage>(backend_->source(), dir.path, dir.id);
storage_ << make_shared<FilesystemMusicStorage>(backend_->source(), dir.path, dir.id);
appendRow(item);
}

View File

@ -23,8 +23,6 @@
#include "config.h"
#include <memory>
#include <QObject>
#include <QStandardItemModel>
#include <QList>
@ -32,6 +30,8 @@
#include <QString>
#include <QIcon>
#include "core/shared_ptr.h"
class QModelIndex;
struct CollectionDirectory;
@ -42,8 +42,7 @@ class CollectionDirectoryModel : public QStandardItemModel {
Q_OBJECT
public:
explicit CollectionDirectoryModel(CollectionBackend *backend, QObject *parent = nullptr);
~CollectionDirectoryModel() override;
explicit CollectionDirectoryModel(SharedPtr<CollectionBackend> collection_backend, QObject *parent = nullptr);
// To be called by GUIs
void AddDirectory(const QString &path);
@ -60,8 +59,8 @@ class CollectionDirectoryModel : public QStandardItemModel {
static const int kIdRole = Qt::UserRole + 1;
QIcon dir_icon_;
CollectionBackend *backend_;
QList<std::shared_ptr<MusicStorage>> storage_;
SharedPtr<CollectionBackend> backend_;
QList<SharedPtr<MusicStorage>> storage_;
};
#endif // COLLECTIONDIRECTORYMODEL_H

View File

@ -53,6 +53,8 @@
#include <QSettings>
#include <QStandardPaths>
#include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
#include "core/application.h"
#include "core/database.h"
#include "core/iconloader.h"
@ -78,7 +80,7 @@ const char *CollectionModel::kPixmapDiskCacheDir = "pixmapcache";
QNetworkDiskCache *CollectionModel::sIconCache = nullptr;
CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, QObject *parent)
CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Application *app, QObject *parent)
: SimpleTreeModel<CollectionItem>(new CollectionItem(this), parent),
backend_(backend),
app_(app),
@ -103,7 +105,7 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
group_by_[2] = GroupBy::None;
if (app_) {
QObject::connect(app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &CollectionModel::AlbumCoverLoaded);
QObject::connect(&*app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &CollectionModel::AlbumCoverLoaded);
}
QIcon nocover = IconLoader::Load("cdcase");
@ -118,14 +120,14 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
QObject::connect(app_, &Application::ClearPixmapDiskCache, this, &CollectionModel::ClearDiskCache);
}
QObject::connect(backend_, &CollectionBackend::SongsDiscovered, this, &CollectionModel::SongsDiscovered);
QObject::connect(backend_, &CollectionBackend::SongsDeleted, this, &CollectionModel::SongsDeleted);
QObject::connect(backend_, &CollectionBackend::DatabaseReset, this, &CollectionModel::Reset);
QObject::connect(backend_, &CollectionBackend::TotalSongCountUpdated, this, &CollectionModel::TotalSongCountUpdatedSlot);
QObject::connect(backend_, &CollectionBackend::TotalArtistCountUpdated, this, &CollectionModel::TotalArtistCountUpdatedSlot);
QObject::connect(backend_, &CollectionBackend::TotalAlbumCountUpdated, this, &CollectionModel::TotalAlbumCountUpdatedSlot);
QObject::connect(backend_, &CollectionBackend::SongsStatisticsChanged, this, &CollectionModel::SongsSlightlyChanged);
QObject::connect(backend_, &CollectionBackend::SongsRatingChanged, this, &CollectionModel::SongsSlightlyChanged);
QObject::connect(&*backend_, &CollectionBackend::SongsDiscovered, this, &CollectionModel::SongsDiscovered);
QObject::connect(&*backend_, &CollectionBackend::SongsDeleted, this, &CollectionModel::SongsDeleted);
QObject::connect(&*backend_, &CollectionBackend::DatabaseReset, this, &CollectionModel::Reset);
QObject::connect(&*backend_, &CollectionBackend::TotalSongCountUpdated, this, &CollectionModel::TotalSongCountUpdatedSlot);
QObject::connect(&*backend_, &CollectionBackend::TotalArtistCountUpdated, this, &CollectionModel::TotalArtistCountUpdatedSlot);
QObject::connect(&*backend_, &CollectionBackend::TotalAlbumCountUpdated, this, &CollectionModel::TotalAlbumCountUpdatedSlot);
QObject::connect(&*backend_, &CollectionBackend::SongsStatisticsChanged, this, &CollectionModel::SongsSlightlyChanged);
QObject::connect(&*backend_, &CollectionBackend::SongsRatingChanged, this, &CollectionModel::SongsSlightlyChanged);
backend_->UpdateTotalSongCountAsync();
backend_->UpdateTotalArtistCountAsync();
@ -136,7 +138,11 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
}
CollectionModel::~CollectionModel() {
qLog(Debug) << "Collection model" << this << "for" << Song::TextForSource(backend_->source()) << "deleted";
delete root_;
}
void CollectionModel::set_pretty_covers(const bool use_pretty_covers) {
@ -632,10 +638,10 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
// Try to load it from the disk cache
if (use_disk_cache_ && sIconCache) {
std::unique_ptr<QIODevice> disk_cache_img(sIconCache->data(AlbumIconPixmapDiskCacheKey(cache_key)));
ScopedPtr<QIODevice> disk_cache_img(sIconCache->data(AlbumIconPixmapDiskCacheKey(cache_key)));
if (disk_cache_img) {
QImage cached_image;
if (cached_image.load(disk_cache_img.get(), "XPM")) {
if (cached_image.load(&*disk_cache_img, "XPM")) {
QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_image));
return QPixmap::fromImage(cached_image);
}
@ -688,7 +694,7 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderR
// If we have a valid cover not already in the disk cache
if (use_disk_cache_ && sIconCache && result.success && !result.image_scaled.isNull()) {
const QUrl disk_cache_key = AlbumIconPixmapDiskCacheKey(cache_key);
std::unique_ptr<QIODevice> disk_cache_img(sIconCache->data(disk_cache_key));
ScopedPtr<QIODevice> disk_cache_img(sIconCache->data(disk_cache_key));
if (!disk_cache_img) {
QNetworkCacheMetaData disk_cache_metadata;
disk_cache_metadata.setSaveToDisk(true);

View File

@ -45,6 +45,7 @@
#include <QPixmap>
#include <QNetworkDiskCache>
#include "core/shared_ptr.h"
#include "core/simpletreemodel.h"
#include "core/song.h"
#include "core/sqlrow.h"
@ -64,7 +65,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
Q_OBJECT
public:
explicit CollectionModel(CollectionBackend *backend, Application *app, QObject *parent = nullptr);
explicit CollectionModel(SharedPtr<CollectionBackend> backend, Application *app, QObject *parent = nullptr);
~CollectionModel() override;
static const int kPrettyCoverSize;
@ -131,7 +132,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
bool create_va;
};
CollectionBackend *backend() const { return backend_; }
SharedPtr<CollectionBackend> backend() const { return backend_; }
CollectionDirectoryModel *directory_model() const { return dir_model_; }
// Call before Init()
@ -273,7 +274,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
static qint64 MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id, const qint64 cache_size_default);
private:
CollectionBackend *backend_;
SharedPtr<CollectionBackend> backend_;
Application *app_;
CollectionDirectoryModel *dir_model_;
bool show_various_artists_;

View File

@ -19,10 +19,11 @@
#include <QString>
#include "core/shared_ptr.h"
#include "core/taskmanager.h"
#include "collectiontask.h"
CollectionTask::CollectionTask(TaskManager *task_manager, const QString &message) : task_manager_(task_manager), task_id_(-1) {
CollectionTask::CollectionTask(SharedPtr<TaskManager> task_manager, const QString &message) : task_manager_(task_manager), task_id_(-1) {
if (task_manager_) task_id_ = task_manager_->StartTask(message);

View File

@ -23,15 +23,17 @@
#include <QtGlobal>
#include <QString>
#include "core/shared_ptr.h"
class TaskManager;
class CollectionTask {
public:
explicit CollectionTask(TaskManager *task_manager, const QString &message);
explicit CollectionTask(SharedPtr<TaskManager> task_manager, const QString &message);
~CollectionTask();
private:
TaskManager *task_manager_;
SharedPtr<TaskManager> task_manager_;
int task_id_;
Q_DISABLE_COPY(CollectionTask)

View File

@ -71,6 +71,8 @@
#include "organize/organizeerrordialog.h"
#include "settings/collectionsettingspage.h"
using std::make_unique;
CollectionView::CollectionView(QWidget *parent)
: AutoExpandingTreeView(parent),
app_(nullptr),
@ -573,7 +575,7 @@ SongList CollectionView::GetSelectedSongs() const {
void CollectionView::Organize() {
if (!organize_dialog_) {
organize_dialog_ = std::make_unique<OrganizeDialog>(app_->task_manager(), app_->collection_backend(), this);
organize_dialog_ = make_unique<OrganizeDialog>(app_->task_manager(), app_->collection_backend(), this);
}
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
@ -591,8 +593,8 @@ void CollectionView::Organize() {
void CollectionView::EditTracks() {
if (!edit_tag_dialog_) {
edit_tag_dialog_ = std::make_unique<EditTagDialog>(app_, this);
QObject::connect(edit_tag_dialog_.get(), &EditTagDialog::Error, this, &CollectionView::EditTagError);
edit_tag_dialog_ = make_unique<EditTagDialog>(app_, this);
QObject::connect(&*edit_tag_dialog_, &EditTagDialog::Error, this, &CollectionView::EditTagError);
}
const SongList songs = GetSelectedSongs();
edit_tag_dialog_->SetSongs(songs);
@ -614,7 +616,7 @@ void CollectionView::CopyToDevice() {
#ifndef Q_OS_WIN
if (!organize_dialog_) {
organize_dialog_ = std::make_unique<OrganizeDialog>(app_->task_manager(), nullptr, this);
organize_dialog_ = make_unique<OrganizeDialog>(app_->task_manager(), nullptr, this);
}
organize_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
@ -686,7 +688,7 @@ void CollectionView::Delete() {
if (DeleteConfirmationDialog::warning(files) != QDialogButtonBox::Yes) return;
// We can cheat and always take the storage of the first directory, since they'll all be FilesystemMusicStorage in a collection and deleting doesn't check the actual directory.
std::shared_ptr<MusicStorage> storage = app_->collection_model()->directory_model()->index(0, 0).data(MusicStorage::Role_Storage).value<std::shared_ptr<MusicStorage>>();
SharedPtr<MusicStorage> storage = app_->collection_model()->directory_model()->index(0, 0).data(MusicStorage::Role_Storage).value<SharedPtr<MusicStorage>>();
DeleteFiles *delete_files = new DeleteFiles(app_->task_manager(), storage, true);
QObject::connect(delete_files, &DeleteFiles::Finished, this, &CollectionView::DeleteFilesFinished);

View File

@ -24,8 +24,6 @@
#include "config.h"
#include <memory>
#include <QObject>
#include <QAbstractItemModel>
#include <QAbstractItemView>
@ -33,6 +31,7 @@
#include <QPixmap>
#include <QSet>
#include "core/scoped_ptr.h"
#include "core/song.h"
#include "widgets/autoexpandingtreeview.h"
@ -148,8 +147,8 @@ class CollectionView : public AutoExpandingTreeView {
QAction *action_no_show_in_various_;
QAction *action_delete_files_;
std::unique_ptr<OrganizeDialog> organize_dialog_;
std::unique_ptr<EditTagDialog> edit_tag_dialog_;
ScopedPtr<OrganizeDialog> organize_dialog_;
ScopedPtr<EditTagDialog> edit_tag_dialog_;
bool is_in_keyboard_search_;
bool delete_files_;

View File

@ -119,6 +119,12 @@ CollectionWatcher::CollectionWatcher(Song::Source source, QObject *parent)
}
CollectionWatcher::~CollectionWatcher() {
qLog(Debug) << "Collection watcher" << this << "for" << Song::TextForSource(source_) << "deleted.";
}
void CollectionWatcher::ExitAsync() {
QMetaObject::invokeMethod(this, &CollectionWatcher::Exit, Qt::QueuedConnection);
}

View File

@ -35,6 +35,7 @@
#include <QUrl>
#include "collectiondirectory.h"
#include "core/shared_ptr.h"
#include "core/song.h"
class QThread;
@ -50,11 +51,12 @@ class CollectionWatcher : public QObject {
public:
explicit CollectionWatcher(Song::Source source, QObject *parent = nullptr);
~CollectionWatcher();
Song::Source source() { return source_; }
void set_backend(CollectionBackend *backend) { backend_ = backend; }
void set_task_manager(TaskManager *task_manager) { task_manager_ = task_manager; }
void set_backend(SharedPtr<CollectionBackend> backend) { backend_ = backend; }
void set_task_manager(SharedPtr<TaskManager> task_manager) { task_manager_ = task_manager; }
void set_device_name(const QString &device_name) { device_name_ = device_name; }
void IncrementalScanAsync();
@ -208,8 +210,8 @@ class CollectionWatcher : public QObject {
private:
Song::Source source_;
CollectionBackend *backend_;
TaskManager *task_manager_;
SharedPtr<CollectionBackend> backend_;
SharedPtr<TaskManager> task_manager_;
QString device_name_;
FileSystemWatcherInterface *fs_watcher_;

View File

@ -21,7 +21,7 @@
#include "config.h"
#include <functional>
#include <memory>
#include <QDialog>
#include <QWidget>
@ -41,6 +41,8 @@
#include <boost/multi_index_container_fwd.hpp>
#include <boost/operators.hpp>
using std::make_unique;
using boost::multi_index_container;
using boost::multi_index::indexed_by;
using boost::multi_index::ordered_unique;
@ -69,7 +71,7 @@ class GroupByDialogPrivate {
MappingContainer mapping_;
};
GroupByDialog::GroupByDialog(QWidget *parent) : QDialog(parent), ui_(new Ui_GroupByDialog), p_(new GroupByDialogPrivate) {
GroupByDialog::GroupByDialog(QWidget *parent) : QDialog(parent), ui_(make_unique<Ui_GroupByDialog>()), p_(make_unique<GroupByDialogPrivate>()) {
ui_->setupUi(this);
Reset();

View File

@ -24,12 +24,11 @@
#include "config.h"
#include <memory>
#include <QDialog>
#include <QObject>
#include <QString>
#include "core/scoped_ptr.h"
#include "collectionmodel.h"
#include "ui_groupbydialog.h"
@ -55,8 +54,8 @@ class GroupByDialog : public QDialog {
void Reset();
private:
std::unique_ptr<Ui_GroupByDialog> ui_;
std::unique_ptr<GroupByDialogPrivate> p_;
ScopedPtr<Ui_GroupByDialog> ui_;
ScopedPtr<GroupByDialogPrivate> p_;
};
#endif // GROUPBYDIALOG_H

View File

@ -37,12 +37,16 @@
#include <QContextMenuEvent>
#include <QPaintEvent>
#include "core/shared_ptr.h"
#include "utilities/imageutils.h"
#include "covermanager/albumcoverchoicecontroller.h"
#include "contextview.h"
#include "contextalbum.h"
using std::make_unique;
using std::make_shared;
const int ContextAlbum::kFadeTimeLineMs = 1000;
ContextAlbum::ContextAlbum(QWidget *parent)
@ -155,15 +159,15 @@ void ContextAlbum::SetImage(QImage image) {
ScaleCover();
if (!pixmap_previous.isNull()) {
std::shared_ptr<PreviousCover> previous_cover = std::make_shared<PreviousCover>();
SharedPtr<PreviousCover> previous_cover = make_shared<PreviousCover>();
previous_cover->image = image_previous;
previous_cover->pixmap = pixmap_previous;
previous_cover->opacity = opacity_previous;
previous_cover->timeline.reset(new QTimeLine(kFadeTimeLineMs), [](QTimeLine *timeline) { timeline->deleteLater(); });
previous_cover->timeline->setDirection(QTimeLine::Backward);
previous_cover->timeline->setCurrentTime(timeline_fade_->state() == QTimeLine::Running ? timeline_fade_->currentTime() : kFadeTimeLineMs);
QObject::connect(previous_cover->timeline.get(), &QTimeLine::valueChanged, this, [this, previous_cover]() { FadePreviousCover(previous_cover); });
QObject::connect(previous_cover->timeline.get(), &QTimeLine::finished, this, [this, previous_cover]() { FadePreviousCoverFinished(previous_cover); });
QObject::connect(&*previous_cover->timeline, &QTimeLine::valueChanged, this, [this, previous_cover]() { FadePreviousCover(previous_cover); });
QObject::connect(&*previous_cover->timeline, &QTimeLine::finished, this, [this, previous_cover]() { FadePreviousCoverFinished(previous_cover); });
previous_covers_ << previous_cover;
previous_cover->timeline->start();
}
@ -194,7 +198,7 @@ void ContextAlbum::DrawSpinner(QPainter *p) {
void ContextAlbum::DrawPreviousCovers(QPainter *p) {
for (std::shared_ptr<PreviousCover> previous_cover : previous_covers_) {
for (SharedPtr<PreviousCover> previous_cover : previous_covers_) {
DrawImage(p, previous_cover->pixmap, previous_cover->opacity);
}
@ -217,7 +221,7 @@ void ContextAlbum::FadeCurrentCoverFinished() {
}
void ContextAlbum::FadePreviousCover(std::shared_ptr<PreviousCover> previous_cover) {
void ContextAlbum::FadePreviousCover(SharedPtr<PreviousCover> previous_cover) {
if (previous_cover->timeline->currentValue() >= previous_cover->opacity) return;
@ -225,7 +229,7 @@ void ContextAlbum::FadePreviousCover(std::shared_ptr<PreviousCover> previous_cov
}
void ContextAlbum::FadePreviousCoverFinished(std::shared_ptr<PreviousCover> previous_cover) {
void ContextAlbum::FadePreviousCoverFinished(SharedPtr<PreviousCover> previous_cover) {
previous_covers_.removeAll(previous_cover);
@ -245,7 +249,7 @@ void ContextAlbum::ScaleCover() {
void ContextAlbum::ScalePreviousCovers() {
for (std::shared_ptr<PreviousCover> previous_cover : previous_covers_) {
for (SharedPtr<PreviousCover> previous_cover : previous_covers_) {
QImage image = ImageUtils::ScaleImage(previous_cover->image, QSize(desired_height_, desired_height_), devicePixelRatioF(), true);
if (image.isNull()) {
previous_cover->pixmap = QPixmap();
@ -262,8 +266,8 @@ void ContextAlbum::SearchCoverInProgress() {
downloading_covers_ = true;
// Show a spinner animation
spinner_animation_ = std::make_unique<QMovie>(":/pictures/spinner.gif", QByteArray(), this);
QObject::connect(spinner_animation_.get(), &QMovie::updated, this, &ContextAlbum::Update);
spinner_animation_ = make_unique<QMovie>(":/pictures/spinner.gif", QByteArray(), this);
QObject::connect(&*spinner_animation_, &QMovie::updated, this, &ContextAlbum::Update);
spinner_animation_->start();
update();

View File

@ -33,6 +33,9 @@
#include <QPixmap>
#include <QMovie>
#include "core/scoped_ptr.h"
#include "core/shared_ptr.h"
class QMenu;
class QTimeLine;
class QPainter;
@ -64,10 +67,10 @@ class ContextAlbum : public QWidget {
QImage image;
QPixmap pixmap;
qreal opacity;
std::shared_ptr<QTimeLine> timeline;
SharedPtr<QTimeLine> timeline;
};
QList<std::shared_ptr<PreviousCover>> previous_covers_;
QList<SharedPtr<PreviousCover>> previous_covers_;
void DrawImage(QPainter *p, const QPixmap &pixmap, const qreal opacity);
void DrawSpinner(QPainter *p);
@ -84,8 +87,8 @@ class ContextAlbum : public QWidget {
void AutomaticCoverSearchDone();
void FadeCurrentCover(const qreal value);
void FadeCurrentCoverFinished();
void FadePreviousCover(std::shared_ptr<PreviousCover> previouscover);
void FadePreviousCoverFinished(std::shared_ptr<PreviousCover> previouscover);
void FadePreviousCover(SharedPtr<PreviousCover> previouscover);
void FadePreviousCoverFinished(SharedPtr<PreviousCover> previouscover);
public slots:
void SearchCoverInProgress();
@ -103,7 +106,7 @@ class ContextAlbum : public QWidget {
QImage image_original_;
QPixmap pixmap_current_;
qreal pixmap_current_opacity_;
std::unique_ptr<QMovie> spinner_animation_;
ScopedPtr<QMovie> spinner_animation_;
int desired_height_;
};

View File

@ -31,10 +31,11 @@
#include <QThread>
#include <QString>
#include "core/lazy.h"
#include "core/tagreaderclient.h"
#include "core/logging.h"
#include "shared_ptr.h"
#include "lazy.h"
#include "tagreaderclient.h"
#include "database.h"
#include "taskmanager.h"
#include "player.h"
@ -98,99 +99,103 @@
#include "radios/radioservices.h"
#include "radios/radiobackend.h"
using std::make_shared;
using namespace std::chrono_literals;
class ApplicationImpl {
public:
explicit ApplicationImpl(Application *app) :
tag_reader_client_([app]() {
TagReaderClient *client = new TagReaderClient(app);
tag_reader_client_([app](){
TagReaderClient *client = new TagReaderClient();
app->MoveToNewThread(client);
client->Start();
return client;
}),
database_([app]() {
Database *db = new Database(app, app);
Database *db = new Database(app);
app->MoveToNewThread(db);
QTimer::singleShot(30s, db, &Database::DoBackup);
return db;
}),
task_manager_([app]() { return new TaskManager(app); }),
player_([app]() { return new Player(app, app); }),
network_([app]() { return new NetworkAccessManager(app); }),
device_finders_([app]() { return new DeviceFinders(app); }),
task_manager_([]() { return new TaskManager(); }),
player_([app]() { return new Player(app); }),
network_([]() { return new NetworkAccessManager(); }),
device_finders_([]() { return new DeviceFinders(); }),
#ifndef Q_OS_WIN
device_manager_([app]() { return new DeviceManager(app, app); }),
device_manager_([app]() { return new DeviceManager(app); }),
#endif
collection_([app]() { return new SCollection(app, app); }),
collection_([app]() { return new SCollection(app); }),
playlist_backend_([this, app]() {
PlaylistBackend *backend = new PlaylistBackend(app, app);
PlaylistBackend *backend = new PlaylistBackend(app);
app->MoveToThread(backend, database_->thread());
return backend;
}),
playlist_manager_([app]() { return new PlaylistManager(app); }),
cover_providers_([app]() {
CoverProviders *cover_providers = new CoverProviders(app);
CoverProviders *cover_providers = new CoverProviders();
// Initialize the repository of cover providers.
cover_providers->AddProvider(new LastFmCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new MusicbrainzCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new DiscogsCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new DeezerCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new MusixmatchCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new SpotifyCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new LastFmCoverProvider(app, app->network()));
cover_providers->AddProvider(new MusicbrainzCoverProvider(app, app->network()));
cover_providers->AddProvider(new DiscogsCoverProvider(app, app->network()));
cover_providers->AddProvider(new DeezerCoverProvider(app, app->network()));
cover_providers->AddProvider(new MusixmatchCoverProvider(app, app->network()));
cover_providers->AddProvider(new SpotifyCoverProvider(app, app->network()));
#ifdef HAVE_TIDAL
cover_providers->AddProvider(new TidalCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new TidalCoverProvider(app, app->network()));
#endif
#ifdef HAVE_QOBUZ
cover_providers->AddProvider(new QobuzCoverProvider(app, app->network(), app));
cover_providers->AddProvider(new QobuzCoverProvider(app, app->network()));
#endif
cover_providers->ReloadSettings();
return cover_providers;
}),
album_cover_loader_([app]() {
AlbumCoverLoader *loader = new AlbumCoverLoader(app);
AlbumCoverLoader *loader = new AlbumCoverLoader();
app->MoveToNewThread(loader);
return loader;
}),
current_albumcover_loader_([app]() { return new CurrentAlbumCoverLoader(app, app); }),
current_albumcover_loader_([app]() { return new CurrentAlbumCoverLoader(app); }),
lyrics_providers_([app]() {
LyricsProviders *lyrics_providers = new LyricsProviders(app);
// Initialize the repository of lyrics providers.
lyrics_providers->AddProvider(new GeniusLyricsProvider(app->network(), app));
lyrics_providers->AddProvider(new OVHLyricsProvider(app->network(), app));
lyrics_providers->AddProvider(new LoloLyricsProvider(app->network(), app));
lyrics_providers->AddProvider(new MusixmatchLyricsProvider(app->network(), app));
lyrics_providers->AddProvider(new ChartLyricsProvider(app->network(), app));
lyrics_providers->AddProvider(new LyricsComLyricsProvider(app->network(), app));
lyrics_providers->AddProvider(new GeniusLyricsProvider(app->network()));
lyrics_providers->AddProvider(new OVHLyricsProvider(app->network()));
lyrics_providers->AddProvider(new LoloLyricsProvider(app->network()));
lyrics_providers->AddProvider(new MusixmatchLyricsProvider(app->network()));
lyrics_providers->AddProvider(new ChartLyricsProvider(app->network()));
lyrics_providers->AddProvider(new LyricsComLyricsProvider(app->network()));
lyrics_providers->ReloadSettings();
return lyrics_providers;
}),
internet_services_([app]() {
InternetServices *internet_services = new InternetServices(app);
InternetServices *internet_services = new InternetServices();
#ifdef HAVE_SUBSONIC
internet_services->AddService(new SubsonicService(app, internet_services));
internet_services->AddService(make_shared<SubsonicService>(app));
#endif
#ifdef HAVE_TIDAL
internet_services->AddService(new TidalService(app, internet_services));
internet_services->AddService(make_shared<TidalService>(app));
#endif
#ifdef HAVE_QOBUZ
internet_services->AddService(new QobuzService(app, internet_services));
internet_services->AddService(make_shared<QobuzService>(app));
#endif
return internet_services;
}),
radio_services_([app]() { return new RadioServices(app, app); }),
radio_services_([app]() { return new RadioServices(app); }),
scrobbler_([app]() {
AudioScrobbler *scrobbler = new AudioScrobbler(app);
scrobbler->AddService(new LastFMScrobbler(scrobbler, app->network(), app));
scrobbler->AddService(new LibreFMScrobbler(scrobbler, app->network(), app));
scrobbler->AddService(new ListenBrainzScrobbler(scrobbler, app->network(), app));
scrobbler->AddService(make_shared<LastFMScrobbler>(scrobbler->settings(), app->network()));
scrobbler->AddService(make_shared<LibreFMScrobbler>(scrobbler->settings(), app->network()));
scrobbler->AddService(make_shared<ListenBrainzScrobbler>(scrobbler->settings(), app->network()));
#ifdef HAVE_SUBSONIC
scrobbler->AddService(make_shared<SubsonicScrobbler>(scrobbler->settings(), app));
#endif
return scrobbler;
}),
#ifdef HAVE_MOODBAR
moodbar_loader_([app]() { return new MoodbarLoader(app, app); }),
moodbar_controller_([app]() { return new MoodbarController(app, app); }),
moodbar_loader_([app]() { return new MoodbarLoader(app); }),
moodbar_controller_([app]() { return new MoodbarController(app); }),
#endif
lastfm_import_([app]() { return new LastFMImport(app->network(), app); })
lastfm_import_([app]() { return new LastFMImport(app->network()); })
{}
Lazy<TagReaderClient> tag_reader_client_;
@ -227,17 +232,13 @@ Application::Application(QObject *parent)
collection()->Init();
tag_reader_client();
QObject::connect(database(), &Database::Error, this, &Application::ErrorAdded);
QObject::connect(&*database(), &Database::Error, this, &Application::ErrorAdded);