Skip to content
This repository

A few database/query optimizations #1085

Merged
merged 9 commits into from almost 2 years ago

8 participants

Sascha Montellese Garrett Brown Cory Fields Michal Piechowiak jmarshallnz Matt Filetto Chris Browet Matthias Kortstiege
Sascha Montellese
Collaborator

vdrfan and myself took the time to log all the SQL queries we run in XBMC (especially during startup etc) and we were surprised by the huge number of queries that are run when XBMC starts (without doing a single action as a user). We have taken a look at the queries that appeared most in the log and tracked them down. We have done the following optimizations (in the order of the commits):

  1. On every CDatabase::Open we check the version of the database we are opening to see if we need to update the database. These queries make up about 20% of all queries that are run in XBMC. Once a database has been updated, we will never have to update it again while XBMC runs so there's no need to check for it every time. Using a map we remember which databases we have already opened (and updated) and don't run the version query anymore if the db is already in the map.
  2. Adding bookmark.timeInSeconds and bookmark.totalTimeInSeconds to the video views saves us from having to make those calls to retrieve a video's resume point manually. This saves at least one query for every video when listed in the GUI.
  3. In the recently added job for recently added album songs we iterate over all retrieved songs and retrieve their album id and album thumb (two extra queries per song). The album id is already available in CMusicInfoTag (just not exposed) so we can save that query completely. Furthermore as we retreive multiple songs from the same album they can all use the same album cover so we can just remember the cover of the current album until the album changes and only then retrieve the album's cover. These two changes saved 190 (of 195) queries for the recently added album songs widget in my setup.
  4. see 5.
  5. jmarshall added a new seasons table in his recent work and that seasonid is needed to retrieve season thumbs. By storing the idSeason value in the video views and in CVideoInfoTag we can save a query for every episode. Furthermore we can save some queries in recently added episodes by also remembering the season and show thumb for every season/show and only querying the database if we haven't come across that season/show yet. This saves about half of the queries for the recently added episodes widget.
  6. the implementation for recently added albums retrieves the values for rating, year, artist and album title manually with 1 query per attribute (i.e. 4 queries per album) even though that data is already available in the CAlbum object's we get from the database.
  7. When retrieving sets, we retrieve all movies that are part of a set and put the set together based on those movies (to get additional metadata like rating, year etc). In that case we don't need to retrieve the stream details because we don't use them and they'll be retrieved when browsing into the set in the GUI. So we can save those queries.
  8. When a user adds addon shortcuts to the confluence home screen, the addon title and icon are constantly retrieved from CGUIInfoManager to be able to show them in the GUI. During that query we also check against the addon database, if the addon is disabled even though we don't use that information, so that check is unnecessary. This saves a lot of queries because they are repeated periodically as long as the user is on the home screen. This is even worse for the global search addon which has been integrated into the confluence home screen by default. For every frame (i.e. 60 times per second) we query the enabled/disabled state of the addon from the database (SYSTEM_HAS_ADDON). We haven't looked into that yet, but maybe someone can shed some light on it.
  9. When changing a view/window in the GUI we have to retrieve the next view/viewstate which includes queries to the ViewState database. Instead of doing one query to retrieve the view state we run the same query 3-4 times in different places. Especially on embedded devices these queries are rather costly and slow down the changing of views/windows. This commit is highly experimental because neither vdrfan nor myself have any real knowledge about this process.

All in all with these changes the number of queries on startup (before doing a single user interaction) goes down to 20-30%. On fast systems there's no real noteable speed-up because some of those queries are not expensive at all but on embedded devices (where I/O (i.e. accessing the sqlite database file) is more time intensive and computation power more scarce) it could speed up the startup process and some loading times of item lists.

Garrett Brown
Collaborator

Off topic: Something that struck me as weird is that databases aren't loaded on startup, they're loaded "just in time." Thus, a database update isn't done on app load, it's done when the skin first uses "HasContent(Video)". Just something I found weird, and something that made debugging the DB creation/update process a little more difficult.

Cory Fields
Owner
theuni commented June 17, 2012

nice work! can't comment on the code, though I applaud the effort.

Sascha Montellese
Collaborator

OK I've pushed a few changes/fixes (as extra commits which can be squashed later on):
1. I removed the last commit about the view states as it is not correct and will take more time to look into.
2. I've added a comment in CGUIInfoManager concerning the retrieval of addon information and not checking whether the addon is disabled or not.
3. I've removed CMusicInfoTag::GetArtistId() as requested.
4. I've moved the calls to CVideoDatabase::GetStreamDetails to CVideoThumbLoader. During some of the test I ran when I re-wrote the sorting implementation I noticed that about 20-30% of the time needed to retrieve a list of movies is caused by retrieving the streamdetails for all the movies. So this might speed things up a bit. It would replace the commit about removing an unnecessary call to GetStreamDetails when retrieving movie sets.

Still open are the discussion on database updates and on the season/show thumb in recently added episodes.

Michal Piechowiak
Collaborator
pieh commented June 18, 2012

Could we also add some flags to item lists like "has already fetched metadata" and "has already fetched resume point" (or single flag after commit that joins bookmark table to movie/episode/musicvideo views)?

