strawberry-audio-player-win.../src/collection/collectionbackend.h

311 lines
14 KiB
C
Raw Normal View History

2018-02-27 18:06:05 +01:00
/*
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
2021-03-20 21:14:47 +01:00
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
2018-02-27 18:06:05 +01:00
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
2018-08-09 18:39:44 +02:00
*
2018-02-27 18:06:05 +01:00
*/
#ifndef COLLECTIONBACKEND_H
#define COLLECTIONBACKEND_H
#include "config.h"
#include <optional>
#include <QtGlobal>
2018-02-27 18:06:05 +01:00
#include <QObject>
#include <QFileInfo>
#include <QList>
#include <QString>
#include <QStringList>
2018-02-27 18:06:05 +01:00
#include <QUrl>
#include <QSqlDatabase>
#include <QSqlQuery>
2018-02-27 18:06:05 +01:00
#include "core/song.h"
#include "core/sqlquery.h"
#include "collectionfilteroptions.h"
#include "collectionquery.h"
#include "collectiondirectory.h"
2018-02-27 18:06:05 +01:00
class QThread;
class TaskManager;
2018-02-27 18:06:05 +01:00
class Database;
class SmartPlaylistSearch;
2018-02-27 18:06:05 +01:00
class CollectionBackendInterface : public QObject {
Q_OBJECT
public:
2020-04-07 16:49:15 +02:00
explicit CollectionBackendInterface(QObject *parent = nullptr) : QObject(parent) {}
2018-02-27 18:06:05 +01:00
struct Album {
2023-02-18 14:09:27 +01:00
Album() : filetype(Song::FileType::Unknown) {}
2021-07-11 09:49:38 +02:00
Album(const QString &_album_artist, const QString &_album, const QUrl &_art_automatic, const QUrl &_art_manual, const QList<QUrl> &_urls, const Song::FileType _filetype, const QString &_cue_path)
: album_artist(_album_artist),
album(_album),
art_automatic(_art_automatic),
art_manual(_art_manual),
urls(_urls),
filetype(_filetype),
cue_path(_cue_path) {}
2018-02-27 18:06:05 +01:00
QString album_artist;
QString album;
2018-02-27 18:06:05 +01:00
QUrl art_automatic;
QUrl art_manual;
QList<QUrl> urls;
Song::FileType filetype;
QString cue_path;
2018-02-27 18:06:05 +01:00
};
2022-10-13 22:39:31 +02:00
using AlbumList = QList<Album>;
2018-02-27 18:06:05 +01:00
virtual QString songs_table() const = 0;
virtual QString fts_table() const = 0;
virtual Song::Source source() const = 0;
virtual Database *db() const = 0;
2018-02-27 18:06:05 +01:00
// Get a list of directories in the collection. Emits DirectoriesDiscovered.
virtual void LoadDirectoriesAsync() = 0;
virtual void UpdateTotalSongCountAsync() = 0;
virtual void UpdateTotalArtistCountAsync() = 0;
virtual void UpdateTotalAlbumCountAsync() = 0;
2020-09-10 22:05:12 +02:00
virtual SongList FindSongsInDirectory(const int id) = 0;
virtual SongList SongsWithMissingFingerprint(const int id) = 0;
virtual CollectionSubdirectoryList SubdirsInDirectory(const int id) = 0;
virtual CollectionDirectoryList GetAllDirectories() = 0;
2020-09-10 22:05:12 +02:00
virtual void ChangeDirPath(const int id, const QString &old_path, const QString &new_path) = 0;
2018-02-27 18:06:05 +01:00
virtual SongList GetAllSongs() = 0;
virtual QStringList GetAllArtists(const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
virtual QStringList GetAllArtistsWithAlbums(const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
virtual SongList GetArtistSongs(const QString &effective_albumartist, const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
virtual SongList GetAlbumSongs(const QString &effective_albumartist, const QString &album, const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
virtual SongList GetSongsByAlbum(const QString &album, const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
2018-02-27 18:06:05 +01:00
virtual SongList GetCompilationSongs(const QString &album, const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
2018-02-27 18:06:05 +01:00
virtual AlbumList GetAllAlbums(const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
virtual AlbumList GetAlbumsByArtist(const QString &artist, const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
virtual AlbumList GetCompilationAlbums(const CollectionFilterOptions &opt = CollectionFilterOptions()) = 0;
2018-02-27 18:06:05 +01:00
virtual void UpdateManualAlbumArtAsync(const QString &effective_albumartist, const QString &album, const QUrl &cover_url, const bool clear_art_automatic = false) = 0;
virtual void UpdateAutomaticAlbumArtAsync(const QString &effective_albumartist, const QString &album, const QUrl &cover_url, const bool clear_art_manual = false) = 0;
virtual Album GetAlbumArt(const QString &effective_albumartist, const QString &album) = 0;
2018-02-27 18:06:05 +01:00
2020-09-10 22:05:12 +02:00
virtual Song GetSongById(const int id) = 0;
2018-02-27 18:06:05 +01:00
virtual SongList GetSongsByFingerprint(const QString &fingerprint) = 0;
// Returns all sections of a song with the given filename. If there's just one section the resulting list will have it's size equal to 1.
2021-06-05 02:50:20 +02:00
virtual SongList GetSongsByUrl(const QUrl &url, const bool unavailable = false) = 0;
// Returns a section of a song with the given filename and beginning. If the section is not present in collection, returns invalid song.
2018-02-27 18:06:05 +01:00
// Using default beginning value is suitable when searching for single-section songs.
virtual Song GetSongByUrl(const QUrl &url, const qint64 beginning = 0) = 0;
2018-02-27 18:06:05 +01:00
virtual void AddDirectory(const QString &path) = 0;
virtual void RemoveDirectory(const CollectionDirectory &dir) = 0;
2018-02-27 18:06:05 +01:00
};
class CollectionBackend : public CollectionBackendInterface {
Q_OBJECT
public:
2020-06-15 21:55:05 +02:00
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());
void Close();
void ExitAsync();
2018-02-27 18:06:05 +01:00
void ReportErrors(const CollectionQuery &query);
Song::Source source() const override { return source_; }
Database *db() const override { return db_; }
2018-02-27 18:06:05 +01:00
2020-06-15 21:55:05 +02:00
QString songs_table() const override { return songs_table_; }
QString fts_table() const override { return fts_table_; }
2018-02-27 18:06:05 +01:00
QString dirs_table() const { return dirs_table_; }
QString subdirs_table() const { return subdirs_table_; }
// Get a list of directories in the collection. Emits DirectoriesDiscovered.
2020-06-15 21:55:05 +02:00
void LoadDirectoriesAsync() override;
2018-02-27 18:06:05 +01:00
2020-06-15 21:55:05 +02:00
void UpdateTotalSongCountAsync() override;
void UpdateTotalArtistCountAsync() override;
void UpdateTotalAlbumCountAsync() override;
2018-02-27 18:06:05 +01:00
2020-06-15 21:55:05 +02:00
SongList FindSongsInDirectory(const int id) override;
SongList SongsWithMissingFingerprint(const int id) override;
CollectionSubdirectoryList SubdirsInDirectory(const int id) override;
CollectionDirectoryList GetAllDirectories() override;
2020-06-15 21:55:05 +02:00
void ChangeDirPath(const int id, const QString &old_path, const QString &new_path) override;
2018-02-27 18:06:05 +01:00
SongList GetAllSongs() override;
QStringList GetAll(const QString &column, const CollectionFilterOptions &filter_options = CollectionFilterOptions());
QStringList GetAllArtists(const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
QStringList GetAllArtistsWithAlbums(const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
SongList GetArtistSongs(const QString &effective_albumartist, const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
SongList GetAlbumSongs(const QString &effective_albumartist, const QString &album, const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
SongList GetSongsByAlbum(const QString &album, const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
2018-02-27 18:06:05 +01:00
SongList GetCompilationSongs(const QString &album, const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
2018-02-27 18:06:05 +01:00
AlbumList GetAllAlbums(const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
AlbumList GetCompilationAlbums(const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
AlbumList GetAlbumsByArtist(const QString &artist, const CollectionFilterOptions &opt = CollectionFilterOptions()) override;
2018-02-27 18:06:05 +01:00
2021-06-22 13:56:27 +02:00
void UpdateManualAlbumArtAsync(const QString &effective_albumartist, const QString &album, const QUrl &cover_url, const bool clear_art_automatic = false) override;
void UpdateAutomaticAlbumArtAsync(const QString &effective_albumartist, const QString &album, const QUrl &cover_url, const bool clear_art_manual = false) override;
2021-06-22 13:56:27 +02:00
Album GetAlbumArt(const QString &effective_albumartist, const QString &album) override;
2018-02-27 18:06:05 +01:00
2020-06-15 21:55:05 +02:00
Song GetSongById(const int id) override;
2018-02-27 18:06:05 +01:00
SongList GetSongsById(const QList<int> &ids);
SongList GetSongsById(const QStringList &ids);
SongList GetSongsByForeignId(const QStringList &ids, const QString &table, const QString &column);
2021-06-05 02:50:20 +02:00
SongList GetSongsByUrl(const QUrl &url, const bool unavailable = false) override;
2020-06-15 21:55:05 +02:00
Song GetSongByUrl(const QUrl &url, qint64 beginning = 0) override;
2018-02-27 18:06:05 +01:00
2020-06-15 21:55:05 +02:00
void AddDirectory(const QString &path) override;
void RemoveDirectory(const CollectionDirectory &dir) override;
2018-02-27 18:06:05 +01:00
bool ExecCollectionQuery(CollectionQuery *query, SongList &songs);
bool ExecCollectionQuery(CollectionQuery *query, SongMap &songs);
2018-02-27 18:06:05 +01:00
2020-04-23 21:08:28 +02:00
void IncrementPlayCountAsync(const int id);
void IncrementSkipCountAsync(const int id, const float progress);
void ResetPlayStatisticsAsync(const int id, const bool save_tags = false);
void ResetPlayStatisticsAsync(const QList<int> &id_list, const bool save_tags = false);
2018-02-27 18:06:05 +01:00
void DeleteAllAsync();
2018-02-27 18:06:05 +01:00
2020-04-13 03:39:51 +02:00
Song GetSongBySongId(const QString &song_id);
SongList GetSongsBySongId(const QStringList &song_ids);
SongList GetSongsByFingerprint(const QString &fingerprint) override;
2021-06-28 00:16:22 +02:00
SongList SmartPlaylistsGetAllSongs();
SongList SmartPlaylistsFindSongs(const SmartPlaylistSearch &search);
2020-05-12 18:45:24 +02:00
void AddOrUpdateSongsAsync(const SongList &songs);
void UpdateSongsBySongIDAsync(const SongMap &new_songs);
2020-05-12 18:45:24 +02:00
2021-10-30 18:53:14 +02:00
void UpdateSongRatingAsync(const int id, const float rating, const bool save_tags = false);
void UpdateSongsRatingAsync(const QList<int> &ids, const float rating, const bool save_tags = false);
2018-02-27 18:06:05 +01:00
public slots:
void Exit();
2018-02-27 18:06:05 +01:00
void LoadDirectories();
void UpdateTotalSongCount();
void UpdateTotalArtistCount();
void UpdateTotalAlbumCount();
void AddOrUpdateSongs(const SongList &songs);
void UpdateSongsBySongID(const SongMap &new_songs);
2018-02-27 18:06:05 +01:00
void UpdateMTimesOnly(const SongList &songs);
void DeleteSongs(const SongList &songs);
2020-09-10 22:05:12 +02:00
void MarkSongsUnavailable(const SongList &songs, const bool unavailable = true);
void AddOrUpdateSubdirs(const CollectionSubdirectoryList &subdirs);
2021-01-26 16:48:04 +01:00
void CompilationsNeedUpdating();
void UpdateManualAlbumArt(const QString &effective_albumartist, const QString &album, const QUrl &cover_url, const bool clear_art_automatic = false);
void UpdateAutomaticAlbumArt(const QString &effective_albumartist, const QString &album, const QUrl &cover_url, const bool clear_art_manual = false);
2020-04-23 21:08:28 +02:00
void ForceCompilation(const QString &album, const QList<QString> &artists, const bool on);
void IncrementPlayCount(const int id);
void IncrementSkipCount(const int id, const float progress);
void ResetPlayStatistics(const int id, const bool save_tags = false);
void ResetPlayStatistics(const QList<int> &id_list, const bool save_tags = false);
bool ResetPlayStatistics(const QStringList &id_str_list);
void DeleteAll();
void SongPathChanged(const Song &song, const QFileInfo &new_file, const std::optional<int> new_collection_directory_id);
2018-02-27 18:06:05 +01:00
2020-08-30 18:09:13 +02:00
SongList GetSongsBy(const QString &artist, const QString &album, const QString &title);
void UpdateLastPlayed(const QString &artist, const QString &album, const QString &title, const qint64 lastplayed);
void UpdatePlayCount(const QString &artist, const QString &title, const int playcount, const bool save_tags = false);
2020-08-30 18:09:13 +02:00
2021-10-30 18:53:14 +02:00
void UpdateSongRating(const int id, const float rating, const bool save_tags = false);
void UpdateSongsRating(const QList<int> &id_list, const float rating, const bool save_tags = false);
void UpdateLastSeen(const int directory_id, const int expire_unavailable_songs_days);
void ExpireSongs(const int directory_id, const int expire_unavailable_songs_days);
signals:
void DirectoryDiscovered(CollectionDirectory, CollectionSubdirectoryList);
void DirectoryDeleted(CollectionDirectory);
2018-02-27 18:06:05 +01:00
void SongsDiscovered(SongList);
void SongsDeleted(SongList);
void SongsStatisticsChanged(SongList, bool = false);
2018-02-27 18:06:05 +01:00
void DatabaseReset();
void TotalSongCountUpdated(int);
void TotalArtistCountUpdated(int);
void TotalAlbumCountUpdated(int);
void SongsRatingChanged(SongList, bool);
2018-02-27 18:06:05 +01:00
void ExitFinished();
void Error(QString);
2018-02-27 18:06:05 +01:00
private:
struct CompilationInfo {
2019-11-03 23:23:04 +01:00
CompilationInfo() : has_compilation_detected(0), has_not_compilation_detected(0) {}
2018-02-27 18:06:05 +01:00
2019-11-03 23:23:04 +01:00
QList<QUrl> urls;
QStringList artists;
2018-02-27 18:06:05 +01:00
2019-11-03 23:23:04 +01:00
int has_compilation_detected;
int has_not_compilation_detected;
2018-02-27 18:06:05 +01:00
};
bool UpdateCompilations(const QSqlDatabase &db, SongList &deleted_songs, SongList &added_songs, const QUrl &url, const bool compilation_detected);
AlbumList GetAlbums(const QString &artist, const QString &album_artist, const bool compilation_required = false, const CollectionFilterOptions &opt = CollectionFilterOptions());
AlbumList GetAlbums(const QString &artist, const bool compilation_required, const CollectionFilterOptions &opt = CollectionFilterOptions());
CollectionSubdirectoryList SubdirsInDirectory(const int id, QSqlDatabase &db);
2018-02-27 18:06:05 +01:00
2020-04-23 21:08:28 +02:00
Song GetSongById(const int id, QSqlDatabase &db);
2018-02-27 18:06:05 +01:00
SongList GetSongsById(const QStringList &ids, QSqlDatabase &db);
2020-04-13 03:39:51 +02:00
Song GetSongBySongId(const QString &song_id, QSqlDatabase &db);
2019-06-08 12:03:48 +02:00
SongList GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db);
2018-02-27 18:06:05 +01:00
private:
Database *db_;
TaskManager *task_manager_;
Song::Source source_;
2018-02-27 18:06:05 +01:00
QString songs_table_;
QString dirs_table_;
QString subdirs_table_;
QString fts_table_;
QThread *original_thread_;
2018-02-27 18:06:05 +01:00
};
#endif // COLLECTIONBACKEND_H