1 /* 2 * Copyright (C) 2005-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 /*! 12 \file MusicDatabase.h 13 \brief 14 */ 15 16 #include <utility> 17 #include <vector> 18 19 #include "addons/Scraper.h" 20 #include "Album.h" 21 #include "dbwrappers/Database.h" 22 #include "MusicDbUrl.h" 23 #include "MediaSource.h" 24 #include "settings/LibExportSettings.h" 25 #include "utils/SortUtils.h" 26 27 class CArtist; 28 class CFileItem; 29 30 namespace dbiplus 31 { 32 class field_value; 33 typedef std::vector<field_value> sql_record; 34 } 35 36 #include <set> 37 #include <string> 38 39 // return codes of Cleaning up the Database 40 // numbers are strings from strings.po 41 #define ERROR_OK 317 42 #define ERROR_CANCEL 0 43 #define ERROR_DATABASE 315 44 #define ERROR_REORG_SONGS 319 45 #define ERROR_REORG_ARTIST 321 46 #define ERROR_REORG_OTHER 323 47 #define ERROR_REORG_PATH 325 48 #define ERROR_REORG_ALBUM 327 49 #define ERROR_WRITING_CHANGES 329 50 #define ERROR_COMPRESSING 332 51 52 #define NUM_SONGS_BEFORE_COMMIT 500 53 54 /*! 55 \ingroup music 56 \brief A set of std::string objects, used for CMusicDatabase 57 \sa ISETPATHS, CMusicDatabase 58 */ 59 typedef std::set<std::string> SETPATHS; 60 61 /*! 62 \ingroup music 63 \brief The SETPATHS iterator 64 \sa SETPATHS, CMusicDatabase 65 */ 66 typedef std::set<std::string>::iterator ISETPATHS; 67 68 /*! 69 \ingroup music 70 \brief A structure used for fetching music art data 71 \sa CMusicDatabase::GetArtForItem() 72 */ 73 74 typedef struct { 75 std::string mediaType; 76 std::string artType; 77 std::string prefix; 78 std::string url; 79 } ArtForThumbLoader; 80 81 class CGUIDialogProgress; 82 class CFileItemList; 83 84 /*! 85 \ingroup music 86 \brief Class to store and read tag information 87 88 CMusicDatabase can be used to read and store 89 tag information for faster access. It is based on 90 sqlite (http://www.sqlite.org). 91 92 Here is the database layout: 93 \image html musicdatabase.png 94 95 \sa CAlbum, CSong, VECSONGS, CMapSong, VECARTISTS, VECALBUMS, VECGENRES 96 */ 97 class CMusicDatabase : public CDatabase 98 { 99 friend class DatabaseUtils; 100 friend class TestDatabaseUtilsHelper; 101 102 public: 103 CMusicDatabase(void); 104 ~CMusicDatabase(void) override; 105 106 bool Open() override; 107 bool CommitTransaction() override; 108 void EmptyCache(); 109 void Clean(); 110 int Cleanup(CGUIDialogProgress* progressDialog = nullptr); 111 bool LookupCDDBInfo(bool bRequery=false); 112 void DeleteCDDBInfo(); 113 114 ///////////////////////////////////////////////// 115 // Song CRUD 116 ///////////////////////////////////////////////// 117 /*! \brief Add a song to the database 118 \param idSong [in] the original database ID of the song to reuse (-1 when new) 119 \param dtDateNew [in] the datetime the original ID was new 120 \param idAlbum [in] the database ID of the album for the song 121 \param strTitle [in] the title of the song (required to be non-empty) 122 \param strMusicBrainzTrackID [in] the MusicBrainz track ID of the song 123 \param strPathAndFileName [in] the path and filename to the song 124 \param strComment [in] the ids of the added songs 125 \param strMood [in] the mood of the added song 126 \param strThumb [in] the ids of the added songs 127 \param artistDisp [in] the assembled artist name(s) display string 128 \param artistSort [in] the artist name(s) sort string 129 \param genres [in] a vector of genres to which this song belongs 130 \param iTrack [in] the track number and disc number of the song 131 \param iDuration [in] the duration of the song 132 \param strReleaseDate [in] the release date of the song ISO8601 format 133 \param strOrigReleaseDate [in] the original release date of the song ISO8601 format 134 \param strDiscSubtitle [in] subtitle of a disc 135 \param iTimesPlayed [in] the number of times the song has been played 136 \param iStartOffset [in] the start offset of the song (when using a single audio file with a .cue) 137 \param iEndOffset [in] the end offset of the song (when using a single audio file with .cue) 138 \param dtLastPlayed [in] the time the song was last played 139 \param rating [in] a rating for the song 140 \param userrating [in] a userrating (my rating) for the song 141 \param votes [in] a vote counter for the song rating 142 \param replayGain [in] album and track replaygain and peak values 143 \return the id of the song 144 */ 145 int AddSong(const int idSong, const CDateTime& dtDateNew, 146 const int idAlbum, 147 const std::string& strTitle, 148 const std::string& strMusicBrainzTrackID, 149 const std::string& strPathAndFileName, 150 const std::string& strComment, 151 const std::string& strMood, 152 const std::string& strThumb, 153 const std::string &artistDisp, const std::string &artistSort, 154 const std::vector<std::string>& genres, 155 int iTrack, int iDuration, 156 const std::string& strReleaseDate, 157 const std::string& strOrigReleaseDate, 158 std::string& strDiscSubtitle, 159 const int iTimesPlayed, int iStartOffset, int iEndOffset, 160 const CDateTime& dtLastPlayed, float rating, int userrating, int votes, 161 int iBPM, int iBitRate, int iSampleRate, int iChannels, 162 const ReplayGain& replayGain); 163 bool GetSong(int idSong, CSong& song); 164 165 /*! \brief Update a song and all its nested entities (genres, artists, contributors) 166 \param song [in/out] the song to update, artist ids are returned in artist credits 167 \param bArtists to update artist credits and contributors, default is true 168 \param bArtists to check and log if artist links have changed, default is true 169 \return true if sucessfull 170 */ 171 bool UpdateSong(CSong& song, bool bArtists = true, bool bArtistLinks = true); 172 173 /*! \brief Update a song in the database 174 \param idSong [in] the database ID of the song to update 175 \param strTitle [in] the title of the song (required to be non-empty) 176 \param strMusicBrainzTrackID [in] the MusicBrainz track ID of the song 177 \param strPathAndFileName [in] the path and filename to the song 178 \param strComment [in] the ids of the added songs 179 \param strMood [in] the mood of the added song 180 \param strThumb [in] the ids of the added songs 181 \param artistDisp [in] the artist name(s) display string 182 \param artistSort [in] the artist name(s) sort string 183 \param genres [in] a vector of genres to which this song belongs 184 \param iTrack [in] the track number and disc number of the song 185 \param iDuration [in] the duration of the song 186 \param strReleaseDate [in] the release date of the song ISO8601 format 187 \param strOrigReleaseDate [in] the original release date of the song ISO8601 format 188 \param strDiscSubtitle [in] subtitle of a disc 189 \param iTimesPlayed [in] the number of times the song has been played 190 \param iStartOffset [in] the start offset of the song (when using a single audio file with a .cue) 191 \param iEndOffset [in] the end offset of the song (when using a single audio file with .cue) 192 \param dtLastPlayed [in] the time the song was last played 193 \param rating [in] a rating for the song 194 \param userrating [in] a userrating (my rating) for the song 195 \param votes [in] a vote counter for the song rating 196 \param replayGain [in] album and track replaygain and peak values 197 \param iBPM [in] the beats per minute of a song 198 \param iBitRate [in] the bitrate of the song file 199 \param iSampleRate [in] the sample rate of the song file 200 \param iChannels [in] the number of audio channels in the song file 201 \return the id of the song 202 */ 203 int UpdateSong(int idSong, 204 const std::string& strTitle, const std::string& strMusicBrainzTrackID, 205 const std::string& strPathAndFileName, const std::string& strComment, 206 const std::string& strMood, const std::string& strThumb, 207 const std::string& artistDisp, const std::string& artistSort, 208 const std::vector<std::string>& genres, 209 int iTrack, int iDuration, 210 const std::string& strReleaseDate, 211 const std::string& strOrigReleaseDate, 212 const std::string& strDiscSubtitle, 213 int iTimesPlayed, int iStartOffset, int iEndOffset, 214 const CDateTime& dtLastPlayed, float rating, int userrating, int votes, 215 const ReplayGain& replayGain, 216 int iBPM, int iBitRate, int iSampleRate, int iChannels); 217 218 //// Misc Song 219 bool GetSongByFileName(const std::string& strFileName, CSong& song, int64_t startOffset = 0); 220 bool GetSongsByPath(const std::string& strPath, MAPSONGS& songmap, bool bAppendToMap = false); 221 bool Search(const std::string& search, CFileItemList &items); 222 bool RemoveSongsFromPath(const std::string &path, MAPSONGS& songmap, bool exact=true); 223 void CheckArtistLinksChanged(); 224 bool SetSongUserrating(const std::string &filePath, int userrating); 225 bool SetSongUserrating(int idSong, int userrating); 226 bool SetSongVotes(const std::string &filePath, int votes); 227 int GetSongByArtistAndAlbumAndTitle(const std::string& strArtist, const std::string& strAlbum, const std::string& strTitle); 228 229 ///////////////////////////////////////////////// 230 // Album 231 ///////////////////////////////////////////////// 232 /*! \brief Add an album and all its songs to the database 233 \param album the album to add 234 \param idSource the music source id 235 \return the id of the album 236 */ 237 bool AddAlbum(CAlbum& album, int idSource); 238 239 /*! \brief Update an album and all its nested entities (artists, songs etc) 240 \param album the album to update 241 \return true or false 242 */ 243 bool UpdateAlbum(CAlbum& album); 244 245 /*! \brief Add an album to the database 246 \param strAlbum the album title 247 \param strMusicBrainzAlbumID the Musicbrainz Id 248 \param strArtist the album artist name(s) display string 249 \param strArtistSort the album artist name(s) sort string 250 \param strGenre the album genre(s) 251 \param strReleaseDate [in] the release date of the album ISO8601 format 252 \param strOrigReleaseDate [in] the original release date of the album ISO8601 format 253 \param bBoxedSet if the album is a boxset 254 \param strRecordLabel the recording label 255 \param strType album type (Musicbrainz release type e.g. "Broadcast, Soundtrack, live"), 256 \param strReleaseStatus (see https://musicbrainz.org/doc/Release#Status) 257 \param bCompilation if the album is a compilation 258 \param releaseType "album" or "single" 259 \return the id of the album 260 */ 261 int AddAlbum(const std::string& strAlbum, const std::string& strMusicBrainzAlbumID, 262 const std::string& strReleaseGroupMBID, 263 const std::string& strArtist, const std::string& strArtistSort, 264 const std::string& strGenre, 265 const std::string& strReleaseDate, const std::string& strOrigReleaseDate, 266 bool bBoxedSet, 267 const std::string& strRecordLabel, const std::string& strType, 268 const std::string& strReleaseStatus, 269 bool bCompilation, CAlbum::ReleaseType releaseType); 270 271 /*! \brief retrieve an album, optionally with all songs. 272 \param idAlbum the database id of the album. 273 \param album [out] the album to fill. 274 \param getSongs whether or not to retrieve songs, defaults to true. 275 \return true if the album is retrieved, false otherwise. 276 */ 277 bool GetAlbum(int idAlbum, CAlbum& album, bool getSongs = true); 278 int UpdateAlbum(int idAlbum, 279 const std::string& strAlbum, const std::string& strMusicBrainzAlbumID, 280 const std::string& strReleaseGroupMBID, 281 const std::string& strArtist, const std::string& strArtistSort, 282 const std::string& strGenre, 283 const std::string& strMoods, const std::string& strStyles, 284 const std::string& strThemes, const std::string& strReview, 285 const std::string& strImage, const std::string& strLabel, 286 const std::string& strType, 287 const std::string& strReleaseStatus, 288 float fRating, int iUserrating, int iVotes, 289 const std::string& strReleaseDate, const std::string& strOrigReleaseDate, 290 bool bBoxedSet, 291 bool bCompilation, 292 CAlbum::ReleaseType releaseType, 293 bool bScrapedMBID); 294 bool ClearAlbumLastScrapedTime(int idAlbum); 295 bool HasAlbumBeenScraped(int idAlbum); 296 297 ///////////////////////////////////////////////// 298 // Audiobook 299 ///////////////////////////////////////////////// 300 bool AddAudioBook(const CFileItem& item); 301 bool SetResumeBookmarkForAudioBook(const CFileItem& item, int bookmark); 302 bool GetResumeBookmarkForAudioBook(const CFileItem& item, int& bookmark); 303 304 /*! \brief Checks if the given path is inside a folder that has already been scanned into the library 305 \param path the path we want to check 306 */ 307 bool InsideScannedPath(const std::string& path); 308 309 //// Misc Album 310 int GetAlbumIdByPath(const std::string& path); 311 bool GetAlbumFromSong(int idSong, CAlbum &album); 312 int GetAlbumByName(const std::string& strAlbum, const std::string& strArtist=""); 313 int GetAlbumByName(const std::string& strAlbum, const std::vector<std::string>& artist); 314 bool GetMatchingMusicVideoAlbum(const std::string& strAlbum, 315 const std::string& strArtist, 316 int& idAlbum, 317 std::string& strReview); 318 bool SearchAlbumsByArtistName(const std::string& strArtist, CFileItemList& items); 319 int GetAlbumByMatch(const CAlbum& album); 320 std::string GetAlbumById(int id); 321 std::string GetAlbumDiscTitle(int idAlbum, int idDisc); 322 bool SetAlbumUserrating(const int idAlbum, int userrating); 323 int GetAlbumDiscsCount(int idAlbum); 324 325 ///////////////////////////////////////////////// 326 // Artist CRUD 327 ///////////////////////////////////////////////// 328 bool UpdateArtist(const CArtist& artist); 329 330 int AddArtist(const std::string& strArtist, const std::string& strMusicBrainzArtistID, const std::string& strSortName, bool bScrapedMBID = false); 331 int AddArtist(const std::string& strArtist, const std::string& strMusicBrainzArtistID, bool bScrapedMBID = false); 332 bool GetArtist(int idArtist, CArtist& artist, bool fetchAll = false); 333 bool GetArtistExists(int idArtist); 334 int GetLastArtist(); 335 int GetArtistFromMBID(const std::string& strMusicBrainzArtistID, std::string& artistname); 336 int UpdateArtist(int idArtist, 337 const std::string& strArtist, const std::string& strSortName, 338 const std::string& strMusicBrainzArtistID, bool bScrapedMBID, 339 const std::string& strType, const std::string& strGender, 340 const std::string& strDisambiguation, 341 const std::string& strBorn, const std::string& strFormed, 342 const std::string& strGenres, const std::string& strMoods, 343 const std::string& strStyles, const std::string& strInstruments, 344 const std::string& strBiography, const std::string& strDied, 345 const std::string& strDisbanded, const std::string& strYearsActive, 346 const std::string& strImage); 347 bool UpdateArtistScrapedMBID(int idArtist, const std::string& strMusicBrainzArtistID); GetTranslateBlankArtist()348 bool GetTranslateBlankArtist() { return m_translateBlankArtist; } SetTranslateBlankArtist(bool translate)349 void SetTranslateBlankArtist(bool translate) { m_translateBlankArtist = translate; } 350 bool HasArtistBeenScraped(int idArtist); 351 bool ClearArtistLastScrapedTime(int idArtist); 352 int AddArtistDiscography(int idArtist, const CDiscoAlbum& discoAlbum); 353 bool DeleteArtistDiscography(int idArtist); 354 bool GetArtistDiscography(int idArtist, CFileItemList& items); 355 356 std::string GetArtistById(int id); 357 int GetArtistByName(const std::string& strArtist); 358 int GetArtistByMatch(const CArtist& artist); 359 bool GetArtistFromSong(int idSong, CArtist &artist); 360 bool IsSongArtist(int idSong, int idArtist); 361 bool IsSongAlbumArtist(int idSong, int idArtist); 362 std::string GetRoleById(int id); 363 364 /*! \brief Propagate artist sort name into the concatenated artist sort name strings 365 held for songs and albums 366 \param int idArtist to propagate sort name for, -1 means all artists 367 */ 368 bool UpdateArtistSortNames(int idArtist = -1); 369 370 ///////////////////////////////////////////////// 371 // Paths 372 ///////////////////////////////////////////////// 373 int AddPath(const std::string& strPath); 374 375 bool GetPaths(std::set<std::string> &paths); 376 bool SetPathHash(const std::string &path, const std::string &hash); 377 bool GetPathHash(const std::string &path, std::string &hash); 378 bool GetAlbumPaths(int idAlbum, std::vector<std::pair<std::string, int>>& paths); 379 bool GetAlbumPath(int idAlbum, std::string &basePath); 380 int GetDiscnumberForPathID(int idPath); 381 bool GetOldArtistPath(int idArtist, std::string &path); 382 bool GetArtistPath(const CArtist& artist, std::string &path); 383 bool GetAlbumFolder(const CAlbum& album, const std::string &strAlbumPath, std::string &strFolder); 384 bool GetArtistFolderName(const CArtist& artist, std::string &strFolder); 385 bool GetArtistFolderName(const std::string &strArtist, const std::string &strMusicBrainzArtistID, std::string &strFolder); 386 387 ///////////////////////////////////////////////// 388 // Sources 389 ///////////////////////////////////////////////// 390 bool UpdateSources(); 391 int AddSource(const std::string& strName, const std::string& strMultipath, const std::vector<std::string>& vecPaths, int id = -1); 392 int UpdateSource(const std::string& strOldName, const std::string& strName, const std::string& strMultipath, const std::vector<std::string>& vecPaths); 393 bool RemoveSource(const std::string& strName); 394 int GetSourceFromPath(const std::string& strPath); 395 bool AddAlbumSource(int idAlbum, int idSource); 396 bool AddAlbumSources(int idAlbum, const std::string& strPath); 397 bool DeleteAlbumSources(int idAlbum); 398 bool GetSources(CFileItemList& items); 399 400 bool GetSourcesByArtist(int idArtist, CFileItem* item); 401 bool GetSourcesByAlbum(int idAlbum, CFileItem* item); 402 bool GetSourcesBySong(int idSong, const std::string& strPath, CFileItem* item); 403 int GetSourceByName(const std::string& strSource); 404 std::string GetSourceById(int id); 405 406 ///////////////////////////////////////////////// 407 // Genres 408 ///////////////////////////////////////////////// 409 int AddGenre(std::string& strGenre); 410 std::string GetGenreById(int id); 411 int GetGenreByName(const std::string& strGenre); 412 413 ///////////////////////////////////////////////// 414 // Link tables 415 ///////////////////////////////////////////////// 416 bool AddAlbumArtist(int idArtist, int idAlbum, const std::string& strArtist, int iOrder); 417 bool GetAlbumsByArtist(int idArtist, std::vector<int>& albums); 418 bool GetArtistsByAlbum(int idAlbum, CFileItem* item); 419 bool GetArtistsByAlbum(int idAlbum, std::vector<std::string>& artistIDs); 420 bool DeleteAlbumArtistsByAlbum(int idAlbum); 421 422 int AddRole(const std::string &strRole); 423 bool AddSongArtist(int idArtist, int idSong, const std::string& strRole, const std::string& strArtist, int iOrder); 424 bool AddSongArtist(int idArtist, int idSong, int idRole, const std::string& strArtist, int iOrder); 425 int AddSongContributor(int idSong, const std::string& strRole, const std::string& strArtist, const std::string &strSort); 426 void AddSongContributors(int idSong, const VECMUSICROLES& contributors, const std::string &strSort); 427 int GetRoleByName(const std::string& strRole); 428 bool GetRolesByArtist(int idArtist, CFileItem* item); 429 bool GetSongsByArtist(int idArtist, std::vector<int>& songs); 430 bool GetArtistsBySong(int idSong, std::vector<int>& artists); 431 bool DeleteSongArtistsBySong(int idSong); 432 433 bool AddSongGenres(int idSong, const std::vector<std::string>& genres); 434 bool GetGenresBySong(int idSong, std::vector<int>& genres); 435 436 bool GetGenresByAlbum(int idAlbum, CFileItem* item); 437 438 bool GetGenresByArtist(int idArtist, CFileItem* item); 439 bool GetIsAlbumArtist(int idArtist, CFileItem* item); 440 441 ///////////////////////////////////////////////// 442 // Top 100 443 ///////////////////////////////////////////////// 444 bool GetTop100(const std::string& strBaseDir, CFileItemList& items); 445 bool GetTop100Albums(VECALBUMS& albums); 446 bool GetTop100AlbumSongs(const std::string& strBaseDir, CFileItemList& item); 447 448 ///////////////////////////////////////////////// 449 // Recently added 450 ///////////////////////////////////////////////// 451 bool GetRecentlyAddedAlbums(VECALBUMS& albums, unsigned int limit=0); 452 bool GetRecentlyAddedAlbumSongs(const std::string& strBaseDir, CFileItemList& item, unsigned int limit=0); 453 bool GetRecentlyPlayedAlbums(VECALBUMS& albums); 454 bool GetRecentlyPlayedAlbumSongs(const std::string& strBaseDir, CFileItemList& item); 455 456 ///////////////////////////////////////////////// 457 // Compilations 458 ///////////////////////////////////////////////// 459 int GetCompilationAlbumsCount(); 460 461 //////////////////////////////////////////////// 462 // Boxsets 463 //////////////////////////////////////////////// 464 bool IsAlbumBoxset(int idAlbum); 465 int GetBoxsetsCount(); 466 467 int GetSinglesCount(); 468 469 int GetArtistCountForRole(int role); 470 int GetArtistCountForRole(const std::string& strRole); 471 472 /*! \brief Increment the playcount of an item 473 Increments the playcount and updates the last played date 474 \param item CFileItem to increment the playcount for 475 */ 476 void IncrementPlayCount(const CFileItem &item); 477 bool CleanupOrphanedItems(); 478 479 ///////////////////////////////////////////////// 480 // VIEWS 481 ///////////////////////////////////////////////// 482 bool GetGenresNav(const std::string& strBaseDir, CFileItemList& items, const Filter &filter = Filter(), bool countOnly = false); 483 bool GetSourcesNav(const std::string& strBaseDir, CFileItemList& items, const Filter &filter = Filter(), bool countOnly = false); 484 bool GetYearsNav(const std::string& strBaseDir, CFileItemList& items, const Filter &filter = Filter()); 485 bool GetRolesNav(const std::string& strBaseDir, CFileItemList& items, const Filter &filter = Filter()); 486 bool GetArtistsNav(const std::string& strBaseDir, CFileItemList& items, bool albumArtistsOnly = false, int idGenre = -1, int idAlbum = -1, int idSong = -1, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription(), bool countOnly = false); 487 bool GetCommonNav(const std::string &strBaseDir, const std::string &table, const std::string &labelField, CFileItemList &items, const Filter &filter /* = Filter() */, bool countOnly /* = false */); 488 bool GetAlbumTypesNav(const std::string &strBaseDir, CFileItemList &items, const Filter &filter = Filter(), bool countOnly = false); 489 bool GetMusicLabelsNav(const std::string &strBaseDir, CFileItemList &items, const Filter &filter = Filter(), bool countOnly = false); 490 bool GetAlbumsNav(const std::string& strBaseDir, CFileItemList& items, int idGenre = -1, int idArtist = -1, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription(), bool countOnly = false); 491 bool GetDiscsNav(const std::string& strBaseDir, 492 CFileItemList& items, 493 int idAlbum, 494 const Filter& filter = Filter(), 495 const SortDescription& sortDescription = SortDescription(), 496 bool countOnly = false); 497 bool GetAlbumsByYear(const std::string& strBaseDir, CFileItemList& items, int year); 498 bool GetSongsNav(const std::string& strBaseDir, CFileItemList& items, int idGenre, int idArtist,int idAlbum, const SortDescription &sortDescription = SortDescription()); 499 bool GetSongsByYear(const std::string& baseDir, CFileItemList& items, int year); 500 bool GetSongsByWhere(const std::string &baseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription()); 501 bool GetSongsFullByWhere(const std::string &baseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription(), bool artistData = false); 502 bool GetAlbumsByWhere(const std::string &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription = SortDescription(), bool countOnly = false); 503 bool GetDiscsByWhere(const std::string& baseDir, 504 const Filter& filter, 505 CFileItemList& items, 506 const SortDescription& sortDescription = SortDescription(), 507 bool countOnly = false); 508 bool GetDiscsByWhere(CMusicDbUrl& musicUrl, 509 const Filter& filter, 510 CFileItemList& items, 511 const SortDescription& sortDescription = SortDescription(), 512 bool countOnly = false); 513 bool GetArtistsByWhere(const std::string& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription(), bool countOnly = false); 514 int GetDiscsCount(const std::string& baseDir, const Filter& filter = Filter()); 515 int GetSongsCount(const Filter &filter = Filter()); 516 bool GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription &sorting) override; 517 int GetOrderFilter(const std::string& type, const SortDescription& sorting, Filter& filter); 518 519 ///////////////////////////////////////////////// 520 // Party Mode 521 ///////////////////////////////////////////////// 522 /*! \brief Gets song IDs in random order that match the filter criteria 523 \param filter the criteria to apply in the query 524 \param songIDs a vector of <1, id> pairs suited to party mode use 525 \return count of song ids found. 526 */ 527 unsigned int GetRandomSongIDs(const Filter &filter, std::vector<std::pair<int, int> > &songIDs); 528 529 ///////////////////////////////////////////////// 530 // JSON-RPC 531 ///////////////////////////////////////////////// 532 bool GetGenresJSON(CFileItemList& items, bool bSources = false); 533 bool GetArtistsByWhereJSON(const std::set<std::string>& fields, const std::string& baseDir, 534 CVariant& result, int& total, const SortDescription& sortDescription = SortDescription()); 535 bool GetAlbumsByWhereJSON(const std::set<std::string>& fields, const std::string& baseDir, 536 CVariant& result, int& total, const SortDescription& sortDescription = SortDescription()); 537 bool GetSongsByWhereJSON(const std::set<std::string>& fields, const std::string& baseDir, 538 CVariant& result, int& total, const SortDescription& sortDescription = SortDescription()); 539 540 ///////////////////////////////////////////////// 541 // Scraper 542 ///////////////////////////////////////////////// 543 bool SetScraper(int id, const CONTENT_TYPE& content, const ADDON::ScraperPtr& scraper); 544 bool SetScraperAll(const std::string& strBaseDir, const ADDON::ScraperPtr& scraper); 545 bool GetScraper(int id, const CONTENT_TYPE &content, ADDON::ScraperPtr& scraper); 546 547 /*! \brief Check whether a given scraper is in use. 548 \param scraperID the scraper to check for. 549 \return true if the scraper is in use, false otherwise. 550 */ 551 bool ScraperInUse(const std::string &scraperID) const; 552 553 ///////////////////////////////////////////////// 554 // Filters 555 ///////////////////////////////////////////////// 556 bool GetItems(const std::string &strBaseDir, CFileItemList &items, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription()); 557 bool GetItems(const std::string &strBaseDir, const std::string &itemType, CFileItemList &items, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription()); 558 std::string GetItemById(const std::string &itemType, int id); 559 560 ///////////////////////////////////////////////// 561 // XML 562 ///////////////////////////////////////////////// 563 void ExportToXML(const CLibExportSettings& settings, CGUIDialogProgress* progressDialog = nullptr); 564 bool ExportSongHistory(TiXmlNode* pNode, CGUIDialogProgress* progressDialog = nullptr); 565 void ImportFromXML(const std::string& xmlFile, CGUIDialogProgress* progressDialog = nullptr); 566 bool ImportSongHistory(const std::string& xmlFile, const int total, CGUIDialogProgress* progressDialog = nullptr); 567 568 ///////////////////////////////////////////////// 569 // Properties 570 ///////////////////////////////////////////////// 571 void SetPropertiesForFileItem(CFileItem& item); 572 static void SetPropertiesFromArtist(CFileItem& item, const CArtist& artist); 573 static void SetPropertiesFromAlbum(CFileItem& item, const CAlbum& album); 574 void SetItemUpdated(int mediaId, const std::string& mediaType); 575 576 ///////////////////////////////////////////////// 577 // Art 578 ///////////////////////////////////////////////// 579 /*! \brief Sets art for a database item. 580 Sets a single piece of art for a database item. 581 \param mediaId the id in the media (song/artist/album) table. 582 \param mediaType the type of media, which corresponds to the table the item resides in (song/artist/album). 583 \param artType the type of art to set, e.g. "thumb", "fanart" 584 \param url the url to the art (this is the original url, not a cached url). 585 \sa GetArtForItem 586 */ 587 void SetArtForItem(int mediaId, const std::string &mediaType, const std::string &artType, const std::string &url); 588 589 /*! \brief Sets art for a database item. 590 Sets multiple pieces of art for a database item. 591 \param mediaId the id in the media (song/artist/album) table. 592 \param mediaType the type of media, which corresponds to the table the item resides in (song/artist/album). 593 \param art a map of <type, url> where type is "thumb", "fanart", etc. and url is the original url of the art. 594 \sa GetArtForItem 595 */ 596 void SetArtForItem(int mediaId, const std::string &mediaType, const std::map<std::string, std::string> &art); 597 598 599 /*! \brief Fetch all related art for a database item. 600 Fetches multiple pieces of art for a database item including that for related media types 601 Given song id art for the related album, artist(s) and albumartist(s) will also be fetched, looking up the 602 album and artist when ids are not provided. 603 Given album id (and not song id) art for the related artist(s) will also be fetched, looking up the 604 artist(s) when id are not provided. 605 \param songId the id in the song table, -1 when song art not being fetched 606 \param albumId the id in the album table, -1 when album art not being fetched 607 \param artistId the id in the artist table, -1 when artist not known 608 \param bPrimaryArtist true if art from only the first song artist or album artist is to be fetched 609 \param art [out] a vector, each element having media type e.g. "artist", "album" or "song", 610 artType e.g. "thumb", "fanart", etc., prefix of "", "artist" or "albumartist" etc. giving the kind of artist 611 relationship, and the original url of the art. 612 613 \return true if art is retrieved, false if no art is found. 614 \sa SetArtForItem 615 */ 616 bool GetArtForItem(int songId, int albumId, int artistId, bool bPrimaryArtist, std::vector<ArtForThumbLoader> &art); 617 618 /*! \brief Fetch art for a database item. 619 Fetches multiple pieces of art for a database item. 620 \param mediaId the id in the media (song/artist/album) table. 621 \param mediaType the type of media, which corresponds to the table the item resides in (song/artist/album). 622 \param art [out] a map of <type, url> where type is "thumb", "fanart", etc. and url is the original url of the art. 623 \return true if art is retrieved, false if no art is found. 624 \sa SetArtForItem 625 */ 626 bool GetArtForItem(int mediaId, const std::string &mediaType, std::map<std::string, std::string> &art); 627 628 /*! \brief Fetch art for a database item. 629 Fetches a single piece of art for a database item. 630 \param mediaId the id in the media (song/artist/album) table. 631 \param mediaType the type of media, which corresponds to the table the item resides in (song/artist/album). 632 \param artType the type of art to retrieve, eg "thumb", "fanart". 633 \return the original URL to the piece of art, if available. 634 \sa SetArtForItem 635 */ 636 std::string GetArtForItem(int mediaId, const std::string &mediaType, const std::string &artType); 637 638 /*! \brief Remove art for a database item. 639 Removes a single piece of art for a database item. 640 \param mediaId the id in the media (song/artist/album) table. 641 \param mediaType the type of media, which corresponds to the table the item resides in (song/artist/album). 642 \param artType the type of art to remove, eg "thumb", "fanart". 643 \return true if art is removed, false if no art is found. 644 \sa RemoveArtForItem 645 */ 646 bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType); 647 648 /*! \brief Remove art for a database item. 649 Removes multiple pieces of art for a database item. 650 \param mediaId the id in the media (song/artist/album) table. 651 \param mediaType the type of media, which corresponds to the table the item resides in (song/artist/album). 652 \param arttypes a set of types, e.g. "thumb", "fanart", etc. to be removed. 653 \return true if art is removed, false if no art is found. 654 \sa RemoveArtForItem 655 */ 656 bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::set<std::string> &artTypes); 657 658 /*! \brief Fetch the distinct types of art held in the database for a type of media. 659 \param mediaType the type of media, which corresponds to the table the item resides in (song/artist/album). 660 \param artTypes [out] the types of art e.g. "thumb", "fanart", etc. 661 \return true if art is found, false if no art is found. 662 */ 663 bool GetArtTypes(const MediaType &mediaType, std::vector<std::string> &artTypes); 664 665 /*! \brief Fetch the distinct types of available-but-unassigned art held in the 666 database for a specific media item. 667 \param mediaId the id in the media (artist/album) table. 668 \param mediaType the type of media, which corresponds to the table the item resides in (artist/album). 669 \return the types of art e.g. "thumb", "fanart", etc. 670 */ 671 std::vector<std::string> GetAvailableArtTypesForItem(int mediaId, const MediaType& mediaType); 672 673 /*! \brief Fetch the list of available-but-unassigned art URLs held in the 674 database for a specific media item and art type. 675 \param mediaId the id in the media (artist/album) table. 676 \param mediaType corresponds to the table the item resides in (artist/album). 677 \param artType e.g. "thumb", "fanart", etc. 678 \return list of URLs 679 */ 680 std::vector<CScraperUrl::SUrlEntry> GetAvailableArtForItem( 681 int mediaId, const MediaType& mediaType, const std::string& artType); 682 683 ///////////////////////////////////////////////// 684 // Tag Scan Version 685 ///////////////////////////////////////////////// 686 /*! \brief Check if music files need all tags rescanning regardless of file being unchanged 687 because the tag processing has changed (which may happen without db version changes) since they 688 where last scanned. 689 \return -1 if an error occurred, 0 if no scan is needed, or the version number of tags if not the same as current. 690 */ 691 virtual int GetMusicNeedsTagScan(); 692 693 /*! \brief Set minimum version number of db needed when tag data scanned from music files 694 \param version the version number of db 695 */ 696 void SetMusicNeedsTagScan(int version); 697 698 /*! \brief Set the version number of tag data 699 \param version the version number of db when tags last scanned, 0 (default) means current db version 700 */ 701 void SetMusicTagScanVersion(int version = 0); 702 703 std::string GetLibraryLastUpdated(); 704 void SetLibraryLastUpdated(); 705 std::string GetLibraryLastCleaned(); 706 void SetLibraryLastCleaned(); 707 std::string GetArtistLinksUpdated(); 708 void SetArtistLinksUpdated(); 709 std::string GetGenresLastAdded(); 710 std::string GetSongsLastAdded(); 711 std::string GetAlbumsLastAdded(); 712 std::string GetArtistsLastAdded(); 713 std::string GetSongsLastModified(); 714 std::string GetAlbumsLastModified(); 715 std::string GetArtistsLastModified(); 716 717 718 protected: 719 std::map<std::string, int> m_genreCache; 720 std::map<std::string, int> m_pathCache; 721 722 void CreateTables() override; 723 void CreateAnalytics() override; GetMinSchemaVersion()724 int GetMinSchemaVersion() const override { return 32; } 725 int GetSchemaVersion() const override; 726 GetBaseDBName()727 const char *GetBaseDBName() const override { return "MyMusic"; }; 728 729 private: 730 /*! \brief (Re)Create the generic database views for songs and albums 731 */ 732 virtual void CreateViews(); 733 void CreateNativeDBFunctions(); 734 void CreateRemovedLinkTriggers(); 735 736 void SplitPath(const std::string& strFileNameAndPath, std::string& strPath, std::string& strFileName); 737 738 CSong GetSongFromDataset(); 739 CSong GetSongFromDataset(const dbiplus::sql_record* const record, int offset = 0); 740 CArtist GetArtistFromDataset(dbiplus::Dataset* pDS, int offset = 0, bool needThumb = true); 741 CArtist GetArtistFromDataset(const dbiplus::sql_record* const record, int offset = 0, bool needThumb = true); 742 CAlbum GetAlbumFromDataset(dbiplus::Dataset* pDS, int offset = 0, bool imageURL = false); 743 CAlbum GetAlbumFromDataset(const dbiplus::sql_record* const record, int offset = 0, bool imageURL = false); 744 CArtistCredit GetArtistCreditFromDataset(const dbiplus::sql_record* const record, int offset = 0); 745 CMusicRole GetArtistRoleFromDataset(const dbiplus::sql_record* const record, int offset = 0); 746 std::string GetMediaDateFromFile(const std::string& strFileNameAndPath); 747 void GetFileItemFromDataset(CFileItem* item, const CMusicDbUrl &baseUrl); 748 void GetFileItemFromDataset(const dbiplus::sql_record* const record, CFileItem* item, const CMusicDbUrl &baseUrl); 749 void GetFileItemFromArtistCredits(VECARTISTCREDITS& artistCredits, CFileItem* item); 750 751 bool DeleteRemovedLinks(); 752 753 bool CleanupSongs(CGUIDialogProgress* progressDialog = nullptr); 754 bool CleanupSongsByIds(const std::string &strSongIds); 755 bool CleanupPaths(); 756 bool CleanupAlbums(); 757 bool CleanupArtists(); 758 bool CleanupGenres(); 759 bool CleanupInfoSettings(); 760 bool CleanupRoles(); 761 void UpdateTables(int version) override; 762 bool SearchArtists(const std::string& search, CFileItemList &artists); 763 bool SearchAlbums(const std::string& search, CFileItemList &albums); 764 bool SearchSongs(const std::string& strSearch, CFileItemList &songs); 765 int GetSongIDFromPath(const std::string &filePath); 766 void NormaliseSongDates(std::string& strRelease, std::string& strOriginal); 767 bool TrimImageURLs(std::string& strImage, const size_t space); 768 769 /*! \brief Build SQL for sort subquery from ignore article token list 770 \param strField original name or title field that articles could be removed from 771 \return SQL string e.g. WHEN strField LIKE 'the_' ESCAPE '_' THEN SUBSTR(strArtist, 5) 772 */ 773 std::string GetIgnoreArticleSQL(const std::string& strField); 774 775 /*! \brief Build SQL for sort name scalar subquery from sort attributes and ignore article list. 776 \param strAlias alias name of scalar subquery field 777 \param sortAttributes the sort attributes e.g. SortAttributeIgnoreArticle 778 \param strField original name or title field that articles could be removed from 779 \param strSortField sort name or title field to be used instead of original (when data not null) 780 \return SQL string e.g. 781 CASE WHEN strArtistSort IS NOT NULL THEN strArtistSort 782 WHEN strField LIKE 'the ' OR strField LIKE 'the_' ESCAPE '_' THEN SUBSTR(strArtist, 5) 783 ELSE strField 784 END AS strAlias 785 */ 786 std::string SortnameBuildSQL(const std::string& strAlias, const SortAttribute& sortAttributes, 787 const std::string& strField, const std::string& strSortField); 788 789 /*! \brief Build SQL for sorting field naturally and case insensitvely (in SQLite). 790 \param strField field name 791 \param sortOrder the sort order 792 \return SQL string e.g. 793 CASE WHEN CAST(strTitle AS INTEGER) = 0 THEN 100000000 794 ELSE CAST(strTitle AS INTEGER) END DESC, strTitle COLLATE NOCASE DESC 795 */ 796 std::string AlphanumericSortSQL(const std::string& strField, const SortOrder& sortOrder); 797 798 /*! \brief Checks that source table matches sources.xml 799 returns true when they do 800 */ 801 bool CheckSources(VECSOURCES& sources); 802 803 /*! \brief Initially fills source table from sources.xml for use only at 804 migration of db from an earlier version than 72 805 returns true when successfuly done 806 */ 807 bool MigrateSources(); 808 809 bool m_translateBlankArtist; 810 811 // Fields should be ordered as they 812 // appear in the songview 813 static enum _SongFields 814 { 815 song_idSong=0, 816 song_strArtists, 817 song_strArtistSort, 818 song_strGenres, 819 song_strTitle, 820 song_iTrack, 821 song_iDuration, 822 song_strReleaseDate, 823 song_strOrigReleaseDate, 824 song_strDiscSubtitle, 825 song_strFileName, 826 song_strMusicBrainzTrackID, 827 song_iTimesPlayed, 828 song_iStartOffset, 829 song_iEndOffset, 830 song_lastplayed, 831 song_rating, 832 song_userrating, 833 song_votes, 834 song_comment, 835 song_idAlbum, 836 song_strAlbum, 837 song_strPath, 838 song_strReleaseStatus, 839 song_bCompilation, 840 song_bBoxedSet, 841 song_strAlbumArtists, 842 song_strAlbumArtistSort, 843 song_strAlbumReleaseType, 844 song_mood, 845 song_strReplayGain, 846 song_iBPM, 847 song_iBitRate, 848 song_iSampleRate, 849 song_iChannels, 850 song_iAlbumDuration, 851 song_iDiscTotal, 852 song_dateAdded, 853 song_dateNew, 854 song_dateModified, 855 song_enumCount // end of the enum, do not add past here 856 } SongFields; 857 858 // Fields should be ordered as they 859 // appear in the albumview 860 static enum _AlbumFields 861 { 862 album_idAlbum=0, 863 album_strAlbum, 864 album_strMusicBrainzAlbumID, 865 album_strReleaseGroupMBID, 866 album_strArtists, 867 album_strArtistSort, 868 album_strGenres, 869 album_strReleaseDate, 870 album_strOrigReleaseDate, 871 album_bBoxedSet, 872 album_strMoods, 873 album_strStyles, 874 album_strThemes, 875 album_strReview, 876 album_strLabel, 877 album_strType, 878 album_strReleaseStatus, 879 album_strThumbURL, 880 album_fRating, 881 album_iUserrating, 882 album_iVotes, 883 album_bCompilation, 884 album_bScrapedMBID, 885 album_lastScraped, 886 album_dateAdded, 887 album_dateNew, 888 album_dateModified, 889 album_iTimesPlayed, 890 album_strReleaseType, 891 album_iTotalDiscs, 892 album_dtLastPlayed, 893 album_iAlbumDuration, 894 album_enumCount // end of the enum, do not add past here 895 } AlbumFields; 896 897 // Fields should be ordered as they 898 // appear in the songartistview/albumartistview 899 static enum _ArtistCreditFields 900 { 901 // used for GetAlbum to get the cascaded album/song artist credits 902 artistCredit_idEntity = 0, // can be idSong or idAlbum depending on context 903 artistCredit_idArtist, 904 artistCredit_idRole, 905 artistCredit_strRole, 906 artistCredit_strArtist, 907 artistCredit_strSortName, 908 artistCredit_strMusicBrainzArtistID, 909 artistCredit_iOrder, 910 artistCredit_enumCount 911 } ArtistCreditFields; 912 913 // Fields should be ordered as they 914 // appear in the artistview 915 static enum _ArtistFields 916 { 917 artist_idArtist=0, 918 artist_strArtist, 919 artist_strSortName, 920 artist_strMusicBrainzArtistID, 921 artist_strType, 922 artist_strGender, 923 artist_strDisambiguation, 924 artist_strBorn, 925 artist_strFormed, 926 artist_strGenres, 927 artist_strMoods, 928 artist_strStyles, 929 artist_strInstruments, 930 artist_strBiography, 931 artist_strDied, 932 artist_strDisbanded, 933 artist_strYearsActive, 934 artist_strImage, 935 artist_bScrapedMBID, 936 artist_lastScraped, 937 artist_dateAdded, 938 artist_dateNew, 939 artist_dateModified, 940 artist_enumCount // end of the enum, do not add past here 941 } ArtistFields; 942 943 // Fields fetched by GetArtistsByWhereJSON, order same as in JSONtoDBArtist 944 static enum _JoinToArtistFields 945 { 946 joinToArtist_isSong = 0, 947 joinToArtist_idSourceAlbum, 948 joinToArtist_idSourceSong, 949 joinToArtist_idSongGenreAlbum, 950 joinToArtist_idSongGenreSong, 951 joinToArtist_strSongGenreAlbum, 952 joinToArtist_strSongGenreSong, 953 joinToArtist_idArt, 954 joinToArtist_artType, 955 joinToArtist_artURL, 956 joinToArtist_idRole, 957 joinToArtist_strRole, 958 joinToArtist_iOrderRole, 959 joinToArtist_isalbumartist, 960 joinToArtist_thumbnail, 961 joinToArtist_fanart, 962 joinToArtist_enumCount // end of the enum, do not add past here 963 } JoinToArtistFields; 964 965 // Fields fetched by GetAlbumsByWhereJSON, order same as in JSONtoDBAlbum 966 static enum _JoinToAlbumFields 967 { 968 joinToAlbum_idArtist = 0, 969 joinToAlbum_strArtist, 970 joinToAlbum_strArtistMBID, 971 joinToAlbum_enumCount // end of the enum, do not add past here 972 } JoinToAlbumFields; 973 974 // Fields fetched by GetSongsByWhereJSON, order same as in JSONtoDBSong 975 static enum _JoinToSongFields 976 { 977 // Used by GetSongsByWhereJSON 978 joinToSongs_idAlbumArtist = 0, 979 joinToSongs_strAlbumArtist, 980 joinToSongs_strAlbumArtistMBID, 981 joinToSongs_iOrderAlbumArtist, 982 joinToSongs_idArtist, 983 joinToSongs_strArtist, 984 joinToSongs_strArtistMBID, 985 joinToSongs_iOrderArtist, 986 joinToSongs_idRole, 987 joinToSongs_strRole, 988 joinToSongs_iOrderRole, 989 joinToSongs_idGenre, 990 joinToSongs_iOrderGenre, 991 joinToSongs_enumCount // end of the enum, do not add past here 992 } JoinToSongFields; 993 994 }; 995