From 7cf615f6715cccb415ebf6dcf051396d9457a316 Mon Sep 17 00:00:00 2001 From: marcelveldt Date: Tue, 19 Jan 2016 21:27:58 +0100 Subject: [PATCH] simplify channel browse code add experimental support for live tv channels and recordings (without pvr) --- resources/lib/artwork.py | 2 +- resources/lib/entrypoint.py | 112 +++++++++---------------------- resources/lib/playutils.py | 10 ++- resources/lib/read_embyserver.py | 30 +++++++++ 4 files changed, 73 insertions(+), 81 deletions(-) diff --git a/resources/lib/artwork.py b/resources/lib/artwork.py index 25860bb4..b1d408e6 100644 --- a/resources/lib/artwork.py +++ b/resources/lib/artwork.py @@ -506,7 +506,7 @@ class Artwork(): id = item['Id'] artworks = item['ImageTags'] - backdrops = item['BackdropImageTags'] + backdrops = item.get('BackdropImageTags',[]) maxHeight = 10000 maxWidth = 10000 diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 391cb7ac..1240e738 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -76,7 +76,11 @@ def doMainListing(): addDirectoryItem(label, path) elif path and not xbmc.getCondVisibility("Window.IsActive(VideoLibrary) | Window.IsActive(Pictures) | Window.IsActive(MusicLibrary)"): addDirectoryItem(label, path) - + + #experimental live tv nodes + addDirectoryItem("Live Tv Channels (experimental)", "plugin://plugin.video.emby/?mode=browsecontent&type=tvchannels&folderid=root") + addDirectoryItem("Live Tv Recordings (experimental)", "plugin://plugin.video.emby/?mode=browsecontent&type=recordings&folderid=root") + # some extra entries for settings and stuff. TODO --> localize the labels addDirectoryItem("Network credentials", "plugin://plugin.video.emby/?mode=passwords") addDirectoryItem("Settings", "plugin://plugin.video.emby/?mode=settings") @@ -395,10 +399,12 @@ def refreshPlaylist(): time=1000, sound=False) -##### BROWSE EMBY HOMEVIDEOS AND PICTURES ##### +##### BROWSE EMBY NODES DIRECTLY ##### def BrowseContent(viewname, type="", folderid=None, filter=""): emby = embyserver.Read_EmbyServer() + art = artwork.Artwork() + doUtils = downloadutils.DownloadUtils() utils.logMsg("BrowseHomeVideos","viewname: %s - type: %s - folderid: %s - filter: %s" %(viewname, type, folderid, filter)) xbmcplugin.setPluginCategory(int(sys.argv[1]), viewname) #get views for root level @@ -421,7 +427,11 @@ def BrowseContent(viewname, type="", folderid=None, filter=""): itemtype = "" #get the actual listing - if filter == "recent": + if type == "recordings": + listing = emby.getTvRecordings(folderid) + elif type == "tvchannels": + listing = emby.getTvChannels() + elif filter == "recent": listing = emby.getFilteredSection("", itemtype=itemtype.split(",")[0], sortby="DateCreated", recursive=True, limit=25, sortorder="Descending") elif filter == "random": listing = emby.getFilteredSection("", itemtype=itemtype.split(",")[0], sortby="Random", recursive=True, limit=150, sortorder="Descending") @@ -435,7 +445,7 @@ def BrowseContent(viewname, type="", folderid=None, filter=""): #process the listing if listing: for item in listing.get("Items"): - li = createListItemFromEmbyItem(item) + li = createListItemFromEmbyItem(item,art,doUtils) if item.get("IsFolder") == True: #for folders we add an additional browse request, passing the folderId path = "%s?id=%s&mode=browsecontent&type=%s&folderid=%s" % (sys.argv[0], viewname, type, item.get("Id")) @@ -455,10 +465,8 @@ def BrowseContent(viewname, type="", folderid=None, filter=""): xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_RUNTIME) ##### CREATE LISTITEM FROM EMBY METADATA ##### -def createListItemFromEmbyItem(item): +def createListItemFromEmbyItem(item,art=artwork.Artwork(),doUtils=downloadutils.DownloadUtils()): API = api.API(item) - art = artwork.Artwork() - doUtils = downloadutils.DownloadUtils() itemid = item['Id'] title = item.get('Name') @@ -495,10 +503,11 @@ def createListItemFromEmbyItem(item): genre = API.getGenres() overlay = 0 userdata = API.getUserData() + runtime = item.get("RunTimeTicks",0)/ 10000000.0 seektime = userdata['Resume'] if seektime: li.setProperty("resumetime", seektime) - li.setProperty("totaltime", item.get("RunTimeTicks")/ 10000000.0) + li.setProperty("totaltime", str(runtime)) played = userdata['Played'] if played: overlay = 7 @@ -515,26 +524,35 @@ def createListItemFromEmbyItem(item): 'id': itemid, 'rating': rating, 'year': item.get('ProductionYear'), - 'premieredate': premieredate, - 'date': premieredate, 'genre': genre, 'playcount': str(playcount), 'title': title, 'plot': API.getOverview(), 'Overlay': str(overlay), + 'duration': runtime } + if premieredate: + extradata["premieredate"] = premieredate + extradata["date"] = premieredate li.setInfo('video', infoLabels=extradata) - li.setThumbnailImage(allart.get('Primary')) + if allart.get('Primary'): + li.setThumbnailImage(allart.get('Primary')) + else: li.setThumbnailImage('DefaultTVShows.png') li.setIconImage('DefaultTVShows.png') if not allart.get('Background'): #add image as fanart for use with skinhelper auto thumb/backgrund creation li.setArt( {"fanart": allart.get('Primary') } ) else: pbutils.PlaybackUtils(item).setArtwork(li) - + mediastreams = API.getMediaStreams() + videostreamFound = False if mediastreams: for key, value in mediastreams.iteritems(): + if key == "video" and value: videostreamFound = True if value: li.addStreamInfo(key, value[0]) + if not videostreamFound: + #just set empty streamdetails to prevent errors in the logs + li.addStreamInfo("video", {'duration': runtime}) return li @@ -558,84 +576,20 @@ def BrowseChannels(itemid, folderid=None): url = "{server}/emby/Channels/%s/Items?UserId={UserId}&format=json" % itemid result = doUtils.downloadUrl(url) - try: - channels = result['Items'] - except TypeError: - pass - else: - for item in channels: - - API = api.API(item) + if result and result.get("Items"): + for item in result.get("Items"): itemid = item['Id'] itemtype = item['Type'] - title = item.get('Name', "Missing Title") - li = xbmcgui.ListItem(title) - + li = createListItemFromEmbyItem(item,art,doUtils) if itemtype == "ChannelFolderItem": isFolder = True else: isFolder = False - channelId = item.get('ChannelId', "") channelName = item.get('ChannelName', "") - - premieredate = API.getPremiereDate() - # Process Genres - genre = API.getGenres() - # Process UserData - overlay = 0 - - userdata = API.getUserData() - seektime = userdata['Resume'] - played = userdata['Played'] - if played: - overlay = 7 - else: - overlay = 6 - - favorite = userdata['Favorite'] - if favorite: - overlay = 5 - - playcount = userdata['PlayCount'] - if playcount is None: - playcount = 0 - - # Populate the details list - details = { - - 'title': title, - 'channelname': channelName, - 'plot': API.getOverview(), - 'Overlay': str(overlay), - 'playcount': str(playcount) - } - - if itemtype == "ChannelVideoItem": - xbmcplugin.setContent(_addon_id, 'movies') - elif itemtype == "ChannelAudioItem": - xbmcplugin.setContent(_addon_id, 'songs') - - # Populate the extradata list and artwork - pbutils.PlaybackUtils(item).setArtwork(li) - extradata = { - - 'id': itemid, - 'rating': item.get('CommunityRating'), - 'year': item.get('ProductionYear'), - 'premieredate': premieredate, - 'genre': genre, - 'playcount': str(playcount), - 'itemtype': itemtype - } - li.setInfo('video', infoLabels=extradata) - li.setThumbnailImage(art.getAllArtwork(item)['Primary']) - li.setIconImage('DefaultTVShows.png') - if itemtype == "Channel": path = "%s?id=%s&mode=channels" % (_addon_url, itemid) xbmcplugin.addDirectoryItem(handle=_addon_id, url=path, listitem=li, isFolder=True) - elif isFolder: path = "%s?id=%s&mode=channelsfolder&folderid=%s" % (_addon_url, channelId, itemid) xbmcplugin.addDirectoryItem(handle=_addon_id, url=path, listitem=li, isFolder=True) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index cc04d3b2..443792de 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -34,9 +34,17 @@ class PlayUtils(): def getPlayUrl(self): item = self.item + print "playutilks" + print item playurl = None + + if item.get('Type') in ["Recording","TvChannel"] and item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http": + #Is this the right way to play a Live TV or recordings ? + self.logMsg("File protocol is http (livetv).", 1) + playurl = "%s/emby/Videos/%s/live.m3u8?static=true" % (self.server, item['Id']) + utils.window('emby_%s.playmethod' % playurl, value="DirectPlay") - if item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http": + elif item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http": # Only play as http self.logMsg("File protocol is http.", 1) playurl = self.httpPlay() diff --git a/resources/lib/read_embyserver.py b/resources/lib/read_embyserver.py index 323745d4..665972fc 100644 --- a/resources/lib/read_embyserver.py +++ b/resources/lib/read_embyserver.py @@ -149,6 +149,36 @@ class Read_EmbyServer(): } return doUtils.downloadUrl(url, parameters=params) + def getTvChannels(self): + doUtils = self.doUtils + url = "{server}/emby/LiveTv/Channels/?userid={UserId}&format=json" + params = { + + 'EnableImages': True, + 'Fields': ( "Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines," + "CommunityRating,OfficialRating,CumulativeRunTimeTicks," + "Metascore,AirTime,DateCreated,MediaStreams,People,Overview," + "CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations," + "Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers") + } + return doUtils.downloadUrl(url, parameters=params) + + def getTvRecordings(self, groupid): + doUtils = self.doUtils + url = "{server}/emby/LiveTv/Recordings/?userid={UserId}&format=json" + if groupid == "root": groupid = "" + params = { + + 'GroupId': groupid, + 'EnableImages': True, + 'Fields': ( "Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines," + "CommunityRating,OfficialRating,CumulativeRunTimeTicks," + "Metascore,AirTime,DateCreated,MediaStreams,People,Overview," + "CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations," + "Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers") + } + return doUtils.downloadUrl(url, parameters=params) + def getSection(self, parentid, itemtype=None, sortby="SortName", basic=False, dialog=None): doUtils = self.doUtils