From 44b22e7a67687378f82e31908544b14553e7f7d7 Mon Sep 17 00:00:00 2001 From: im85288 <ianmalcolmmclaughlin@gmail.com> Date: Wed, 6 May 2015 22:41:44 +0100 Subject: [PATCH 1/2] replaced auto play episode with custom nextup dialog, also added ItemInfo and PersonInfo from the old addon --- default.py | 7 + resources/language/English/strings.xml | 5 + resources/lib/API.py | 1 + resources/lib/Entrypoint.py | 25 + resources/lib/ItemInfo.py | 526 ++++++++++++++++++++ resources/lib/NextUpInfo.py | 102 ++++ resources/lib/PersonInfo.py | 169 +++++++ resources/lib/Player.py | 31 +- resources/lib/WriteKodiDB.py | 17 +- resources/settings.xml | 8 +- resources/skins/default/720p/ItemInfo.xml | 415 +++++++++++++++ resources/skins/default/720p/NextUpInfo.xml | 245 +++++++++ resources/skins/default/720p/PersonInfo.xml | 205 ++++++++ service.py | 11 +- 14 files changed, 1741 insertions(+), 26 deletions(-) create mode 100644 resources/lib/ItemInfo.py create mode 100644 resources/lib/NextUpInfo.py create mode 100644 resources/lib/PersonInfo.py create mode 100644 resources/skins/default/720p/ItemInfo.xml create mode 100644 resources/skins/default/720p/NextUpInfo.xml create mode 100644 resources/skins/default/720p/PersonInfo.xml diff --git a/default.py b/default.py index 54074ad8..a50efa3f 100644 --- a/default.py +++ b/default.py @@ -21,6 +21,7 @@ try: params = utils.get_params(sys.argv[2]) mode = params['mode'] id = params.get('id', None) + name = params.get('name',None) except: params = {} mode = None @@ -28,6 +29,12 @@ except: ##### Play items via plugin://plugin.video.emby/ ##### if mode == "play": entrypoint.doPlayback(id) + +elif mode == "info": + entrypoint.showInfo(id) + +elif mode == "person": + entrypoint.showPersonInfo(id,name) ##### DO DATABASE RESET ##### elif mode == "reset": diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index 532dbd65..347fb2c4 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -245,6 +245,11 @@ <string id="30243">Enable HTTPS</string> <string id="30245">Force Transcoding Codecs</string> + <string id="30246">Enable Netflix style next up notification</string> + <string id="30247"> - The number of seconds before the end to show the notification</string> + <string id="30248">Show Emby Info dialog on play/select action</string> + + <!-- Default views --> <string id="30300">Active</string> <string id="30301">Clear Settings</string> diff --git a/resources/lib/API.py b/resources/lib/API.py index 3239f60b..7823f45e 100644 --- a/resources/lib/API.py +++ b/resources/lib/API.py @@ -2,6 +2,7 @@ # This class helps translate more complex cases from the MediaBrowser API to the XBMC API from datetime import datetime +from random import randrange import xbmc import xbmcgui import xbmcaddon diff --git a/resources/lib/Entrypoint.py b/resources/lib/Entrypoint.py index 64bcac16..bb3f5ff3 100644 --- a/resources/lib/Entrypoint.py +++ b/resources/lib/Entrypoint.py @@ -17,6 +17,8 @@ from PlaybackUtils import PlaybackUtils from DownloadUtils import DownloadUtils from ReadEmbyDB import ReadEmbyDB from API import API +from ItemInfo import ItemInfo +from PersonInfo import PersonInfo ##### Play items via plugin://plugin.video.emby/ ##### @@ -26,6 +28,29 @@ def doPlayback(id): item = PlaybackUtils().PLAY(result, setup="default") +##### Show the item info window ##### +def showInfo(id): + xbmcplugin.endOfDirectory(int(sys.argv[1]), cacheToDisc=False) + addonSettings = xbmcaddon.Addon(id='plugin.video.emby') + infoPage = ItemInfo("ItemInfo.xml", addonSettings.getAddonInfo('path'), "default", "720p") + infoPage.setId(id) + infoPage.doModal() + del infoPage + + +def showPersonInfo(id,basename): + xbmcplugin.endOfDirectory(int(sys.argv[1]), cacheToDisc=False) + addonSettings = xbmcaddon.Addon(id='plugin.video.emby') + infoPage = PersonInfo("PersonInfo.xml", addonSettings.getAddonInfo('path'), "default", "720p") + infoPage.setPersonName(basename) + infoPage.doModal() + + if(infoPage.showMovies == True): + xbmc.log("RUNNING_PLUGIN: " + infoPage.pluginCastLink) + xbmc.executebuiltin(infoPage.pluginCastLink) + + del infoPage + #### DO RESET AUTH ##### def resetAuth(): # User tried login and failed too many times diff --git a/resources/lib/ItemInfo.py b/resources/lib/ItemInfo.py new file mode 100644 index 00000000..cb890c88 --- /dev/null +++ b/resources/lib/ItemInfo.py @@ -0,0 +1,526 @@ + +import sys +import xbmc +import xbmcgui +import xbmcaddon +import json as json +import urllib +from DownloadUtils import DownloadUtils +from API import API + + +_MODE_BASICPLAY=12 +_MODE_CAST_LIST=14 +_MODE_PERSON_DETAILS=15 +CP_ADD_URL = 'plugin://plugin.video.couchpotato_manager/movies/add?title=' +CP_ADD_VIA_IMDB = 'plugin://plugin.video.couchpotato_manager/movies/add?imdb_id=' + + +class ItemInfo(xbmcgui.WindowXMLDialog): + + id = "" + playUrl = "" + trailerUrl = "" + couchPotatoUrl = "" + userid = "" + server = "" + downloadUtils = DownloadUtils() + item= [] + isTrailer = False + + def __init__(self, *args, **kwargs): + xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) + xbmc.log("WINDOW INITIALISED") + + def onInit(self): + self.action_exitkeys_id = [10, 13] + url = "{server}/mediabrowser/Users/{UserId}/Items/" + self.id + "?Fields=SeriesGenres,AirTime&format=json" + item = self.downloadUtils.downloadUrl(url) + self.item = item + + id = item.get("Id") + WINDOW = xbmcgui.Window( 10025 ) + WINDOW.setProperty('ItemGUID', id) + + name = item.get("Name") + image = API().getArtwork(item, "poster") + fanArt = API().getArtwork(item, "BackdropNoIndicators") + self.getControl(3001).setImage(fanArt) + + discart = API().getArtwork(item ,"Disc") + logo = API().getArtwork(item ,"Logo") + # calculate the percentage complete + userData = item.get("UserData") + cappedPercentage = 0 + + if(userData != None): + playBackTicks = float(userData.get("PlaybackPositionTicks")) + if(playBackTicks != None and playBackTicks > 0): + runTimeTicks = float(item.get("RunTimeTicks", "0")) + if(runTimeTicks > 0): + percentage = int((playBackTicks / runTimeTicks) * 100.0) + cappedPercentage = percentage - (percentage % 10) + if(cappedPercentage == 0): + cappedPercentage = 10 + if(cappedPercentage == 100): + cappedPercentage = 90 + + try: + watchedButton = self.getControl(3192) + except: + watchedButton = None + if(watchedButton != None): + if userData.get("Played") == True: + watchedButton.setSelected(True) + else: + watchedButton.setSelected(False) + + try: + dislikeButton = self.getControl(3193) + except: + dislikeButton = None + if(dislikeButton != None): + if userData.get("Likes") != None and userData.get("Likes") == False: + dislikeButton.setSelected(True) + else: + dislikeButton.setSelected(False) + + try: + likeButton = self.getControl(3194) + except: + likeButton = None + if(likeButton != None): + if userData.get("Likes") != None and userData.get("Likes") == True: + likeButton.setSelected(True) + else: + likeButton.setSelected(False) + + try: + favouriteButton = self.getControl(3195) + except: + favouriteButton = None + if(favouriteButton != None): + if userData.get("IsFavorite") == True: + favouriteButton.setSelected(True) + else: + favouriteButton.setSelected(False) + + + episodeInfo = "" + type = item.get("Type") + WINDOW.setProperty('ItemType', type) + if(type == "Episode" or type == "Season"): + WINDOW.setProperty('ItemGUID', item.get("SeriesId")) + name = item.get("SeriesName") + ": " + name + season = str(item.get("ParentIndexNumber")).zfill(2) + episodeNum = str(item.get("IndexNumber")).zfill(2) + episodeInfo = "S" + season + "xE" + episodeNum + elif type == "Movie": + if item.get("Taglines") != None and item.get("Taglines") != [] and item.get("Taglines")[0] != None: + episodeInfo = item.get("Taglines")[0] + elif type == "ChannelVideoItem": + if item.get("ExtraType") != None: + if item.get('ExtraType') == "Trailer": + self.isTrailer = True + + + self.playUrl = "plugin://plugin.video.emby/?id=%s&mode=play" % id + + try: + trailerButton = self.getControl(3102) + if(trailerButton != None): + if not self.isTrailer and item.get("LocalTrailerCount") != None and item.get("LocalTrailerCount") > 0: + itemTrailerUrl = "{server}/mediabrowser/Users/{UserId}/Items/" + id + "/LocalTrailers?format=json" + jsonData = self.downloadUtils.downloadUrl(itemTrailerUrl) + if(jsonData != ""): + trailerItem = jsonData + self.trailerUrl = "plugin://plugin.video.emby/trailer/?id=%s&mode=play" % trailerItem[0][u'Id'] + else: + trailerButton.setEnabled(False) + except: + pass + + try: + couchPotatoButton = self.getControl(3103) + if(couchPotatoButton != None): + if self.isTrailer and item.get("ProviderIds") != None and item.get("ProviderIds").get("Imdb") != None: + self.couchPotatoUrl = CP_ADD_VIA_IMDB + item.get("ProviderIds").get("Imdb") + elif self.isTrailer: + self.couchPotatoUrl = CP_ADD_URL + name + elif not self.isTrailer: + couchPotatoButton.setEnabled(False) + except: + pass + + # all the media stream info + mediaList = self.getControl(3220) + + mediaStreams = item.get("MediaStreams") + if(mediaStreams != None): + for mediaStream in mediaStreams: + if(mediaStream.get("Type") == "Video"): + videocodec = mediaStream.get("Codec") + if(videocodec == "mpeg2video"): + videocodec = "mpeg2" + height = str(mediaStream.get("Height")) + width = str(mediaStream.get("Width")) + aspectratio = mediaStream.get("AspectRatio") + fr = mediaStream.get("RealFrameRate") + videoInfo = width + "x" + height + " " + videocodec + " " + str(round(fr, 2)) + listItem = xbmcgui.ListItem("Video:", videoInfo) + mediaList.addItem(listItem) + if(mediaStream.get("Type") == "Audio"): + audiocodec = mediaStream.get("Codec") + channels = mediaStream.get("Channels") + lang = mediaStream.get("Language") + audioInfo = audiocodec + " " + str(channels) + if(lang != None and len(lang) > 0 and lang != "und"): + audioInfo = audioInfo + " " + lang + listItem = xbmcgui.ListItem("Audio:", audioInfo) + mediaList.addItem(listItem) + if(mediaStream.get("Type") == "Subtitle"): + lang = mediaStream.get("Language") + codec = mediaStream.get("Codec") + subInfo = codec + if(lang != None and len(lang) > 0 and lang != "und"): + subInfo = subInfo + " " + lang + listItem = xbmcgui.ListItem("Sub:", subInfo) + mediaList.addItem(listItem) + + + #for x in range(0, 10): + # listItem = xbmcgui.ListItem("Test:", "Test 02 " + str(x)) + # mediaList.addItem(listItem) + + # add overview + overview = item.get("Overview") + self.getControl(3223).setText(overview) + + # add people + peopleList = self.getControl(3230) + people = item.get("People") + director='' + writer='' + for person in people: + displayName = person.get("Name") + if person.get("Role") != None and person.get("Role") != '': + role = "as " + person.get("Role") + else: + role = '' + id = person.get("Id") + tag = person.get("PrimaryImageTag") + + baseName = person.get("Name") + baseName = baseName.replace(" ", "+") + baseName = baseName.replace("&", "_") + baseName = baseName.replace("?", "_") + baseName = baseName.replace("=", "_") + + actionUrl = "plugin://plugin.video.emby?mode=person&name=" + baseName + + if(tag != None and len(tag) > 0): + thumbPath = self.downloadUtils.imageUrl(id, "Primary", 0, 400, 400) + listItem = xbmcgui.ListItem(label=displayName, label2=role, iconImage=thumbPath, thumbnailImage=thumbPath) + else: + listItem = xbmcgui.ListItem(label=displayName, label2=role) + + listItem.setProperty("ActionUrl", actionUrl) + peopleList.addItem(listItem) + if(person.get("Type") == "Director") and director =='': + director = displayName + if(tag != None and len(tag) > 0): + thumbPath = self.downloadUtils.imageUrl(id, "Primary", 0, 580, 860) + directorlistItem = xbmcgui.ListItem("Director:", label2=displayName, iconImage=thumbPath, thumbnailImage=thumbPath) + else: + directorlistItem = xbmcgui.ListItem("Director:", label2=displayName) + directorlistItem.setProperty("ActionUrl", actionUrl) + if(person.get("Type") == "Writing") and writer == '': + writer = person.get("Name") + if(tag != None and len(tag) > 0): + thumbPath = self.downloadUtils.imageUrl(id, "Primary", 0, 580, 860) + writerlistItem = xbmcgui.ListItem("Writer:", label2=displayName, iconImage=thumbPath, thumbnailImage=thumbPath) + else: + writerlistItem = xbmcgui.ListItem("Writer:", label2=displayName) + writerlistItem.setProperty("ActionUrl", actionUrl) + if(person.get("Type") == "Writer") and writer == '': + writer = person.get("Name") + if(tag != None and len(tag) > 0): + thumbPath = self.downloadUtils.imageUrl(id, "Primary", 0, 580, 860) + writerlistItem = xbmcgui.ListItem("Writer:", label2=displayName, iconImage=thumbPath, thumbnailImage=thumbPath) + else: + writerlistItem = xbmcgui.ListItem("Writer:", label2=displayName) + writerlistItem.setProperty("ActionUrl", actionUrl) + # add general info + infoList = self.getControl(3226) + listItem = xbmcgui.ListItem("Year:", str(item.get("ProductionYear"))) + infoList.addItem(listItem) + listItem = xbmcgui.ListItem("Rating:", str(item.get("CommunityRating"))) + infoList.addItem(listItem) + listItem = xbmcgui.ListItem("MPAA:", str(item.get("OfficialRating"))) + infoList.addItem(listItem) + duration = str(int(item.get("RunTimeTicks", "0"))/(10000000*60)) + listItem = xbmcgui.ListItem("RunTime:", str(duration) + " Minutes") + infoList.addItem(listItem) + + genre = "" + genres = item.get("Genres") + if genres != None and genres != []: + for genre_string in genres: + if genre == "": #Just take the first genre + genre = genre_string + else: + genre = genre + " / " + genre_string + elif item.get("SeriesGenres") != None and item.get("SeriesGenres") != '': + genres = item.get("SeriesGenres") + if genres != None and genres != []: + for genre_string in genres: + if genre == "": #Just take the first genre + genre = genre_string + else: + genre = genre + " / " + genre_string + + genrelistItem = xbmcgui.ListItem("Genre:", genre) + genrelistItem2 = xbmcgui.ListItem("Genre:", genre) + infoList.addItem(genrelistItem) + + path = item.get('Path') + pathlistItem = xbmcgui.ListItem("Path:", path) + pathlistItem2 = xbmcgui.ListItem("Path:", path) + infoList.addItem(pathlistItem) + + if item.get("CriticRating") != None: + listItem = xbmcgui.ListItem("CriticRating:", str(item.get("CriticRating"))) + infoList.addItem(listItem) + + # Process Studio + studio = "" + if item.get("SeriesStudio") != None and item.get("SeriesStudio") != '': + studio = item.get("SeriesStudio") + if studio == "": + studios = item.get("Studios") + if(studios != None): + for studio_string in studios: + if studio=="": #Just take the first one + temp=studio_string.get("Name") + studio=temp.encode('utf-8') + + if studio != "": + listItem = xbmcgui.ListItem("Studio:", studio) + infoList.addItem(listItem) + + if item.get("Metascore") != None: + listItem = xbmcgui.ListItem("Metascore:", str(item.get("Metascore"))) + infoList.addItem(listItem) + + playCount = 0 + if(userData != None and userData.get("Played") == True): + playCount = 1 + listItem = xbmcgui.ListItem("PlayedCount:", str(playCount)) + infoList.addItem(listItem) + + if item.get("ProviderIds") != None and item.get("ProviderIds").get("Imdb") != None and type == "Movie": + listItem = xbmcgui.ListItem("ID:", item.get("ProviderIds").get("Imdb")) + infoList.addItem(listItem) + elif item.get("ProviderIds") != None and item.get("ProviderIds").get("Tvdb") != None and type == "Series": + listItem = xbmcgui.ListItem("ID:", item.get("ProviderIds").get("Tvdb")) + infoList.addItem(listItem) + elif (type == "Episode" or type == "Season"): + url = "{server}/mediabrowser/Users/{UserId}/Items/" + item.get("SeriesId") + "?Fields=SeriesGenres,AirTime&format=json" + seriesitem = self.downloadUtils.downloadUrl(url) + + if seriesitem.get("ProviderIds") != None and seriesitem.get("ProviderIds").get("Tvdb") != None: + listItem = xbmcgui.ListItem("ID:", seriesitem.get("ProviderIds").get("Tvdb")) + infoList.addItem(listItem) + + # alternate list + try: + alternateList = self.getControl(3291) + if alternateList != None: + if directorlistItem != None: + alternateList.addItem(directorlistItem) + if writerlistItem != None: + alternateList.addItem(writerlistItem) + alternateList.addItem(genrelistItem2) + if item.get("ProductionLocations") !=None and item.get("ProductionLocations") != []: + listItem = xbmcgui.ListItem("Country:", item.get("ProductionLocations")[0]) + alternateList.addItem(listItem) + elif item.get("AirTime") !=None: + listItem = xbmcgui.ListItem("Air Time:", item.get("AirTime")) + alternateList.addItem(listItem) + if(item.get("PremiereDate") != None): + premieredatelist = (item.get("PremiereDate")).split("T") + premieredate = premieredatelist[0] + listItem = xbmcgui.ListItem("Premiered Date:", premieredate) + alternateList.addItem(listItem) + alternateList.addItem(pathlistItem2) + + except: + pass + + self.getControl(3000).setLabel(name) + self.getControl(3003).setLabel(episodeInfo) + + try: + discartImageControl = self.getControl(3091) + artImageControl = self.getControl(3092) + thumbImageControl = self.getControl(3093) + logoImageControl = self.getControl(3094) + + if discartImageControl != None and artImageControl != None and thumbImageControl != None and logoImageControl != None: + + if logo != "": + self.getControl(3094).setImage(logo) + else: + self.getControl(3000).setVisible(True) + + if discart != '': + self.getControl(3091).setImage(discart) + self.getControl(3092).setVisible(False) + self.getControl(3093).setVisible(False) + else: + self.getControl(3091).setVisible(False) + art = API().getArtwork(item,"Art") + if (artImageControl != None): + if art != '': + self.getControl(3092).setImage(art) + self.getControl(3093).setVisible(False) + else: + self.getControl(3092).setVisible(False) + if (type == "Episode"): + thumb = API().getArtwork(item,"Thumb3") + else: + thumb = API().getArtwork(item,"Thumb") + if (thumbImageControl != None): + if thumb != '': + self.getControl(3093).setImage(thumb) + else: + self.getControl(3093).setVisible(False) + + + except: + pass + + if(type == "Episode"): + # null_pointer - I have removed this in favor of letting the user chose from the setting and using the "poster" type in the above image url create + #image = API().getArtwork(seriesitem, "Primary") + seriesimage = API().getArtwork(item, "SeriesPrimary") + try: + self.getControl(3099).setImage(seriesimage) + except: + pass + + self.getControl(3009).setImage(image) + if(cappedPercentage != None): + self.getControl(3010).setImage("Progress\progress_" + str(cappedPercentage) + ".png") + else: + self.getControl(3011).setImage(image) + if(cappedPercentage != None): + self.getControl(3012).setImage("Progress\progress_" + str(cappedPercentage) + ".png") + + # disable play button + if(type == "Season" or type == "Series"): + self.setFocusId(3226) + self.getControl(3002).setEnabled(False) + + def setId(self, id): + self.id = id + + def onFocus(self, controlId): + pass + + def doAction(self): + pass + + def closeDialog(self): + self.close() + + def onClick(self, controlID): + + if(controlID == 3002): + + # close all dialogs when playing an item + xbmc.executebuiltin("Dialog.Close(all,true)") + + xbmc.executebuiltin("RunPlugin(" + self.playUrl + ")") + self.close() + + elif(controlID == 3102): + + # close all dialogs when playing an item + xbmc.executebuiltin("Dialog.Close(all,true)") + + xbmc.executebuiltin("RunPlugin(" + self.trailerUrl + ")") + self.close() + + elif(controlID == 3103): + + # close all dialogs when playing an item + xbmc.executebuiltin("Dialog.Close(all,true)") + xbmc.executebuiltin("RunPlugin(" + self.couchPotatoUrl + ")") + + elif(controlID == 3230): + + peopleList = self.getControl(3230) + item = peopleList.getSelectedItem() + action = item.getProperty("ActionUrl") + + xbmc.log(action) + xbmc.executebuiltin("RunPlugin(" + action + ")") + elif(controlID == 3291): + + list = self.getControl(3291) + item = list.getSelectedItem() + action = item.getProperty("ActionUrl") + + xbmc.log(action) + xbmc.executebuiltin("RunPlugin(" + action + ")") + elif(controlID == 3192): + url = '{server}/mediabrowser/Users/{UserId}/PlayedItems/' + self.id + button = self.getControl(3192) + watched = button.isSelected() + if watched == True: + self.postUrl(url) + else: + self.deleteUrl(url) + self.onInit() + elif(controlID == 3193): + url = '{server}/mediabrowser/Users/{UserId}/Items/' + self.id + '/Rating' + dislikebutton = self.getControl(3193) + dislike = dislikebutton.isSelected() + if dislike == True: + url = url + '?likes=false' + self.postUrl(url) + else: + self.deleteUrl(url) + self.onInit() + elif(controlID == 3194): + url = '{server}/mediabrowser/Users/{UserId}/Items/' + self.id + '/Rating' + likebutton = self.getControl(3194) + like = likebutton.isSelected() + if like == True: + url = url + '?likes=true' + self.postUrl(url) + else: + self.deleteUrl(url) + self.onInit() + elif(controlID == 3195): + url = '{server}/mediabrowser/Users/{UserId}/FavoriteItems/' + self.id + button = self.getControl(3195) + favourite = button.isSelected() + if favourite == True: + self.postUrl(url) + else: + self.deleteUrl(url) + self.onInit() + elif(controlID == 3006): + url = "{server}/mediabrowser/Users/{UserId}/PlayingItems/" + self.id + "/Progress?PositionTicks=0" + self.postUrl(url) + self.onInit() + pass + + def postUrl (self,url): + self.downloadUtils.downloadUrl(url, postBody="", type="POST") + + def deleteUrl (self,url): + self.downloadUtils.downloadUrl(url, type="DELETE") + diff --git a/resources/lib/NextUpInfo.py b/resources/lib/NextUpInfo.py new file mode 100644 index 00000000..ec54567a --- /dev/null +++ b/resources/lib/NextUpInfo.py @@ -0,0 +1,102 @@ + +import sys +import xbmc +import xbmcgui +import xbmcaddon +import json as json +import urllib +from API import API +from PlaybackUtils import PlaybackUtils + +ACTION_PLAYER_STOP = 13 + +class NextUpInfo(xbmcgui.WindowXMLDialog): + + item = None + cancel = False + watchnow = False + + def __init__(self, *args, **kwargs): + xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) + + def onInit(self): + self.action_exitkeys_id = [10, 13] + + image = API().getArtwork(self.item, "Primary2") + clearartimage = API().getArtwork(self.item, "Art") + overview = API().getOverview(self.item) + name = API().getName(self.item) + + episodeInfo = "" + season = str(self.item.get("ParentIndexNumber")) + episodeNum = str(self.item.get("IndexNumber")) + episodeInfo = season + "x" + episodeNum + "." + + rating = None + if self.item.get("CommunityRating") != None and self.item.get("CommunityRating") !="": + rating = str(self.item.get("CommunityRating")) + year = API().getPremiereDate(self.item) + duration = str(int(self.item.get("RunTimeTicks", "0"))/(10000000*60)) + info = year + " " + str(duration) + " min" + # set the dialog data + self.getControl(3000).setLabel(name) + self.getControl(3001).setText(overview) + self.getControl(3002).setLabel(episodeInfo) + self.getControl(3004).setLabel(info) + + self.getControl(3009).setImage(image) + self.getControl(3006).setImage(clearartimage) + + if rating != None: + self.getControl(3003).setLabel(rating) + else: + self.getControl(3003).setVisible(False) + + + def setItem(self, item): + self.item = item + + def setCancel(self, cancel): + self.cancel = cancel + + def isCancel(self): + return self.cancel + + def setWatchNow(self, watchnow): + self.watchnow = watchnow + + def isWatchNow(self): + return self.watchnow + + def onFocus(self, controlId): + pass + + def doAction(self): + pass + + def closeDialog(self): + self.close() + + def onClick(self, controlID): + + xbmc.log("nextup info onclick: "+str(controlID)) + + if(controlID == 3012): + # watch now + self.setWatchNow(True) + self.close() + + elif(controlID == 3013): + #cancel + self.setCancel(True) + self.close() + + pass + + def onAction(self, action): + + xbmc.log("nextup info action: "+str(action.getId())) + if action == ACTION_PLAYER_STOP: + self.close() + + diff --git a/resources/lib/PersonInfo.py b/resources/lib/PersonInfo.py new file mode 100644 index 00000000..56af1813 --- /dev/null +++ b/resources/lib/PersonInfo.py @@ -0,0 +1,169 @@ + +import sys +import xbmc +import xbmcgui +import xbmcaddon +import json as json +import urllib +from DownloadUtils import DownloadUtils +from API import API + +_MODE_GETCONTENT=0 +_MODE_ITEM_DETAILS=17 + +class PersonInfo(xbmcgui.WindowXMLDialog): + + pluginCastLink = "" + showMovies = False + personName = "" + + def __init__(self, *args, **kwargs): + xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) + + def onInit(self): + self.action_exitkeys_id = [10, 13] + downloadUtils = DownloadUtils() + url = "{server}/mediabrowser/Persons/" + self.personName + "?format=json" + jsonData = downloadUtils.downloadUrl(url ) + result = jsonData + + name = result.get("Name") + id = result.get("Id") + + # other lib items count + contentCounts = "" + if(result.get("AdultVideoCount") != None and result.get("AdultVideoCount") > 0): + contentCounts = contentCounts + "\nAdult Count : " + str(result.get("AdultVideoCount")) + if(result.get("MovieCount") != None and result.get("MovieCount") > 0): + contentCounts = contentCounts + "\nMovie Count : " + str(result.get("MovieCount")) + if(result.get("SeriesCount") != None and result.get("SeriesCount") > 0): + contentCounts = contentCounts + "\nSeries Count : " + str(result.get("SeriesCount")) + if(result.get("EpisodeCount") != None and result.get("EpisodeCount") > 0): + contentCounts = contentCounts + "\nEpisode Count : " + str(result.get("EpisodeCount")) + + if(len(contentCounts) > 0): + contentCounts = "Total Library Counts:" + contentCounts + + #overview + overview = "" + if(len(contentCounts) > 0): + overview = contentCounts + "\n\n" + over = result.get("Overview") + if(over == None or over == ""): + overview = overview + "No details available" + else: + overview = overview + over + + #person image + image = API().getArtwork(result, "Primary") + + #get other movies + encoded = name.encode("utf-8") + encoded = urllib.quote(encoded) + url = "{server}/mediabrowser/Users/{UserId}/Items/?Recursive=True&Person=" + encoded + "&format=json" + jsonData = downloadUtils.downloadUrl(url) + otherMovieResult = jsonData + + baseName = name.replace(" ", "+") + baseName = baseName.replace("&", "_") + baseName = baseName.replace("?", "_") + baseName = baseName.replace("=", "_") + + #detailsString = getDetailsString() + #search_url = "http://" + host + ":" + port + "/mediabrowser/Users/" + userid + "/Items/?Recursive=True&Person=PERSON_NAME&Fields=" + detailsString + "&format=json" + #search_url = "http://" + host + ":" + port + "/mediabrowser/Users/" + userid + "/Items/?Recursive=True&Person=PERSON_NAME&format=json" + #search_url = urllib.quote(search_url) + #search_url = search_url.replace("PERSON_NAME", baseName) + #self.pluginCastLink = "XBMC.Container.Update(plugin://plugin.video.xbmb3c?mode=" + str(_MODE_GETCONTENT) + "&url=" + search_url + ")" + + otherItemsList = None + try: + otherItemsList = self.getControl(3010) + + items = otherMovieResult.get("Items") + if(items == None): + items = [] + + for item in items: + item_id = item.get("Id") + item_name = item.get("Name") + + type_info = "" + image_id = item_id + item_type = item.get("Type") + + if(item_type == "Season"): + image_id = item.get("SeriesId") + season = item.get("IndexNumber") + type_info = "Season " + str(season).zfill(2) + elif(item_type == "Series"): + image_id = item.get("Id") + type_info = "Series" + elif(item_type == "Movie"): + image_id = item.get("Id") + type_info = "Movie" + elif(item_type == "Episode"): + image_id = item.get("SeriesId") + season = item.get("ParentIndexNumber") + eppNum = item.get("IndexNumber") + type_info = "S" + str(season).zfill(2) + "E" + str(eppNum).zfill(2) + + thumbPath = downloadUtils.imageUrl(image_id, "Primary", 0, 200, 200) + + fanArt = downloadUtils.imageUrl(image_id, "Backdrop",0,10000,10000) + listItem = xbmcgui.ListItem(label=item_name, label2=type_info, iconImage=thumbPath, thumbnailImage=thumbPath) + listItem.setArt({"fanart":fanArt}) + + actionUrl = "plugin://plugin.video.emby?id=" + item_id + "&mode=info" + listItem.setProperty("ActionUrl", actionUrl) + + otherItemsList.addItem(listItem) + + except Exception, e: + xbmc.log("Exception : " + str(e)) + pass + + + + # set the dialog data + self.getControl(3000).setLabel(name) + self.getControl(3001).setText(overview) + self.getControl(3009).setImage(image) + + def setPersonName(self, name): + self.personName = name + + def setInfo(self, data): + self.details = data + + def onFocus(self, controlId): + pass + + def doAction(self): + pass + + def closeDialog(self): + self.close() + + def onClick(self, controlID): + + if(controlID == 3002): + self.showMovies = True + + xbmc.executebuiltin('Dialog.Close(movieinformation)') + self.close() + + elif(controlID == 3010): + + #xbmc.executebuiltin("Dialog.Close(all,true)") + + itemList = self.getControl(3010) + item = itemList.getSelectedItem() + action = item.getProperty("ActionUrl") + + xbmc.executebuiltin("RunPlugin(" + action + ")") + + self.close() + + pass + diff --git a/resources/lib/Player.py b/resources/lib/Player.py index 56d0838f..5025400b 100644 --- a/resources/lib/Player.py +++ b/resources/lib/Player.py @@ -18,6 +18,7 @@ from LibrarySync import LibrarySync from PlaybackUtils import PlaybackUtils from ReadEmbyDB import ReadEmbyDB from API import API +from NextUpInfo import NextUpInfo librarySync = LibrarySync() # service class for playback monitoring @@ -348,29 +349,23 @@ class Player( xbmc.Player ): seasonId = MB3Episode["SeasonId"] url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&ImageTypeLimit=1&Limit=1&SortBy=SortName&SortOrder=Ascending&Filters=IsUnPlayed&IncludeItemTypes=Episode&IsVirtualUnaired=false&Recursive=true&IsMissing=False&format=json" % seasonId jsonData = self.doUtils.downloadUrl(url) - if(jsonData != ""): seasonData = jsonData - if seasonData.get("Items") != None: item = seasonData.get("Items")[0] - pDialog.create("Auto Play next episode", str(item.get("ParentIndexNumber")) + "x" + str(item.get("IndexNumber")) + ". " + item["Name"] + " found","Cancel to stop automatic play") - count = 0 - while(pDialog.iscanceled()==False and count < 10): - xbmc.sleep(1000) - count += 1 - progress = count * 10 - remainingsecs = 10 - count - pDialog.update(progress, str(item.get("ParentIndexNumber")) + "x" + str(item.get("IndexNumber")) + ". " + item["Name"] + " found","Cancel to stop automatic play", str(remainingsecs) + " second(s) until auto dismiss") - - pDialog.close() - - if pDialog.iscanceled()==False: + item = ReadEmbyDB().getItem(item["Id"]) + nextUpPage = NextUpInfo("NextUpInfo.xml", addonSettings.getAddonInfo('path'), "default", "720p") + nextUpPage.setItem(item) playTime = xbmc.Player().getTime() totalTime = xbmc.Player().getTotalTime() - while xbmc.Player().isPlaying() and (totalTime-playTime > 2): - xbmc.sleep(500) + nextUpPage.show() + playTime = xbmc.Player().getTime() + totalTime = xbmc.Player().getTotalTime() + while xbmc.Player().isPlaying() and (totalTime-playTime > 1) and not nextUpPage.isCancel() and not nextUpPage.isWatchNow(): + xbmc.sleep(100) playTime = xbmc.Player().getTime() totalTime = xbmc.Player().getTotalTime() - - PlaybackUtils().PLAYAllEpisodes(seasonData.get("Items")) \ No newline at end of file + nextUpPage.close() + if not nextUpPage.isCancel(): + PlaybackUtils().PLAY(item) + diff --git a/resources/lib/WriteKodiDB.py b/resources/lib/WriteKodiDB.py index 6acdb7e0..133cd8ab 100644 --- a/resources/lib/WriteKodiDB.py +++ b/resources/lib/WriteKodiDB.py @@ -122,8 +122,13 @@ class WriteKodiDB(): #### ADD OR UPDATE THE FILE AND PATH ########### #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY path = "plugin://plugin.video.emby/movies/%s/" % MBitem["Id"] - filename = "plugin://plugin.video.emby/movies/%s/?id=%s&mode=play" % (MBitem["Id"],MBitem["Id"]) - + addonSettings = xbmcaddon.Addon(id='plugin.video.emby') + selectAction = addonSettings.getSetting('selectAction') + if(selectAction == "1"): + filename = "plugin://plugin.video.emby/movies/%s/?id=%s&mode=info" % (MBitem["Id"],MBitem["Id"]) + else: + filename = "plugin://plugin.video.emby/movies/%s/?id=%s&mode=play" % (MBitem["Id"],MBitem["Id"]) + #create the path cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) result = cursor.fetchone() @@ -543,8 +548,14 @@ class WriteKodiDB(): #### ADD OR UPDATE THE FILE AND PATH ########### #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY path = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/" - filename = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/?id=" + MBitem["Id"] + "&mode=play" + addonSettings = xbmcaddon.Addon(id='plugin.video.emby') + selectAction = addonSettings.getSetting('selectAction') + if(selectAction == "1"): + filename = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/?id=" + MBitem["Id"] + "&mode=info" + else: + filename = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/?id=" + MBitem["Id"] + "&mode=play" + #create the new path - return id if already exists cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) result = cursor.fetchone() diff --git a/resources/settings.xml b/resources/settings.xml index c571617a..ec3d8736 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -22,8 +22,12 @@ <category label="Playback"> <!-- Extra Sync options --> <setting id="smbusername" type="text" label="30007" default="" visible="true" enable="true" /> <setting id="smbpassword" type="text" label="30008" default="" option="hidden" visible="true" enable="true" /> - <setting id="autoPlaySeason" type="bool" label="30216" default="false" visible="true" enable="true" /> - <setting type="sep" /> + <setting type="sep"/> + <setting id="autoPlaySeason" type="bool" label="30246" default="false" visible="true" enable="true" /> + <setting id="autoPlaySeasonTime" type="number" label="30247" default="20" visible="eq(-1,true)" enable="true" /> + <setting type="sep" /> + <setting id="selectAction" type="enum" label="30248" values="Play|Info" default="0" /> + <setting type="sep" /> <setting id="playFromStream" type="bool" label="30002" visible="true" enable="true" default="false" /> <setting id="videoBitRate" type="enum" label="30160" values="664 Kbps SD|996 Kbps HD|1.3 Mbps HD|2.0 Mbps HD|3.2 Mbps HD|4.7 Mbps HD|6.2 Mbps HD|7.7 Mbps HD|9.2 Mbps HD|10.7 Mbps HD|12.2 Mbps HD|13.7 Mbps HD|15.2 Mbps HD|16.7 Mbps HD|18.2 Mbps HD|20.0 Mbps HD|40.0 Mbps HD|100.0 Mbps HD [default]|1000.0 Mbps HD" visible="eq(-1,true)" default="17" /> <setting id="forceTranscodingCodecs" type="text" label="30245" visible="eq(-2,true)" /> diff --git a/resources/skins/default/720p/ItemInfo.xml b/resources/skins/default/720p/ItemInfo.xml new file mode 100644 index 00000000..64d100c2 --- /dev/null +++ b/resources/skins/default/720p/ItemInfo.xml @@ -0,0 +1,415 @@ +<?xml version="1.0" encoding="UTF-8"?> +<window id="3300" type="dialog"> + <defaultcontrol always="true">3002</defaultcontrol> + <zorder>2</zorder> + <coordinates> + <system>1</system> + <left>120</left> + <top>50</top> + </coordinates> + <include>dialogeffect</include> + <controls> + + <control type="image"> + <left>0</left> + <top>0</top> + <width>1040</width> + <height>600</height> + <texture border="40">DialogBack.png</texture> + </control> + + <control type="image" id="3001"> + <left>20</left> + <top>20</top> + <width>1000</width> + <height>560</height> + <colordiffuse>FF444444</colordiffuse> + </control> + + <control type="label" id="3000"> + <left>30</left> + <top>25</top> + <width>950</width> + <height>20</height> + <align>left</align> + <label>-</label> + <font>font24_title</font> + <textcolor>FFFFFFFFFF</textcolor> + </control> + + <control type="label" id="3003"> + <left>30</left> + <top>55</top> + <width>300</width> + <height>20</height> + <align>left</align> + <label>-</label> + <font>font18_title</font> + <textcolor>FFFFFFFFFF</textcolor> + </control> + + <!-- episode image 16x9 --> + <control type="image" id="3009"> + <left>40</left> + <top>130</top> + <width>250</width> + <height>140</height> + <aspectratio>stretch</aspectratio> + </control> + <control type="image" id="3010"> + <left>40</left> + <top>265</top> + <width>250</width> + <height>5</height> + <texture background="true">-</texture> + <colordiffuse>AAFFFFFF</colordiffuse> + <aspectratio>stretch</aspectratio> + </control> + + <!-- poster image --> + <control type="image" id="3011"> + <left>60</left> + <top>100</top> + <width>175</width> + <height>250</height> + <aspectratio>stretch</aspectratio> + </control> + <control type="image" id="3012"> + <left>60</left> + <top>345</top> + <width>175</width> + <height>5</height> + <texture background="true">-</texture> + <colordiffuse>AAFFFFFF</colordiffuse> + <aspectratio>stretch</aspectratio> + </control> + + <control type="list" id="3220"> + <left>30</left> + <top>380</top> + <width>240</width> + <height>120</height> + <onleft>3002</onleft> + <onright>3221</onright> + <onup>3235</onup> + <ondown>3002</ondown> + <pagecontrol>3221</pagecontrol> + <scrolltime>200</scrolltime> + <itemlayout height="20"> + <control type="label"> + <left>60</left> + <top>0</top> + <width>60</width> + <height>20</height> + <font>font10</font> + <align>right</align> + <aligny>center</aligny> + <textcolor>blue</textcolor> + <selectedcolor>selected</selectedcolor> + <info>ListItem.Label</info> + </control> + <control type="label"> + <left>65</left> + <top>0</top> + <width>180</width> + <height>20</height> + <font>font10</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>white</textcolor> + <selectedcolor>white</selectedcolor> + <info>ListItem.Label2</info> + </control> + </itemlayout> + <focusedlayout height="20"> + <control type="image"> + <left>0</left> + <top>0</top> + <width>240</width> + <height>20</height> + <visible>Control.HasFocus(3220)</visible> + <texture>MenuItemFO.png</texture> + <include>VisibleFadeEffect</include> + </control> + <control type="label"> + <left>60</left> + <top>0</top> + <width>60</width> + <height>20</height> + <font>font10</font> + <align>right</align> + <aligny>center</aligny> + <textcolor>blue</textcolor> + <selectedcolor>selected</selectedcolor> + <info>ListItem.Label</info> + </control> + <control type="label"> + <left>65</left> + <top>0</top> + <width>180</width> + <height>20</height> + <font>font10</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>white</textcolor> + <selectedcolor>white</selectedcolor> + <info>ListItem.Label2</info> + </control> + </focusedlayout> + </control> + <control type="scrollbar" id="3221"> + <left>270</left> + <top>380</top> + <width>20</width> + <height>120</height> + <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground> + <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar> + <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus> + <textureslidernib>ScrollBarNib.png</textureslidernib> + <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus> + <onleft>3220</onleft> + <onright>3226</onright> + <showonepage>false</showonepage> + <orientation>vertical</orientation> + </control> + + <control type="list" id="3226"> + <left>310</left> + <top>380</top> + <width>415</width> + <height>120</height> + <onleft>3221</onleft> + <onright>3235</onright> + <onup>3235</onup> + <ondown>3002</ondown> + <pagecontrol>-</pagecontrol> + <scrolltime>200</scrolltime> + <itemlayout height="20"> + <control type="label"> + <left>70</left> + <top>0</top> + <width>70</width> + <height>20</height> + <font>font10</font> + <align>right</align> + <aligny>center</aligny> + <textcolor>blue</textcolor> + <selectedcolor>selected</selectedcolor> + <info>ListItem.Label</info> + </control> + <control type="label"> + <left>75</left> + <top>0</top> + <width>340</width> + <height>20</height> + <font>font10</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>white</textcolor> + <selectedcolor>white</selectedcolor> + <info>ListItem.Label2</info> + </control> + </itemlayout> + <focusedlayout height="20"> + <control type="image"> + <left>0</left> + <top>0</top> + <width>400</width> + <height>20</height> + <visible>Control.HasFocus(3226)</visible> + <texture>MenuItemFO.png</texture> + <include>VisibleFadeEffect</include> + </control> + <control type="label"> + <left>70</left> + <top>0</top> + <width>70</width> + <height>20</height> + <font>font10</font> + <align>right</align> + <aligny>center</aligny> + <textcolor>blue</textcolor> + <selectedcolor>selected</selectedcolor> + <info>ListItem.Label</info> + </control> + <control type="label"> + <left>75</left> + <top>0</top> + <width>340</width> + <height>20</height> + <font>font10</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>white</textcolor> + <selectedcolor>white</selectedcolor> + <info>ListItem.Label2</info> + </control> + </focusedlayout> + </control> + <!-- + <control type="scrollbar" id="3227"> + <left>270</left> + <top>380</top> + <width>20</width> + <height>120</height> + <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground> + <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar> + <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus> + <textureslidernib>ScrollBarNib.png</textureslidernib> + <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus> + <onleft>3220</onleft> + <onright>3235</onright> + <showonepage>false</showonepage> + <orientation>vertical</orientation> + </control> + --> + + <control type="textbox" id="3223"> + <left>320</left> + <top>100</top> + <width>400</width> + <height>250</height> + <font>font12</font> + <!--<align>justify</align>--> + <textcolor>white</textcolor> + <pagecontrol>3235</pagecontrol> + <visible>true</visible> + </control> + <control type="scrollbar" id="3235"> + <left>720</left> + <top>100</top> + <width>20</width> + <height>250</height> + <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground> + <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar> + <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus> + <textureslidernib>ScrollBarNib.png</textureslidernib> + <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus> + <onleft>3226</onleft> + <onup>-</onup> + <onright>3230</onright> + <showonepage>false</showonepage> + <orientation>vertical</orientation> + </control> + + <control type="list" id="3230"> + <left>760</left> + <top>100</top> + <width>245calc</width> + <height>450</height> + <onleft>3235</onleft> + <onright>3231</onright> + <onup>-</onup> + <ondown>-</ondown> + <pagecontrol>3231</pagecontrol> + <scrolltime>200</scrolltime> + <itemlayout height="60"> + <control type="image"> + <left>0</left> + <top>0</top> + <width>60</width> + <height>60</height> + <texture fallback="DefaultArtist.png">$INFO[Listitem.Icon]</texture> + <aspectratio>scale</aspectratio> + </control> + <control type="label"> + <left>65</left> + <top>0</top> + <width>160</width> + <height>30</height> + <font>font12</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>blue</textcolor> + <selectedcolor>selected</selectedcolor> + <info>ListItem.Label</info> + </control> + <control type="label"> + <left>65</left> + <top>30</top> + <width>160</width> + <height>30</height> + <font>font10</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>white</textcolor> + <selectedcolor>white</selectedcolor> + <info>ListItem.Label2</info> + </control> + </itemlayout> + <focusedlayout height="60"> + <control type="image"> + <left>0</left> + <top>0</top> + <width>60</width> + <height>60</height> + <texture fallback="DefaultArtist.png">$INFO[Listitem.Icon]</texture> + <aspectratio>scale</aspectratio> + </control> + <control type="image"> + <left>60</left> + <top>0</top> + <width>160</width> + <height>30</height> + <visible>Control.HasFocus(3230)</visible> + <texture>MenuItemFO.png</texture> + <include>VisibleFadeEffect</include> + </control> + <control type="label"> + <left>65</left> + <top>0</top> + <width>160</width> + <height>30</height> + <font>font12</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>blue</textcolor> + <selectedcolor>selected</selectedcolor> + <info>ListItem.Label</info> + </control> + <control type="label"> + <left>65</left> + <top>30</top> + <width>160</width> + <height>30</height> + <font>font10</font> + <align>left</align> + <aligny>center</aligny> + <textcolor>white</textcolor> + <selectedcolor>white</selectedcolor> + <info>ListItem.Label2</info> + </control> + </focusedlayout> + </control> + <control type="scrollbar" id="3231"> + <left>985</left> + <top>100</top> + <width>20</width> + <height>450</height> + <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground> + <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar> + <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus> + <textureslidernib>ScrollBarNib.png</textureslidernib> + <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus> + <onleft>3230</onleft> + <onright>-</onright> + <showonepage>false</showonepage> + <orientation>vertical</orientation> + </control> + + <control type="button" id="3002"> + <left>30</left> + <top>520</top> + <width>150</width> + <height>40</height> + <align>center</align> + <label>Play</label> + <font>font13</font> + <onleft>-</onleft> + <onright>3220</onright> + <onup>3220</onup> + </control> + + + </controls> +</window> \ No newline at end of file diff --git a/resources/skins/default/720p/NextUpInfo.xml b/resources/skins/default/720p/NextUpInfo.xml new file mode 100644 index 00000000..05ada47a --- /dev/null +++ b/resources/skins/default/720p/NextUpInfo.xml @@ -0,0 +1,245 @@ +<?xml version="1.0" encoding="UTF-8"?> +<window> + <defaultcontrol always="true">3012</defaultcontrol> + <zorder>0</zorder> + <controls> + <control type="group"> + <control type="image"> + <left>0</left> + <top>-150</top> + <width>1280</width> + <height>256</height> + <texture flipy="true" border="1">HomeNowPlayingBack.png</texture> + </control> + <control type="label" id="1"> + <description>Clock label</description> + <left>450</left> + <top>5</top> + <width>800</width> + <height>25</height> + <align>right</align> + <aligny>center</aligny> + <font>font13</font> + <textcolor>white</textcolor> + <shadowcolor>black</shadowcolor> + <label>$INFO[System.Time]</label> + <animation effect="slide" start="0,0" end="-70,0" time="0" condition="Window.IsVisible(VideoOSD)">conditional</animation> + </control> + <control type="image"> + <left>0</left> + <top>230r</top> + <width>1280</width> + <height>230</height> + <texture border="1">HomeNowPlayingBack.png</texture> + </control> + <control type="image" id="3009"> + <description>cover image</description> + <left>20</left> + <top>350r</top> + <width>300</width> + <height>330</height> + </control> + <control type="image" id="3006"> + <description>clearart</description> + <visible>false</visible> + </control> + <control type="group" id="1"> + <left>330</left> + <top>185r</top> + <control type="label" id="1"> + <description>TV Show label</description> + <left>20</left> + <top>30</top> + <width>910</width> + <height>25</height> + <align>left</align> + <font>font12</font> + <label>$INFO[Control.GetLabel(3002),Up Next... ,][COLOR=orange]$INFO[Control.GetLabel(3000), ,][/COLOR]</label> + <textcolor>grey2</textcolor> + <shadowcolor>black</shadowcolor> + <visible>VideoPlayer.Content(Episodes)</visible> + </control> + <control type="label" description="episode/season info" id="3002"> + <width>100%</width> + <top>0</top> + <left>175</left> + <height>40</height> + <visible>false</visible> + </control> + <control type="label" description="Title" id="3000"> + <width>100%</width> + <left>267</left> + <top>0</top> + <height>40</height> + <visible>false</visible> + </control> + <control type="textbox" id="3001"> + <description>text</description> + <left>30</left> + <top>62</top> + <width>550</width> + <height>98</height> + <align>left</align> + <label>-</label> + <font>font13</font> + <autoscroll time="3000" delay="4000" repeat="5000">true</autoscroll> + <visible>false</visible> + </control> + <control type="grouplist" id="1"> + <left>20</left> + <top>60</top> + <width>910</width> + <height>35</height> + <itemgap>5</itemgap> + <orientation>horizontal</orientation> + <control type="label" id="3003" description="rating"> + <width>100%</width> + <top>50</top> + <height>40</height> + <visible>false</visible> + </control> + <control type="label" id="3004" description="year/runtime"> + <width>100%</width> + <top>50</top> + <height>40</height> + <scroll>false</scroll> + <visible>false</visible> + </control> + <control type="label" id="1"> + <width min="10" max="520">auto</width> + <height>30</height> + <font>font30</font> + <align>left</align> + <aligny>center</aligny> + <label>$INFO[Control.GetLabel(3003)]$INFO[Control.GetLabel(3004), ,]</label> + <textcolor>grey</textcolor> + <scroll>true</scroll> + </control> + <control type="button" id="3012"> + <description>Watch now button</description> + <width>200</width> + <height>40</height> + <label>Watch Now</label> + <font>font12_title</font> + <onleft>3013</onleft> + <onright>3013</onright> + </control> + <control type="button" id="3013"> + <description>cancel button</description> + <width>200</width> + <height>40</height> + <label>222</label> + <font>font12_title</font> + <onleft>3012</onleft> + <onright>3012</onright> + </control> + </control> + <control type="label" id="1"> + <left>0</left> + <top>120</top> + <width>910</width> + <height>25</height> + <label>$INFO[Player.TimeRemaining(ss),Press cancel to stop automatic play of next episode , seconds remaining]</label> + <align>center</align> + <aligny>center</aligny> + <font>font12</font> + <textcolor>grey</textcolor> + <scroll>true</scroll> + <visible>!Window.IsVisible(VideoOSD) + !VideoPlayer.Content(LiveTV)</visible> + <animation effect="fade" time="200">VisibleChange</animation> + </control> + </control> + <control type="group" id="1"> + <left>330</left> + <top>95r</top> + <visible>!VideoPlayer.Content(LiveTV) | [VideoPlayer.Content(LiveTV) + VideoPlayer.HasEpg]</visible> + <control type="label" id="1"> + <visible>!VideoPlayer.Content(LiveTV)</visible> + <left>0</left> + <top>0</top> + <width>100</width> + <height>40</height> + <font>font13</font> + <align>left</align> + <aligny>center</aligny> + <label>$INFO[Player.Time(hh:mm:ss)]</label> + </control> + <control type="progress" id="1"> + <description>ProgressbarCache</description> + <left>100</left> + <top>15</top> + <width>720</width> + <height>16</height> + <info>Player.ProgressCache</info> + <midtexture border="6,0,6,0">OSDProgressMidLight.png</midtexture> + </control> + <control type="progress" id="1"> + <description>Progressbar</description> + <left>100</left> + <top>15</top> + <width>720</width> + <height>16</height> + <info>Player.Progress</info> + </control> + <control type="label" id="1"> + <visible>!VideoPlayer.Content(LiveTV)</visible> + <left>820</left> + <top>0</top> + <width>100</width> + <height>40</height> + <font>font13</font> + <align>right</align> + <aligny>center</aligny> + <label>$INFO[Player.Duration(hh:mm:ss)]</label> + </control> + </control> + </control> + <!-- codec info --> + <control type="group" id="0"> + <left>0</left> + <top>20</top> + <animation effect="fade" time="200">VisibleChange</animation> + <control type="image"> + <description>media info background image</description> + <left>0</left> + <top>0</top> + <width>1280</width> + <height>160</height> + <texture>black-back.png</texture> + </control> + <control type="label" id="10"> + <description>row 1 label</description> + <left>50</left> + <top>10</top> + <width>1180</width> + <height>30</height> + <align>left</align> + <aligny>center</aligny> + <font>font12</font> + <label>-</label> + </control> + <control type="label" id="11"> + <description>row 2 label</description> + <left>50</left> + <top>55</top> + <width>1180</width> + <height>30</height> + <align>left</align> + <aligny>center</aligny> + <font>font12</font> + <label>-</label> + </control> + <control type="label" id="12"> + <description>row 3 label</description> + <left>50</left> + <top>100</top> + <width>1180</width> + <height>45</height> + <align>left</align> + <aligny>center</aligny> + <font>font12</font> + <label>-</label> + </control> + </control> + </controls> +</window> \ No newline at end of file diff --git a/resources/skins/default/720p/PersonInfo.xml b/resources/skins/default/720p/PersonInfo.xml new file mode 100644 index 00000000..e05ca112 --- /dev/null +++ b/resources/skins/default/720p/PersonInfo.xml @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<window> + <defaultcontrol always="true">3010</defaultcontrol> + <zorder>2</zorder> + <coordinates> + <system>1</system> + <left>120</left> + <top>50</top> + </coordinates> + <include>dialogeffect</include> + <controls> + <control type="image"> + <left>0</left> + <top>0</top> + <width>1040</width> + <height>600</height> + <texture border="40">DialogBack.png</texture> + </control> + + <control type="image"> + <left>20</left> + <top>20</top> + <width>1000</width> + <height>560</height> + <texture>$INFO[Skin.CurrentTheme,special://skin/backgrounds/,.jpg]</texture> + <visible>![Skin.HasSetting(UseCustomBackground) + !IsEmpty(Skin.String(CustomBackgroundPath))]</visible> + <include>VisibleFadeEffect</include> + <colordiffuse>FF444444</colordiffuse> + </control> + + <control type="image"> + <description>Dialog Header image</description> + <left>40</left> + <top>16</top> + <width>960</width> + <height>40</height> + <texture>dialogheader.png</texture> + </control> + + <control type="label" id="1"> + <description>header label</description> + <left>40</left> + <top>20</top> + <width>960</width> + <height>30</height> + <font>font13_title</font> + <label>Person Info</label> + <align>center</align> + <aligny>center</aligny> + <textcolor>selected</textcolor> + <shadowcolor>black</shadowcolor> + </control> + + <!-- + <control type="button" id="8"> + <description>Close Window button</description> + <left>960</left> + <top>15</top> + <width>64</width> + <height>32</height> + <label>-</label> + <font>-</font> + <onclick>PreviousMenu</onclick> + <texturefocus>DialogCloseButton-focus.png</texturefocus> + <texturenofocus>DialogCloseButton.png</texturenofocus> + <onleft>-</onleft> + <onright>-</onright> + <onup>-</onup> + <ondown>3005</ondown> + </control> + --> + + <control type="label" id="3000"> + <description>person name</description> + <left>30</left> + <top>65</top> + <width>550</width> + <height>100</height> + <align>left</align> + <label>-</label> + <font>font13</font> + <textcolor>white</textcolor> + </control> + + <control type="image" id="3009"> + <left>30</left> + <top>120</top> + <width>250</width> + <height>250</height> + <aspectratio>keep</aspectratio> + </control> + + <control type="textbox" id="3001"> + <description>text</description> + <left>300</left> + <top>100</top> + <width>630</width> + <height>280</height> + <align>left</align> + <label>-</label> + <font>font12</font> + <pagecontrol>3005</pagecontrol> + </control> + <control type="scrollbar" id="3005"> + <left>940</left> + <top>100</top> + <width>20</width> + <height>280</height> + <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground> + <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar> + <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus> + <textureslidernib>ScrollBarNib.png</textureslidernib> + <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus> + <onup>8</onup> + <onleft>3001</onleft> + <onright>-</onright> + <ondown>3010</ondown> + <showonepage>false</showonepage> + <orientation>vertical</orientation> + </control> + + + <control type="list" id="3010"> + <left>40</left> + <top>390</top> + <width>940</width> + <height>170</height> + <onleft>-</onleft> + <onright>-</onright> + <onup>3005</onup> + <ondown>3011</ondown> + <pagecontrol>3011</pagecontrol> + <scrolltime>200</scrolltime> + <orientation>horizontal</orientation> + <itemlayout width="120"> + <control type="image"> + <left>0</left> + <top>0</top> + <width>100</width> + <height>150</height> + <texture>$INFO[Listitem.Icon]</texture> + <bordertexture border="5">button-nofocus.png</bordertexture> + <bordersize>5</bordersize> + </control> + <control type="label"> + <left>0</left> + <top>150</top> + <width>100</width> + <height>20</height> + <align>left</align> + <font>font10</font> + <textcolor>FFFFFFFFFF</textcolor> + <label>$INFO[Listitem.Label2]</label> + </control> + </itemlayout> + <focusedlayout width="120"> + <control type="image"> + <left>0</left> + <top>0</top> + <width>100</width> + <height>150</height> + <texture>$INFO[Listitem.Icon]</texture> + <bordertexture border="5">button-nofocus.png</bordertexture> + <bordersize>5</bordersize> + </control> + <control type="image"> + <left>0</left> + <top>0</top> + <width>100</width> + <height>150</height> + <texture>$INFO[Listitem.Icon]</texture> + <bordertexture border="5">button-focus.png</bordertexture> + <bordersize>5</bordersize> + <visible>Control.HasFocus(3010)</visible> + </control> + <control type="label"> + <left>0</left> + <top>150</top> + <width>100</width> + <height>20</height> + <align>left</align> + <font>font10</font> + <textcolor>FFFFFFFFFF</textcolor> + <label>$INFO[Listitem.Label2]</label> + </control> + </focusedlayout> + </control> + <control type="scrollbar" id="3011"> + <left>40</left> + <top>560</top> + <width>940</width> + <height>20</height> + <texturesliderbackground border="14,0,14,0">ScrollBarH.png</texturesliderbackground> + <texturesliderbar border="16,2,16,2">ScrollBarH_bar.png</texturesliderbar> + <texturesliderbarfocus border="16,2,16,2">ScrollBarH_bar_focus.png</texturesliderbarfocus> + <textureslidernib>ScrollBarNib.png</textureslidernib> + <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus> + <onup>3010</onup> + <showonepage>false</showonepage> + <orientation>horizontal</orientation> + </control> + + + </controls> +</window> diff --git a/service.py b/service.py index 80395ad4..f21bb036 100644 --- a/service.py +++ b/service.py @@ -94,9 +94,14 @@ class Service(): pass lastProgressUpdate = datetime.today() # only try autoplay when there's 20 seconds or less remaining and only once! - if (totalTime - playTime <= 20 and (lastFile==None or lastFile!=currentFile)): - lastFile = currentFile - player.autoPlayPlayback() + addonSettings = xbmcaddon.Addon(id='plugin.video.emby') + + # if its an episode see if autoplay is enabled + if addonSettings.getSetting("autoPlaySeason")=="true": + notificationtime = addonSettings.getSetting("autoPlaySeasonTime") + if (totalTime - playTime <= int(notificationtime) and (lastFile==None or lastFile!=currentFile)): + lastFile = currentFile + player.autoPlayPlayback() except Exception, e: self.logMsg("Exception in Playback Monitor Service: %s" % e) From 07f2ee80ca6496128dd245165d2f12446898be5f Mon Sep 17 00:00:00 2001 From: im85288 <ianmalcolmmclaughlin@gmail.com> Date: Wed, 6 May 2015 22:42:27 +0100 Subject: [PATCH 2/2] version bump --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 38c6828d..251b2e56 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="plugin.video.emby" name="Emby" - version="0.1.1" + version="0.1.2" provider-name="Emby.media"> <requires> <import addon="xbmc.python" version="2.1.0"/>