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