xbmc/xbmc — pull request #1150 by Montellese (2012-07-12 11:32:37+00:00)
Title: [GSoC] videodb:// URL extensions

This is more of an RFC for now because I have only discussed the idea with @jmarshallnz in the context of my GSoC work. There are two "problems" that this work tries (and succeeds) to solve:

1. When e.g. making a smartplaylist with the rule "Director contains James Cameron" and the user has a "Terminator Collection" set (as provided by TMDb) containing all four Terminator movies, the resulting list will show the "Terminator Collection" set in the list (and not the individual movies). When entering the set it will show all 4 movies even though only the first two Terminator movies were directed by James Cameron while the last two were not. The same result can be achieved by going to Videos -> Library -> Movies -> Directors -> James Cameron. The problem is that when retrieving the movies in the set we don't know about the previously applied filter(s) and simply ignore them and retrieve all movies belonging to the set.
2. In my GSoC work for advanced filtering I use a smartplaylist which contains all the filters specified by the user. This works great for movies, tvshows and musicvideos but doesn't really work for episodes because in the GUI they are "pre-filtered" by tvshow and season. But the advanced filter has no clue about this pre-filtering because it's only really visible in the videodb:// URL of those items (which is used by CVideoDatabaseDirectory et. al.) and nowhere else.

To solve these two problems (which also apply to the music database, but I started with the video database as a proof-of-concept) I have added two classes CDbUrl and CVideoDbUrl (derived from CDbUrl) which are meant to handle and extend a videodb:// URL with additional information about the current context. The current URL schema is not changed but in addition GET options are added so when e.g. viewing all movies directed by James Cameron through Videos -> Library -> Movies -> Directors -> James Cameron the resulting URL will look like this: videodb://1/5/1234/?directorid=1234. When the user then enters the "Terminator Collection" set, that CFileItem will have the URL videodb://1/7/5678/?directorid=1234 and therefore knows that it also has to filter by the director with ID 1234 (which is James Cameron in this example). Adding those options is done in CVideoDatabase::GetFooNav() etc and the handling of those options is done in CVideoDatabase::GetFooByWhere() etc by first parsing the videodb:// URL using CVideoDbUrl::FromString and then calling CVideoDatabase::GetFilter() which will put together all the JOIN/WHERE SQL clauses necessary to do the proper filtering.
To also cover filtering by a smartplaylist, the smartplaylist is converted into a CVariant object and then serialized as a JSON object and that JSON object (or rather its string representation) is then added as an option to the videodb:// URL. I went with a JSON representation because it is less verbose than XML and a lot easier to read (although this might only come in handy during debugging).

The disadvantages of this approach are that the URLs can get rather long (but we never output them to the user) and that it is more crucial to actually provide to correct base path when calling CVideoDatabase::GetFooNav(). The second disadvantage might however actually be an advantage because it will make it easier to hunt down incorrectly provided base paths (e.g. videodb://1/1/ instead of videodb://1/2/ for the retrieval of all movie titles).