I would certainly use these flags to determine if we can return or need to fetch metadata and playcount here (the "if clause" on L364 is to determine if we already queried database): pieh@0f63058#L0L364

I could also make retrieving resume points for files mode smarter (it's not actually working in master - just in my branch). Instead of checking and quering every item as now in thumbloader, i could do single query for files+bookmarks for pathId of directory item list is representing.

I'll supply patch if that would be ok

jmarshallnz
Owner

@pieh You could probably tap the resume stuff into the routine that grabs all playcounts for the current listing - IIRC that does a similar thing using a single query - see LoadVideoInfo()

Sascha Montellese
Collaborator

@jmarshallnz I saw you comment in the thread about ShowThumb and SeasonThumb for recently added episodes and added a commit that removes those two for now. With that we can also get rid of the optimizations I came up with for that part.

That mainly leaves the database update procedure to be optimized in this PR. Should I remove that commit (because it will be fixed later on) or should I add the necessary locks around my optimizations or is there a specific plan on how to do it?

Matt Filetto

i dont know if this PR is related to my problem but as of recently i had to redo my entire media server to had to rescan my libraries (what a pain) anyways i noticed xbmc no longer grabs the codec info of the movies or tv shows automaticily anymore you have to actually play the file. I remember a bug like this a long time ago before 10.1 will this PR fix that?

Sascha Montellese
Collaborator

AFAIK you don't have to play a video file you just have to view a GUI listing which contains the file and then XBMC will automatically read the streamdetails (codec, resolution, ...) of the video. AFAIK it has never been the way that XBMC grabs this information during the scanning process (don't know why though).

Matt Filetto
jmarshallnz
Owner

@Montellese: I'd just remove season thumb - show thumb still kinda makes sense I think (balances with show fanart).

As for the db update, it's up to you - you can either protect the map with a lock or drop and we'll isolate with a proper db update thing. For a proper db update, I think we'd need to:

  1. Have a static indicating that db's were OK to open (and critical section to guard).
  2. Have a function in each db to do the update.
  3. Call said function as early as possible on app start.

It might be as simple as dividing CDatabase::Open() into two functions, one that does OpenAndUpdate() and the other that just does Open(). The latter would just check the static for whether the db is up to date and fail if not, else call Connect(currentDB, false). I think the OpenAndUpdate() would handle correctly setting up the advancedsettings and handle fallback to sqlite etc.

Sascha Montellese
Collaborator

@jmarshallnz I've re-added the ShowThumb for recently added episodes (and squashed it with the commit that removed it) and I've added a lock to CDatabase::UpdateVersion()

Sascha Montellese
Collaborator

So do we want to wait till someone has the time to come up with a proper fix for the database update or should I rebase & squash the commits so they can be merged?

jmarshallnz
Owner

IMO rebase + squash and push it in.

Sascha Montellese
Collaborator

OK I've rebased and squashed the commits. There were a few conflicts in RecentlyAdded.cpp (see 27e3814#commitcomment-1544120) so I'll wait till that's settled.

Sascha Montellese
Collaborator

Okay I rebased again. I had to re-arrange the optimization for retrieving cover and fanart of albums in recently added album songs because the code changed from manual lookups to calling CMusicThumbLoader::LoadItem.

jmarshallnz
Owner

If we're leaving b5b9fa8 in, then I think we mayaswell keep the season art there as well. I'm not sure whether it's worth it otherwise?

Also, abb44bf should probably be split to removing the season thumb separate (or keep it in and we can remove it later?)

Sascha Montellese
Collaborator

I don't really care whether we keep the season art/thumb or not. Personally I'd always prefer to see either the tvshow thumb or the episode thumb and never the season thumb in recently added episodes but I guess that comes down to personal preferences.

jmarshallnz
Owner

Just leave it in then and I'll kill it off later once we properly handle banners+posters?

and others added some commits June 17, 2012
Sascha Montellese recentlyadded: save queries for season id and season/show thumbs
Use the idSeason value available through episodeview instead of having to
retrieve it for every episode. Furthermore remember the already retrieved
season/show thumbs to save querying the same images again.
f95c66b
Sascha Montellese recentlyadded: use values from CAlbum instead of manually querying th…
…em one by one for every album
60ba8b1
videodb: do not retrieve streamdetails for set items - the actual str…
…eamdetails will be queried for the single items later on
30e9f45
fixed: do not query the addon state when asking the guiinfomanager fo…
…r addon title and/or icon

This commit removes tons of useless queries made from the mainloop when using addon shortcuts on
the home screen. As the infomanager is asked for the icon or title only, it's not needed to check
whether the addon is enabled or disabled all the time.
5c10498
Sascha Montellese move call to GetStreamDetails to CVideoThumbLoader fcb6107
Sascha Montellese recentlyadded: remember the cover and fanart of an album
When retrieving multiple songs of the same album for recently added album
songs, remember the album's cover and fanart and therefore avoid querying
and retrieving the same cover and fanart multiple times.
ea3ea36
Sascha Montellese
Collaborator

