1 /*
2  *  Copyright (C) 2016-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 #include "Bookmark.h"
12 #include "VideoInfoTag.h"
13 #include "addons/Scraper.h"
14 #include "dbwrappers/Database.h"
15 #include "utils/SortUtils.h"
16 #include "video/VideoDbUrl.h"
17 
18 #include <memory>
19 #include <set>
20 #include <utility>
21 #include <vector>
22 
23 class CFileItem;
24 class CFileItemList;
25 class CVideoSettings;
26 class CGUIDialogProgress;
27 class CGUIDialogProgressBarHandle;
28 
29 namespace dbiplus
30 {
31   class field_value;
32   typedef std::vector<field_value> sql_record;
33 }
34 
35 #ifndef my_offsetof
36 #ifndef TARGET_POSIX
37 #define my_offsetof(TYPE, MEMBER) offsetof(TYPE, MEMBER)
38 #else
39 /*
40    Custom version of standard offsetof() macro which can be used to get
41    offsets of members in class for non-POD types (according to the current
42    version of C++ standard offsetof() macro can't be used in such cases and
43    attempt to do so causes warnings to be emitted, OTOH in many cases it is
44    still OK to assume that all instances of the class has the same offsets
45    for the same members).
46  */
47 #define my_offsetof(TYPE, MEMBER) \
48                ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10))
49 #endif
50 #endif
51 
52 typedef std::vector<CVideoInfoTag> VECMOVIES;
53 
54 namespace VIDEO
55 {
56   class IVideoInfoScannerObserver;
57   struct SScanSettings;
58 }
59 
60 enum VideoDbDetails
61 {
62   VideoDbDetailsNone     = 0x00,
63   VideoDbDetailsRating   = 0x01,
64   VideoDbDetailsTag      = 0x02,
65   VideoDbDetailsShowLink = 0x04,
66   VideoDbDetailsStream   = 0x08,
67   VideoDbDetailsCast     = 0x10,
68   VideoDbDetailsBookmark = 0x20,
69   VideoDbDetailsUniqueID = 0x40,
70   VideoDbDetailsAll      = 0xFF
71 } ;
72 
73 // these defines are based on how many columns we have and which column certain data is going to be in
74 // when we do GetDetailsForMovie()
75 #define VIDEODB_MAX_COLUMNS 24
76 #define VIDEODB_DETAILS_FILEID      1
77 
78 #define VIDEODB_DETAILS_MOVIE_SET_ID            VIDEODB_MAX_COLUMNS + 2
79 #define VIDEODB_DETAILS_MOVIE_USER_RATING       VIDEODB_MAX_COLUMNS + 3
80 #define VIDEODB_DETAILS_MOVIE_PREMIERED         VIDEODB_MAX_COLUMNS + 4
81 #define VIDEODB_DETAILS_MOVIE_SET_NAME          VIDEODB_MAX_COLUMNS + 5
82 #define VIDEODB_DETAILS_MOVIE_SET_OVERVIEW      VIDEODB_MAX_COLUMNS + 6
83 #define VIDEODB_DETAILS_MOVIE_FILE              VIDEODB_MAX_COLUMNS + 7
84 #define VIDEODB_DETAILS_MOVIE_PATH              VIDEODB_MAX_COLUMNS + 8
85 #define VIDEODB_DETAILS_MOVIE_PLAYCOUNT         VIDEODB_MAX_COLUMNS + 9
86 #define VIDEODB_DETAILS_MOVIE_LASTPLAYED        VIDEODB_MAX_COLUMNS + 10
87 #define VIDEODB_DETAILS_MOVIE_DATEADDED         VIDEODB_MAX_COLUMNS + 11
88 #define VIDEODB_DETAILS_MOVIE_RESUME_TIME       VIDEODB_MAX_COLUMNS + 12
89 #define VIDEODB_DETAILS_MOVIE_TOTAL_TIME        VIDEODB_MAX_COLUMNS + 13
90 #define VIDEODB_DETAILS_MOVIE_PLAYER_STATE      VIDEODB_MAX_COLUMNS + 14
91 #define VIDEODB_DETAILS_MOVIE_RATING            VIDEODB_MAX_COLUMNS + 15
92 #define VIDEODB_DETAILS_MOVIE_VOTES             VIDEODB_MAX_COLUMNS + 16
93 #define VIDEODB_DETAILS_MOVIE_RATING_TYPE       VIDEODB_MAX_COLUMNS + 17
94 #define VIDEODB_DETAILS_MOVIE_UNIQUEID_VALUE    VIDEODB_MAX_COLUMNS + 18
95 #define VIDEODB_DETAILS_MOVIE_UNIQUEID_TYPE     VIDEODB_MAX_COLUMNS + 19
96 
97 #define VIDEODB_DETAILS_EPISODE_TVSHOW_ID       VIDEODB_MAX_COLUMNS + 2
98 #define VIDEODB_DETAILS_EPISODE_USER_RATING     VIDEODB_MAX_COLUMNS + 3
99 #define VIDEODB_DETAILS_EPISODE_SEASON_ID       VIDEODB_MAX_COLUMNS + 4
100 #define VIDEODB_DETAILS_EPISODE_FILE            VIDEODB_MAX_COLUMNS + 5
101 #define VIDEODB_DETAILS_EPISODE_PATH            VIDEODB_MAX_COLUMNS + 6
102 #define VIDEODB_DETAILS_EPISODE_PLAYCOUNT       VIDEODB_MAX_COLUMNS + 7
103 #define VIDEODB_DETAILS_EPISODE_LASTPLAYED      VIDEODB_MAX_COLUMNS + 8
104 #define VIDEODB_DETAILS_EPISODE_DATEADDED       VIDEODB_MAX_COLUMNS + 9
105 #define VIDEODB_DETAILS_EPISODE_TVSHOW_NAME     VIDEODB_MAX_COLUMNS + 10
106 #define VIDEODB_DETAILS_EPISODE_TVSHOW_GENRE    VIDEODB_MAX_COLUMNS + 11
107 #define VIDEODB_DETAILS_EPISODE_TVSHOW_STUDIO   VIDEODB_MAX_COLUMNS + 12
108 #define VIDEODB_DETAILS_EPISODE_TVSHOW_AIRED    VIDEODB_MAX_COLUMNS + 13
109 #define VIDEODB_DETAILS_EPISODE_TVSHOW_MPAA     VIDEODB_MAX_COLUMNS + 14
110 #define VIDEODB_DETAILS_EPISODE_RESUME_TIME     VIDEODB_MAX_COLUMNS + 15
111 #define VIDEODB_DETAILS_EPISODE_TOTAL_TIME      VIDEODB_MAX_COLUMNS + 16
112 #define VIDEODB_DETAILS_EPISODE_PLAYER_STATE    VIDEODB_MAX_COLUMNS + 17
113 #define VIDEODB_DETAILS_EPISODE_RATING          VIDEODB_MAX_COLUMNS + 18
114 #define VIDEODB_DETAILS_EPISODE_VOTES           VIDEODB_MAX_COLUMNS + 19
115 #define VIDEODB_DETAILS_EPISODE_RATING_TYPE     VIDEODB_MAX_COLUMNS + 20
116 #define VIDEODB_DETAILS_EPISODE_UNIQUEID_VALUE  VIDEODB_MAX_COLUMNS + 21
117 #define VIDEODB_DETAILS_EPISODE_UNIQUEID_TYPE   VIDEODB_MAX_COLUMNS + 22
118 
119 #define VIDEODB_DETAILS_TVSHOW_USER_RATING      VIDEODB_MAX_COLUMNS + 1
120 #define VIDEODB_DETAILS_TVSHOW_DURATION         VIDEODB_MAX_COLUMNS + 2
121 #define VIDEODB_DETAILS_TVSHOW_PARENTPATHID     VIDEODB_MAX_COLUMNS + 3
122 #define VIDEODB_DETAILS_TVSHOW_PATH             VIDEODB_MAX_COLUMNS + 4
123 #define VIDEODB_DETAILS_TVSHOW_DATEADDED        VIDEODB_MAX_COLUMNS + 5
124 #define VIDEODB_DETAILS_TVSHOW_LASTPLAYED       VIDEODB_MAX_COLUMNS + 6
125 #define VIDEODB_DETAILS_TVSHOW_NUM_EPISODES     VIDEODB_MAX_COLUMNS + 7
126 #define VIDEODB_DETAILS_TVSHOW_NUM_WATCHED      VIDEODB_MAX_COLUMNS + 8
127 #define VIDEODB_DETAILS_TVSHOW_NUM_SEASONS      VIDEODB_MAX_COLUMNS + 9
128 #define VIDEODB_DETAILS_TVSHOW_RATING           VIDEODB_MAX_COLUMNS + 10
129 #define VIDEODB_DETAILS_TVSHOW_VOTES            VIDEODB_MAX_COLUMNS + 11
130 #define VIDEODB_DETAILS_TVSHOW_RATING_TYPE      VIDEODB_MAX_COLUMNS + 12
131 #define VIDEODB_DETAILS_TVSHOW_UNIQUEID_VALUE   VIDEODB_MAX_COLUMNS + 13
132 #define VIDEODB_DETAILS_TVSHOW_UNIQUEID_TYPE    VIDEODB_MAX_COLUMNS + 14
133 
134 #define VIDEODB_DETAILS_MUSICVIDEO_USER_RATING  VIDEODB_MAX_COLUMNS + 2
135 #define VIDEODB_DETAILS_MUSICVIDEO_PREMIERED    VIDEODB_MAX_COLUMNS + 3
136 #define VIDEODB_DETAILS_MUSICVIDEO_FILE         VIDEODB_MAX_COLUMNS + 4
137 #define VIDEODB_DETAILS_MUSICVIDEO_PATH         VIDEODB_MAX_COLUMNS + 5
138 #define VIDEODB_DETAILS_MUSICVIDEO_PLAYCOUNT    VIDEODB_MAX_COLUMNS + 6
139 #define VIDEODB_DETAILS_MUSICVIDEO_LASTPLAYED   VIDEODB_MAX_COLUMNS + 7
140 #define VIDEODB_DETAILS_MUSICVIDEO_DATEADDED    VIDEODB_MAX_COLUMNS + 8
141 #define VIDEODB_DETAILS_MUSICVIDEO_RESUME_TIME  VIDEODB_MAX_COLUMNS + 9
142 #define VIDEODB_DETAILS_MUSICVIDEO_TOTAL_TIME   VIDEODB_MAX_COLUMNS + 10
143 #define VIDEODB_DETAILS_MUSICVIDEO_PLAYER_STATE VIDEODB_MAX_COLUMNS + 11
144 
145 #define VIDEODB_TYPE_UNUSED 0
146 #define VIDEODB_TYPE_STRING 1
147 #define VIDEODB_TYPE_INT 2
148 #define VIDEODB_TYPE_FLOAT 3
149 #define VIDEODB_TYPE_BOOL 4
150 #define VIDEODB_TYPE_COUNT 5
151 #define VIDEODB_TYPE_STRINGARRAY 6
152 #define VIDEODB_TYPE_DATE 7
153 #define VIDEODB_TYPE_DATETIME 8
154 
155 typedef enum
156 {
157   VIDEODB_CONTENT_UNKNOWN = 0,
158   VIDEODB_CONTENT_MOVIES = 1,
159   VIDEODB_CONTENT_TVSHOWS = 2,
160   VIDEODB_CONTENT_MUSICVIDEOS = 3,
161   VIDEODB_CONTENT_EPISODES = 4,
162   VIDEODB_CONTENT_MOVIE_SETS = 5,
163   VIDEODB_CONTENT_MUSICALBUMS = 6
164 } VIDEODB_CONTENT_TYPE;
165 
166 typedef enum // this enum MUST match the offset struct further down!! and make sure to keep min and max at -1 and sizeof(offsets)
167 {
168   VIDEODB_ID_MIN = -1,
169   VIDEODB_ID_TITLE = 0,
170   VIDEODB_ID_PLOT = 1,
171   VIDEODB_ID_PLOTOUTLINE = 2,
172   VIDEODB_ID_TAGLINE = 3,
173   VIDEODB_ID_VOTES = 4, // unused
174   VIDEODB_ID_RATING_ID = 5,
175   VIDEODB_ID_CREDITS = 6,
176   VIDEODB_ID_YEAR = 7, // unused
177   VIDEODB_ID_THUMBURL = 8,
178   VIDEODB_ID_IDENT_ID = 9,
179   VIDEODB_ID_SORTTITLE = 10,
180   VIDEODB_ID_RUNTIME = 11,
181   VIDEODB_ID_MPAA = 12,
182   VIDEODB_ID_TOP250 = 13,
183   VIDEODB_ID_GENRE = 14,
184   VIDEODB_ID_DIRECTOR = 15,
185   VIDEODB_ID_ORIGINALTITLE = 16,
186   VIDEODB_ID_THUMBURL_SPOOF = 17,
187   VIDEODB_ID_STUDIOS = 18,
188   VIDEODB_ID_TRAILER = 19,
189   VIDEODB_ID_FANART = 20,
190   VIDEODB_ID_COUNTRY = 21,
191   VIDEODB_ID_BASEPATH = 22,
192   VIDEODB_ID_PARENTPATHID = 23,
193   VIDEODB_ID_MAX
194 } VIDEODB_IDS;
195 
196 const struct SDbTableOffsets
197 {
198   int type;
199   size_t offset;
200 } DbMovieOffsets[] =
201 {
202   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTitle) },
203   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) },
204   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlotOutline) },
205   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTagLine) },
206   { VIDEODB_TYPE_UNUSED, 0 }, // unused
207   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdRating) },
208   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_writingCredits) },
209   { VIDEODB_TYPE_UNUSED, 0 }, // unused
210   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_data) },
211   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdUniqueID) },
212   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strSortTitle) },
213   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_duration) },
214   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strMPAARating) },
215   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iTop250) },
216   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_genre) },
217   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_director) },
218   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strOriginalTitle) },
219   { VIDEODB_TYPE_UNUSED, 0 }, // unused
220   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_studio) },
221   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTrailer) },
222   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_fanart.m_xml) },
223   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_country) },
224   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_basePath) },
225   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_parentPathID) }
226 };
227 
228 typedef enum // this enum MUST match the offset struct further down!! and make sure to keep min and max at -1 and sizeof(offsets)
229 {
230   VIDEODB_ID_TV_MIN = -1,
231   VIDEODB_ID_TV_TITLE = 0,
232   VIDEODB_ID_TV_PLOT = 1,
233   VIDEODB_ID_TV_STATUS = 2,
234   VIDEODB_ID_TV_VOTES = 3, // unused
235   VIDEODB_ID_TV_RATING_ID = 4,
236   VIDEODB_ID_TV_PREMIERED = 5,
237   VIDEODB_ID_TV_THUMBURL = 6,
238   VIDEODB_ID_TV_THUMBURL_SPOOF = 7,
239   VIDEODB_ID_TV_GENRE = 8,
240   VIDEODB_ID_TV_ORIGINALTITLE = 9,
241   VIDEODB_ID_TV_EPISODEGUIDE = 10,
242   VIDEODB_ID_TV_FANART = 11,
243   VIDEODB_ID_TV_IDENT_ID = 12,
244   VIDEODB_ID_TV_MPAA = 13,
245   VIDEODB_ID_TV_STUDIOS = 14,
246   VIDEODB_ID_TV_SORTTITLE = 15,
247   VIDEODB_ID_TV_TRAILER = 16,
248   VIDEODB_ID_TV_MAX
249 } VIDEODB_TV_IDS;
250 
251 const struct SDbTableOffsets DbTvShowOffsets[] =
252 {
253   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTitle) },
254   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) },
255   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strStatus) },
256   { VIDEODB_TYPE_UNUSED, 0 }, //unused
257   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdRating) },
258   { VIDEODB_TYPE_DATE, my_offsetof(CVideoInfoTag,m_premiered) },
259   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_data) },
260   { VIDEODB_TYPE_UNUSED, 0 }, // unused
261   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_genre) },
262   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strOriginalTitle)},
263   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strEpisodeGuide)},
264   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_fanart.m_xml)},
265   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdUniqueID)},
266   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strMPAARating)},
267   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_studio)},
268   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strSortTitle)},
269   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTrailer)}
270 };
271 
272 //! @todo is this comment valid for seasons? There is no offset structure or am I wrong?
273 typedef enum // this enum MUST match the offset struct further down!! and make sure to keep min and max at -1 and sizeof(offsets)
274 {
275   VIDEODB_ID_SEASON_MIN = -1,
276   VIDEODB_ID_SEASON_ID = 0,
277   VIDEODB_ID_SEASON_TVSHOW_ID = 1,
278   VIDEODB_ID_SEASON_NUMBER = 2,
279   VIDEODB_ID_SEASON_NAME = 3,
280   VIDEODB_ID_SEASON_USER_RATING = 4,
281   VIDEODB_ID_SEASON_TVSHOW_PATH = 5,
282   VIDEODB_ID_SEASON_TVSHOW_TITLE = 6,
283   VIDEODB_ID_SEASON_TVSHOW_PLOT = 7,
284   VIDEODB_ID_SEASON_TVSHOW_PREMIERED = 8,
285   VIDEODB_ID_SEASON_TVSHOW_GENRE = 9,
286   VIDEODB_ID_SEASON_TVSHOW_STUDIO = 10,
287   VIDEODB_ID_SEASON_TVSHOW_MPAA = 11,
288   VIDEODB_ID_SEASON_EPISODES_TOTAL = 12,
289   VIDEODB_ID_SEASON_EPISODES_WATCHED = 13,
290   VIDEODB_ID_SEASON_PREMIERED = 14,
291   VIDEODB_ID_SEASON_MAX
292 } VIDEODB_SEASON_IDS;
293 
294 typedef enum // this enum MUST match the offset struct further down!! and make sure to keep min and max at -1 and sizeof(offsets)
295 {
296   VIDEODB_ID_EPISODE_MIN = -1,
297   VIDEODB_ID_EPISODE_TITLE = 0,
298   VIDEODB_ID_EPISODE_PLOT = 1,
299   VIDEODB_ID_EPISODE_VOTES = 2, // unused
300   VIDEODB_ID_EPISODE_RATING_ID = 3,
301   VIDEODB_ID_EPISODE_CREDITS = 4,
302   VIDEODB_ID_EPISODE_AIRED = 5,
303   VIDEODB_ID_EPISODE_THUMBURL = 6,
304   VIDEODB_ID_EPISODE_THUMBURL_SPOOF = 7,
305   VIDEODB_ID_EPISODE_PLAYCOUNT = 8, // unused - feel free to repurpose
306   VIDEODB_ID_EPISODE_RUNTIME = 9,
307   VIDEODB_ID_EPISODE_DIRECTOR = 10,
308   VIDEODB_ID_EPISODE_PRODUCTIONCODE = 11,
309   VIDEODB_ID_EPISODE_SEASON = 12,
310   VIDEODB_ID_EPISODE_EPISODE = 13,
311   VIDEODB_ID_EPISODE_ORIGINALTITLE = 14,
312   VIDEODB_ID_EPISODE_SORTSEASON = 15,
313   VIDEODB_ID_EPISODE_SORTEPISODE = 16,
314   VIDEODB_ID_EPISODE_BOOKMARK = 17,
315   VIDEODB_ID_EPISODE_BASEPATH = 18,
316   VIDEODB_ID_EPISODE_PARENTPATHID = 19,
317   VIDEODB_ID_EPISODE_IDENT_ID = 20,
318   VIDEODB_ID_EPISODE_MAX
319 } VIDEODB_EPISODE_IDS;
320 
321 const struct SDbTableOffsets DbEpisodeOffsets[] =
322 {
323   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strTitle) },
324   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) },
325   { VIDEODB_TYPE_UNUSED, 0 }, // unused
326   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdRating) },
327   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_writingCredits) },
328   { VIDEODB_TYPE_DATE, my_offsetof(CVideoInfoTag,m_firstAired) },
329   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_data) },
330   { VIDEODB_TYPE_UNUSED, 0 }, // unused
331   { VIDEODB_TYPE_UNUSED, 0 }, // unused
332   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_duration) },
333   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_director) },
334   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strProductionCode) },
335   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iSeason) },
336   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iEpisode) },
337   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strOriginalTitle)},
338   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iSpecialSortSeason) },
339   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iSpecialSortEpisode) },
340   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iBookmarkId) },
341   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_basePath) },
342   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_parentPathID) },
343   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdUniqueID) }
344 };
345 
346 typedef enum // this enum MUST match the offset struct further down!! and make sure to keep min and max at -1 and sizeof(offsets)
347 {
348   VIDEODB_ID_MUSICVIDEO_MIN = -1,
349   VIDEODB_ID_MUSICVIDEO_TITLE = 0,
350   VIDEODB_ID_MUSICVIDEO_THUMBURL = 1,
351   VIDEODB_ID_MUSICVIDEO_THUMBURL_SPOOF = 2,
352   VIDEODB_ID_MUSICVIDEO_PLAYCOUNT = 3, // unused - feel free to repurpose
353   VIDEODB_ID_MUSICVIDEO_RUNTIME = 4,
354   VIDEODB_ID_MUSICVIDEO_DIRECTOR = 5,
355   VIDEODB_ID_MUSICVIDEO_STUDIOS = 6,
356   VIDEODB_ID_MUSICVIDEO_YEAR = 7, // unused
357   VIDEODB_ID_MUSICVIDEO_PLOT = 8,
358   VIDEODB_ID_MUSICVIDEO_ALBUM = 9,
359   VIDEODB_ID_MUSICVIDEO_ARTIST = 10,
360   VIDEODB_ID_MUSICVIDEO_GENRE = 11,
361   VIDEODB_ID_MUSICVIDEO_TRACK = 12,
362   VIDEODB_ID_MUSICVIDEO_BASEPATH = 13,
363   VIDEODB_ID_MUSICVIDEO_PARENTPATHID = 14,
364   VIDEODB_ID_MUSICVIDEO_MAX
365 } VIDEODB_MUSICVIDEO_IDS;
366 
367 const struct SDbTableOffsets DbMusicVideoOffsets[] =
368 {
369   { VIDEODB_TYPE_STRING, my_offsetof(class CVideoInfoTag,m_strTitle) },
370   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_data) },
371   { VIDEODB_TYPE_UNUSED, 0 }, // unused
372   { VIDEODB_TYPE_UNUSED, 0 }, // unused
373   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_duration) },
374   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_director) },
375   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_studio) },
376   { VIDEODB_TYPE_UNUSED, 0 }, // unused
377   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPlot) },
378   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strAlbum) },
379   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_artist) },
380   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_genre) },
381   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iTrack) },
382   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_basePath) },
383   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_parentPathID) }
384 };
385 
386 #define COMPARE_PERCENTAGE     0.90f // 90%
387 #define COMPARE_PERCENTAGE_MIN 0.50f // 50%
388 
389 class CVideoDatabase : public CDatabase
390 {
391 public:
392 
393   class CActor    // used for actor retrieval for non-master users
394   {
395   public:
396     std::string name;
397     std::string thumb;
398     int playcount;
399     int appearances;
400   };
401 
402   class CSeason   // used for season retrieval for non-master users
403   {
404   public:
405     std::string path;
406     std::vector<std::string> genre;
407     int numEpisodes;
408     int numWatched;
409     int id;
410   };
411 
412   class CSetInfo
413   {
414   public:
415     std::string name;
416     VECMOVIES movies;
417     DatabaseResults results;
418   };
419 
420   CVideoDatabase(void);
421   ~CVideoDatabase(void) override;
422 
423   bool Open() override;
424   bool CommitTransaction() override;
425 
426   int AddMovie(const std::string& strFilenameAndPath);
427   int AddEpisode(int idShow, const std::string& strFilenameAndPath);
428 
429   // editing functions
430   /*! \brief Set the playcount of an item
431    Sets the playcount and last played date to a given value
432    \param item CFileItem to set the playcount for
433    \param count The playcount to set.
434    \param date The date the file was last viewed (does not denote the video was watched to completion).  If empty we current datetime (if count > 0) or never viewed (if count = 0).
435    \sa GetPlayCount, IncrementPlayCount, UpdateLastPlayed
436    */
437   void SetPlayCount(const CFileItem &item, int count, const CDateTime &date = CDateTime());
438 
439   /*! \brief Increment the playcount of an item
440    Increments the playcount and updates the last played date
441    \param item CFileItem to increment the playcount for
442    \sa GetPlayCount, SetPlayCount, GetPlayCounts
443    */
444   void IncrementPlayCount(const CFileItem &item);
445 
446   /*! \brief Get the playcount of an item
447    \param item CFileItem to get the playcount for
448    \return the playcount of the item, or -1 on error
449    \sa SetPlayCount, IncrementPlayCount, GetPlayCounts
450    */
451   int GetPlayCount(const CFileItem &item);
452 
453   /*! \brief Get the playcount of a filename and path
454    \param strFilenameAndPath filename and path to get the playcount for
455    \return the playcount of the item, or -1 on error
456    \sa SetPlayCount, IncrementPlayCount, GetPlayCounts
457    */
458   int GetPlayCount(const std::string& strFilenameAndPath);
459 
460   /*! \brief Update the last played time of an item
461    Updates the last played date
462    \param item CFileItem to update the last played time for
463    \sa GetPlayCount, SetPlayCount, IncrementPlayCount, GetPlayCounts
464    */
465   void UpdateLastPlayed(const CFileItem &item);
466 
467   /*! \brief Get the playcount and resume point of a list of items
468    Note that if the resume point is already set on an item, it won't be overridden.
469    \param path the path to fetch videos from
470    \param items CFileItemList to fetch the playcounts for
471    \sa GetPlayCount, SetPlayCount, IncrementPlayCount
472    */
473   bool GetPlayCounts(const std::string &path, CFileItemList &items);
474 
475   void UpdateMovieTitle(int idMovie, const std::string& strNewMovieTitle, VIDEODB_CONTENT_TYPE iType=VIDEODB_CONTENT_MOVIES);
476   bool UpdateVideoSortTitle(int idDb, const std::string& strNewSortTitle, VIDEODB_CONTENT_TYPE iType = VIDEODB_CONTENT_MOVIES);
477 
478   bool HasMovieInfo(const std::string& strFilenameAndPath);
479   bool HasTvShowInfo(const std::string& strFilenameAndPath);
480   bool HasEpisodeInfo(const std::string& strFilenameAndPath);
481   bool HasMusicVideoInfo(const std::string& strFilenameAndPath);
482 
483   void GetFilePathById(int idMovie, std::string &filePath, VIDEODB_CONTENT_TYPE iType);
484   std::string GetGenreById(int id);
485   std::string GetCountryById(int id);
486   std::string GetSetById(int id);
487   std::string GetTagById(int id);
488   std::string GetPersonById(int id);
489   std::string GetStudioById(int id);
490   std::string GetTvShowTitleById(int id);
491   std::string GetMusicVideoAlbumById(int id);
492   int GetTvShowForEpisode(int idEpisode);
493   int GetSeasonForEpisode(int idEpisode);
494 
495   bool LoadVideoInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int getDetails = VideoDbDetailsAll);
496   bool GetMovieInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int idMovie = -1, int getDetails = VideoDbDetailsAll);
497   bool GetTvShowInfo(const std::string& strPath, CVideoInfoTag& details, int idTvShow = -1, CFileItem* item = NULL, int getDetails = VideoDbDetailsAll);
498   bool GetSeasonInfo(int idSeason, CVideoInfoTag& details, bool allDetails = true);
499   bool GetEpisodeBasicInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int idEpisode  = -1);
500   bool GetEpisodeInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int idEpisode = -1, int getDetails = VideoDbDetailsAll);
501   bool GetMusicVideoInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int idMVideo = -1, int getDetails = VideoDbDetailsAll);
502   bool GetSetInfo(int idSet, CVideoInfoTag& details);
503   bool GetFileInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int idFile = -1);
504 
505   int GetPathId(const std::string& strPath);
506   int GetTvShowId(const std::string& strPath);
507   int GetEpisodeId(const std::string& strFilenameAndPath, int idEpisode=-1, int idSeason=-1); // idEpisode, idSeason are used for multipart episodes as hints
508   int GetSeasonId(int idShow, int season);
509 
510   void GetEpisodesByFile(const std::string& strFilenameAndPath, std::vector<CVideoInfoTag>& episodes);
511 
512   int SetDetailsForItem(CVideoInfoTag& details, const std::map<std::string, std::string> &artwork);
513   int SetDetailsForItem(int id, const MediaType& mediaType, CVideoInfoTag& details, const std::map<std::string, std::string> &artwork);
514 
515   int SetDetailsForMovie(const std::string& strFilenameAndPath, CVideoInfoTag& details, const std::map<std::string, std::string> &artwork, int idMovie = -1);
516   int SetDetailsForMovieSet(const CVideoInfoTag& details, const std::map<std::string, std::string> &artwork, int idSet = -1);
517 
518   /*! \brief add a tvshow to the library, setting metadata detail
519    First checks for whether this TV Show is already in the database (based on idTvShow, or via GetMatchingTvShow)
520    and if present adds the paths to the show.  If not present, we add a new show and set the show metadata.
521    \param paths a vector<string,string> list of the path(s) and parent path(s) for the show.
522    \param details a CVideoInfoTag filled with the metadata for the show.
523    \param artwork the artwork map for the show.
524    \param seasonArt the artwork map for seasons.
525    \param idTvShow the database id of the tvshow if known (defaults to -1)
526    \return the id of the tvshow.
527    */
528   int SetDetailsForTvShow(const std::vector< std::pair<std::string, std::string> > &paths, CVideoInfoTag& details, const std::map<std::string, std::string> &artwork, const std::map<int, std::map<std::string, std::string> > &seasonArt, int idTvShow = -1);
529   bool UpdateDetailsForTvShow(int idTvShow, CVideoInfoTag &details, const std::map<std::string, std::string> &artwork, const std::map<int, std::map<std::string, std::string> > &seasonArt);
530   int SetDetailsForSeason(const CVideoInfoTag& details, const std::map<std::string, std::string> &artwork, int idShow, int idSeason = -1);
531   int SetDetailsForEpisode(const std::string& strFilenameAndPath, CVideoInfoTag& details, const std::map<std::string, std::string> &artwork, int idShow, int idEpisode=-1);
532   int SetDetailsForMusicVideo(const std::string& strFilenameAndPath, const CVideoInfoTag& details, const std::map<std::string, std::string> &artwork, int idMVideo = -1);
533   void SetStreamDetailsForFile(const CStreamDetails& details, const std::string &strFileNameAndPath);
534   void SetStreamDetailsForFileId(const CStreamDetails& details, int idFile);
535 
536   bool SetSingleValue(VIDEODB_CONTENT_TYPE type, int dbId, int dbField, const std::string &strValue);
537   bool SetSingleValue(VIDEODB_CONTENT_TYPE type, int dbId, Field dbField, const std::string &strValue);
538   bool SetSingleValue(const std::string &table, const std::string &fieldName, const std::string &strValue,
539                       const std::string &conditionName = "", int conditionValue = -1);
540 
541   int UpdateDetailsForMovie(int idMovie, CVideoInfoTag& details, const std::map<std::string, std::string> &artwork, const std::set<std::string> &updatedDetails);
542 
543   void DeleteMovie(int idMovie, bool bKeepId = false);
544   void DeleteMovie(const std::string& strFilenameAndPath, bool bKeepId = false);
545   void DeleteTvShow(int idTvShow, bool bKeepId = false);
546   void DeleteTvShow(const std::string& strPath);
547   void DeleteSeason(int idSeason, bool bKeepId = false);
548   void DeleteEpisode(int idEpisode, bool bKeepId = false);
549   void DeleteEpisode(const std::string& strFilenameAndPath, bool bKeepId = false);
550   void DeleteMusicVideo(int idMusicVideo, bool bKeepId = false);
551   void DeleteMusicVideo(const std::string& strFilenameAndPath, bool bKeepId = false);
552   void DeleteDetailsForTvShow(int idTvShow);
553   void DeleteDetailsForTvShow(const std::string& strPath);
554   void DeleteStreamDetails(int idFile);
555   void RemoveContentForPath(const std::string& strPath,CGUIDialogProgress *progress = NULL);
556   void UpdateFanart(const CFileItem &item, VIDEODB_CONTENT_TYPE type);
557   void DeleteSet(int idSet);
558   void DeleteTag(int idTag, VIDEODB_CONTENT_TYPE mediaType);
559 
560   /*! \brief Get video settings for the specified file id
561    \param idFile file id to get the settings for
562    \return true if video settings found, false otherwise
563    \sa SetVideoSettings
564    */
565   bool GetVideoSettings(int idFile, CVideoSettings &settings);
566 
567   /*! \brief Get video settings for the specified file item
568    \param item item to get the settings for
569    \return true if video settings found, false otherwise
570    \sa SetVideoSettings
571    */
572   bool GetVideoSettings(const CFileItem &item, CVideoSettings &settings);
573 
574   /*! \brief Get video settings for the specified file path
575    \param filePath filepath to get the settings for
576    \return true if video settings found, false otherwise
577    \sa SetVideoSettings
578    */
579   bool GetVideoSettings(const std::string &filePath, CVideoSettings &settings);
580 
581   /*! \brief Set video settings for the specified file path
582    \param fileItem to set the settings for
583    \sa GetVideoSettings
584    */
585   void SetVideoSettings(const CFileItem &item, const CVideoSettings &settings);
586 
587   /*! \brief Set video settings for the specified file path
588    \param fileId to set the settings for
589    \sa GetVideoSettings
590    */
591   void SetVideoSettings(int idFile, const CVideoSettings &settings);
592 
593   /**
594    * Erases video settings for file item
595    * @param fileitem
596    */
597   void EraseVideoSettings(const CFileItem &item);
598 
599   /**
600    * Erases all video settings
601    */
602   void EraseAllVideoSettings();
603 
604   /**
605    * Erases video settings for files starting with path
606    * @param path pattern
607    */
608   void EraseAllVideoSettings(const std::string& path);
609 
610   bool GetStackTimes(const std::string &filePath, std::vector<uint64_t> &times);
611   void SetStackTimes(const std::string &filePath, const std::vector<uint64_t> &times);
612 
613   void GetBookMarksForFile(const std::string& strFilenameAndPath, VECBOOKMARKS& bookmarks, CBookmark::EType type = CBookmark::STANDARD, bool bAppend=false, long partNumber=0);
614   void AddBookMarkToFile(const std::string& strFilenameAndPath, const CBookmark &bookmark, CBookmark::EType type = CBookmark::STANDARD);
615   bool GetResumeBookMark(const std::string& strFilenameAndPath, CBookmark &bookmark);
616   void DeleteResumeBookMark(const CFileItem& item);
617   void ClearBookMarkOfFile(const std::string& strFilenameAndPath, CBookmark& bookmark, CBookmark::EType type = CBookmark::STANDARD);
618   void ClearBookMarksOfFile(const std::string& strFilenameAndPath, CBookmark::EType type = CBookmark::STANDARD);
619   void ClearBookMarksOfFile(int idFile, CBookmark::EType type = CBookmark::STANDARD);
620   bool GetBookMarkForEpisode(const CVideoInfoTag& tag, CBookmark& bookmark);
621   void AddBookMarkForEpisode(const CVideoInfoTag& tag, const CBookmark& bookmark);
622   void DeleteBookMarkForEpisode(const CVideoInfoTag& tag);
623   bool GetResumePoint(CVideoInfoTag& tag);
624   bool GetStreamDetails(CFileItem& item);
625   bool GetStreamDetails(CVideoInfoTag& tag) const;
626   CVideoInfoTag GetDetailsByTypeAndId(VIDEODB_CONTENT_TYPE type, int id);
627 
628   // scraper settings
629   void SetScraperForPath(const std::string& filePath, const ADDON::ScraperPtr& info, const VIDEO::SScanSettings& settings);
630   ADDON::ScraperPtr GetScraperForPath(const std::string& strPath);
631   ADDON::ScraperPtr GetScraperForPath(const std::string& strPath, VIDEO::SScanSettings& settings);
632 
633   /*! \brief Retrieve the scraper and settings we should use for the specified path
634    If the scraper is not set on this particular path, we'll recursively check parent folders.
635    \param strPath path to start searching in.
636    \param settings [out] scan settings for this folder.
637    \param foundDirectly [out] true if a scraper was found directly for strPath, false if it was in a parent path.
638    \return A ScraperPtr containing the scraper information. Returns NULL if a trivial (Content == CONTENT_NONE)
639            scraper or no scraper is found.
640    */
641   ADDON::ScraperPtr GetScraperForPath(const std::string& strPath, VIDEO::SScanSettings& settings, bool& foundDirectly);
642 
643   /*! \brief Retrieve the content type of videos in the given path
644    If content is set on the folder, we return the given content type, except in the case of tvshows,
645    where we first check for whether we have episodes directly in the path (thus return episodes) or whether
646    we've found a scraper directly (shows).  Any folders inbetween are treated as seasons (regardless of whether
647    they actually are seasons). Note that any subfolders in movies will be treated as movies.
648    \param strPath path to start searching in.
649    \return A content type string for the current path.
650    */
651   std::string GetContentForPath(const std::string& strPath);
652 
653   /*! \brief Get videos of the given content type from the given path
654    \param content the content type to fetch.
655    \param path the path to fetch videos from.
656    \param items the returned items
657    \return true if items are found, false otherwise.
658    */
659   bool GetItemsForPath(const std::string &content, const std::string &path, CFileItemList &items);
660 
661   /*! \brief Check whether a given scraper is in use.
662    \param scraperID the scraper to check for.
663    \return true if the scraper is in use, false otherwise.
664    */
665   bool ScraperInUse(const std::string &scraperID) const;
666 
667   // scanning hashes and paths scanned
668   bool SetPathHash(const std::string &path, const std::string &hash);
669   bool GetPathHash(const std::string &path, std::string &hash);
670   bool GetPaths(std::set<std::string> &paths);
671   bool GetPathsForTvShow(int idShow, std::set<int>& paths);
672 
673   /*! \brief return the paths linked to a tvshow.
674    \param idShow the id of the tvshow.
675    \param paths [out] the list of paths associated with the show.
676    \return true on success, false on failure.
677    */
678   bool GetPathsLinkedToTvShow(int idShow, std::vector<std::string> &paths);
679 
680   /*! \brief retrieve subpaths of a given path.  Assumes a hierarchical folder structure
681    \param basepath the root path to retrieve subpaths for
682    \param subpaths the returned subpaths
683    \return true if we successfully retrieve subpaths (may be zero), false on error
684    */
685   bool GetSubPaths(const std::string& basepath, std::vector< std::pair<int, std::string> >& subpaths);
686 
687   bool GetSourcePath(const std::string &path, std::string &sourcePath);
688   bool GetSourcePath(const std::string &path, std::string &sourcePath, VIDEO::SScanSettings& settings);
689 
690   // for music + musicvideo linkups - if no album and title given it will return the artist id, else the id of the matching video
691   int GetMatchingMusicVideo(const std::string& strArtist, const std::string& strAlbum = "", const std::string& strTitle = "");
692 
693   // searching functions
694   void GetMoviesByActor(const std::string& strActor, CFileItemList& items);
695   void GetTvShowsByActor(const std::string& strActor, CFileItemList& items);
696   void GetEpisodesByActor(const std::string& strActor, CFileItemList& items);
697 
698   void GetMusicVideosByArtist(const std::string& strArtist, CFileItemList& items);
699   void GetMusicVideosByAlbum(const std::string& strAlbum, CFileItemList& items);
700 
701   void GetMovieGenresByName(const std::string& strSearch, CFileItemList& items);
702   void GetTvShowGenresByName(const std::string& strSearch, CFileItemList& items);
703   void GetMusicVideoGenresByName(const std::string& strSearch, CFileItemList& items);
704 
705   void GetMovieCountriesByName(const std::string& strSearch, CFileItemList& items);
706 
707   void GetMusicVideoAlbumsByName(const std::string& strSearch, CFileItemList& items);
708 
709   void GetMovieActorsByName(const std::string& strSearch, CFileItemList& items);
710   void GetTvShowsActorsByName(const std::string& strSearch, CFileItemList& items);
711   void GetMusicVideoArtistsByName(const std::string& strSearch, CFileItemList& items);
712 
713   void GetMovieDirectorsByName(const std::string& strSearch, CFileItemList& items);
714   void GetTvShowsDirectorsByName(const std::string& strSearch, CFileItemList& items);
715   void GetMusicVideoDirectorsByName(const std::string& strSearch, CFileItemList& items);
716 
717   void GetMoviesByName(const std::string& strSearch, CFileItemList& items);
718   void GetTvShowsByName(const std::string& strSearch, CFileItemList& items);
719   void GetEpisodesByName(const std::string& strSearch, CFileItemList& items);
720   void GetMusicVideosByName(const std::string& strSearch, CFileItemList& items);
721 
722   void GetEpisodesByPlot(const std::string& strSearch, CFileItemList& items);
723   void GetMoviesByPlot(const std::string& strSearch, CFileItemList& items);
724 
725   bool LinkMovieToTvshow(int idMovie, int idShow, bool bRemove);
726   bool IsLinkedToTvshow(int idMovie);
727   bool GetLinksToTvShow(int idMovie, std::vector<int>& ids);
728 
729   // general browsing
730   bool GetGenresNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
731   bool GetCountriesNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
732   bool GetStudiosNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
733   bool GetYearsNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter());
734   bool GetActorsNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
735   bool GetDirectorsNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
736   bool GetWritersNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
737   bool GetSetsNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool ignoreSingleMovieSets = false);
738   bool GetTagsNav(const std::string& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
739   bool GetMusicVideoAlbumsNav(const std::string& strBaseDir, CFileItemList& items, int idArtist, const Filter &filter = Filter(), bool countOnly = false);
740 
741   bool GetMoviesNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1, int idCountry=-1, int idSet=-1, int idTag=-1, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
742   bool GetTvShowsNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1, int idTag=-1, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
743   bool GetSeasonsNav(const std::string& strBaseDir, CFileItemList& items, int idActor=-1, int idDirector=-1, int idGenre=-1, int idYear=-1, int idShow=-1, bool getLinkedMovies = true);
744   bool GetEpisodesNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idShow=-1, int idSeason=-1, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
745   bool GetMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idArtist=-1, int idDirector=-1, int idStudio=-1, int idAlbum=-1, int idTag=-1, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
746 
747   bool GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, int getDetails = VideoDbDetailsNone);
748   bool GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, int getDetails = VideoDbDetailsNone);
749   bool GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, int getDetails = VideoDbDetailsNone);
750   bool GetInProgressTvShowsNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, int getDetails = VideoDbDetailsNone);
751 
752   bool HasContent();
753   bool HasContent(VIDEODB_CONTENT_TYPE type);
754   bool HasSets() const;
755 
756   void CleanDatabase(CGUIDialogProgressBarHandle* handle = NULL, const std::set<int>& paths = std::set<int>(), bool showProgress = true);
757 
758   /*! \brief Add a file to the database, if necessary
759    If the file is already in the database, we simply return its id.
760    \param url - full path of the file to add.
761    \return id of the file, -1 if it could not be added.
762    */
763   int AddFile(const std::string& url);
764 
765   /*! \brief Add a file to the database, if necessary
766    Works for both videodb:// items and normal fileitems
767    \param item CFileItem to add.
768    \return id of the file, -1 if it could not be added.
769    */
770   int AddFile(const CFileItem& item);
771 
772   /*! \brief Add a path to the database, if necessary
773    If the path is already in the database, we simply return its id.
774    \param strPath the path to add
775    \param parentPath the parent path of the path to add. If empty, URIUtils::GetParentPath() will determine the path.
776    \param dateAdded datetime when the path was added to the filesystem/database
777    \return id of the file, -1 if it could not be added.
778    */
779   int AddPath(const std::string& strPath, const std::string &parentPath = "", const CDateTime& dateAdded = CDateTime());
780 
781   /*! \brief Updates the dateAdded field in the files table for the file
782    with the given idFile and the given path based on the files modification date
783    \param idFile id of the file in the files table
784    \param strFileNameAndPath path to the file
785    \param dateAdded datetime when the file was added to the filesystem/database
786    */
787   void UpdateFileDateAdded(int idFile, const std::string& strFileNameAndPath, const CDateTime& dateAdded = CDateTime());
788 
789   void ExportToXML(const std::string &path, bool singleFile = true, bool images=false, bool actorThumbs=false, bool overwrite=false);
790   void ExportActorThumbs(const std::string &path, const CVideoInfoTag& tag, bool singleFiles, bool overwrite=false);
791   void ImportFromXML(const std::string &path);
792   void DumpToDummyFiles(const std::string &path);
793   bool ImportArtFromXML(const TiXmlNode *node, std::map<std::string, std::string> &artwork);
794 
795   // smart playlists and main retrieval work in these functions
796   bool GetMoviesByWhere(const std::string& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
797   bool GetSetsByWhere(const std::string& strBaseDir, const Filter &filter, CFileItemList& items, bool ignoreSingleMovieSets = false);
798   bool GetTvShowsByWhere(const std::string& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
799   bool GetSeasonsByWhere(const std::string& strBaseDir, const Filter &filter, CFileItemList& items, bool appendFullShowPath = true, const SortDescription &sortDescription = SortDescription());
800   bool GetEpisodesByWhere(const std::string& strBaseDir, const Filter &filter, CFileItemList& items, bool appendFullShowPath = true, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
801   bool GetMusicVideosByWhere(const std::string &baseDir, const Filter &filter, CFileItemList& items, bool checkLocks = true, const SortDescription &sortDescription = SortDescription(), int getDetails = VideoDbDetailsNone);
802 
803   // retrieve sorted and limited items
804   bool GetSortedVideos(const MediaType &mediaType, const std::string& strBaseDir, const SortDescription &sortDescription, CFileItemList& items, const Filter &filter = Filter());
805 
806   // retrieve a list of items
807   bool GetItems(const std::string &strBaseDir, CFileItemList &items, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription());
808   bool GetItems(const std::string &strBaseDir, const std::string &mediaType, const std::string &itemType, CFileItemList &items, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription());
809   bool GetItems(const std::string &strBaseDir, VIDEODB_CONTENT_TYPE mediaType, const std::string &itemType, CFileItemList &items, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription());
810   std::string GetItemById(const std::string &itemType, int id);
811 
812   // partymode
813   /*! \brief Gets music video IDs in random order that match the where clause
814   \param strWhere the SQL where clause to apply in the query
815   \param songIDs a vector of <2, id> pairs suited to party mode use
816   \return count of music video IDs found.
817   */
818   unsigned int GetRandomMusicVideoIDs(const std::string& strWhere, std::vector<std::pair<int, int> > &songIDs);
819 
VideoContentTypeToString(VIDEODB_CONTENT_TYPE type,std::string & out)820   static void VideoContentTypeToString(VIDEODB_CONTENT_TYPE type, std::string& out)
821   {
822     switch (type)
823     {
824     case VIDEODB_CONTENT_MOVIES:
825       out = MediaTypeMovie;
826       break;
827     case VIDEODB_CONTENT_TVSHOWS:
828       out = MediaTypeTvShow;
829       break;
830     case VIDEODB_CONTENT_EPISODES:
831       out = MediaTypeEpisode;
832       break;
833     case VIDEODB_CONTENT_MUSICVIDEOS:
834       out = MediaTypeMusicVideo;
835       break;
836     default:
837       break;
838     }
839   }
840 
841   void SetArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType, const std::string &url);
842   void SetArtForItem(int mediaId, const MediaType &mediaType, const std::map<std::string, std::string> &art);
843   bool GetArtForItem(int mediaId, const MediaType &mediaType, std::map<std::string, std::string> &art);
844   std::string GetArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType);
845   bool HasArtForItem(int mediaId, const MediaType &mediaType);
846   bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType);
847   bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::set<std::string> &artTypes);
848   bool GetTvShowSeasons(int showId, std::map<int, int> &seasons);
849   bool GetTvShowNamedSeasons(int showId, std::map<int, std::string> &seasons);
850   bool GetTvShowSeasonArt(int mediaId, std::map<int, std::map<std::string, std::string> > &seasonArt);
851   bool GetArtTypes(const MediaType &mediaType, std::vector<std::string> &artTypes);
852 
853   /*! \brief Fetch the distinct types of available-but-unassigned art held in the
854   database for a specific media item.
855   \param mediaId the id in the media table.
856   \param mediaType the type of media, which corresponds to the table the item resides in.
857   \return the types of art e.g. "thumb", "fanart", etc.
858   */
859   std::vector<std::string> GetAvailableArtTypesForItem(int mediaId, const MediaType& mediaType);
860 
861   /*! \brief Fetch the list of available-but-unassigned art URLs held in the
862   database for a specific media item and art type.
863   \param mediaId the id in the media table.
864   \param mediaType corresponds to the table the item resides in.
865   \param artType e.g. "thumb", "fanart", etc.
866   \return list of URLs
867   */
868   std::vector<CScraperUrl::SUrlEntry> GetAvailableArtForItem(
869     int mediaId, const MediaType& mediaType, const std::string& artType);
870 
871   int AddTag(const std::string &tag);
872   void AddTagToItem(int idItem, int idTag, const std::string &type);
873   void RemoveTagFromItem(int idItem, int idTag, const std::string &type);
874   void RemoveTagsFromItem(int idItem, const std::string &type);
875 
876   bool GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription &sorting) override;
877 
878   /*! \brief Will check if the season exists and if that is not the case add it to the database.
879   \param showID The id of the show in question.
880   \param season The season number we want to add.
881   \return The dbId of the season.
882   */
883   int AddSeason(int showID, int season, const std::string& name = "");
884   int AddSet(const std::string& strSet, const std::string& strOverview = "");
885   void ClearMovieSet(int idMovie);
886   void SetMovieSet(int idMovie, int idSet);
887   bool SetVideoUserRating(int dbId, int rating, const MediaType& mediaType);
888   bool GetUseAllExternalAudioForVideo(const std::string& videoPath);
889 
890 protected:
891   int GetMovieId(const std::string& strFilenameAndPath);
892   int GetMusicVideoId(const std::string& strFilenameAndPath);
893 
894   /*! \brief Get the id of this fileitem
895    Works for both videodb:// items and normal fileitems
896    \param item CFileItem to grab the fileid of
897    \return id of the file, -1 if it is not in the db.
898    */
899   int GetFileId(const CFileItem &item);
900 
901   /*! \brief Get the id of a file from path
902    \param url full path to the file
903    \return id of the file, -1 if it is not in the db.
904    */
905   int GetFileId(const std::string& url);
906 
907   int AddToTable(const std::string& table, const std::string& firstField, const std::string& secondField, const std::string& value);
908   int UpdateRatings(int mediaId, const char *mediaType, const RatingMap& values, const std::string& defaultRating);
909   int AddRatings(int mediaId, const char *mediaType, const RatingMap& values, const std::string& defaultRating);
910   int UpdateUniqueIDs(int mediaId, const char *mediaType, const CVideoInfoTag& details);
911   int AddUniqueIDs(int mediaId, const char *mediaType, const CVideoInfoTag& details);
912   int AddActor(const std::string& strActor, const std::string& thumbURL, const std::string &thumb = "");
913 
914   int AddTvShow();
915   int AddMusicVideo(const std::string& strFilenameAndPath);
916 
917   /*! \brief Adds a path to the tvshow link table.
918    \param idShow the id of the show.
919    \param path the path to add.
920    \param parentPath the parent path of the path to add.
921    \param dateAdded date/time when the path was added
922    \return true if successfully added, false otherwise.
923    */
924   bool AddPathToTvShow(int idShow, const std::string &path, const std::string &parentPath, const CDateTime& dateAdded = CDateTime());
925 
926   /*! \brief Check whether a show is already in the library.
927    Matches on unique identifier or matching title and premiered date.
928    \param show the details of the show to check for.
929    \return the show id if found, else -1.
930    */
931   int GetMatchingTvShow(const CVideoInfoTag &show);
932 
933   // link functions - these two do all the work
934   void AddLinkToActor(int mediaId, const char *mediaType, int actorId, const std::string &role, int order);
935   void AddToLinkTable(int mediaId, const std::string& mediaType, const std::string& table, int valueId, const char *foreignKey = NULL);
936   void RemoveFromLinkTable(int mediaId, const std::string& mediaType, const std::string& table, int valueId, const char *foreignKey = NULL);
937 
938   void AddLinksToItem(int mediaId, const std::string& mediaType, const std::string& field, const std::vector<std::string>& values);
939   void UpdateLinksToItem(int mediaId, const std::string& mediaType, const std::string& field, const std::vector<std::string>& values);
940   void AddActorLinksToItem(int mediaId, const std::string& mediaType, const std::string& field, const std::vector<std::string>& values);
941   void UpdateActorLinksToItem(int mediaId, const std::string& mediaType, const std::string& field, const std::vector<std::string>& values);
942 
943   void AddCast(int mediaId, const char *mediaType, const std::vector<SActorInfo> &cast);
944 
945   CVideoInfoTag GetDetailsForMovie(std::unique_ptr<dbiplus::Dataset> &pDS, int getDetails = VideoDbDetailsNone);
946   CVideoInfoTag GetDetailsForMovie(const dbiplus::sql_record* const record, int getDetails = VideoDbDetailsNone);
947   CVideoInfoTag GetDetailsForTvShow(std::unique_ptr<dbiplus::Dataset> &pDS, int getDetails = VideoDbDetailsNone, CFileItem* item = NULL);
948   CVideoInfoTag GetDetailsForTvShow(const dbiplus::sql_record* const record, int getDetails = VideoDbDetailsNone, CFileItem* item = NULL);
949   CVideoInfoTag GetBasicDetailsForEpisode(std::unique_ptr<dbiplus::Dataset> &pDS);
950   CVideoInfoTag GetBasicDetailsForEpisode(const dbiplus::sql_record* const record);
951   CVideoInfoTag GetDetailsForEpisode(std::unique_ptr<dbiplus::Dataset> &pDS, int getDetails = VideoDbDetailsNone);
952   CVideoInfoTag GetDetailsForEpisode(const dbiplus::sql_record* const record, int getDetails = VideoDbDetailsNone);
953   CVideoInfoTag GetDetailsForMusicVideo(std::unique_ptr<dbiplus::Dataset> &pDS, int getDetails = VideoDbDetailsNone);
954   CVideoInfoTag GetDetailsForMusicVideo(const dbiplus::sql_record* const record, int getDetails = VideoDbDetailsNone);
955   bool GetPeopleNav(const std::string& strBaseDir, CFileItemList& items, const char *type, int idContent = -1, const Filter &filter = Filter(), bool countOnly = false);
956   bool GetNavCommon(const std::string& strBaseDir, CFileItemList& items, const char *type, int idContent=-1, const Filter &filter = Filter(), bool countOnly = false);
957   void GetCast(int media_id, const std::string &media_type, std::vector<SActorInfo> &cast);
958   void GetTags(int media_id, const std::string &media_type, std::vector<std::string> &tags);
959   void GetRatings(int media_id, const std::string &media_type, RatingMap &ratings);
960   void GetUniqueIDs(int media_id, const std::string &media_type, CVideoInfoTag& details);
961 
962   void GetDetailsFromDB(std::unique_ptr<dbiplus::Dataset> &pDS, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset = 2);
963   void GetDetailsFromDB(const dbiplus::sql_record* const record, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset = 2);
964   std::string GetValueString(const CVideoInfoTag &details, int min, int max, const SDbTableOffsets *offsets) const;
965 
966 private:
967   void CreateTables() override;
968   void CreateAnalytics() override;
969   void UpdateTables(int version) override;
970   void CreateLinkIndex(const char *table);
971   void CreateForeignLinkIndex(const char *table, const char *foreignkey);
972 
973   /*! \brief (Re)Create the generic database views for movies, tvshows,
974      episodes and music videos
975    */
976   virtual void CreateViews();
977 
978   /*! \brief Helper to get a database id given a query.
979    Returns an integer, -1 if not found, and greater than 0 if found.
980    \param query the SQL that will retrieve a database id.
981    \return -1 if not found, else a valid database id (i.e. > 0)
982    */
983   int GetDbId(const std::string &query);
984 
985   /*! \brief Run a query on the main dataset and return the number of rows
986    If no rows are found we close the dataset and return 0.
987    \param sql the sql query to run
988    \return the number of rows, -1 for an error.
989    */
990   int RunQuery(const std::string &sql);
991 
992   void AppendIdLinkFilter(const char* field, const char *table, const MediaType& mediaType, const char *view, const char *viewKey, const CUrlOptions::UrlOptions& options, Filter &filter);
993   void AppendLinkFilter(const char* field, const char *table, const MediaType& mediaType, const char *view, const char *viewKey, const CUrlOptions::UrlOptions& options, Filter &filter);
994 
995   /*! \brief Determine whether the path is using lookup using folders
996    \param path the path to check
997    \param shows whether this path is from a tvshow (defaults to false)
998    */
999   bool LookupByFolders(const std::string &path, bool shows = false);
1000 
1001   /*! \brief Get the playcount for a file id
1002    \param iFileId file id to get the playcount for
1003    \return the playcount of the item, or -1 on error
1004    \sa SetPlayCount, IncrementPlayCount, GetPlayCounts
1005    */
1006   int GetPlayCount(int iFileId);
1007 
GetMinSchemaVersion()1008   int GetMinSchemaVersion() const override { return 75; };
1009   int GetSchemaVersion() const override;
GetExportVersion()1010   virtual int GetExportVersion() const { return 1; };
GetBaseDBName()1011   const char *GetBaseDBName() const override { return "MyVideos"; };
1012 
1013   void ConstructPath(std::string& strDest, const std::string& strPath, const std::string& strFileName);
1014   void SplitPath(const std::string& strFileNameAndPath, std::string& strPath, std::string& strFileName);
1015   void InvalidatePathHash(const std::string& strPath);
1016 
1017   /*! \brief Get a safe filename from a given string
1018    \param dir directory to use for the file
1019    \param name movie, show name, or actor to get a safe filename for
1020    \return safe filename based on this title
1021    */
1022   std::string GetSafeFile(const std::string &dir, const std::string &name) const;
1023 
1024   std::vector<int> CleanMediaType(const std::string &mediaType, const std::string &cleanableFileIDs,
1025                                   std::map<int, bool> &pathsDeleteDecisions, std::string &deletedFileIDs, bool silent);
1026 
1027   static void AnnounceRemove(const std::string& content, int id, bool scanning = false);
1028   static void AnnounceUpdate(const std::string& content, int id);
1029 };
1030