From 52240f53cfe84a532d4799644e451e133de0a7b5 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Fri, 13 Apr 2018 00:07:30 +0200 Subject: [PATCH 1/8] prepare add-on whitelist for Titan and skin shortcuts fix skin.pm3 typo --- xbmc/addons/AddonManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index ec40f42194..ebfe18ab19 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -201,12 +201,14 @@ static constexpr const char* addonWhiteList[] = { "screensaver.xbmc.builtin.system", "script.module.requests", "script.plex", + "script.skinshortcuts", "skin.amber", "skin.blackglassnova", "skin.mrmc", "skin.opacity", - "skin.pm3.hd", + "skin.pm3-hd", "skin.sio2", + "skin.titan", "visualization.spectrum", "visualization.waveform", "webinterface.default", From ea99c5e6ab5ef9751a07cb4283f89d70b614d9e8 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 14 Apr 2018 00:21:03 +0200 Subject: [PATCH 2/8] ass possibility to load skin includes from outside the skin root folder Script like skinshortcuts provide xml includes to build dynamic menus. Instead of modifiying files in the skin directory, let the scripts generate a custom xml file in the addon_data folder of the skin. Much safer than the current approach and also fixes MrMc compatability with these scripts. --- xbmc/addons/Skin.cpp | 14 ++++++++++++++ xbmc/addons/Skin.h | 7 +++++++ xbmc/guilib/GUIIncludes.cpp | 6 +++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp index fcdb426ae6..4f44d98ea3 100644 --- a/xbmc/addons/Skin.cpp +++ b/xbmc/addons/Skin.cpp @@ -235,6 +235,19 @@ void CSkinInfo::Start() m_currentAspect = res.strId; } } + +std::string CSkinInfo::GetSkinIncludeFile(const std::string& strFile) const +{ + // try to load include from alternate location (support for skinshortcuts etc.) + std::string strPathAlt = URIUtils::AddFileToFolder(Profile(), strFile); + if (CFile::Exists(strPathAlt)) + { + CLog::Log(LOGDEBUG, "Loading skin include from non-default location: %s", strPathAlt.c_str()); + return strPathAlt; + } + else + return GetSkinPath(strFile); +} std::string CSkinInfo::GetSkinPath(const std::string& strFile, RESOLUTION_INFO *res, const std::string& strBaseDir /* = "" */) const { @@ -264,6 +277,7 @@ std::string CSkinInfo::GetSkinPath(const std::string& strFile, RESOLUTION_INFO * strPath = URIUtils::AddFileToFolder(strPathToUse, res->strMode); strPath = URIUtils::AddFileToFolder(strPath, strFile); + return strPath; } diff --git a/xbmc/addons/Skin.h b/xbmc/addons/Skin.h index a1278bed68..b78d7afde3 100644 --- a/xbmc/addons/Skin.h +++ b/xbmc/addons/Skin.h @@ -117,6 +117,13 @@ class CSkinInfo : public CAddon void Start(); bool HasSkinFile(const std::string &strFile) const; + + /*! \brief Get the full path for the specified file in the skin's include definition. + Try custom path first (for compatability with scripts like skinshortcuts etc.) + \param file XML file to look for + \return path to the XML file + */ + std::string GetSkinIncludeFile(const std::string& strFile) const; /*! \brief Get the full path to the specified file in the skin We search for XML files in the skin folder that best matches the current resolution. diff --git a/xbmc/guilib/GUIIncludes.cpp b/xbmc/guilib/GUIIncludes.cpp index 3ee1138be7..5590087476 100644 --- a/xbmc/guilib/GUIIncludes.cpp +++ b/xbmc/guilib/GUIIncludes.cpp @@ -146,20 +146,20 @@ bool CGUIIncludes::LoadIncludesFromXML(const TiXmlElement *root) } else if (node->Attribute("file")) { + std::string includeFile = g_SkinInfo->GetSkinIncludeFile(node->Attribute("file")); const char *condition = node->Attribute("condition"); if (condition) { // check this condition INFO::InfoPtr conditionID = g_infoManager.Register(condition); bool value = conditionID->Get(); - if (value) { // load this file in as well - LoadIncludes(g_SkinInfo->GetSkinPath(node->Attribute("file"))); + LoadIncludes(includeFile); } } else - LoadIncludes(g_SkinInfo->GetSkinPath(node->Attribute("file"))); + LoadIncludes(includeFile); } node = node->NextSiblingElement("include"); } From 23bef99f689a017c50f5ca7ccbbe70ab98846db7 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 14 Apr 2018 22:33:12 +0200 Subject: [PATCH 3/8] add library nodes for services This will fix the library nodes tree when services (plex/emby) are active. --- system/library/music/albums_services.xml | 6 ++++++ system/library/music/artists_services.xml | 7 +++++++ system/library/music/recentlyaddedalbums.xml | 4 ++-- system/library/music/songs_services.xml | 7 +++++++ system/library/video/inprogressmovies.xml | 4 ++-- system/library/video/inprogressshows.xml | 4 ++-- system/library/video/movies_services/actors.xml | 8 ++++++++ system/library/video/movies_services/country.xml | 7 +++++++ system/library/video/movies_services/directors.xml | 7 +++++++ system/library/video/movies_services/genres.xml | 7 +++++++ system/library/video/movies_services/index.xml | 6 ++++++ system/library/video/movies_services/sets.xml | 7 +++++++ system/library/video/movies_services/studios.xml | 7 +++++++ system/library/video/movies_services/tags.xml | 7 +++++++ system/library/video/movies_services/titles.xml | 8 ++++++++ system/library/video/movies_services/years.xml | 8 ++++++++ system/library/video/recentlyaddedepisodes.xml | 4 ++-- system/library/video/recentlyaddedmovies.xml | 4 ++-- system/library/video/tvshows_services/actors.xml | 7 +++++++ system/library/video/tvshows_services/genres.xml | 7 +++++++ system/library/video/tvshows_services/index.xml | 5 +++++ system/library/video/tvshows_services/studios.xml | 7 +++++++ system/library/video/tvshows_services/tags.xml | 7 +++++++ system/library/video/tvshows_services/titles.xml | 8 ++++++++ system/library/video/tvshows_services/years.xml | 7 +++++++ system/library/video_flat/inprogressmovies.xml | 7 +++++++ system/library/video_flat/inprogressshows.xml | 4 ++-- system/library/video_flat/movies.xml | 3 ++- system/library/video_flat/recentlyaddedepisodes.xml | 4 ++-- system/library/video_flat/recentlyaddedmovies.xml | 4 ++-- system/library/video_flat/tvshows.xml | 3 ++- 31 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 system/library/music/albums_services.xml create mode 100644 system/library/music/artists_services.xml create mode 100644 system/library/music/songs_services.xml create mode 100644 system/library/video/movies_services/actors.xml create mode 100644 system/library/video/movies_services/country.xml create mode 100644 system/library/video/movies_services/directors.xml create mode 100644 system/library/video/movies_services/genres.xml create mode 100644 system/library/video/movies_services/index.xml create mode 100644 system/library/video/movies_services/sets.xml create mode 100644 system/library/video/movies_services/studios.xml create mode 100644 system/library/video/movies_services/tags.xml create mode 100644 system/library/video/movies_services/titles.xml create mode 100644 system/library/video/movies_services/years.xml create mode 100644 system/library/video/tvshows_services/actors.xml create mode 100644 system/library/video/tvshows_services/genres.xml create mode 100644 system/library/video/tvshows_services/index.xml create mode 100644 system/library/video/tvshows_services/studios.xml create mode 100644 system/library/video/tvshows_services/tags.xml create mode 100644 system/library/video/tvshows_services/titles.xml create mode 100644 system/library/video/tvshows_services/years.xml create mode 100644 system/library/video_flat/inprogressmovies.xml diff --git a/system/library/music/albums_services.xml b/system/library/music/albums_services.xml new file mode 100644 index 0000000000..f5784688da --- /dev/null +++ b/system/library/music/albums_services.xml @@ -0,0 +1,6 @@ + + + + DefaultMusicAlbums.png + services://music/albums/ + diff --git a/system/library/music/artists_services.xml b/system/library/music/artists_services.xml new file mode 100644 index 0000000000..ca35795f77 --- /dev/null +++ b/system/library/music/artists_services.xml @@ -0,0 +1,7 @@ + + + + DefaultMusicArtists.png + artists + services://music/artists/ + diff --git a/system/library/music/recentlyaddedalbums.xml b/system/library/music/recentlyaddedalbums.xml index 549d1c2fd4..ede74c35b9 100644 --- a/system/library/music/recentlyaddedalbums.xml +++ b/system/library/music/recentlyaddedalbums.xml @@ -1,6 +1,6 @@ - + DefaultMusicRecentlyAdded.png - musicdb://recentlyaddedalbums/ + services://music/recentlyaddedalbums/ diff --git a/system/library/music/songs_services.xml b/system/library/music/songs_services.xml new file mode 100644 index 0000000000..bc2d03b064 --- /dev/null +++ b/system/library/music/songs_services.xml @@ -0,0 +1,7 @@ + + + + DefaultMusicSongs.png + songs + services://music/songs/ + diff --git a/system/library/video/inprogressmovies.xml b/system/library/video/inprogressmovies.xml index ed3f14a2d3..fbb89bd974 100644 --- a/system/library/video/inprogressmovies.xml +++ b/system/library/video/inprogressmovies.xml @@ -1,7 +1,7 @@ - + DefaultInProgressShows.png movies - + services://movies/inprogressmovies diff --git a/system/library/video/inprogressshows.xml b/system/library/video/inprogressshows.xml index f058db54bf..c3eaf0b9db 100644 --- a/system/library/video/inprogressshows.xml +++ b/system/library/video/inprogressshows.xml @@ -1,7 +1,7 @@ - + DefaultInProgressShows.png tvshows - + services://tvshows/inprogressshows/ diff --git a/system/library/video/movies_services/actors.xml b/system/library/video/movies_services/actors.xml new file mode 100644 index 0000000000..2ce84dbf39 --- /dev/null +++ b/system/library/video/movies_services/actors.xml @@ -0,0 +1,8 @@ + + + + DefaultActor.png + movies + services://movies/actors/ + + diff --git a/system/library/video/movies_services/country.xml b/system/library/video/movies_services/country.xml new file mode 100644 index 0000000000..a419a503bb --- /dev/null +++ b/system/library/video/movies_services/country.xml @@ -0,0 +1,7 @@ + + + + DefaultCountry.png + movies + services://movies/countries/ + diff --git a/system/library/video/movies_services/directors.xml b/system/library/video/movies_services/directors.xml new file mode 100644 index 0000000000..710a8de0f9 --- /dev/null +++ b/system/library/video/movies_services/directors.xml @@ -0,0 +1,7 @@ + + + + DefaultDirector.png + movies + services://movies/directors/ + diff --git a/system/library/video/movies_services/genres.xml b/system/library/video/movies_services/genres.xml new file mode 100644 index 0000000000..040f202ea4 --- /dev/null +++ b/system/library/video/movies_services/genres.xml @@ -0,0 +1,7 @@ + + + + DefaultGenre.png + movies + services://movies/genres/ + diff --git a/system/library/video/movies_services/index.xml b/system/library/video/movies_services/index.xml new file mode 100644 index 0000000000..2c8cf9de7c --- /dev/null +++ b/system/library/video/movies_services/index.xml @@ -0,0 +1,6 @@ + + + + + DefaultMovies.png + diff --git a/system/library/video/movies_services/sets.xml b/system/library/video/movies_services/sets.xml new file mode 100644 index 0000000000..d84b734f68 --- /dev/null +++ b/system/library/video/movies_services/sets.xml @@ -0,0 +1,7 @@ + + + + DefaultSets.png + movies + services://movies/sets/ + diff --git a/system/library/video/movies_services/studios.xml b/system/library/video/movies_services/studios.xml new file mode 100644 index 0000000000..1883604ab3 --- /dev/null +++ b/system/library/video/movies_services/studios.xml @@ -0,0 +1,7 @@ + + + + DefaultStudios.png + movies + services://movies/studios/ + diff --git a/system/library/video/movies_services/tags.xml b/system/library/video/movies_services/tags.xml new file mode 100644 index 0000000000..2a1d807670 --- /dev/null +++ b/system/library/video/movies_services/tags.xml @@ -0,0 +1,7 @@ + + + + DefaultTags.png + movies + services://movies/tags/ + diff --git a/system/library/video/movies_services/titles.xml b/system/library/video/movies_services/titles.xml new file mode 100644 index 0000000000..261ad13813 --- /dev/null +++ b/system/library/video/movies_services/titles.xml @@ -0,0 +1,8 @@ + + + + DefaultMovieTitle.png + movies + sorttitle + services://movies/titles/ + diff --git a/system/library/video/movies_services/years.xml b/system/library/video/movies_services/years.xml new file mode 100644 index 0000000000..45e3fb2ee6 --- /dev/null +++ b/system/library/video/movies_services/years.xml @@ -0,0 +1,8 @@ + + + + DefaultYear.png + movies + services://movies/years/ + + diff --git a/system/library/video/recentlyaddedepisodes.xml b/system/library/video/recentlyaddedepisodes.xml index caf13574d8..42eedce004 100644 --- a/system/library/video/recentlyaddedepisodes.xml +++ b/system/library/video/recentlyaddedepisodes.xml @@ -1,6 +1,6 @@ - + DefaultRecentlyAddedEpisodes.png - videodb://recentlyaddedepisodes/ + services://tvshows/recentlyaddedepisodes/ diff --git a/system/library/video/recentlyaddedmovies.xml b/system/library/video/recentlyaddedmovies.xml index 1363d4b854..d8d01f2ce0 100644 --- a/system/library/video/recentlyaddedmovies.xml +++ b/system/library/video/recentlyaddedmovies.xml @@ -1,6 +1,6 @@ - + DefaultRecentlyAddedMovies.png - videodb://recentlyaddedmovies/ + services://movies/recentlyaddedmovies/ diff --git a/system/library/video/tvshows_services/actors.xml b/system/library/video/tvshows_services/actors.xml new file mode 100644 index 0000000000..2a8bd5b6ed --- /dev/null +++ b/system/library/video/tvshows_services/actors.xml @@ -0,0 +1,7 @@ + + + + DefaultActor.png + tvshows + services://tvshows/actors/ + diff --git a/system/library/video/tvshows_services/genres.xml b/system/library/video/tvshows_services/genres.xml new file mode 100644 index 0000000000..ac07cb0097 --- /dev/null +++ b/system/library/video/tvshows_services/genres.xml @@ -0,0 +1,7 @@ + + + + DefaultGenre.png + tvshows + services://tvshows/genres/ + diff --git a/system/library/video/tvshows_services/index.xml b/system/library/video/tvshows_services/index.xml new file mode 100644 index 0000000000..5a86f1f3c5 --- /dev/null +++ b/system/library/video/tvshows_services/index.xml @@ -0,0 +1,5 @@ + + + + DefaultTVShows.png + diff --git a/system/library/video/tvshows_services/studios.xml b/system/library/video/tvshows_services/studios.xml new file mode 100644 index 0000000000..3cf1932e78 --- /dev/null +++ b/system/library/video/tvshows_services/studios.xml @@ -0,0 +1,7 @@ + + + + DefaultStudios.png + tvshows + services://tvshows/studios/ + diff --git a/system/library/video/tvshows_services/tags.xml b/system/library/video/tvshows_services/tags.xml new file mode 100644 index 0000000000..d6103a510c --- /dev/null +++ b/system/library/video/tvshows_services/tags.xml @@ -0,0 +1,7 @@ + + + + DefaultTags.png + tvshows + services://tvshows/tags/ + diff --git a/system/library/video/tvshows_services/titles.xml b/system/library/video/tvshows_services/titles.xml new file mode 100644 index 0000000000..7fba49a70d --- /dev/null +++ b/system/library/video/tvshows_services/titles.xml @@ -0,0 +1,8 @@ + + + + DefaultTVShowTitle.png + tvshows + services://tvshows/titles/ + sorttitle + diff --git a/system/library/video/tvshows_services/years.xml b/system/library/video/tvshows_services/years.xml new file mode 100644 index 0000000000..9823ec0c15 --- /dev/null +++ b/system/library/video/tvshows_services/years.xml @@ -0,0 +1,7 @@ + + + + DefaultYear.png + tvshows + services://tvshows/years/ + diff --git a/system/library/video_flat/inprogressmovies.xml b/system/library/video_flat/inprogressmovies.xml new file mode 100644 index 0000000000..fbb89bd974 --- /dev/null +++ b/system/library/video_flat/inprogressmovies.xml @@ -0,0 +1,7 @@ + + + + DefaultInProgressShows.png + movies + services://movies/inprogressmovies + diff --git a/system/library/video_flat/inprogressshows.xml b/system/library/video_flat/inprogressshows.xml index f058db54bf..c3eaf0b9db 100644 --- a/system/library/video_flat/inprogressshows.xml +++ b/system/library/video_flat/inprogressshows.xml @@ -1,7 +1,7 @@ - + DefaultInProgressShows.png tvshows - + services://tvshows/inprogressshows/ diff --git a/system/library/video_flat/movies.xml b/system/library/video_flat/movies.xml index 13f2904e84..2cc29768fd 100644 --- a/system/library/video_flat/movies.xml +++ b/system/library/video_flat/movies.xml @@ -1,7 +1,8 @@ - + DefaultMovies.png movies sorttitle + services://movies/titles/ diff --git a/system/library/video_flat/recentlyaddedepisodes.xml b/system/library/video_flat/recentlyaddedepisodes.xml index caf13574d8..42eedce004 100644 --- a/system/library/video_flat/recentlyaddedepisodes.xml +++ b/system/library/video_flat/recentlyaddedepisodes.xml @@ -1,6 +1,6 @@ - + DefaultRecentlyAddedEpisodes.png - videodb://recentlyaddedepisodes/ + services://tvshows/recentlyaddedepisodes/ diff --git a/system/library/video_flat/recentlyaddedmovies.xml b/system/library/video_flat/recentlyaddedmovies.xml index 1363d4b854..d8d01f2ce0 100644 --- a/system/library/video_flat/recentlyaddedmovies.xml +++ b/system/library/video_flat/recentlyaddedmovies.xml @@ -1,6 +1,6 @@ - + DefaultRecentlyAddedMovies.png - videodb://recentlyaddedmovies/ + services://movies/recentlyaddedmovies/ diff --git a/system/library/video_flat/tvshows.xml b/system/library/video_flat/tvshows.xml index 5f19e4d89b..2eba10cd2d 100644 --- a/system/library/video_flat/tvshows.xml +++ b/system/library/video_flat/tvshows.xml @@ -1,7 +1,8 @@ - + DefaultTVShows.png tvshows sorttitle + services://movies/titles/ From 6604222add5d789b5c59e80f23393eddeac60ee6 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Mon, 16 Apr 2018 00:31:29 +0200 Subject: [PATCH 4/8] fix playback and updating for media provided by services especially essential for the usecase where widgets are loading onto the homescreen using VFS paths like services://movies/recentlyaddedmovies --- xbmc/FileItem.cpp | 5 ++ xbmc/FileItem.h | 1 + xbmc/filesystem/FavouritesDirectory.cpp | 2 + xbmc/interfaces/IAnnouncer.h | 3 +- xbmc/listproviders/DirectoryProvider.cpp | 94 ++++++++++++++++++------ xbmc/utils/HomeShelfJob.cpp | 4 + 6 files changed, 85 insertions(+), 24 deletions(-) diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index 094d53de52..57b11a4fa1 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -1150,6 +1150,11 @@ bool CFileItem::IsVirtualDirectoryRoot() const return (m_bIsFolder && m_strPath.empty()); } +bool CFileItem::IsFolder() const +{ + return m_bIsFolder; +} + bool CFileItem::IsRemovable() const { return IsOnDVD() || IsCDDA() || m_iDriveType == CMediaSource::SOURCE_TYPE_REMOVABLE; diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h index 03d6c72dc9..eaf562bc9c 100644 --- a/xbmc/FileItem.h +++ b/xbmc/FileItem.h @@ -218,6 +218,7 @@ class CFileItem : bool IsPVRRadioRDS() const; bool IsType(const char *ext) const; bool IsVirtualDirectoryRoot() const; + bool IsFolder() const; bool IsReadOnly() const; bool CanQueue() const; void SetCanQueue(bool bYesNo); diff --git a/xbmc/filesystem/FavouritesDirectory.cpp b/xbmc/filesystem/FavouritesDirectory.cpp index cc09b0db9b..5606f7c78f 100644 --- a/xbmc/filesystem/FavouritesDirectory.cpp +++ b/xbmc/filesystem/FavouritesDirectory.cpp @@ -201,6 +201,8 @@ std::string CFavouritesDirectory::GetExecutePath(const CFileItem &item, const st { if (item.IsVideoDb() && item.HasVideoInfoTag()) execute = StringUtils::Format("PlayMedia(%s)", StringUtils::Paramify(item.GetVideoInfoTag()->m_strFileNameAndPath).c_str()); + else if (item.IsMediaServiceBased() && item.HasVideoInfoTag()) + execute = StringUtils::Format("PlayMedia(%s)", StringUtils::Paramify(item.GetVideoInfoTag()->m_strFileNameAndPath).c_str()); else if (item.IsMusicDb() && item.HasMusicInfoTag()) execute = StringUtils::Format("PlayMedia(%s)", StringUtils::Paramify(item.GetMusicInfoTag()->GetURL()).c_str()); else if (item.IsPicture()) diff --git a/xbmc/interfaces/IAnnouncer.h b/xbmc/interfaces/IAnnouncer.h index e3dfdd1f58..b3c5baae16 100644 --- a/xbmc/interfaces/IAnnouncer.h +++ b/xbmc/interfaces/IAnnouncer.h @@ -33,7 +33,8 @@ namespace ANNOUNCEMENT Application = 0x040, Input = 0x080, PVR = 0x100, - Other = 0x200 + Other = 0x200, + MediaService = 0x300 }; #define ANNOUNCE_ALL (Player | Playlist | GUI | System | VideoLibrary | AudioLibrary | Application | Input | ANNOUNCEMENT::PVR | Other) diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp index d13a157a8a..e412872065 100644 --- a/xbmc/listproviders/DirectoryProvider.cpp +++ b/xbmc/listproviders/DirectoryProvider.cpp @@ -39,6 +39,9 @@ #include "utils/Variant.h" #include "utils/XMLUtils.h" #include "video/VideoThumbLoader.h" +#include "services/ServicesManager.h" +#include "playlists/PlayList.h" +#include "PlayListPlayer.h" using namespace XFILE; using namespace ANNOUNCEMENT; @@ -212,19 +215,20 @@ bool CDirectoryProvider::Update(bool forceRefresh) void CDirectoryProvider::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) { // we are only interested in library changes - if ((flag & (VideoLibrary | AudioLibrary)) == 0) + if ((flag & (VideoLibrary | AudioLibrary | MediaService)) == 0) return; - { CSingleLock lock(m_section); // we don't need to refresh anything if there are no fitting // items in this list provider for the announcement flag - if (((flag & VideoLibrary) && - (std::find(m_itemTypes.begin(), m_itemTypes.end(), VIDEO) == m_itemTypes.end())) || - ((flag & AudioLibrary) && - (std::find(m_itemTypes.begin(), m_itemTypes.end(), AUDIO) == m_itemTypes.end()))) - return; - + if (m_itemTypes.size() > 0) + { + if (((flag & VideoLibrary) && + (std::find(m_itemTypes.begin(), m_itemTypes.end(), VIDEO) == m_itemTypes.end())) || + ((flag & AudioLibrary) && + (std::find(m_itemTypes.begin(), m_itemTypes.end(), AUDIO) == m_itemTypes.end()))) + return; + } // if we're in a database transaction, don't bother doing anything just yet if (data.isMember("transaction") && data["transaction"].asBoolean()) return; @@ -234,6 +238,7 @@ void CDirectoryProvider::Announce(AnnouncementFlag flag, const char *sender, con if (strcmp(message, "OnScanFinished") == 0 || strcmp(message, "OnCleanFinished") == 0 || strcmp(message, "OnUpdate") == 0 || + strcmp(message, "ServicesUpdated") == 0 || strcmp(message, "OnRemove") == 0) m_updateState = PENDING; } @@ -290,22 +295,65 @@ bool CDirectoryProvider::OnClick(const CGUIListItemPtr &item) if (item->IsFileItem()) { CFileItem fileItem(*std::static_pointer_cast(item)); - std::string target = fileItem.GetProperty("node.target").asString(); - if (target.empty()) - target = m_currentTarget; - if (target.empty()) - target = m_target.GetLabel(m_parentID, false); - if (fileItem.HasProperty("node.target_url")) - fileItem.SetPath(fileItem.GetProperty("node.target_url").asString()); - // grab the execute string - std::string execute = CFavouritesDirectory::GetExecutePath(fileItem, target); - if (!execute.empty()) + + if (fileItem.IsMediaServiceBased() && !fileItem.IsFolder()) { - CGUIMessage message(GUI_MSG_EXECUTE, 0, 0); - message.SetStringParam(execute); - g_windowManager.SendMessage(message); + // handle playback for items from mediaservice + if (fileItem.IsAudio()) + { + // music items + CFileItemList items; + CServicesManager::GetInstance().GetAlbumSongs(fileItem, items); + g_playlistPlayer.Reset(); + g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC); + PLAYLIST::CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC); + playlist.Clear(); + playlist.Add(items); + // play full album, starting with first song... + g_playlistPlayer.Play(0); + g_windowManager.ActivateWindow(WINDOW_VISUALISATION); + } + else + { + // video items + if (!CServicesManager::GetInstance().GetResolutions(fileItem)) + return false; + CServicesManager::GetInstance().GetURL(fileItem); + + // always resume at resume point for now + fileItem.m_lStartOffset = STARTOFFSET_RESUME; + + g_playlistPlayer.Reset(); + g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); + PLAYLIST::CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_VIDEO); + playlist.Clear(); + CFileItemPtr movieItem(new CFileItem(fileItem)); + playlist.Add(movieItem); + + // play item + g_playlistPlayer.Play(0); + } return true; } + else + { + std::string target = fileItem.GetProperty("node.target").asString(); + if (target.empty()) + target = m_currentTarget; + if (target.empty()) + target = m_target.GetLabel(m_parentID, false); + if (fileItem.HasProperty("node.target_url")) + fileItem.SetPath(fileItem.GetProperty("node.target_url").asString()); + // grab the execute string + std::string execute = CFavouritesDirectory::GetExecutePath(fileItem, target); + if (!execute.empty()) + { + CGUIMessage message(GUI_MSG_EXECUTE, 0, 0); + message.SetStringParam(execute); + g_windowManager.SendMessage(message); + return true; + } + } } return false; } @@ -346,8 +394,8 @@ bool CDirectoryProvider::UpdateURL() m_currentUrl = value; - // Register this provider only if we have library content - RegisterListProvider(URIUtils::IsLibraryContent(m_currentUrl)); + // Register this provider only if we have library content or a media service + RegisterListProvider(URIUtils::IsLibraryContent(m_currentUrl) || URIUtils::IsServices(m_currentUrl)); return true; } diff --git a/xbmc/utils/HomeShelfJob.cpp b/xbmc/utils/HomeShelfJob.cpp index 212af03525..b24a5f23ec 100644 --- a/xbmc/utils/HomeShelfJob.cpp +++ b/xbmc/utils/HomeShelfJob.cpp @@ -36,6 +36,7 @@ #include "video/VideoThumbLoader.h" #include "settings/Settings.h" #include "services/ServicesManager.h" +#include "interfaces/AnnouncementManager.h" #if defined(TARGET_DARWIN_TVOS) #include "platform/darwin/DarwinUtils.h" @@ -305,6 +306,9 @@ bool CHomeShelfJob::UpdateTotal() EpWatched = EpWatched + (mediaTotals.iEpisodeTotal - mediaTotals.iEpisodeUnwatched); EpCount = EpCount + mediaTotals.iEpisodeTotal; TvShowsWatched = TvShowsWatched + (mediaTotals.iShowTotal - mediaTotals.iShowUnwatched); + + // signal library providers that our services have been updated so lists can be refreshed if needed etc. + ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::MediaService, "xbmc", "ServicesUpdated"); } home->SetProperty("Music.SongsCount" , MusSongTotals); From f8eddf1767f1dd9fd020b4aa32f953257abf0506 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 28 Apr 2018 09:51:24 +0200 Subject: [PATCH 5/8] fix plex music listings --- system/library/music/albums_services.xml | 3 +- xbmc/filesystem/PlexDirectory.cpp | 41 +++++++++++++++++------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/system/library/music/albums_services.xml b/system/library/music/albums_services.xml index f5784688da..a7bf5da687 100644 --- a/system/library/music/albums_services.xml +++ b/system/library/music/albums_services.xml @@ -2,5 +2,6 @@ DefaultMusicAlbums.png - services://music/albums/ + services://music/albums + albums diff --git a/xbmc/filesystem/PlexDirectory.cpp b/xbmc/filesystem/PlexDirectory.cpp index efa45335d6..cbdb345647 100644 --- a/xbmc/filesystem/PlexDirectory.cpp +++ b/xbmc/filesystem/PlexDirectory.cpp @@ -54,11 +54,16 @@ bool CPlexDirectory::GetDirectory(const CURL& url, CFileItemList &items) CLog::Log(LOGDEBUG, "CPlexDirectory::GetDirectory strURL = %s", strUrl.c_str()); - CVideoDatabase database; - database.Open(); - bool hasMovies = database.HasContent(VIDEODB_CONTENT_MOVIES); - bool hasShows = database.HasContent(VIDEODB_CONTENT_TVSHOWS); - database.Close(); + CVideoDatabase vdatabase; + vdatabase.Open(); + bool hasMovies = vdatabase.HasContent(VIDEODB_CONTENT_MOVIES); + bool hasShows = vdatabase.HasContent(VIDEODB_CONTENT_TVSHOWS); + vdatabase.Close(); + CMusicDatabase mdatabase; + mdatabase.Open(); + bool hasMusic = mdatabase.HasContent(); + mdatabase.Close(); + if (StringUtils::StartsWithNoCase(strUrl, "plex://movies/")) { @@ -306,15 +311,27 @@ bool CPlexDirectory::GetDirectory(const CURL& url, CFileItemList &items) { if (section.empty()) { - //look through all plex servers and pull content data for "show" type + std::string pathsection = ""; + if (basePath == "artists") + pathsection = "all"; + else if (basePath == "albums") + pathsection = "all?type=9"; + else if (basePath == "songs") + pathsection = "all?type=10"; + else if (basePath == "recentlyaddedalbums") + pathsection = "recentlyAdded"; + //look through all plex servers and pull content data for "music" type std::vector clients; CPlexServices::GetInstance().GetClients(clients); for (const auto &client : clients) { client->ClearSectionItems(); std::vector contents = client->GetArtistContent(); - if (contents.size() > 1 || ((items.Size() > 0 || CServicesManager::GetInstance().HasEmbyServices() || clients.size() > 1) && contents.size() == 1)) + if (contents.size() > 1 || + ((items.Size() > 0 || hasMusic || CServicesManager::GetInstance().HasEmbyServices() || + clients.size() > 1) && contents.size() == 1)) { + // multiple folders or providers found, add root folder for each node for (const auto &content : contents) { std::string title = client->FormatContentTitle(content.title); @@ -325,7 +342,7 @@ bool CPlexDirectory::GetDirectory(const CURL& url, CFileItemList &items) // have to do it this way because raw url has authToken as protocol option CURL curl(client->GetUrl()); curl.SetProtocol(client->GetProtocol()); - std::string filename = StringUtils::Format("%s/%s", content.section.c_str(), (basePath == "root" || basePath == "artists"? "all":basePath.c_str())); + std::string filename = StringUtils::Format("%s/%s", content.section.c_str(), pathsection.c_str()); curl.SetFileName(filename); pItem->SetPath("plex://music/" + basePath + "/" + Base64URL::Encode(curl.Get())); pItem->SetLabel(title); @@ -341,16 +358,16 @@ bool CPlexDirectory::GetDirectory(const CURL& url, CFileItemList &items) } else if (contents.size() == 1) { + // only one folder/provider found, pull content directly CURL curl(client->GetUrl()); curl.SetProtocol(client->GetProtocol()); - curl.SetFileName(contents[0].section + "/all"); - CPlexUtils::GetPlexArtistsOrAlbum(items, curl.Get(), false); + std::string filename = StringUtils::Format("%s/%s", contents[0].section.c_str(), pathsection.c_str()); + curl.SetFileName(filename); + CDirectory::GetDirectory("plex://music/" + basePath + "/" + Base64URL::Encode(curl.Get()), items); items.SetContent("artists"); - items.SetPath("plex://music/albums/"); CPlexUtils::SetPlexItemProperties(items, client); for (int item = 0; item < items.Size(); ++item) CPlexUtils::SetPlexItemProperties(*items[item], client); - CLog::Log(LOGDEBUG, "CPlexDirectory::GetDirectory '/all' client(%s), shows(%d)", client->GetServerName().c_str(), items.Size()); } std::string label = basePath; if (URIUtils::GetFileName(basePath) == "recentlyaddedalbums") From a059b150a914bd1c92b028a51af3aa24b18c1cee Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 28 Apr 2018 09:52:08 +0200 Subject: [PATCH 6/8] fix content from services in Files.GetDirectory json rpc api --- xbmc/Util.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp index 674f6ff767..8231d0f872 100644 --- a/xbmc/Util.cpp +++ b/xbmc/Util.cpp @@ -1033,6 +1033,12 @@ int CUtil::GetMatchingSource(const std::string& strPath1, VECSOURCES& VECSOURCES strPath = checkURL.GetHostName(); if (checkURL.IsProtocol("plugin")) return 1; + if (checkURL.IsProtocol("services")) + return 1; + if (checkURL.IsProtocol("plex")) + return 1; + if (checkURL.IsProtocol("emby")) + return 1; if (checkURL.IsProtocol("multipath")) strPath = CMultiPathDirectory::GetFirstPath(strPath); From 247340ef06e2dab23e829164656989f9ad91e3e1 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 28 Apr 2018 11:03:57 +0200 Subject: [PATCH 7/8] fix typo in PlexUtils --- xbmc/services/plex/PlexUtils.cpp | 8 ++++---- xbmc/services/plex/PlexUtils.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/xbmc/services/plex/PlexUtils.cpp b/xbmc/services/plex/PlexUtils.cpp index cce24435b0..818fc51487 100644 --- a/xbmc/services/plex/PlexUtils.cpp +++ b/xbmc/services/plex/PlexUtils.cpp @@ -616,7 +616,7 @@ bool CPlexUtils::GetItemSubtiles(CFileItem &item) for (auto variantIt = variantMedia.begin_array(); variantIt != variantMedia.end_array(); ++variantIt) { if (*variantIt != CVariant::VariantTypeNull) - GetMediaDetals(item, curl, *variantIt, item.GetProperty("PlexMediaID").asString()); + GetMediaDetails(item, curl, *variantIt, item.GetProperty("PlexMediaID").asString()); } } } @@ -681,7 +681,7 @@ bool CPlexUtils::GetMoreResolutions(CFileItem &item) if (*variantIt != CVariant::VariantTypeNull) { CFileItem mediaItem(item); - GetMediaDetals(mediaItem, curl, *variantIt); + GetMediaDetails(mediaItem, curl, *variantIt); resolutionList.push_back(mediaItem); choices.Add(resolutionList.size(), mediaItem.GetProperty("PlexResolutionChoice").c_str()); } @@ -1306,7 +1306,7 @@ bool CPlexUtils::ParsePlexVideos(CFileItemList &items, CURL url, const CVariant plexItem->m_lStartOffset = item["viewOffset"].asInteger() / 1000; const CVariant media = makeVariantArrayIfSingleItem(item["Media"]); - GetMediaDetals(*plexItem, url, media[0]); + GetMediaDetails(*plexItem, url, media[0]); if (formatLabel) { @@ -1848,7 +1848,7 @@ void CPlexUtils::GetMusicDetails(CFileItem &item, const CVariant &video) */ } -void CPlexUtils::GetMediaDetals(CFileItem &item, CURL url, const CVariant &media, std::string id) +void CPlexUtils::GetMediaDetails(CFileItem &item, CURL url, const CVariant &media, std::string id) { if (!media.isNull() && (id == "0" || media["id"].asString() == id)) { diff --git a/xbmc/services/plex/PlexUtils.h b/xbmc/services/plex/PlexUtils.h index 07453a7c6f..1eff6b5df5 100644 --- a/xbmc/services/plex/PlexUtils.h +++ b/xbmc/services/plex/PlexUtils.h @@ -100,7 +100,7 @@ class CPlexUtils static void ReportToServer(std::string url, std::string filename); static void GetVideoDetails(CFileItem &item, const CVariant &variant); static void GetMusicDetails(CFileItem &item, const CVariant &video); - static void GetMediaDetals(CFileItem &item, CURL url, const CVariant &media, std::string id = "0"); + static void GetMediaDetails(CFileItem &item, CURL url, const CVariant &media, std::string id = "0"); static CVariant GetPlexCVariant(std::string url, std::string filter = ""); static TiXmlDocument GetPlexXML(std::string url, std::string filter = ""); static int ParsePlexCVariant(const CVariant &item); From ed194c4edde2421936c62584b23098c3cb009515 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Mon, 30 Apr 2018 10:26:36 +0200 Subject: [PATCH 8/8] properly assign ratings from Plex Retrieve all ratings from plex and set them on the listitem's properties. --- xbmc/services/plex/PlexUtils.cpp | 48 ++++++++++++++++++++++++++++++-- xbmc/services/plex/PlexUtils.h | 1 + 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/xbmc/services/plex/PlexUtils.cpp b/xbmc/services/plex/PlexUtils.cpp index 818fc51487..d552e4cabd 100644 --- a/xbmc/services/plex/PlexUtils.cpp +++ b/xbmc/services/plex/PlexUtils.cpp @@ -165,6 +165,47 @@ void CPlexUtils::SetPlexItemProperties(CFileItem &item, const CPlexClientPtr &cl item.SetProperty("MediaServicesLocalItem", true); } +void CPlexUtils::SetPlexRatingProperties(CFileItem &plexItem, const CVariant &item) +{ + // set rating (extract ratingtype from ratingimage) + std::string ratingProvider = ""; + std::string ratingDelimiter = "://"; + std::string ratingImageValue = item["ratingImage"].asString(); + if (ratingImageValue != "") + { + std::string::size_type pos = ratingImageValue.find(ratingDelimiter); + ratingProvider = ratingImageValue.substr(0, pos); + std::string ratingImage = ratingImageValue.substr(pos + ratingDelimiter.length()); + plexItem.SetProperty("ratingImage", ratingImage); + if (ratingProvider == "rottentomatoes") + plexItem.SetProperty("RottenTomatoesRating", item["rating"].asFloat() * 10); + } + plexItem.GetVideoInfoTag()->SetRating(item["rating"].asFloat(), ratingProvider, true); + + // audience rating + std::string audienceRatingImageValue = item["audienceRatingImage"].asString(); + if (audienceRatingImageValue != "") + { + std::string::size_type pos = audienceRatingImageValue.find(ratingDelimiter); + ratingProvider = audienceRatingImageValue.substr(0, pos); + std::string audienceRatingImage = audienceRatingImageValue.substr(pos + ratingDelimiter.length()); + plexItem.SetProperty("audienceRatingImage", audienceRatingImage); + plexItem.SetProperty("audienceRating", item["audienceRating"].asString()); + if (ratingProvider == "rottentomatoes") + plexItem.SetProperty("RottenTomatoesAudienceRating", item["audienceRating"].asFloat() * 10); + ratingProvider += "audience"; + plexItem.GetVideoInfoTag()->SetRating(item["audienceRating"].asFloat(), ratingProvider, false); + } + + // User rating + if (item["userRating"].asString() != "") { + plexItem.GetVideoInfoTag()->SetUserrating(item["userRating"].asInteger()); + } + + // MPAA rating + plexItem.GetVideoInfoTag()->m_strMPAARating = item["contentRating"].asString(); +} + #pragma mark - Plex Server Utils void CPlexUtils::SetWatched(CFileItem &item) { @@ -1287,9 +1328,10 @@ bool CPlexUtils::ParsePlexVideos(CFileItemList &items, CURL url, const CVariant plexItem->SetArt("fanart", url.Get()); plexItem->GetVideoInfoTag()->SetYear(item["year"].asInteger()); - plexItem->GetVideoInfoTag()->SetRating(item["rating"].asFloat()); - plexItem->GetVideoInfoTag()->m_strMPAARating = item["contentRating"].asString(); - + + // Set ratings + SetPlexRatingProperties(*plexItem, item); + // lastViewedAt means that it was watched, if so we set m_playCount to 1 and set overlay. // If we have "viewOffset" that means we are partially watched and shoudl not set m_playCount to 1 if (item.isMember("lastViewedAt") && !item.isMember("viewOffset")) diff --git a/xbmc/services/plex/PlexUtils.h b/xbmc/services/plex/PlexUtils.h index 1eff6b5df5..22e5502582 100644 --- a/xbmc/services/plex/PlexUtils.h +++ b/xbmc/services/plex/PlexUtils.h @@ -45,6 +45,7 @@ class CPlexUtils static void GetDefaultHeaders(XFILE::CCurlFile &curl); static void SetPlexItemProperties(CFileItem &item); static void SetPlexItemProperties(CFileItem &item, const CPlexClientPtr &client); + static void SetPlexRatingProperties(CFileItem &plexItem, const CVariant &item); // Plex Server Utils static void SetWatched(CFileItem &item);