OK I re-added the SeasonThumb for recently added episodes and removed that one query for the albumid as it will never be executed anyway.

jmarshallnz
Owner

Looks good - pull it in.

Sascha Montellese
Collaborator

Seeing that you have started working on the real db update fix should I remove that optimization from this PR to save you a rebase?

jmarshallnz
Owner

Doesn't worry me either way - I'm sure before it goes in I'll need to rebase anyway :)

Sascha Montellese Montellese merged commit 35c9f14 into from July 07, 2012
Sascha Montellese Montellese closed this July 07, 2012
Chris Browet
Collaborator

Hi,

It looks that between this and some later thumb loading optimizations, the streamdetails are actually never fetched, and thus streamdetails is always NULL from JSON.

Not sure how to best solve this...

Collaborator

We'll probably have to manually get the stream details for all the video items that JSON-RPC wants to return to the client (but only if streamdetails are requested by the client).

Collaborator

Another solution would be to keep the "GetStreamDetails" as they were, but adding a bool to CVideoInfoTag indicating whether the details were already fetched, to avoid duplicate db fetches (trying this now)

Or do both...

Collaborator

The reason why I moved the call to the thumbloader is that there are several calls to GetMoviesByWhere (and therefore GetDetailsForMovie) which fetch the streamdetails (which causes an additional query and therefore additional processing time) but don't need the streamdetails. The problem isn't knowing whether the streamdetails were already retrieved or not. We want to do as few SQL queries as possible. Making the necessary calls to GetStreamDetails from JSON-RPC will not increase the number of SQL queries compared to how it worked before this commit . There will still be the same amound of SQL queries per movie but they will be triggered from a different location.

Collaborator

Re as few SQL as possible, I understand that.
I meant to do:

