Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Video library reorganisation via XML #903

Merged
merged 10 commits into from

3 participants

@jmarshallnz
Owner

This is v2 of the original #335. This allows the addition of (or removal of) nodes in the video library. By default nothing should change (even library flattening is implemented).

There's a couple of gotchas:

  1. Smartplaylists don't support proper sorting of sets - this is an existing problem in mainline, which is why 8cb48681 is in place. This could be dropped later when the sorting is fixed (problem is that the set items don't have the appropriate metadata associated, so sort on top). It may be that we need to readdress (yet again) the grouping of sets in certain nodes. It may be that this is something that @Montellese GSoC may look into?

  2. The sorting of nodes is done via the order attribute inside the XMLs. I'm not sure if this is the most intuitive way to do it or not. An alternative is to sort by filesystem order (i.e. just name them as 01genres.xml etc.)

  3. The flattening is a bit of a hack (2 directory structures in place) but I figured it was better to get this in while we can so we can see what other things folk will want rather than waiting until a more friendly way to setup the structure was in place. Again, perhaps @Montellese GSoC may address this by making it available via JSON-RPC then the web-interface.

Would like this in May :)

@sholafsson

I had a little play, this is simply a thing of beauty.
Is it possible that type filter and folder have different sorting options available?

@Montellese
Owner

