1 /* This file is part of Clementine. 2 Copyright 2010, David Sansome <me@davidsansome.com> 3 4 Clementine is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 Clementine is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with Clementine. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef LIBRARYBACKEND_H 19 #define LIBRARYBACKEND_H 20 21 #include <QObject> 22 #include <QSet> 23 #include <QUrl> 24 #include <QFileInfo> 25 26 #include "directory.h" 27 #include "libraryquery.h" 28 #include "core/song.h" 29 30 class Database; 31 32 namespace smart_playlists { 33 class Search; 34 } 35 36 class LibraryBackendInterface : public QObject { 37 Q_OBJECT 38 39 public: QObject(parent)40 LibraryBackendInterface(QObject* parent = nullptr) : QObject(parent) {} ~LibraryBackendInterface()41 virtual ~LibraryBackendInterface() {} 42 43 struct Album { AlbumAlbum44 Album() {} AlbumAlbum45 Album(const QString& _artist, const QString& _album_artist, 46 const QString& _album_name, const QString& _art_automatic, 47 const QString& _art_manual, const QUrl& _first_url) 48 : artist(_artist), 49 album_artist(_album_artist), 50 album_name(_album_name), 51 art_automatic(_art_automatic), 52 art_manual(_art_manual), 53 first_url(_first_url) {} 54 effective_albumartistAlbum55 const QString& effective_albumartist() const { 56 return album_artist.isEmpty() ? artist : album_artist; 57 } 58 59 QString artist; 60 QString album_artist; 61 QString album_name; 62 63 QString art_automatic; 64 QString art_manual; 65 QUrl first_url; 66 }; 67 typedef QList<Album> AlbumList; 68 69 virtual QString songs_table() const = 0; 70 71 // Get a list of directories in the library. Emits DirectoriesDiscovered. 72 virtual void LoadDirectoriesAsync() = 0; 73 74 // Counts the songs in the library. Emits TotalSongCountUpdated 75 virtual void UpdateTotalSongCountAsync() = 0; 76 77 virtual SongList FindSongsInDirectory(int id) = 0; 78 virtual SubdirectoryList SubdirsInDirectory(int id) = 0; 79 virtual DirectoryList GetAllDirectories() = 0; 80 virtual void ChangeDirPath(int id, const QString& old_path, 81 const QString& new_path) = 0; 82 83 virtual QStringList GetAllArtists( 84 const QueryOptions& opt = QueryOptions()) = 0; 85 virtual QStringList GetAllArtistsWithAlbums( 86 const QueryOptions& opt = QueryOptions()) = 0; 87 virtual SongList GetSongsByAlbum( 88 const QString& album, const QueryOptions& opt = QueryOptions()) = 0; 89 virtual SongList GetSongs(const QString& artist, const QString& album, 90 const QueryOptions& opt = QueryOptions()) = 0; 91 92 virtual SongList GetCompilationSongs( 93 const QString& album, const QueryOptions& opt = QueryOptions()) = 0; 94 95 virtual AlbumList GetAllAlbums(const QueryOptions& opt = QueryOptions()) = 0; 96 virtual AlbumList GetAlbumsByArtist( 97 const QString& artist, const QueryOptions& opt = QueryOptions()) = 0; 98 virtual AlbumList GetCompilationAlbums( 99 const QueryOptions& opt = QueryOptions()) = 0; 100 101 virtual void UpdateManualAlbumArtAsync(const QString& artist, 102 const QString& albumartist, 103 const QString& album, 104 const QString& art) = 0; 105 virtual Album GetAlbumArt(const QString& artist, const QString& albumartist, 106 const QString& album) = 0; 107 108 virtual Song GetSongById(int id) = 0; 109 110 // Returns all sections of a song with the given filename. If there's just one 111 // section 112 // the resulting list will have it's size equal to 1. 113 virtual SongList GetSongsByUrl(const QUrl& url) = 0; 114 // Returns a section of a song with the given filename and beginning. If the 115 // section 116 // is not present in library, returns invalid song. 117 // Using default beginning value is suitable when searching for single-section 118 // songs. 119 virtual Song GetSongByUrl(const QUrl& url, qint64 beginning = 0) = 0; 120 121 virtual void AddDirectory(const QString& path) = 0; 122 virtual void RemoveDirectory(const Directory& dir) = 0; 123 124 virtual bool ExecQuery(LibraryQuery* q) = 0; 125 }; 126 127 class LibraryBackend : public LibraryBackendInterface { 128 Q_OBJECT 129 130 public: 131 static const char* kSettingsGroup; 132 133 Q_INVOKABLE LibraryBackend(QObject* parent = nullptr); 134 void Init(Database* db, const QString& songs_table, const QString& dirs_table, 135 const QString& subdirs_table, const QString& fts_table); 136 db()137 Database* db() const { return db_; } 138 songs_table()139 QString songs_table() const { return songs_table_; } dirs_table()140 QString dirs_table() const { return dirs_table_; } subdirs_table()141 QString subdirs_table() const { return subdirs_table_; } 142 143 // Get a list of directories in the library. Emits DirectoriesDiscovered. 144 void LoadDirectoriesAsync(); 145 146 // Counts the songs in the library. Emits TotalSongCountUpdated 147 void UpdateTotalSongCountAsync(); 148 149 SongList FindSongsInDirectory(int id); 150 SubdirectoryList SubdirsInDirectory(int id); 151 DirectoryList GetAllDirectories(); 152 void ChangeDirPath(int id, const QString& old_path, const QString& new_path); 153 154 QStringList GetAll(const QString& column, 155 const QueryOptions& opt = QueryOptions()); 156 QStringList GetAllArtists(const QueryOptions& opt = QueryOptions()); 157 QStringList GetAllArtistsWithAlbums(const QueryOptions& opt = QueryOptions()); 158 SongList GetSongsByAlbum(const QString& album, 159 const QueryOptions& opt = QueryOptions()); 160 SongList GetSongs(const QString& artist, const QString& album, 161 const QueryOptions& opt = QueryOptions()); 162 163 SongList GetCompilationSongs(const QString& album, 164 const QueryOptions& opt = QueryOptions()); 165 166 AlbumList GetAllAlbums(const QueryOptions& opt = QueryOptions()); 167 AlbumList GetAlbumsByArtist(const QString& artist, 168 const QueryOptions& opt = QueryOptions()); 169 AlbumList GetAlbumsByAlbumArtist(const QString& albumartist, 170 const QueryOptions& opt = QueryOptions()); 171 AlbumList GetCompilationAlbums(const QueryOptions& opt = QueryOptions()); 172 173 void UpdateManualAlbumArtAsync(const QString& artist, 174 const QString& albumartist, 175 const QString& album, const QString& art); 176 Album GetAlbumArt(const QString& artist, const QString& albumartist, 177 const QString& album); 178 179 Song GetSongById(int id); 180 SongList GetSongsById(const QList<int>& ids); 181 SongList GetSongsById(const QStringList& ids); 182 SongList GetSongsByForeignId(const QStringList& ids, const QString& table, 183 const QString& column); 184 185 SongList GetSongsByUrl(const QUrl& url); 186 Song GetSongByUrl(const QUrl& url, qint64 beginning = 0); 187 188 void AddDirectory(const QString& path); 189 void RemoveDirectory(const Directory& dir); 190 191 bool ExecQuery(LibraryQuery* q); 192 SongList ExecLibraryQuery(LibraryQuery* query); 193 SongList FindSongs(const smart_playlists::Search& search); 194 SongList GetAllSongs(); 195 196 void IncrementPlayCountAsync(int id); 197 void IncrementSkipCountAsync(int id, float progress); 198 void ResetStatisticsAsync(int id); 199 void UpdateSongRatingAsync(int id, float rating); 200 void UpdateSongsRatingAsync(const QList<int>& ids, float rating); 201 202 void DeleteAll(); 203 204 public slots: 205 void LoadDirectories(); 206 void UpdateTotalSongCount(); 207 void AddOrUpdateSongs(const SongList& songs); 208 void UpdateMTimesOnly(const SongList& songs); 209 void DeleteSongs(const SongList& songs); 210 void MarkSongsUnavailable(const SongList& songs, bool unavailable = true); 211 void AddOrUpdateSubdirs(const SubdirectoryList& subdirs); 212 void UpdateCompilations(); 213 void UpdateManualAlbumArt(const QString& artist, const QString& albumartist, 214 const QString& album, const QString& art); 215 void ForceCompilation(const QString& album, const QList<QString>& artists, 216 bool on); 217 void IncrementPlayCount(int id); 218 void IncrementSkipCount(int id, float progress); 219 void ResetStatistics(int id); 220 void UpdateSongRating(int id, float rating); 221 void UpdateSongsRating(const QList<int>& id_list, float rating); 222 // Tells the library model that a song path has changed 223 void SongPathChanged(const Song& song, const QFileInfo& new_file); 224 225 signals: 226 void DirectoryDiscovered(const Directory& dir, 227 const SubdirectoryList& subdirs); 228 void DirectoryDeleted(const Directory& dir); 229 230 void SongsDiscovered(const SongList& songs); 231 void SongsDeleted(const SongList& songs); 232 void SongsStatisticsChanged(const SongList& songs); 233 void SongsRatingChanged(const SongList& songs); 234 void DatabaseReset(); 235 236 void TotalSongCountUpdated(int total); 237 238 private: 239 struct CompilationInfo { CompilationInfoCompilationInfo240 CompilationInfo() : has_samplers(0), has_not_samplers(0) {} 241 242 QList<QUrl> urls; 243 QStringList artists; 244 245 int has_samplers; 246 int has_not_samplers; 247 }; 248 249 static const char* kNewScoreSql; 250 251 void UpdateCompilations(const QSqlDatabase& db, SongList& deleted_songs, 252 SongList& added_songs, const QUrl& url, 253 const bool sampler); 254 AlbumList GetAlbums(const QString& artist, const QString& album_artist, 255 bool compilation = false, 256 const QueryOptions& opt = QueryOptions()); 257 SubdirectoryList SubdirsInDirectory(int id, QSqlDatabase& db); 258 259 Song GetSongById(int id, QSqlDatabase& db); 260 SongList GetSongsById(const QStringList& ids, QSqlDatabase& db); 261 262 private: 263 Database* db_; 264 QString songs_table_; 265 QString dirs_table_; 266 QString subdirs_table_; 267 QString fts_table_; 268 bool save_statistics_in_file_; 269 bool save_ratings_in_file_; 270 }; 271 272 #endif // LIBRARYBACKEND_H 273