diff --git a/addon.xml b/addon.xml index 0f3e569d..99267db0 100644 --- a/addon.xml +++ b/addon.xml @@ -13,6 +13,7 @@ executable + Plex for Kodi diff --git a/lib/_included_packages/plexnet/photo.py b/lib/_included_packages/plexnet/photo.py index e2036a8c..17107c4d 100644 --- a/lib/_included_packages/plexnet/photo.py +++ b/lib/_included_packages/plexnet/photo.py @@ -52,6 +52,7 @@ def isPhotoOrDirectoryItem(self): @plexobjects.registerLibFactory('photo') +@plexobjects.registerLibFactory('image') def PhotoFactory(data, initpath=None, server=None, container=None): if data.tag == 'Photo': return Photo(data, initpath=initpath, server=server, container=container) diff --git a/lib/_included_packages/plexnet/plexlibrary.py b/lib/_included_packages/plexnet/plexlibrary.py index b8a1f8a6..d153dc28 100644 --- a/lib/_included_packages/plexnet/plexlibrary.py +++ b/lib/_included_packages/plexnet/plexlibrary.py @@ -75,6 +75,9 @@ def optimize(self): def refresh(self): self.server.query('/library/sections/all/refresh') + + def randomArts(self): + return plexobjects.listItems(self.server, '/library/arts?sort=random&type=1%2c2%2c8&X-Plex-Container-Start=0&X-Plex-Container-Size=50') class LibrarySection(plexobjects.PlexObject): diff --git a/lib/util.py b/lib/util.py index 427ff991..b932b3bb 100644 --- a/lib/util.py +++ b/lib/util.py @@ -89,6 +89,7 @@ class AdvancedSettings(object): ("auto_seek", True), ("dynamic_timeline_seek", False), ("fast_back", False), + ("screensaver_quiz", False), ) def __init__(self): diff --git a/lib/windows/slidehshow.py b/lib/windows/slidehshow.py new file mode 100644 index 00000000..fac07bb6 --- /dev/null +++ b/lib/windows/slidehshow.py @@ -0,0 +1,108 @@ +import time +import random + +import kodigui + +from lib import util +from plexnet import plexapp + +class Slideshow(kodigui.BaseWindow, util.CronReceiver): + xmlFile = 'script-plex-slideshow.xml' + path = util.ADDON.getAddonInfo('path') + theme = 'Main' + res = '1080i' + width = 1920 + height = 1080 + + TIME_BETWEEN_IMAGES = 15 + TIME_HIDE_TITLE_IN_QUIZ = 5 + TIME_DISPLAY_MOVE = 60 + + CONTROL_INFO_GROUP = 100 + + def __init__(self, *args, **kwargs): + kodigui.BaseWindow.__init__(self, *args, **kwargs) + self.timeBetweenImages = self.TIME_BETWEEN_IMAGES + self.timeBetweenDisplayMove = self.TIME_DISPLAY_MOVE + self.timeTitleIsHidden = self.TIME_HIDE_TITLE_IN_QUIZ + self.quizMode = util.advancedSettings.screensaverQuiz + self.initialized = False + + def onFirstInit(self): + self.setProperty('clock', '') + self.setProperty('title', '') + self.setProperty('thumb', '') + self.setProperty('align', '0') + + self.infoGroupControl = self.getControl(self.CONTROL_INFO_GROUP) + + util.CRON.registerReceiver(self) + self.timeFormat = util.timeFormat.replace(":%S", "") + self.lastTime = '' + self.displayPosition = 0 + self.changeTime = time.time() - 1 + self.displayMoveTime = time.time() + self.timeBetweenDisplayMove + self.revealTitleTime = None + + self.selectedServer = plexapp.SERVERMANAGER.selectedServer + self.index = -1 + self.images = [] + + self.initialized = True + + def tick(self): + if not self.initialized: + return + + currentTime = time.time() + timestr = time.strftime(self.timeFormat, time.localtime(currentTime)) + if not util.padHour and timestr[0] == "0" and timestr[1] != ":": + timestr = timestr[1:] + + if currentTime > self.changeTime: + nextIndex = self.index + 1 + + if nextIndex >= len(self.images): + if self.selectedServer != None: + self.images = self.selectedServer.library.randomArts(); + util.DEBUG_LOG('[SS] Fetched {0} items'.format(len(self.images))) + nextIndex = 0 + + if len(self.images) == 0: + title = 'No Images' + url = '' + else: + image = self.images[nextIndex] + title = image.get('title') + key = image.get('key') + url = self.selectedServer.getImageTranscodeURL(key, self.width, self.height) + if not self.quizMode: + self.setProperty('title', title) + else: + self.setProperty('title', '') + self.quizTitle = title + self.revealTitleTime = currentTime + self.timeTitleIsHidden + self.setProperty('thumb', url) + + self.index = nextIndex + self.changeTime = time.time() + self.timeBetweenImages + + if self.revealTitleTime != None and currentTime > self.revealTitleTime: + self.setProperty('title', self.quizTitle) + self.revealTitleTime = None + + if currentTime > self.displayMoveTime: + oldDisplayPosition = self.displayPosition + self.displayPosition = (oldDisplayPosition + random.randint(1, 3)) % 4 + + if (oldDisplayPosition&2) != (self.displayPosition&2): + self.setProperty('align', str((self.displayPosition&2)>>1)) + + if (oldDisplayPosition&1) != (self.displayPosition&1): + newY = self.height - self.infoGroupControl.getY() - self.infoGroupControl.getHeight() + self.infoGroupControl.setPosition(self.infoGroupControl.getX(), newY) + + self.displayMoveTime = currentTime + self.timeBetweenDisplayMove + + if timestr != self.lastTime: + self.setProperty('clock', timestr) \ No newline at end of file diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po index 90041a57..80e963ca 100644 --- a/resources/language/English/strings.po +++ b/resources/language/English/strings.po @@ -975,6 +975,13 @@ msgctxt "#32485" msgid "Go back instantly with the previous menu action in scrolled views" msgstr "" +msgctxt "#32488" +msgid "Screensaver" +msgstr "" + +msgctxt "#32489" +msgid "Quiz Mode" +msgstr "" msgctxt "#32492" msgid "Kodi Subtitle Settings" msgstr "" \ No newline at end of file diff --git a/resources/settings.xml b/resources/settings.xml index a30da7ce..aa0742be 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -16,4 +16,7 @@ + + + diff --git a/resources/skins/Main/1080i/script-plex-slideshow.xml b/resources/skins/Main/1080i/script-plex-slideshow.xml new file mode 100644 index 00000000..74ef7e39 --- /dev/null +++ b/resources/skins/Main/1080i/script-plex-slideshow.xml @@ -0,0 +1,63 @@ + + 6 + + + + 0 + 0 + 1920 + 1080 + + keep + 1000 + $INFO[Window.Property(thumb)] + + + 20 + 20 + 100 + 1880 + + String.IsEqual(Window.Property(align),0) + 0 + 50 + font45 + left + FFFFFFFF + FF000000 + + + + String.IsEqual(Window.Property(align),0) + 50 + 20 + font16 + left + FFFFFFFF + FF000000 + + + + String.IsEqual(Window.Property(align),1) + 0 + 50 + font45 + right + FFFFFFFF + FF000000 + + + + String.IsEqual(Window.Property(align),1) + 50 + 20 + font16 + right + FFFFFFFF + FF000000 + + + + + + \ No newline at end of file diff --git a/screensaver.py b/screensaver.py new file mode 100644 index 00000000..8e15051b --- /dev/null +++ b/screensaver.py @@ -0,0 +1,24 @@ +import xbmc + +from lib import plex, util + +from lib.windows import slidehshow + +class ScreensaverMonitor(xbmc.Monitor): + def __init__( self, *args, **kwargs ): + self.action = kwargs['action'] + + def onScreensaverDeactivated(self): + self.action() + +def main(): + util.DEBUG_LOG("[SS] Starting") + if plex.init(): + with util.Cron(1): + ss = slidehshow.Slideshow.create() + ss.monitor = ScreensaverMonitor(action = ss.close) + ss.modal() + del ss + +if __name__ == '__main__': + main() \ No newline at end of file