bool CVideoDatabase::GetStreamDetails(CVideoInfoTag& tag) const
{
  if (tag.m_iFileId < 0)
    return false;

  if (tag.m_streamDetailsLoaded)
    return tag.m_streamDetails.HasItems();

But, obviously, only retrieving stream details when requested doesn't harm either ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 9 unique commits by 2 authors.

Jul 06, 2012
Sascha Montellese CDatabase: remember the databases we already updated and don't check …
…them on every connect/open
bfafe59
Sascha Montellese videodb: add resumeTimeInSeconds and totalTimeInSeconds to the movie/…
…episode/musicvideo view to eliminate extra queries
5170759
Sascha Montellese videodb: make idSeason available through episodeview b5b9fa8
Jul 07, 2012
Sascha Montellese recentlyadded: save queries for season id and season/show thumbs
Use the idSeason value available through episodeview instead of having to
retrieve it for every episode. Furthermore remember the already retrieved
season/show thumbs to save querying the same images again.
f95c66b
Sascha Montellese recentlyadded: use values from CAlbum instead of manually querying th…
…em one by one for every album
60ba8b1
videodb: do not retrieve streamdetails for set items - the actual str…
…eamdetails will be queried for the single items later on
30e9f45
fixed: do not query the addon state when asking the guiinfomanager fo…
…r addon title and/or icon

This commit removes tons of useless queries made from the mainloop when using addon shortcuts on
the home screen. As the infomanager is asked for the icon or title only, it's not needed to check
whether the addon is enabled or disabled all the time.
5c10498
Sascha Montellese move call to GetStreamDetails to CVideoThumbLoader fcb6107
Sascha Montellese recentlyadded: remember the cover and fanart of an album
When retrieving multiple songs of the same album for recently added album
songs, remember the album's cover and fanart and therefore avoid querying
and retrieving the same cover and fanart multiple times.
ea3ea36
This page is out of date. Refresh to see the latest.
8  xbmc/GUIInfoManager.cpp
@@ -2824,11 +2824,15 @@ CStdString CGUIInfoManager::GetMultiInfoLabel(const GUIInfo &info, int contextWi
2824 2824
   else if (info.m_info == SYSTEM_ADDON_TITLE ||
2825 2825
            info.m_info == SYSTEM_ADDON_ICON)
2826 2826
   {
  2827
+    // This logic does not check/care whether an addon has been disabled/marked as broken,
  2828
+    // it simply retrieves it's name or icon that means if an addon is placed on the home screen it
  2829
+    // will stay there even if it's disabled/marked as broken. This might need to be changed/fixed
  2830
+    // in the future.
2827 2831
     AddonPtr addon;
2828 2832
     if (info.GetData2() == 0)
2829  
-      CAddonMgr::Get().GetAddon(const_cast<CGUIInfoManager*>(this)->GetLabel(info.GetData1(), contextWindow),addon);
  2833
+      CAddonMgr::Get().GetAddon(const_cast<CGUIInfoManager*>(this)->GetLabel(info.GetData1(), contextWindow),addon,ADDON_UNKNOWN,false);
2830 2834
     else
2831  
-      CAddonMgr::Get().GetAddon(m_stringParameters[info.GetData1()],addon);
  2835
+      CAddonMgr::Get().GetAddon(m_stringParameters[info.GetData1()],addon,ADDON_UNKNOWN,false);
2832 2836
     if (addon && info.m_info == SYSTEM_ADDON_TITLE)
2833 2837
       return addon->Name();
2834 2838
     if (addon && info.m_info == SYSTEM_ADDON_ICON)
10  xbmc/ThumbLoader.cpp
@@ -199,12 +199,20 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
199 199
   m_database->Open();
200 200
 
201 201
   // resume point
202  
-  if (pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds == 0)
  202
+  if (pItem->HasVideoInfoTag() &&
  203
+      pItem->GetVideoInfoTag()->m_resumePoint.type != CBookmark::RESUME && pItem->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds == 0)
203 204
   {
204 205
     if (m_database->GetResumePoint(*pItem->GetVideoInfoTag()))
205 206
       pItem->SetInvalid();
206 207
   }
207 208
 
  209
+  if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->HasStreamDetails() &&
  210
+     (pItem->GetVideoInfoTag()->m_type == "movie" || pItem->GetVideoInfoTag()->m_type == "episode" || pItem->GetVideoInfoTag()->m_type == "musicvideo"))
  211
+  {
  212
+    if (m_database->GetStreamDetails(*pItem->GetVideoInfoTag()))
  213
+      pItem->SetInvalid();
  214
+  }
  215
+
208 216
   // video db items normally have info in the database
209 217
   if (pItem->HasVideoInfoTag() && pItem->GetArt().empty())
210 218
   {
9  xbmc/dbwrappers/Database.cpp
@@ -31,6 +31,7 @@
31 31
 #include "utils/URIUtils.h"
32 32
 #include "mysqldataset.h"
33 33
 #include "sqlitedataset.h"
  34
+#include "threads/SingleLock.h"
34 35
 
35 36
 
36 37
 using namespace AUTOPTR;
@@ -38,6 +39,8 @@ using namespace dbiplus;
38 39
 
39 40
 #define MAX_COMPRESS_COUNT 20
40 41
 
  42
+std::map<std::string, bool> CDatabase::m_updated;
  43
+
41 44
 CDatabase::CDatabase(void)
42 45
 {
43 46
   m_openCount = 0;
@@ -437,6 +440,10 @@ bool CDatabase::Connect(const DatabaseSettings &dbSettings, bool create)
437 440
 
438 441
 bool CDatabase::UpdateVersion(const CStdString &dbName)
439 442
 {
  443
+  CSingleLock lock(m_critSect);
  444
+  if (m_updated[dbName])
  445
+    return true;
  446
+
440 447
   int version = 0;
441 448
   m_pDS->query("SELECT idVersion FROM version\n");
442 449
   if (m_pDS->num_rows() > 0)
@@ -458,6 +465,8 @@ bool CDatabase::UpdateVersion(const CStdString &dbName)
458 465
     CLog::Log(LOGERROR, "Can't open the database %s as it is a NEWER version than what we were expecting?", dbName.c_str());
459 466
     return false;
460 467
   }
  468
+
  469
+  m_updated[dbName] = true;
461 470
   return true;
462 471
 }
463 472
 
9  xbmc/dbwrappers/Database.h
@@ -21,6 +21,10 @@
21 21
  *
22 22
  */
23 23
 
  24
+#include <map>
  25
+#include <memory>
  26
+
  27
+#include "threads/CriticalSection.h"
24 28
 #include "utils/StdString.h"
25 29
 
26 30
 namespace dbiplus {
@@ -28,8 +32,6 @@ namespace dbiplus {
28 32
   class Dataset;
29 33
 }
30 34
 
31  
-#include <memory>
32  
-
33 35
 class DatabaseSettings; // forward
34 36
 
35 37
 class CDatabase
@@ -139,4 +141,7 @@ class CDatabase
139 141
 
140 142
   bool m_bMultiWrite; /*!< True if there are any queries in the queue, false otherwise */
141 143
   unsigned int m_openCount;
  144
+
  145
+  CCriticalSection m_critSect;
  146
+  static std::map<std::string, bool> m_updated;
142 147
 };
55  xbmc/utils/RecentlyAddedJob.cpp
@@ -100,7 +100,8 @@ bool CRecentlyAddedJob::UpdateVideo()
100 100
   CFileItemList  TVShowItems; 
101 101
  
102 102
   if (videodatabase.GetRecentlyAddedEpisodesNav("videodb://5/", TVShowItems, NUM_ITEMS))
103  
-  {  
  103
+  {
  104
+    std::map<int, std::string> showThumbs;
104 105
     for (; i < TVShowItems.Size(); ++i)
105 106
     {    
106 107
       CFileItemPtr item          = TVShowItems.Get(i);
@@ -109,7 +110,6 @@ bool CRecentlyAddedJob::UpdateVideo()
109 110
       CStdString   EpisodeNo;
110 111
       CStdString   value;
111 112
       CStdString   strRating;
112  
-      CStdString   strSeason;
113 113
       EpisodeNo.Format("s%02de%02d", EpisodeSeason, EpisodeNumber);
114 114
       value.Format("%i", i + 1);
115 115
       strRating.Format("%.1f", item->GetVideoInfoTag()->m_fRating);
@@ -128,9 +128,22 @@ bool CRecentlyAddedJob::UpdateVideo()
128 128
       if (!item->HasThumbnail())
129 129
         m_thumbLoader.LoadItem(item.get());
130 130
 
131  
-      int seasonID = videodatabase.GetSeasonId(item->GetVideoInfoTag()->m_iIdShow, EpisodeSeason);
132  
-      std::string seasonThumb = videodatabase.GetArtForItem(seasonID, "season", "thumb");
133  
-      std::string showThumb = videodatabase.GetArtForItem(item->GetVideoInfoTag()->m_iIdShow, "tvshow", "thumb");
  131
+      std::string showThumb;
  132
+      if (item->GetVideoInfoTag()->m_iIdShow > 0)
  133
+      {
  134
+        std::map<int, std::string>::const_iterator thumbIter;
  135
+        if ((thumbIter = showThumbs.find(item->GetVideoInfoTag()->m_iIdShow)) != showThumbs.end())
  136
+          showThumb = thumbIter->second;
  137
+        else
  138
+        {
  139
+          showThumb = videodatabase.GetArtForItem(item->GetVideoInfoTag()->m_iIdShow, "tvshow", "thumb");
  140
+          showThumbs[item->GetVideoInfoTag()->m_iIdShow] = showThumb;
  141
+        }
  142
+      }
  143
+
  144
+      std::string seasonThumb;
  145
+      if (item->GetVideoInfoTag()->m_iIdSeason > 0)
  146
+        seasonThumb = videodatabase.GetArtForItem(item->GetVideoInfoTag()->m_iIdSeason, "season", "thumb");
134 147
 
135 148
       home->SetProperty("LatestEpisode." + value + ".Thumb"         , item->GetThumbnailImage());
136 149
       home->SetProperty("LatestEpisode." + value + ".ShowThumb"     , showThumb);
@@ -216,9 +229,12 @@ bool CRecentlyAddedJob::UpdateMusic()
216 229
   musicdatabase.Open();
217 230
   
218 231
   if (musicdatabase.GetRecentlyAddedAlbumSongs("musicdb://", musicItems, NUM_ITEMS))
219  
-  { 
  232
+  {
  233
+    long idAlbum = -1;
  234
+    CStdString strAlbumThumb;
  235
+    CStdString strAlbumFanart;
220 236
     for (; i < musicItems.Size(); ++i)
221  
-    {  
  237
+    {
222 238
       CFileItemPtr item = musicItems.Get(i);
223 239
       CStdString   value;
224 240
       value.Format("%i", i + 1);
@@ -226,8 +242,19 @@ bool CRecentlyAddedJob::UpdateMusic()
226 242
       CStdString   strRating;
227 243
       CStdString   strAlbum  = item->GetMusicInfoTag()->GetAlbum();
228 244
       CStdString   strArtist = StringUtils::Join(item->GetMusicInfoTag()->GetArtist(), g_advancedSettings.m_musicItemSeparator);
229  
-      
230  
-      loader.LoadItem(item.get());
  245
+
  246
+      if (idAlbum != item->GetMusicInfoTag()->GetAlbumId())
  247
+      {
  248
+        strAlbumThumb.clear();
  249
+        strAlbumFanart.clear();
  250
+        idAlbum = item->GetMusicInfoTag()->GetAlbumId();
  251
+
  252
+        if (loader.LoadItem(item.get()))
  253
+        {
  254
+          strAlbumThumb = item->GetThumbnailImage();
  255
+          strAlbumFanart = item->GetProperty("fanart_image").asString();
  256
+        }
  257
+      }
231 258
 
232 259
       strRating.Format("%c", item->GetMusicInfoTag()->GetRating());
233 260
       
@@ -237,8 +264,8 @@ bool CRecentlyAddedJob::UpdateMusic()
237 264
       home->SetProperty("LatestSong." + value + ".Album"   , strAlbum);
238 265
       home->SetProperty("LatestSong." + value + ".Rating"  , strRating);
239 266
       home->SetProperty("LatestSong." + value + ".Path"    , item->GetMusicInfoTag()->GetURL());
240  
-      home->SetProperty("LatestSong." + value + ".Thumb"   , item->GetThumbnailImage());
241  
-      home->SetProperty("LatestSong." + value + ".Fanart"  , item->GetProperty("fanart_image"));
  267
+      home->SetProperty("LatestSong." + value + ".Thumb"   , strAlbumThumb);
  268
+      home->SetProperty("LatestSong." + value + ".Fanart"  , strAlbumFanart);
242 269
     }
243 270
   }
244 271
   for (; i < NUM_ITEMS; ++i)
@@ -278,10 +305,10 @@ bool CRecentlyAddedJob::UpdateMusic()
278 305
       
279 306
       CStdString strArtist = musicdatabase.GetSingleValue("albumview", "strArtists", strSQLAlbum);
280 307
       
281  
-      home->SetProperty("LatestAlbum." + value + ".Title"   , musicdatabase.GetAlbumById(album.idAlbum));
282  
-      home->SetProperty("LatestAlbum." + value + ".Year"    , atoi(musicdatabase.GetSingleValue("album", "iYear", strSQLAlbum)));
  308
+      home->SetProperty("LatestAlbum." + value + ".Title"   , album.strAlbum);
  309
+      home->SetProperty("LatestAlbum." + value + ".Year"    , album.iYear);
283 310
       home->SetProperty("LatestAlbum." + value + ".Artist"  , strArtist);      
284  
-      home->SetProperty("LatestAlbum." + value + ".Rating"  , musicdatabase.GetSingleValue("albumview", "iRating", strSQLAlbum));
  311
+      home->SetProperty("LatestAlbum." + value + ".Rating"  , album.iRating);
285 312
       home->SetProperty("LatestAlbum." + value + ".Path"    , strDBpath);
286 313
       home->SetProperty("LatestAlbum." + value + ".Thumb"   , strThumb);
287 314
       home->SetProperty("LatestAlbum." + value + ".Fanart"  , strFanart);
44  xbmc/video/VideoDatabase.cpp
@@ -349,14 +349,21 @@ void CVideoDatabase::CreateViews()
349 349
                                       "  tvshow.c%02d AS strStudio,"
350 350
                                       "  tvshow.c%02d AS premiered,"
351 351
                                       "  tvshow.c%02d AS mpaa,"
352  
-                                      "  tvshow.c%02d AS strShowPath "
  352
+                                      "  tvshow.c%02d AS strShowPath, "
  353
+                                      "  bookmark.timeInSeconds AS resumeTimeInSeconds, "
  354
+                                      "  bookmark.totalTimeInSeconds AS totalTimeInSeconds, "
  355
+                                      "  seasons.idSeason AS idSeason "
353 356
                                       "FROM episode"
354 357
                                       "  JOIN files ON"
355 358
                                       "    files.idFile=episode.idFile"
356 359
                                       "  JOIN tvshow ON"
357 360
                                       "    tvshow.idShow=episode.idShow"
  361
+                                      "  LEFT JOIN seasons ON"
  362
+                                      "    seasons.idShow=episode.idShow AND seasons.season=episode.c%02d"
358 363
                                       "  JOIN path ON"
359  
-                                      "    files.idPath=path.idPath", VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_STUDIOS, VIDEODB_ID_TV_PREMIERED, VIDEODB_ID_TV_MPAA, VIDEODB_ID_TV_BASEPATH);
  364
+                                      "    files.idPath=path.idPath"
  365
+                                      "  LEFT JOIN bookmark ON"
  366
+                                      "    bookmark.idFile=episode.idFile AND bookmark.type=1", VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_STUDIOS, VIDEODB_ID_TV_PREMIERED, VIDEODB_ID_TV_MPAA, VIDEODB_ID_TV_BASEPATH, VIDEODB_ID_EPISODE_SEASON);
360 367
   m_pDS->exec(episodeview.c_str());
361 368
 
362 369
   CLog::Log(LOGINFO, "create tvshowview");
@@ -388,12 +395,16 @@ void CVideoDatabase::CreateViews()
388 395
               "  path.strPath as strPath,"
389 396
               "  files.playCount as playCount,"
390 397
               "  files.lastPlayed as lastPlayed,"
391  
-              "  files.dateAdded as dateAdded "
  398
+              "  files.dateAdded as dateAdded, "
  399
+              "  bookmark.timeInSeconds AS resumeTimeInSeconds, "
  400
+              "  bookmark.totalTimeInSeconds AS totalTimeInSeconds "
392 401
               "FROM musicvideo"
393 402
               "  JOIN files ON"
394 403
               "    files.idFile=musicvideo.idFile"
395 404
               "  JOIN path ON"
396  
-              "    path.idPath=files.idPath");
  405
+              "    path.idPath=files.idPath"
  406
+              "  LEFT JOIN bookmark ON"
  407
+              "    bookmark.idFile=musicvideo.idFile AND bookmark.type=1");
397 408
 
398 409
   CLog::Log(LOGINFO, "create movieview");
399 410
   m_pDS->exec("DROP VIEW IF EXISTS movieview");
@@ -403,12 +414,16 @@ void CVideoDatabase::CreateViews()
403 414
               "  path.strPath AS strPath,"
404 415
               "  files.playCount AS playCount,"
405 416
               "  files.lastPlayed AS lastPlayed, "
406  
-              "  files.dateAdded AS dateAdded "
  417
+              "  files.dateAdded AS dateAdded, "
  418
+              "  bookmark.timeInSeconds AS resumeTimeInSeconds, "
  419
+              "  bookmark.totalTimeInSeconds AS totalTimeInSeconds "
407 420
               "FROM movie"
408 421
               "  JOIN files ON"
409 422
               "    files.idFile=movie.idFile"
410 423
               "  JOIN path ON"
411  
-              "    path.idPath=files.idPath");
  424
+              "    path.idPath=files.idPath"
  425
+              "  LEFT JOIN bookmark ON"
  426
+              "    bookmark.idFile=movie.idFile AND bookmark.type=1");
412 427
 }
413 428
 
414 429
 //********************************************************************************************************************************
@@ -3025,11 +3040,8 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons
3025 3040
   GetCommonDetails(record, details);
3026 3041
   movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis();
3027 3042
 
3028  
-  GetStreamDetails(details);
3029  
-
3030 3043
   if (needsCast)
3031 3044
   {
3032  
-    GetResumePoint(details);
3033 3045
     GetCast("movie", "idMovie", details.m_iDbId, details.m_cast);
3034 3046
 
3035 3047
     castTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis();
@@ -3130,14 +3142,16 @@ CVideoInfoTag CVideoDatabase::GetDetailsForEpisode(const dbiplus::sql_record* co
3130 3142
   details.m_premiered.SetFromDBDate(record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_AIRED).get_asString());
3131 3143
   details.m_iIdShow = record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt();
3132 3144
   details.m_strShowPath = record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_PATH).get_asString();
  3145
+  details.m_iIdSeason = record->at(VIDEODB_DETAILS_EPISODE_SEASON_ID).get_asInt();
3133 3146
 
3134  
-  movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis();
  3147
+  details.m_resumePoint.timeInSeconds = record->at(VIDEODB_DETAILS_EPISODE_RESUME_TIME).get_asInt();
  3148
+  details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_EPISODE_TOTAL_TIME).get_asInt();
  3149
