diff --git a/system/library/music/albums_services.xml b/system/library/music/albums_services.xml
new file mode 100644
index 0000000000..a7bf5da687
--- /dev/null
+++ b/system/library/music/albums_services.xml
@@ -0,0 +1,7 @@
+
+
+
+ DefaultMusicAlbums.png
+ services://music/albums
+ 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/
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/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);
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",
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/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/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")
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");
}
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/services/plex/PlexUtils.cpp b/xbmc/services/plex/PlexUtils.cpp
index cce24435b0..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)
{
@@ -616,7 +657,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 +722,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());
}
@@ -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"))
@@ -1306,7 +1348,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 +1890,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..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);
@@ -100,7 +101,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);
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);