I really like this, excellent work. If we could get smartplaylists to behave (almost) the same as our CVideoDatabase::GetFooNav() methods we could actually get rid of most of the < path > tags and define those as filters as well.

  1. This brings us back to the discussion in #824 about a grouping step before doing the sorting. I think the custom sorting implementation for SmartPlaylists is one of the problems because it doesn't support things like "ignore article" etc. But without it the whole limiting functionality is kind of useless as we would still need to get all the matching items from the database, then do manual sorting and then apply the limiting which slows things done if we e.g. only want to retrieve 10 out of 2000 songs.

  2. Yup this is not very intuitive IMO as you have to open every XML to get an idea of what comes after what in the list. Sorting alphanumerically by filename in combination with XX_foo.xml or XXfoo.xml (where XX is a number) probably gives to fastest and simplest overview when looking at the XMLs. But I have to admit that the "order" attribute looks cleaner.

  3. I probably should have made that comment (jmarshallnz@59b2222#commitcomment-1271352) here instead. Not sure what you mean concerning JSON-RPC and the webinterface?

@jmarshallnz
Owner

Regarding JSON-RPC/web-interface, a UI to allow the user to more easily modify things is probably beyond XBMC's UI - in particular you'd really want drag n drop support and/or a rat + keyboard. A web interface might be able to do it quite nicely though, assuming things like lists with drag n drop are supportable (one presumes there's a bunch of js that could be used). It would be difficult I think to support both a mouse/touch based interface for it in XBMC while still allowing a remote control style interface as well, though perhaps that's something we'll need in future anyway...

@jmarshallnz
Owner

Thanks for the review @Montellese and @Memphiz. Fixups applied + rebased.

I still want to check number 4 above before this goes in, and need to see whether number 2 needs doing a different way (hard to know really - we need to read the XMLs to list anyway, so sort order on the filesystem isn't necessarily that important. However, given that the user will be expected initially to manipulate the filesystem to do their thing, maybe it should be the other way around?)

@jmarshallnz jmarshallnz was assigned
@jmarshallnz
Owner

Ok, rebased again and eliminated the issue where a filter and virtual folder were named the same without the .xml extension - just distinguish between library://video/path/folder/ and library://video/path/folder.xml/ now.

The last question is whether I need to bother with rehashing the order thing. IMO what we have is fine.

@Montellese
Owner

I won't stand in the way concerning how ordering is done. For a quick overview doing it based on the filename is better but having to rename all your files everytime you want to add something in between isn't a nice prospect either.

@jmarshallnz jmarshallnz merged commit 691095a into xbmc:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 1, 2012
  1. initial implementation of library structure from xml

    Jonathan Marshall authored
  2. add viewstate for library:// nodes

    Jonathan Marshall authored
  3. fix const'ness of SmartPlaylist functions

    Jonathan Marshall authored
  4. refactor smartplaylist loading so we can pass XML in directly to fetc…

    Jonathan Marshall authored
    …h a directory
  5. add support for filter nodes in the XML library layout

    Jonathan Marshall authored
  6. make movie sets conditional

    Jonathan Marshall authored
  7. new XML files for lib layout

    Jonathan Marshall authored
  8. enable the library via xml

    Jonathan Marshall authored
  9. add flattened version of video library structure

    Jonathan Marshall authored
  10. use videodb:// urls for recentlyadded until the smartplaylist/sets so…

    Jonathan Marshall authored
    …rting issues are... sorted
This page is out of date. Refresh to see the latest.
Showing with 570 additions and 57 deletions.
  1. +6 −0 XBMC-ATV2.xcodeproj/project.pbxproj
  2. +6 −0 XBMC-IOS.xcodeproj/project.pbxproj
  3. +8 −0 XBMC.xcodeproj/project.pbxproj
  4. +2 −0  project/VS2010Express/XBMC.vcxproj
  5. +6 −0 project/VS2010Express/XBMC.vcxproj.filters
  6. +5 −0 system/library/video/addons.xml
  7. +5 −0 system/library/video/files.xml
  8. +6 −0 system/library/video/movies/actors.xml
  9. +5 −0 system/library/video/movies/country.xml
  10. +5 −0 system/library/video/movies/directors.xml
  11. +5 −0 system/library/video/movies/genres.xml
  12. +5 −0 system/library/video/movies/index.xml
  13. +5 −0 system/library/video/movies/sets.xml
  14. +5 −0 system/library/video/movies/studios.xml
  15. +5 −0 system/library/video/movies/titles.xml
  16. +6 −0 system/library/video/movies/years.xml
  17. +5 −0 system/library/video/musicvideos/albums.xml
  18. +5 −0 system/library/video/musicvideos/artists.xml
  19. +5 −0 system/library/video/musicvideos/directors.xml
  20. +5 −0 system/library/video/musicvideos/genres.xml
  21. +4 −0 system/library/video/musicvideos/index.xml
  22. +5 −0 system/library/video/musicvideos/studios.xml
  23. +5 −0 system/library/video/musicvideos/titles.xml
  24. +5 −0 system/library/video/musicvideos/years.xml
  25. +5 −0 system/library/video/playlists.xml
  26. +5 −0 system/library/video/recentlyaddedepisodes.xml
  27. +5 −0 system/library/video/recentlyaddedmovies.xml
  28. +5 −0 system/library/video/recentlyaddedmusicvideos.xml
  29. +5 −0 system/library/video/tvshows/actors.xml
  30. +5 −0 system/library/video/tvshows/genres.xml
  31. +4 −0 system/library/video/tvshows/index.xml
  32. +5 −0 system/library/video/tvshows/studios.xml
  33. +5 −0 system/library/video/tvshows/titles.xml
  34. +5 −0 system/library/video/tvshows/years.xml
  35. +5 −0 system/library/video_flat/addons.xml
  36. +5 −0 system/library/video_flat/files.xml
  37. +5 −0 system/library/video_flat/movies.xml
  38. +5 −0 system/library/video_flat/musicvideos.xml
  39. +5 −0 system/library/video_flat/playlists.xml
  40. +5 −0 system/library/video_flat/recentlyaddedepisodes.xml
  41. +5 −0 system/library/video_flat/recentlyaddedmovies.xml
  42. +5 −0 system/library/video_flat/recentlyaddedmusicvideos.xml
  43. +5 −0 system/library/video_flat/tvshows.xml
  44. +18 −0 xbmc/GUIInfoManager.cpp
  45. +7 −5 xbmc/GUIInfoManager.h
  46. +20 −1 xbmc/GUIViewState.cpp
  47. +9 −0 xbmc/GUIViewState.h
  48. +2 −0  xbmc/filesystem/DirectoryFactory.cpp
  49. +184 −0 xbmc/filesystem/LibraryDirectory.cpp
  50. +52 −0 xbmc/filesystem/LibraryDirectory.h
  51. +1 −0  xbmc/filesystem/Makefile.in
  52. +23 −11 xbmc/filesystem/SmartPlaylistDirectory.cpp
  53. +4 −0 xbmc/filesystem/SmartPlaylistDirectory.h
  54. +16 −7 xbmc/playlists/SmartPlayList.cpp
  55. +8 −7 xbmc/playlists/SmartPlayList.h
  56. +8 −26 xbmc/video/GUIViewStateVideo.cpp
View
6 XBMC-ATV2.xcodeproj/project.pbxproj
@@ -24,6 +24,7 @@
7C0A7FC913A9E75400AFC2BD /* DirtyRegionTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7FC613A9E75400AFC2BD /* DirtyRegionTracker.cpp */; };
7C0A7FCC13A9E76E00AFC2BD /* GUIWindowDebugInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7FCA13A9E76E00AFC2BD /* GUIWindowDebugInfo.cpp */; };
7C1A89BB152671FB00C63311 /* TextureCacheJob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A89B9152671FB00C63311 /* TextureCacheJob.cpp */; };
+ 7C1F6F8C13ED17CC001726AB /* LibraryDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1F6F8A13ED17CC001726AB /* LibraryDirectory.cpp */; };
7C89627013B702F3003631FE /* GUIWindowScreensaverDim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89626E13B702F3003631FE /* GUIWindowScreensaverDim.cpp */; };
7C99B7AA134072CD00FC2B16 /* GUIDialogPlayEject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C99B7A8134072CD00FC2B16 /* GUIDialogPlayEject.cpp */; };
7CCFD9AA1514952700211D82 /* PCMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CCFD9A81514952700211D82 /* PCMCodec.cpp */; };
@@ -1004,6 +1005,8 @@
7C0A7FCB13A9E76E00AFC2BD /* GUIWindowDebugInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowDebugInfo.h; sourceTree = "<group>"; };
7C1A89B9152671FB00C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; };
7C1A89BA152671FB00C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; };
+ 7C1F6F8A13ED17CC001726AB /* LibraryDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LibraryDirectory.cpp; sourceTree = "<group>"; };
+ 7C1F6F8B13ED17CC001726AB /* LibraryDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LibraryDirectory.h; sourceTree = "<group>"; };
7C89626E13B702F3003631FE /* GUIWindowScreensaverDim.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIWindowScreensaverDim.cpp; sourceTree = "<group>"; };
7C89626F13B702F3003631FE /* GUIWindowScreensaverDim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowScreensaverDim.h; sourceTree = "<group>"; };
7C99B7A8134072CD00FC2B16 /* GUIDialogPlayEject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogPlayEject.cpp; sourceTree = "<group>"; };
@@ -4213,6 +4216,8 @@
F56C7402131EC151000AD0F6 /* LastFMDirectory.h */,
DF93D74E1444B09C007C6459 /* LastFMFile.cpp */,
DF93D74F1444B09C007C6459 /* LastFMFile.h */,
+ 7C1F6F8A13ED17CC001726AB /* LibraryDirectory.cpp */,
+ 7C1F6F8B13ED17CC001726AB /* LibraryDirectory.h */,
DFDB00471516408F005079A4 /* MemBufferCache.cpp */,
DFDB00481516408F005079A4 /* MemBufferCache.h */,
F56C7403131EC151000AD0F6 /* MultiPathDirectory.cpp */,
@@ -7090,6 +7095,7 @@
DFFD594F1506B6300088DE4B /* IOSEAGLView.mm in Sources */,
DFFEFBDB151606CB001294DC /* IOSScreenManager.mm in Sources */,
DFFEFC2215160927001294DC /* IOSExternalTouchController.mm in Sources */,
+ 7C1F6F8C13ED17CC001726AB /* LibraryDirectory.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
6 XBMC-IOS.xcodeproj/project.pbxproj
@@ -25,6 +25,7 @@
7C0A7FB213A9E72E00AFC2BD /* DirtyRegionSolvers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7FAE13A9E72E00AFC2BD /* DirtyRegionSolvers.cpp */; };
7C0A7FB313A9E72E00AFC2BD /* DirtyRegionTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7FB013A9E72E00AFC2BD /* DirtyRegionTracker.cpp */; };
7C1A89CE1526722200C63311 /* TextureCacheJob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A89CC1526722200C63311 /* TextureCacheJob.cpp */; };
+ 7C1F6F7A13ED178F001726AB /* LibraryDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1F6F7813ED178F001726AB /* LibraryDirectory.cpp */; };
7C89628013B7031E003631FE /* GUIWindowScreensaverDim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89627E13B7031E003631FE /* GUIWindowScreensaverDim.cpp */; };
7C99B7BE1340730000FC2B16 /* GUIDialogPlayEject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C99B7BC1340730000FC2B16 /* GUIDialogPlayEject.cpp */; };
7CCFD9991514950700211D82 /* PCMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CCFD9971514950700211D82 /* PCMCodec.cpp */; };
@@ -1004,6 +1005,8 @@
7C0A7FB113A9E72E00AFC2BD /* DirtyRegionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirtyRegionTracker.h; sourceTree = "<group>"; };
7C1A89CC1526722200C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; };
7C1A89CD1526722200C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; };
+ 7C1F6F7813ED178F001726AB /* LibraryDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LibraryDirectory.cpp; sourceTree = "<group>"; };
+ 7C1F6F7913ED178F001726AB /* LibraryDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LibraryDirectory.h; sourceTree = "<group>"; };
7C89627E13B7031E003631FE /* GUIWindowScreensaverDim.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIWindowScreensaverDim.cpp; sourceTree = "<group>"; };
7C89627F13B7031E003631FE /* GUIWindowScreensaverDim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowScreensaverDim.h; sourceTree = "<group>"; };
7C99B7BC1340730000FC2B16 /* GUIDialogPlayEject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogPlayEject.cpp; sourceTree = "<group>"; };
@@ -4569,6 +4572,8 @@
F56C83E5131F42E8000AD0F6 /* LastFMDirectory.h */,
DF93D7AD1444B105007C6459 /* LastFMFile.cpp */,
DF93D7AE1444B105007C6459 /* LastFMFile.h */,
+ 7C1F6F7813ED178F001726AB /* LibraryDirectory.cpp */,
+ 7C1F6F7913ED178F001726AB /* LibraryDirectory.h */,
DFDB00221516403A005079A4 /* MemBufferCache.cpp */,
DFDB00231516403A005079A4 /* MemBufferCache.h */,
F56C83E6131F42E8000AD0F6 /* MultiPathDirectory.cpp */,
@@ -7101,6 +7106,7 @@
DFFD59401506B5B10088DE4B /* IOSEAGLView.mm in Sources */,
DFFEFBEE15160739001294DC /* IOSScreenManager.mm in Sources */,
DFFEFC0415160808001294DC /* IOSExternalTouchController.mm in Sources */,
+ 7C1F6F7A13ED178F001726AB /* LibraryDirectory.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
8 XBMC.xcodeproj/project.pbxproj
@@ -515,6 +515,8 @@
7C0A7EC113A5DBCE00AFC2BD /* AppParamParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7EBE13A5DBCE00AFC2BD /* AppParamParser.cpp */; };
7C1A85651520522500C63311 /* TextureCacheJob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A85631520522500C63311 /* TextureCacheJob.cpp */; };
7C1A85661520522500C63311 /* TextureCacheJob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1A85631520522500C63311 /* TextureCacheJob.cpp */; };
+ 7C1F6EBB13ECCFA7001726AB /* LibraryDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1F6EB913ECCFA7001726AB /* LibraryDirectory.cpp */; };
+ 7C1F6EBC13ECCFA7001726AB /* LibraryDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1F6EB913ECCFA7001726AB /* LibraryDirectory.cpp */; };
7C2D6AE40F35453E00DD2E85 /* SpecialProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C2D6AE20F35453E00DD2E85 /* SpecialProtocol.cpp */; };
7C45DBE910F325C400D4BBF3 /* DAVDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C45DBE710F325C400D4BBF3 /* DAVDirectory.cpp */; };
7C45DBEA10F325C400D4BBF3 /* DAVDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C45DBE710F325C400D4BBF3 /* DAVDirectory.cpp */; };
@@ -2495,6 +2497,8 @@
7C0A7EBF13A5DBCE00AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; };
7C1A85631520522500C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; };
7C1A85641520522500C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; };
+ 7C1F6EB913ECCFA7001726AB /* LibraryDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LibraryDirectory.cpp; sourceTree = "<group>"; };
+ 7C1F6EBA13ECCFA7001726AB /* LibraryDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LibraryDirectory.h; sourceTree = "<group>"; };
7C2D6AE20F35453E00DD2E85 /* SpecialProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpecialProtocol.cpp; sourceTree = "<group>"; };
7C2D6AE30F35453E00DD2E85 /* SpecialProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecialProtocol.h; sourceTree = "<group>"; };
7C45DBE710F325C400D4BBF3 /* DAVDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DAVDirectory.cpp; sourceTree = "<group>"; };
@@ -5845,6 +5849,8 @@
E38E16F60D25F9FA00618676 /* LastFMDirectory.h */,
DF93D6791444A8B0007C6459 /* LastFMFile.cpp */,
DF93D67A1444A8B0007C6459 /* LastFMFile.h */,
+ 7C1F6EB913ECCFA7001726AB /* LibraryDirectory.cpp */,
+ 7C1F6EBA13ECCFA7001726AB /* LibraryDirectory.h */,
E38E16970D25F9FA00618676 /* MemBufferCache.cpp */,
E38E16980D25F9FA00618676 /* MemBufferCache.h */,
E38E17080D25F9FA00618676 /* MultiPathDirectory.cpp */,
@@ -8209,6 +8215,7 @@
7C1A85661520522500C63311 /* TextureCacheJob.cpp in Sources */,
C8936052152C86CF00812418 /* monitor.cpp in Sources */,
C8936056152C86D800812418 /* PythonMonitor.cpp in Sources */,
+ 7C1F6EBB13ECCFA7001726AB /* LibraryDirectory.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -9149,6 +9156,7 @@
7C1A85651520522500C63311 /* TextureCacheJob.cpp in Sources */,
C8936053152C86CF00812418 /* monitor.cpp in Sources */,
C8936057152C86D800812418 /* PythonMonitor.cpp in Sources */,
+ 7C1F6EBC13ECCFA7001726AB /* LibraryDirectory.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
2  project/VS2010Express/XBMC.vcxproj
@@ -380,6 +380,7 @@
<ClCompile Include="..\..\xbmc\filesystem\ISOFile.cpp" />
<ClCompile Include="..\..\xbmc\filesystem\LastFMDirectory.cpp" />
<ClCompile Include="..\..\xbmc\filesystem\LastFMFile.cpp" />
+ <ClCompile Include="..\..\xbmc\filesystem\LibraryDirectory.cpp" />
<ClCompile Include="..\..\xbmc\filesystem\MemBufferCache.cpp" />
<ClCompile Include="..\..\xbmc\filesystem\MultiPathDirectory.cpp" />
<ClCompile Include="..\..\xbmc\filesystem\MultiPathFile.cpp" />
@@ -944,6 +945,7 @@
<ClInclude Include="..\..\xbmc\filesystem\ISOFile.h" />
<ClInclude Include="..\..\xbmc\filesystem\LastFMDirectory.h" />
<ClInclude Include="..\..\xbmc\filesystem\LastFMFile.h" />
+ <ClInclude Include="..\..\xbmc\filesystem\LibraryDirectory.h" />
<ClInclude Include="..\..\xbmc\filesystem\MultiPathDirectory.h" />
<ClInclude Include="..\..\xbmc\filesystem\MultiPathFile.h" />
<ClInclude Include="..\..\xbmc\filesystem\MusicDatabaseDirectory.h" />
View
6 project/VS2010Express/XBMC.vcxproj.filters
@@ -2438,6 +2438,9 @@
<ClCompile Include="..\..\xbmc\filesystem\LastFMFile.cpp">
<Filter>filesystem</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\filesystem\LibraryDirectory.cpp">
+ <Filter>filesystem</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\filesystem\MultiPathDirectory.cpp">
<Filter>filesystem</Filter>
</ClCompile>
@@ -5022,6 +5025,9 @@
<ClInclude Include="..\..\xbmc\filesystem\LastFMFile.h">
<Filter>filesystem</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\filesystem\LibraryDirectory.h">
+ <Filter>filesystem</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\filesystem\MultiPathDirectory.h">
<Filter>filesystem</Filter>
</ClInclude>
View
5 system/library/video/addons.xml
@@ -0,0 +1,5 @@
+<node order="9" type="folder">
+ <label>1037</label>
+ <icon>DefaultAddonVideo.png</icon>
+ <path>addons://sources/video/</path>
+</node>
View
5 system/library/video/files.xml
@@ -0,0 +1,5 @@
+<node order="7" type="folder">
+ <label>744</label>
+ <icon>DefaultFolder.png</icon>
+ <path>sources://video</path>
+</node>
View
6 system/library/video/movies/actors.xml
@@ -0,0 +1,6 @@
+<node order="4" type="folder">
+ <label>344</label>
+ <path>videodb://1/4</path>
+ <icon>DefaultActor.png</icon>
+</node>
+
View
5 system/library/video/movies/country.xml
@@ -0,0 +1,5 @@
+<node order="8" type="folder">
+ <label>20451</label>
+ <path>videodb://1/8</path>
+ <icon>DefaultCountry.png</icon>
+</node>
View
5 system/library/video/movies/directors.xml
@@ -0,0 +1,5 @@
+<node order="5" type="folder">
+ <label>20348</label>
+ <path>videodb://1/5</path>
+ <icon>DefaultDirector.png</icon>
+</node>
View
5 system/library/video/movies/genres.xml
@@ -0,0 +1,5 @@
+<node order="1" type="folder">
+ <label>135</label>
+ <path>videodb://1/1</path>
+ <icon>DefaultGenre.png</icon>
+</node>
View
5 system/library/video/movies/index.xml
@@ -0,0 +1,5 @@
+<node order="1" visible="Library.HasContent(Movies)">
+ <!-- a virtual folder -->
+ <label>342</label>
+ <icon>DefaultMovies.png</icon>
+</node>
View
5 system/library/video/movies/sets.xml
@@ -0,0 +1,5 @@
+<node order="7" type="folder" visible="Library.HasContent(MovieSets)">
+ <label>20434</label>
+ <path>videodb://1/7</path>
+ <icon>DefaultSets.png</icon>
+</node>
View
5 system/library/video/movies/studios.xml
@@ -0,0 +1,5 @@
+<node order="6" type="folder">
+ <label>20388</label>
+ <path>videodb://1/6</path>
+ <icon>DefaultStudios.png</icon>
+</node>
View
5 system/library/video/movies/titles.xml
@@ -0,0 +1,5 @@
+<node order="2" type="folder">
+ <label>369</label>
+ <path>videodb://1/2</path>
+ <icon>DefaultMovieTitle.png</icon>
+</node>
View
6 system/library/video/movies/years.xml
@@ -0,0 +1,6 @@
+<node order="3" type="folder">
+ <label>562</label>
+ <path>videodb://1/3</path>
+ <icon>DefaultYear.png</icon>
+</node>
+
View
5 system/library/video/musicvideos/albums.xml
@@ -0,0 +1,5 @@
+<node order="5" type="folder">
+ <label>132</label>
+ <path>videodb://3/5</path>
+ <icon>DefaultAlbum.png</icon>
+</node>
View
5 system/library/video/musicvideos/artists.xml
@@ -0,0 +1,5 @@
+<node order="4" type="folder">
+ <label>133</label>
+ <path>videodb://3/4</path>
+ <icon>DefaultArtist.png</icon>
+</node>
View
5 system/library/video/musicvideos/directors.xml
@@ -0,0 +1,5 @@
+<node order="6" type="folder">
+ <label>20348</label>
+ <path>videodb://3/6</path>
+ <icon>DefaultDirector.png</icon>
+</node>
View
5 system/library/video/musicvideos/genres.xml
@@ -0,0 +1,5 @@
+<node order="1" type="folder">
+ <label>135</label>
+ <path>videodb://3/1</path>
+ <icon>DefaultGenre.png</icon>
+</node>
View
4 system/library/video/musicvideos/index.xml
@@ -0,0 +1,4 @@
+<node order="3" visible="Library.HasContent(MusicVideos)">
+ <label>20389</label>
+ <icon>DefaultMusicVideos.png</icon>
+</node>
View
5 system/library/video/musicvideos/studios.xml
@@ -0,0 +1,5 @@
+<node order="7" type="folder">
+ <label>20388</label>
+ <path>videodb://3/7</path>
+ <icon>DefaultStudios.png</icon>
+</node>
View
5 system/library/video/musicvideos/titles.xml
@@ -0,0 +1,5 @@
+<node order="2" type="folder">
+ <label>369</label>
+ <path>videodb://3/2</path>
+ <icon>DefaultMusicVideoTitle.png</icon>
+</node>
View
5 system/library/video/musicvideos/years.xml
@@ -0,0 +1,5 @@
+<node order="3" type="folder">
+ <label>562</label>
+ <path>videodb://3/3</path>
+ <icon>DefaultYear.png</icon>
+</node>
View
5 system/library/video/playlists.xml
@@ -0,0 +1,5 @@
+<node order="8" type="folder">
+ <label>136</label>
+ <icon>DefaultVideoPlaylists.png</icon>
+ <path>special://videoplaylists/</path>
+</node>
View
5 system/library/video/recentlyaddedepisodes.xml
@@ -0,0 +1,5 @@
+<node order="5" type="folder" visible="Library.HasContent(TVShows)">
+ <label>20387</label>
+ <icon>DefaultRecentlyAddedEpisodes.png</icon>
+ <path>videodb://5</path>
+</node>
View
5 system/library/video/recentlyaddedmovies.xml
@@ -0,0 +1,5 @@
+<node order="4" type="folder" visible="Library.HasContent(Movies)">
+ <label>20386</label>
+ <icon>DefaultRecentlyAddedMovies.png</icon>
+ <path>videodb://4</path>
+</node>
View
5 system/library/video/recentlyaddedmusicvideos.xml
@@ -0,0 +1,5 @@
+<node order="6" type="folder" visible="Library.HasContent(MusicVideos)">
+ <label>20390</label>
+ <icon>DefaultRecentlyAddedMusicVideos.png</icon>
+ <path>videodb://6</path>
+</node>
View
5 system/library/video/tvshows/actors.xml
@@ -0,0 +1,5 @@
+<node order="4" type="folder">
+ <label>344</label>
+ <path>videodb://2/4</path>
+ <icon>DefaultActor.png</icon>
+</node>
View
5 system/library/video/tvshows/genres.xml
@@ -0,0 +1,5 @@
+<node order="1" type="folder">
+ <label>135</label>
+ <path>videodb://2/1</path>
+ <icon>DefaultGenre.png</icon>
+</node>
View
4 system/library/video/tvshows/index.xml
@@ -0,0 +1,4 @@
+<node order="2" visible="Library.HasContent(TVShows)">
+ <label>20343</label>
+ <icon>DefaultTVShows.png</icon>
+</node>
View
5 system/library/video/tvshows/studios.xml
@@ -0,0 +1,5 @@
+<node order="5" type="folder">
+ <label>20388</label>
+ <path>videodb://2/5</path>
+ <icon>DefaultStudios.png</icon>
+</node>
View
5 system/library/video/tvshows/titles.xml
@@ -0,0 +1,5 @@
+<node order="2" type="folder">
+ <label>369</label>
+ <path>videodb://2/2</path>
+ <icon>DefaultTVShowTitle.png</icon>
+</node>
View
5 system/library/video/tvshows/years.xml
@@ -0,0 +1,5 @@
+<node order="3" type="folder">
+ <label>562</label>
+ <path>videodb://2/3</path>
+ <icon>DefaultYear.png</icon>
+</node>
View
5 system/library/video_flat/addons.xml
@@ -0,0 +1,5 @@
+<node order="9" type="folder">
+ <label>1037</label>
+ <icon>DefaultAddonVideo.png</icon>
+ <path>addons://sources/video/</path>
+</node>
View
5 system/library/video_flat/files.xml
@@ -0,0 +1,5 @@
+<node order="7" type="folder">
+ <label>744</label>
+ <icon>DefaultFolder.png</icon>
+ <path>sources://video</path>
+</node>
View
5 system/library/video_flat/movies.xml
@@ -0,0 +1,5 @@
+<node order="1" type="folder" visible="Library.HasContent(Movies)">
+ <label>342</label>
+ <path>videodb://1/2</path>
+ <icon>DefaultMovieTitle.png</icon>
+</node>
View
5 system/library/video_flat/musicvideos.xml
@@ -0,0 +1,5 @@
+<node order="3" type="folder" visible="Library.HasContent(MusicVideos)">
+ <label>20389</label>
+ <path>videodb://3/2</path>
+ <icon>DefaultMusicVideoTitle.png</icon>
+</node>
View
5 system/library/video_flat/playlists.xml
@@ -0,0 +1,5 @@
+<node order="8" type="folder">
+ <label>136</label>
+ <icon>DefaultVideoPlaylists.png</icon>
+ <path>special://videoplaylists/</path>
+</node>
View
5 system/library/video_flat/recentlyaddedepisodes.xml
@@ -0,0 +1,5 @@
+<node order="5" type="folder" visible="Library.HasContent(TVShows)">
+ <label>20387</label>
+ <icon>DefaultRecentlyAddedEpisodes.png</icon>
+ <path>videodb://5</path>
+</node>
View
5 system/library/video_flat/recentlyaddedmovies.xml
@@ -0,0 +1,5 @@
+<node order="4" type="folder" visible="Library.HasContent(Movies)">
+ <label>20386</label>
+ <icon>DefaultRecentlyAddedMovies.png</icon>
+ <path>videodb://4</path>
+</node>
View
5 system/library/video_flat/recentlyaddedmusicvideos.xml
@@ -0,0 +1,5 @@
+<node order="6" type="folder" visible="Library.HasContent(MusicVideos)">
+ <label>20390</label>
+ <icon>DefaultRecentlyAddedMusicVideos.png</icon>
+ <path>videodb://6</path>
+</node>
View
5 system/library/video_flat/tvshows.xml
@@ -0,0 +1,5 @@
+<node order="2" type="folder" visible="Library.HasContent(TVShows)">
+ <label>20343</label>
+ <path>videodb://2/2</path>
+ <icon>DefaultTVShowTitle.png</icon>
+</node>
View
18 xbmc/GUIInfoManager.cpp
@@ -814,6 +814,7 @@ int CGUIInfoManager::TranslateSingleString(const CStdString &strCondition)
else if (cat == "movies") return LIBRARY_HAS_MOVIES;
else if (cat == "tvshows") return LIBRARY_HAS_TVSHOWS;
else if (cat == "musicvideos") return LIBRARY_HAS_MUSICVIDEOS;
+ else if (cat == "moviesets") return LIBRARY_HAS_MOVIE_SETS;
}
}
else if (cat.name == "musicplayer")
@@ -4490,6 +4491,9 @@ void CGUIInfoManager::SetLibraryBool(int condition, bool value)
case LIBRARY_HAS_MOVIES:
m_libraryHasMovies = value ? 1 : 0;
break;
+ case LIBRARY_HAS_MOVIE_SETS:
+ m_libraryHasMovieSets = value ? 1 : 0;
+ break;
case LIBRARY_HAS_TVSHOWS:
m_libraryHasTVShows = value ? 1 : 0;
break;
@@ -4507,6 +4511,7 @@ void CGUIInfoManager::ResetLibraryBools()
m_libraryHasMovies = -1;
m_libraryHasTVShows = -1;
m_libraryHasMusicVideos = -1;
+ m_libraryHasMovieSets = -1;
}
bool CGUIInfoManager::GetLibraryBool(int condition)
@@ -4537,6 +4542,19 @@ bool CGUIInfoManager::GetLibraryBool(int condition)
}
return m_libraryHasMovies > 0;
}
+ else if (condition == LIBRARY_HAS_MOVIE_SETS)
+ {
+ if (m_libraryHasMovieSets < 0)
+ {
+ CVideoDatabase db;
+ if (db.Open())
+ {
+ m_libraryHasMovieSets = db.HasSets() ? 1 : 0;
+ db.Close();
+ }
+ }
+ return m_libraryHasMovieSets > 0;
+ }
else if (condition == LIBRARY_HAS_TVSHOWS)
{
if (m_libraryHasTVShows < 0)
View
12 xbmc/GUIInfoManager.h
@@ -376,11 +376,12 @@ namespace INFO
#define LIBRARY_HAS_MUSIC 720
#define LIBRARY_HAS_VIDEO 721
#define LIBRARY_HAS_MOVIES 722
-#define LIBRARY_HAS_TVSHOWS 723
-#define LIBRARY_HAS_MUSICVIDEOS 724
-#define LIBRARY_IS_SCANNING 725
-#define LIBRARY_IS_SCANNING_VIDEO 726
-#define LIBRARY_IS_SCANNING_MUSIC 727
+#define LIBRARY_HAS_MOVIE_SETS 723
+#define LIBRARY_HAS_TVSHOWS 724
+#define LIBRARY_HAS_MUSICVIDEOS 725
+#define LIBRARY_IS_SCANNING 726
+#define LIBRARY_IS_SCANNING_VIDEO 727
+#define LIBRARY_IS_SCANNING_MUSIC 728
#define SYSTEM_PLATFORM_XBOX 740
#define SYSTEM_PLATFORM_LINUX 741
@@ -798,6 +799,7 @@ class CGUIInfoManager : public IMsgTargetCallback
int m_libraryHasMovies;
int m_libraryHasTVShows;
int m_libraryHasMusicVideos;
+ int m_libraryHasMovieSets;
CCriticalSection m_critInfo;
};
View
21 xbmc/GUIViewState.cpp
@@ -73,7 +73,8 @@ CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& it
if (url.GetProtocol()=="musicsearch")
return new CGUIViewStateMusicSearch(items);
- if (items.IsSmartPlayList() || url.GetProtocol() == "upnp")
+ if (items.IsSmartPlayList() || url.GetProtocol() == "upnp" ||
+ (url.GetProtocol() == "library" && items.GetProperty("library.filter").asBoolean()))
{
if (items.GetContent() == "songs")
return new CGUIViewStateMusicSmartPlaylist(items);
@@ -89,6 +90,9 @@ CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& it
return new CGUIViewStateVideoMovies(items);
}
+ if (url.GetProtocol() == "library")
+ return new CGUIViewStateLibrary(items);
+
if (items.IsPlayList())
return new CGUIViewStateMusicPlaylist(items);
@@ -472,4 +476,19 @@ void CGUIViewStateFromItems::SaveViewState()
SaveViewToDb(m_items.GetPath(), g_windowManager.GetActiveWindow());
}
+CGUIViewStateLibrary::CGUIViewStateLibrary(const CFileItemList &items) : CGUIViewState(items)
+{
+ AddSortMethod(SORT_METHOD_NONE, 551, LABEL_MASKS("%F", "%I", "%L", "")); // Filename, Size | Foldername, empty
+ SetSortMethod(SORT_METHOD_NONE);
+ SetSortOrder(SORT_ORDER_NONE);
+
+ SetViewAsControl(DEFAULT_VIEW_LIST);
+
+ LoadViewState(items.GetPath(), g_windowManager.GetActiveWindow());
+}
+
+void CGUIViewStateLibrary::SaveViewState()
+{
+ SaveViewToDb(m_items.GetPath(), g_windowManager.GetActiveWindow());
+}
View
9 xbmc/GUIViewState.h
@@ -110,3 +110,12 @@ class CGUIViewStateFromItems : public CGUIViewState
protected:
virtual void SaveViewState();
};
+
+class CGUIViewStateLibrary : public CGUIViewState
+{
+public:
+ CGUIViewStateLibrary(const CFileItemList& items);
+
+protected:
+ virtual void SaveViewState();
+};
View
2  xbmc/filesystem/DirectoryFactory.cpp
@@ -33,6 +33,7 @@
#include "MusicDatabaseDirectory.h"
#include "MusicSearchDirectory.h"
#include "VideoDatabaseDirectory.h"
+#include "LibraryDirectory.h"
#include "AddonsDirectory.h"
#include "SourcesDirectory.h"
#include "LastFMDirectory.h"
@@ -142,6 +143,7 @@ IDirectory* CDirectoryFactory::Create(const CStdString& strPath)
if (strProtocol == "musicdb") return new CMusicDatabaseDirectory();
if (strProtocol == "musicsearch") return new CMusicSearchDirectory();
if (strProtocol == "videodb") return new CVideoDatabaseDirectory();
+ if (strProtocol == "library") return new CLibraryDirectory();
if (strProtocol == "filereader")
return CDirectoryFactory::Create(url.GetFileName());
View
184 xbmc/filesystem/LibraryDirectory.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2011-2012 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "LibraryDirectory.h"
+#include "Directory.h"
+#include "playlists/SmartPlayList.h"
+#include "SmartPlaylistDirectory.h"
+#include "utils/URIUtils.h"
+#include "utils/StringUtils.h"
+#include "utils/XMLUtils.h"
+#include "guilib/GUIControlFactory.h" // for label parsing
+#include "guilib/TextureManager.h"
+#include "FileItem.h"
+#include "File.h"
+#include "settings/Settings.h"
+#include "URL.h"
+#include "GUIInfoManager.h"
+#include "utils/log.h"
+
+using namespace std;
+using namespace XFILE;
+
+CLibraryDirectory::CLibraryDirectory(void)
+{
+}
+
+CLibraryDirectory::~CLibraryDirectory(void)
+{
+}
+
+bool CLibraryDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
+{
+ CStdString libNode = GetNode(strPath);
+ if (libNode.IsEmpty())
+ return false;
+
+ if (URIUtils::GetExtension(libNode).Equals(".xml"))
+ { // a filter node
+ TiXmlElement *node = LoadXML(libNode);
+ if (node)
+ {
+ CStdString type = node->Attribute("type");
+ if (type == "filter")
+ {
+ CSmartPlaylist playlist;
+ CStdString type, label;
+ XMLUtils::GetString(node, "content", type);
+ if (XMLUtils::GetString(node, "label", label))
+ label = CGUIControlFactory::FilterLabel(label);
+ playlist.SetType(type);
+ playlist.SetName(label);
+ if (playlist.LoadFromXML(node) &&
+ CSmartPlaylistDirectory::GetDirectory(playlist, items))
+ {
+ items.SetProperty("library.filter", "true");
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // just a plain node - read the folder for XML nodes and other folders
+ CFileItemList nodes;
+ if (!CDirectory::GetDirectory(libNode, nodes, ".xml", DIR_FLAG_NO_FILE_DIRS))
+ return false;
+
+ // iterate over our nodes
+ for (int i = 0; i < nodes.Size(); i++)
+ {
+ const TiXmlElement *node = NULL;
+ CStdString xml = nodes[i]->GetPath();
+ if (nodes[i]->m_bIsFolder)
+ node = LoadXML(URIUtils::AddFileToFolder(xml, "index.xml"));
+ else
+ {
+ node = LoadXML(xml);
+ if (node && URIUtils::GetFileName(xml).Equals("index.xml"))
+ { // set the label on our items
+ CStdString label;
+ if (XMLUtils::GetString(node, "label", label))
+ label = CGUIControlFactory::FilterLabel(label);
+ items.SetLabel(label);
+ continue;
+ }
+ }
+ if (node)
+ {
+ CStdString label, icon;
+ if (XMLUtils::GetString(node, "label", label))
+ label = CGUIControlFactory::FilterLabel(label);
+ XMLUtils::GetString(node, "icon", icon);
+ CStdString type = node->Attribute("type");
+ int order = 0;
+ node->Attribute("order", &order);
+ CFileItemPtr item;
+ if (type == "folder")
+ { // folder type - grab our path
+ CStdString path;
+ XMLUtils::GetPath(node, "path", path);
+ item.reset(new CFileItem(path, true));
+ }
+ else
+ { // virtual folder or filter
+ URIUtils::RemoveSlashAtEnd(xml);
+ CStdString folder = URIUtils::GetFileName(xml);
+ item.reset(new CFileItem(URIUtils::AddFileToFolder(strPath, folder), true));
+ }
+ item->SetLabel(label);
+ if (!icon.IsEmpty() && g_TextureManager.HasTexture(icon))
+ item->SetIconImage(icon);
+ item->m_iprogramCount = order;
+ items.Add(item);
+ }
+ }
+ items.Sort(SORT_METHOD_PLAYLIST_ORDER, SORT_ORDER_ASC);
+ return true;
+}
+
+TiXmlElement *CLibraryDirectory::LoadXML(const CStdString &xmlFile)
+{
+ if (!CFile::Exists(xmlFile))
+ return NULL;
+
+ if (!m_doc.LoadFile(xmlFile))
+ return NULL;
+
+ TiXmlElement *xml = m_doc.RootElement();
+ if (!xml || xml->ValueStr() != "node")
+ return NULL;
+
+ // check the condition
+ CStdString condition = xml->Attribute("visible");
+ if (condition.IsEmpty() || g_infoManager.EvaluateBool(condition))
+ return xml;
+
+ return NULL;
+}
+
+bool CLibraryDirectory::Exists(const char* strPath)
+{
+ return !GetNode(strPath).IsEmpty();
+}
+
+CStdString CLibraryDirectory::GetNode(const CStdString &path)
+{
+ CURL url(path);
+ CStdString libDir = URIUtils::AddFileToFolder(g_settings.GetDatabaseFolder(), url.GetHostName() + "/");
+ if (!CDirectory::Exists(libDir))
+ libDir = URIUtils::AddFileToFolder("special://xbmc/system/library/", url.GetHostName() + "/");
+
+ libDir = URIUtils::AddFileToFolder(libDir, url.GetFileName());
+
+ // is this a virtual node (aka actual folder on disk?)
+ if (CDirectory::Exists(libDir))
+ return libDir;
+
+ // maybe it's an XML node?
+ CStdString xmlNode = libDir;
+ URIUtils::RemoveSlashAtEnd(xmlNode);
+
+ if (CFile::Exists(xmlNode))
+ return xmlNode;
+
+ return "";
+}
View
52 xbmc/filesystem/LibraryDirectory.h
@@ -0,0 +1,52 @@
+#pragma once
+/*
+ * Copyright (C) 2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "IDirectory.h"
+#include "lib/tinyXML/tinyxml.h"
+
+namespace XFILE
+{
+ class CLibraryDirectory : public IDirectory
+ {
+ public:
+ CLibraryDirectory();
+ virtual ~CLibraryDirectory();
+ virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items);
+ virtual bool Exists(const char* strPath);
+ virtual bool IsAllowed(const CStdString& strFile) const { return true; };
+ private:
+ /*! \brief parse the given path and return the node corresponding to this path
+ \param path the library:// path to parse
+ \return path to the XML file or directory corresponding to this path
+ */
+ CStdString GetNode(const CStdString &path);
+
+ /*! \brief load the XML file and return a pointer to the <node> root element.
+ Checks visible attribute and only returns non-NULL for valid nodes that should be visible.
+ \param xmlFile the XML file to load and parse
+ \return the TiXmlElement pointer to the node, if it should be visible.
+ */
+ TiXmlElement *LoadXML(const CStdString &xmlFile);
+
+ TiXmlDocument m_doc;
+ };
+}
View
1  xbmc/filesystem/Makefile.in
@@ -38,6 +38,7 @@ SRCS=AddonsDirectory.cpp \
ISOFile.cpp \
LastFMDirectory.cpp \
LastFMFile.cpp \
+ LibraryDirectory.cpp \
MemBufferCache.cpp \
MultiPathDirectory.cpp \
MultiPathFile.cpp \
View
34 xbmc/filesystem/SmartPlaylistDirectory.cpp
@@ -45,6 +45,11 @@ namespace XFILE
CSmartPlaylist playlist;
if (!playlist.Load(strPath))
return false;
+ return GetDirectory(playlist, items);
+ }
+
+ bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items)
+ {
bool success = false, success2 = false;
std::set<CStdString> playlists;
if (playlist.GetType().Equals("tvshows"))
@@ -85,33 +90,40 @@ namespace XFILE
{
CMusicDatabase db;
db.Open();
- CStdString type=playlist.GetType();
- if (type.IsEmpty())
- type = "songs";
- if (playlist.GetType().Equals("mixed"))
- playlist.SetType("songs");
+ CStdString whereOrder;
+ if (playlist.GetType().IsEmpty() || playlist.GetType().Equals("mixed"))
+ {
+ CSmartPlaylist songPlaylist(playlist);
+ songPlaylist.SetType("songs");
+ whereOrder = songPlaylist.GetWhereClause(db, playlists) + " " + songPlaylist.GetOrderClause(db);
+ }
+ else
+ whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
- CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
success = db.GetSongsByWhere("", whereOrder, items);
items.SetContent("songs");
db.Close();
- playlist.SetType(type);
}
if (playlist.GetType().Equals("musicvideos") || playlist.GetType().Equals("mixed"))
{
CVideoDatabase db;
db.Open();
- CStdString type=playlist.GetType();
+ CStdString whereOrder;
if (playlist.GetType().Equals("mixed"))
- playlist.SetType("musicvideos");
- CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
+ {
+ CSmartPlaylist mvidPlaylist(playlist);
+ mvidPlaylist.SetType("musicvideos");
+ whereOrder = mvidPlaylist.GetWhereClause(db, playlists) + " " + mvidPlaylist.GetOrderClause(db);
+ }
+ else
+ whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
+
CFileItemList items2;
success2 = db.GetMusicVideosByWhere("videodb://3/2/", whereOrder, items2, false); // TODO: SMARTPLAYLISTS Don't check locks???
db.Close();
items.Append(items2);
if (items2.Size())
items.SetContent("musicvideos");
- playlist.SetType(type);
}
items.SetLabel(playlist.GetName());
// go through and set the playlist order
View
4 xbmc/filesystem/SmartPlaylistDirectory.h
@@ -23,6 +23,8 @@
#include "IFileDirectory.h"
+class CSmartPlaylist;
+
namespace XFILE
{
class CSmartPlaylistDirectory : public IFileDirectory
@@ -35,6 +37,8 @@ namespace XFILE
virtual bool ContainsFiles(const CStdString& strPath);
virtual bool Remove(const char *strPath);
+ static bool GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items);
+
static CStdString GetPlaylistByName(const CStdString& name, const CStdString& playlistType);
};
}
View
23 xbmc/playlists/SmartPlayList.cpp
@@ -139,7 +139,7 @@ void CSmartPlaylistRule::TranslateStrings(const char *field, const char *oper, c
m_parameter = parameter;
}
-TiXmlElement CSmartPlaylistRule::GetAsElement()
+TiXmlElement CSmartPlaylistRule::GetAsElement() const
{
TiXmlElement rule("rule");
TiXmlText parameter(m_parameter.c_str());
@@ -355,14 +355,14 @@ CStdString CSmartPlaylistRule::GetLocalizedOperator(SEARCH_OPERATOR oper)
return g_localizeStrings.Get(16018);
}
-CStdString CSmartPlaylistRule::GetLocalizedRule()
+CStdString CSmartPlaylistRule::GetLocalizedRule() const
{
CStdString rule;
rule.Format("%s %s %s", GetLocalizedField(m_field).c_str(), GetLocalizedOperator(m_operator).c_str(), m_parameter.c_str());
return rule;
}
-CStdString CSmartPlaylistRule::GetVideoResolutionQuery(void)
+CStdString CSmartPlaylistRule::GetVideoResolutionQuery(void) const
{
CStdString retVal(" in (select distinct idFile from streamdetails where iVideoWidth ");
int iRes = atoi(m_parameter.c_str());
@@ -394,7 +394,7 @@ CStdString CSmartPlaylistRule::GetVideoResolutionQuery(void)
return retVal;
}
-CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& strType)
+CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& strType) const
{
SEARCH_OPERATOR op = m_operator;
if ((strType == "tvshows" || strType == "episodes") && m_field == FIELD_YEAR)
@@ -804,6 +804,15 @@ bool CSmartPlaylist::Load(const CStdString &path)
// encoding:
CStdString encoding;
XMLUtils::GetEncoding(&m_xmlDoc, encoding);
+
+ // from here we decode from XML
+ return LoadFromXML(root, encoding);
+}
+
+bool CSmartPlaylist::LoadFromXML(TiXmlElement *root, const CStdString &encoding)
+{
+ if (!root)
+ return false;
TiXmlHandle match = ((TiXmlHandle)root->FirstChild("match")).FirstChild();
if (match.Node())
@@ -913,10 +922,10 @@ void CSmartPlaylist::AddRule(const CSmartPlaylistRule &rule)
m_playlistRules.push_back(rule);
}
-CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, set<CStdString> &referencedPlaylists, bool needWhere /* = true */)
+CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, set<CStdString> &referencedPlaylists, bool needWhere /* = true */) const
{
CStdString rule, currentRule;
- for (vector<CSmartPlaylistRule>::iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it)
+ for (vector<CSmartPlaylistRule>::const_iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it)
{
if (it != m_playlistRules.begin())
rule += m_matchAllRules ? " AND " : " OR ";
@@ -959,7 +968,7 @@ CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, set<CStdString> &refere
return rule;
}
-CStdString CSmartPlaylist::GetOrderClause(CDatabase &db)
+CStdString CSmartPlaylist::GetOrderClause(CDatabase &db) const
{
CStdString order;
if (m_orderField != CSmartPlaylistRule::FIELD_NONE)
View
15 xbmc/playlists/SmartPlayList.h
@@ -115,7 +115,7 @@ class CSmartPlaylistRule
TEXTIN_FIELD
};
- CStdString GetWhereClause(CDatabase &db, const CStdString& strType);
+ CStdString GetWhereClause(CDatabase &db, const CStdString& strType) const;
void TranslateStrings(const char *field, const char *oper, const char *parameter);
static DATABASE_FIELD TranslateField(const char *field);
static CStdString TranslateField(DATABASE_FIELD field);
@@ -127,17 +127,17 @@ class CSmartPlaylistRule
static std::vector<DATABASE_FIELD> GetFields(const CStdString &type, bool sortOrders = false);
static FIELD_TYPE GetFieldType(DATABASE_FIELD field);
- CStdString GetLocalizedRule();
+ CStdString GetLocalizedRule() const;
- TiXmlElement GetAsElement();
+ TiXmlElement GetAsElement() const;
DATABASE_FIELD m_field;
SEARCH_OPERATOR m_operator;
CStdString m_parameter;
private:
- SEARCH_OPERATOR TranslateOperator(const char *oper);
+ static SEARCH_OPERATOR TranslateOperator(const char *oper);
- CStdString GetVideoResolutionQuery(void);
+ CStdString GetVideoResolutionQuery(void) const;
};
class CSmartPlaylist
@@ -149,6 +149,7 @@ class CSmartPlaylist
bool Save(const CStdString &path);
TiXmlElement *OpenAndReadName(const CStdString &path);
+ bool LoadFromXML(TiXmlElement *root, const CStdString &encoding = "UTF-8");
void SetName(const CStdString &name);
void SetType(const CStdString &type); // music, video, mixed
@@ -177,8 +178,8 @@ class CSmartPlaylist
\param referencedPlaylists a set of playlists to know when we reach a cycle
\param needWhere whether we need to prepend the where clause with "WHERE "
*/
- CStdString GetWhereClause(CDatabase &db, std::set<CStdString> &referencedPlaylists, bool needWhere = true);
- CStdString GetOrderClause(CDatabase &db);
+ CStdString GetWhereClause(CDatabase &db, std::set<CStdString> &referencedPlaylists, bool needWhere = true) const;
+ CStdString GetOrderClause(CDatabase &db) const;
const std::vector<CSmartPlaylistRule> &GetRules() const;
View
34 xbmc/video/GUIViewStateVideo.cpp
@@ -54,7 +54,6 @@ int CGUIViewStateWindowVideo::GetPlaylist()
VECSOURCES& CGUIViewStateWindowVideo::GetSources()
{
AddLiveTVSources();
- AddAddonsSource("video", g_localizeStrings.Get(1037), "DefaultAddonVideo.png");
return CGUIViewState::GetSources();
}
@@ -409,9 +408,11 @@ VECSOURCES& CGUIViewStateWindowVideoNav::GetSources()
{
// Setup shares we want to have
m_sources.clear();
- // Musicdb shares
CFileItemList items;
- CDirectory::GetDirectory("videodb://", items, "");
+ if (g_settings.m_bMyVideoNavFlatten)
+ CDirectory::GetDirectory("library://video_flat/", items, "");
+ else
+ CDirectory::GetDirectory("library://video/", items, "");
for (int i=0; i<items.Size(); ++i)
{
CFileItemPtr item=items[i];
@@ -422,25 +423,6 @@ VECSOURCES& CGUIViewStateWindowVideoNav::GetSources()
share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
m_sources.push_back(share);
}
-
- {
- { // Files share
- CMediaSource share;
- share.strName=g_localizeStrings.Get(744); // Files
- share.strPath = "sources://video/";
- share.m_strThumbnailImage = CUtil::GetDefaultFolderThumb("DefaultFolder.png");
- share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
- m_sources.push_back(share);
- }
- }
- { // Playlists share
- CMediaSource share;
- share.strName=g_localizeStrings.Get(136); // Playlists
- share.strPath = "special://videoplaylists/";
- share.m_strThumbnailImage = CUtil::GetDefaultFolderThumb("DefaultVideoPlaylists.png");
- share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
- m_sources.push_back(share);
- }
return CGUIViewStateWindowVideo::GetSources();
}
@@ -505,7 +487,7 @@ CGUIViewStateVideoMovies::CGUIViewStateVideoMovies(const CFileItemList& items) :
AddSortMethod(SORT_METHOD_MPAA_RATING, 20074, LABEL_MASKS("%T", "%O"));
AddSortMethod(SORT_METHOD_YEAR,562, LABEL_MASKS("%T", "%Y"));
- if (items.IsSmartPlayList())
+ if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean())
{
AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS("%T", "%R"));
SetSortMethod(SORT_METHOD_PLAYLIST_ORDER);
@@ -544,7 +526,7 @@ CGUIViewStateVideoMusicVideos::CGUIViewStateVideoMusicVideos(const CFileItemList
AddSortMethod(SORT_METHOD_ALBUM,558, LABEL_MASKS("%B - %T", "%Y"));
}
- if (items.IsSmartPlayList())
+ if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean())
{
AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS("%A - %T", "%Y"));
SetSortMethod(SORT_METHOD_PLAYLIST_ORDER);
@@ -574,7 +556,7 @@ CGUIViewStateVideoTVShows::CGUIViewStateVideoTVShows(const CFileItemList& items)
AddSortMethod(SORT_METHOD_YEAR,562,LABEL_MASKS("%L","%Y","%L","%Y"));
- if (items.IsSmartPlayList())
+ if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean())
{
AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS("%L", "%M", "%L", "%M"));
SetSortMethod(SORT_METHOD_PLAYLIST_ORDER);
@@ -618,7 +600,7 @@ CGUIViewStateVideoEpisodes::CGUIViewStateVideoEpisodes(const CFileItemList& item
AddSortMethod(SORT_METHOD_DATE,552,LABEL_MASKS("%Z - %H. %T","%J"));
}
- if (items.IsSmartPlayList())
+ if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean())
{
AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS("%Z - %H. %T", "%R"));
SetSortMethod(SORT_METHOD_PLAYLIST_ORDER);
Something went wrong with that request. Please try again.