+  details.m_resumePoint.type = CBookmark::RESUME;
3135 3150
 
3136  
-  GetStreamDetails(details);
  3151
+  movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis();
3137 3152
 
3138 3153
   if (needsCast)
3139 3154
   {
3140  
-    GetResumePoint(details);
3141 3155
     GetCast("episode", "idEpisode", details.m_iDbId, details.m_cast);
3142 3156
     GetCast("tvshow", "idShow", details.m_iIdShow, details.m_cast);
3143 3157
 
@@ -3170,9 +3184,6 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMusicVideo(const dbiplus::sql_record*
3170 3184
   GetCommonDetails(record, details);
3171 3185
   movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis();
3172 3186
 
3173  
-  GetStreamDetails(details);
3174  
-  GetResumePoint(details);
3175  
-
3176 3187
   details.m_strPictureURL.Parse();
3177 3188
   return details;
3178 3189
 }
@@ -3191,6 +3202,9 @@ void CVideoDatabase::GetCommonDetails(const dbiplus::sql_record* const record, C
3191 3202
   details.m_playCount = record->at(VIDEODB_DETAILS_PLAYCOUNT).get_asInt();
3192 3203
   details.m_lastPlayed.SetFromDBDateTime(record->at(VIDEODB_DETAILS_LASTPLAYED).get_asString());
3193 3204
   details.m_dateAdded.SetFromDBDateTime(record->at(VIDEODB_DETAILS_DATEADDED).get_asString());
  3205
+  details.m_resumePoint.timeInSeconds = record->at(VIDEODB_DETAILS_RESUME_TIME).get_asInt();
  3206
+  details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_TOTAL_TIME).get_asInt();
  3207
+  details.m_resumePoint.type = CBookmark::RESUME;
3194 3208
 }
3195 3209
 
3196 3210
 void CVideoDatabase::GetCast(const CStdString &table, const CStdString &table_id, int type_id, vector<SActorInfo> &cast)
9  xbmc/video/VideoDatabase.h
@@ -73,6 +73,8 @@ namespace VIDEO
73 73
 #define VIDEODB_DETAILS_PLAYCOUNT		VIDEODB_MAX_COLUMNS + 4
74 74
 #define VIDEODB_DETAILS_LASTPLAYED		VIDEODB_MAX_COLUMNS + 5
75 75
 #define VIDEODB_DETAILS_DATEADDED		VIDEODB_MAX_COLUMNS + 6
  76
+#define VIDEODB_DETAILS_RESUME_TIME		VIDEODB_MAX_COLUMNS + 7
  77
+#define VIDEODB_DETAILS_TOTAL_TIME		VIDEODB_MAX_COLUMNS + 8
76 78
 
77 79
 #define VIDEODB_DETAILS_EPISODE_TVSHOW_ID     VIDEODB_MAX_COLUMNS + 2
78 80
 #define VIDEODB_DETAILS_EPISODE_FILE          VIDEODB_MAX_COLUMNS + 3
@@ -85,6 +87,9 @@ namespace VIDEO
85 87
 #define VIDEODB_DETAILS_EPISODE_TVSHOW_AIRED  VIDEODB_MAX_COLUMNS + 10
86 88
 #define VIDEODB_DETAILS_EPISODE_TVSHOW_MPAA   VIDEODB_MAX_COLUMNS + 11
87 89
 #define VIDEODB_DETAILS_EPISODE_TVSHOW_PATH   VIDEODB_MAX_COLUMNS + 12
  90
+#define VIDEODB_DETAILS_EPISODE_RESUME_TIME   VIDEODB_MAX_COLUMNS + 13
  91
+#define VIDEODB_DETAILS_EPISODE_TOTAL_TIME    VIDEODB_MAX_COLUMNS + 14
  92
+#define VIDEODB_DETAILS_EPISODE_SEASON_ID     VIDEODB_MAX_COLUMNS + 15
88 93
 						
89 94
 #define VIDEODB_DETAILS_TVSHOW_PATH		VIDEODB_MAX_COLUMNS + 1
90 95
 #define VIDEODB_DETAILS_TVSHOW_DATEADDED		VIDEODB_MAX_COLUMNS + 2
@@ -473,6 +478,7 @@ class CVideoDatabase : public CDatabase
473 478
   void AddBookMarkForEpisode(const CVideoInfoTag& tag, const CBookmark& bookmark);
474 479
   void DeleteBookMarkForEpisode(const CVideoInfoTag& tag);
475 480
   bool GetResumePoint(CVideoInfoTag& tag);
  481
+  bool GetStreamDetails(CVideoInfoTag& tag) const;
476 482
 
477 483
   // scraper settings
478 484
   void SetScraperForPath(const CStdString& filePath, const ADDON::ScraperPtr& info, const VIDEO::SScanSettings& settings);
@@ -751,7 +757,6 @@ class CVideoDatabase : public CDatabase
751 757
   void GetDetailsFromDB(std::auto_ptr<dbiplus::Dataset> &pDS, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset = 2);
752 758
   void GetDetailsFromDB(const dbiplus::sql_record* const record, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset = 2);
753 759
   CStdString GetValueString(const CVideoInfoTag &details, int min, int max, const SDbTableOffsets *offsets) const;
754  
-  bool GetStreamDetails(CVideoInfoTag& tag) const;
755 760
 
756 761
 private:
757 762
   virtual bool CreateTables();
@@ -794,7 +799,7 @@ class CVideoDatabase : public CDatabase
794 799
    */
795 800
   bool LookupByFolders(const CStdString &path, bool shows = false);
796 801
 
797  
-  virtual int GetMinVersion() const { return 64; };
  802
+  virtual int GetMinVersion() const { return 66; };
798 803
   virtual int GetExportVersion() const { return 1; };
799 804
   const char *GetBaseDBName() const { return "MyVideos"; };
800 805
 
4  xbmc/video/VideoInfoTag.cpp
@@ -89,6 +89,7 @@ void CVideoInfoTag::Reset()
89 89
   m_resumePoint.Reset();
90 90
   m_resumePoint.type = CBookmark::RESUME;
91 91
   m_iIdShow = -1;
  92
+  m_iIdSeason = -1;
92 93
   m_strShowPath.clear();
93 94
   m_dateAdded.Reset();
94 95
   m_type.clear();
@@ -329,6 +330,7 @@ void CVideoInfoTag::Archive(CArchive& ar)
329 330
     ar << m_strShowPath;
330 331
     ar << m_dateAdded.GetAsDBDateTime();
331 332
     ar << m_type;
  333
+    ar << m_iIdSeason;
332 334
   }
333 335
   else
334 336
   {
@@ -407,6 +409,7 @@ void CVideoInfoTag::Archive(CArchive& ar)
407 409
     ar >> dateAdded;
408 410
     m_dateAdded.SetFromDBDateTime(dateAdded);
409 411
     ar >> m_type;
  412
+    ar >> m_iIdSeason;
410 413
   }
411 414
 }
412 415
 
@@ -476,6 +479,7 @@ void CVideoInfoTag::Serialize(CVariant& value)
476 479
   value["tvshowpath"] = m_strShowPath;
477 480
   value["dateadded"] = m_dateAdded.IsValid() ? m_dateAdded.GetAsDBDateTime() : StringUtils::EmptyString;
478 481
   value["type"] = m_type;
  482
+  value["seasonid"] = m_iIdSeason;
479 483
 }
480 484
 
481 485
 void CVideoInfoTag::ToSortable(SortItem& sortable)
1  xbmc/video/VideoInfoTag.h
@@ -129,6 +129,7 @@ class CVideoInfoTag : public IArchivable, public ISerializable, public ISortable
129 129
   float m_fEpBookmark;
130 130
   int m_iBookmarkId;
131 131
   int m_iIdShow;
  132
+  int m_iIdSeason;
132 133
   CFanart m_fanart;
133 134
   CStreamDetails m_streamDetails;
134 135
   CBookmark m_resumePoint;
6  xbmc/video/dialogs/GUIDialogVideoInfo.cpp
@@ -301,8 +301,10 @@ void CGUIDialogVideoInfo::SetMovie(const CFileItem *item)
301 301
       {
302 302
         if (m_movieItem->GetVideoInfoTag()->m_iSeason > -1)
303 303
         {
304  
-          int seasonID = db.GetSeasonId(m_movieItem->GetVideoInfoTag()->m_iIdShow,
305  
-                                        m_movieItem->GetVideoInfoTag()->m_iSeason);
  304
+          int seasonID = m_movieItem->GetVideoInfoTag()->m_iIdSeason;
  305
+          if (seasonID < 0)
  306
+            seasonID = db.GetSeasonId(m_movieItem->GetVideoInfoTag()->m_iIdShow,
  307
+                                      m_movieItem->GetVideoInfoTag()->m_iSeason);
306 308
           string thumb = db.GetArtForItem(seasonID, "season", "thumb");
307 309
           if (!thumb.empty())
308 310
             m_movieItem->SetProperty("seasonthumb", thumb);
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.