Пример #1
0
 def _startPlayingExistingTheme(self, path):
     log("startPlayingExistingTheme: Playing existing theme for %s" % path)
     # Search for the themes
     themeFiles = ThemeFiles(path)
     if themeFiles.hasThemes():
         playlist = themeFiles.getThemePlaylist()
         # Stop playing any existing theme
         self._stopPlayingTheme()
         xbmc.Player().play(playlist)
     else:
         log("No themes found for %s" % path)
     del themeFiles
Пример #2
0
    def getVideos(self, jsonGet, target):
        json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.%s", "params": {"properties": ["title", "file", "imdbnumber", "year"], "sort": { "method": "title" } }, "id": 1}' % jsonGet)
        json_query = unicode(json_query, 'utf-8', errors='ignore')
        json_response = simplejson.loads(json_query)
        log(json_response)
        videolist = []
        if ("result" in json_response) and (target in json_response['result']):
            for item in json_response['result'][target]:
                # Before we process anything make sure we are not due to shut down
                if xbmc.abortRequested:
                    return videolist

                videoItem = {}
                # Record if this is tvshows or movies
                videoItem['type'] = target
                videoItem['title'] = item['title'].encode("utf-8")
                # The file is actually the path for a TV Show, the video file for movies
                videoItem['file'] = item['file']
                # The name is a bit misleading, it's the ID for whatever scanner was used
                videoItem['imdbnumber'] = item['imdbnumber']

                videoItem['emby'] = False
                if "plugin.video.emby" in item['file']:
                    if not self.isEmbyEnabled:
                        continue
                    videoItem['emby'] = True

                # Get the themes if they exist
                themeFileMgr = ThemeFiles(videoItem['file'], videotitle=item['title'])

                # Make sure there are themes
                if not themeFileMgr.hasThemes():
                    continue

                checkedId = self.getMetaHandlersID(target, videoItem['title'], item['year'])

                # Not sure why there would be a video in the library without an ID, but check just in case
                if videoItem['imdbnumber'] in ["", None]:
                    videoItem['imdbnumber'] = checkedId
                elif (checkedId not in [None, ""]) and (videoItem['imdbnumber'] != checkedId):
                    log("UploadThemes: ID comparison, Original = %s, checked = %s ... Skipping" % (videoItem['imdbnumber'], checkedId))
                    continue

                # Make sure there are themes and the ID is set
                if videoItem['imdbnumber'] not in ["", None]:
                    requiredThemes = self._getThemesToUpload(target, videoItem['imdbnumber'], themeFileMgr.getThemeLocations())
                    if len(requiredThemes) > 0:
                        videoItem['themes'] = requiredThemes
                        videolist.append(videoItem)
        return videolist
Пример #3
0
    def getVideos(self, jsonGet, target):
        json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.%s", "params": {"properties": ["title", "file", "imdbnumber", "year"], "sort": { "method": "title" } }, "id": 1}' % jsonGet)
        json_query = unicode(json_query, 'utf-8', errors='ignore')
        json_response = simplejson.loads(json_query)
        log(json_response)
        videolist = []
        if ("result" in json_response) and (target in json_response['result']):
            for item in json_response['result'][target]:
                # Before we process anything make sure we are not due to shut down
                if xbmc.abortRequested:
                    return []

                videoItem = {}
                # Record if this is tvshows or movies
                videoItem['type'] = target
                videoItem['title'] = item['title'].encode("utf-8")
                videoItem['year'] = item['year']
                # The file is actually the path for a TV Show, the video file for movies
                videoItem['file'] = item['file']
                # The name is a bit misleading, it's the ID for whatever scanner was used
                videoItem['imdbnumber'] = str(item['imdbnumber'])

                # Not sure why there would be a video in the library without an ID, but check just in case
                if videoItem['imdbnumber'] in ["", None]:
                    continue

                isTvShow = False
                if target == 'tvshows':
                    isTvShow = True

                # We have an ID for the video, check to see if we already have
                # something uploaded with this ID
                matchedThemeIds = self._getThemes(videoItem['imdbnumber'], isTvShow)

                if matchedThemeIds not in [None, ""]:
                    log("UploadThemes: Theme for target %s and id %s already in library" % (target, videoItem['imdbnumber']))
                    continue

                # Get the themes if they exist
                themeFileMgr = ThemeFiles(videoItem['file'], videotitle=item['title'])

                # Make sure there are themes
                if not themeFileMgr.hasThemes():
                    continue

                if (len(themeFileMgr.getThemeLocations()) > 1) and self.skipMultipleThemes:
                    log("UploadThemes: Skipping multiple themes")
                    continue

                # Check if any of the themes available as suitable for upload
                requiredThemes = self._getThemesToUpload(videoItem['imdbnumber'], themeFileMgr.getThemeLocations())
                if len(requiredThemes) < 1:
                    log("UploadThemes: No Required themes found")
                    continue

                # This video has themes that are needed
                videoItem['themes'] = requiredThemes

                # Also check our local record of things that have already been done
                if self.isThemeAlreadyUploaded(videoItem):
                    log("UploadThemes: Theme %s already uploaded" % videoItem['imdbnumber'])
                    continue

                videolist.append(videoItem)

        # Before returning the list, randonise it so that things are not always in the same order
        random.shuffle(videolist)

        return videolist
Пример #4
0
class TunesBackend():
    def __init__(self):
        self.themePlayer = ThemePlayer()
        log("### starting TvTunes Backend ###")
        self.newThemeFiles = ThemeFiles("")
        self.oldThemeFiles = ThemeFiles("")
        self.prevThemeFiles = ThemeFiles("")
        self.delayedStart = DelayedStartTheme()

        self.isAlive = False

        # Only used for logging filtering
        self.lastLoggedThemePath = ""

    def runAsAService(self):
        logVideoLibraryNotShowing = True

        while not xbmc.abortRequested:
            # Wait a little before starting the check each time
            xbmc.sleep(200)

            # Check the forced TV Tunes status at the start of the loop, if this is True
            # then we don't want to stop themes until the next iteration, this stops the case
            # where some checks are done and the value changes part was through a single
            # loop iteration
            isForcedTvTunesContinue = WindowShowing.isTvTunesOverrideContinuePlaying()

            # Stop the theme if the shutdown menu appears - it normally means
            # we are about to shut the system down, so get ahead of the game
            if WindowShowing.isShutdownMenu():
                self.stop(fastFade=True)
                continue

            # NOTE: The screensaver kicking in will only be picked up if the option
            # "Use Visualization if Playing Audio" is disabled
            if WindowShowing.isScreensaver():
                if self.isAlive:
                    log("TunesBackend: Screensaver active")
                    self.stop(fastFade=True)

                    # It may be possible that we stopped for the screen-saver about to kick in
                    # If we are using Gotham or higher, it is possible for us to re-kick off the
                    # screen-saver, otherwise the action of us stopping the theme will reset the
                    # timeout and the user will have to wait longer
                    log("TunesBackend: Restarting screensaver that TvTunes stopped")
                    xbmc.executebuiltin("ActivateScreensaver", True)
                continue

            # Check if TvTunes is blocked from playing any themes
            if xbmcgui.Window(10025).getProperty('TvTunesBlocked') not in [None, ""]:
                self.stop(fastFade=True)
                continue

            if (not WindowShowing.isVideoLibrary()) and (not WindowShowing.isMusicSection()):
                log("TunesBackend: Video Library no longer visible", logVideoLibraryNotShowing)
                logVideoLibraryNotShowing = False
                # End playing cleanly (including any fade out) and then stop everything
                self.stop()
                continue
            else:
                logVideoLibraryNotShowing = True

            # There is a valid page selected and there is currently nothing playing
            if self.isPlayingZone() and not WindowShowing.isTvTunesOverrideContinuePrevious():
                newThemes = self.getThemes()
                if self.newThemeFiles != newThemes:
                    self.newThemeFiles = newThemes

            # Check if the file path has changed, if so there is a new file to play
            if self.newThemeFiles != self.oldThemeFiles and self.newThemeFiles.hasThemes():
                log("TunesBackend: old path: %s" % self.oldThemeFiles.getPath())
                log("TunesBackend: new path: %s" % self.newThemeFiles.getPath())
                if self.start_playing():
                    # Now that playing has started, update the current themes that are being used
                    self.oldThemeFiles = self.newThemeFiles

            # Check the operations where we are currently running and we need to stop
            # playing the current theme
            if self.isAlive:
                if self.themePlayer.isPlayingTheme():
                    # There is no theme at this location, so make sure we are stopped
                    if not self.newThemeFiles.hasThemes():
                        log("TunesBackend: No themes to play for current item")
                        self.themePlayer.endPlaying()
                        self.oldThemeFiles.clear()
                        self.prevThemeFiles.clear()
                        self.delayedStart.clear()
                        self.isAlive = False
                else:
                    # This will occur when a theme has stopped playing, maybe is is not set to loop
                    # There can be a delay when playing between playlist items, so give it a little
                    # time to start playing the next one
                    themeIsStillPlaying = False
                    maxLoop = 500
                    while (maxLoop > 0) and (not themeIsStillPlaying):
                        maxLoop = maxLoop - 1
                        xbmc.sleep(1)
                        if self.themePlayer.isPlayingTheme():
                            themeIsStillPlaying = True
                            break

                    if not themeIsStillPlaying:
                        log("TunesBackend: playing ended, restoring settings")
                        self.themePlayer.restoreSettings()
                        self.isAlive = False

            # This is the case where the user has moved from within an area where the themes
            # to an area where the theme is no longer played, so it will trigger a stop and
            # reset everything to highlight that nothing is playing
            if (not self.isPlayingZone()) and (not isForcedTvTunesContinue):
                self.stop()
            else:
                # Check for the case where we are playing the trailer as a theme
                # video, if so we want to stop the trailer playing when the video
                # information screen is displayed. If we don't, when the trailer is
                # started then TvTunes will automatically stop it
                if Settings.useTrailers() and WindowShowing.isMovieInformation() and self.themePlayer.isPlayingTrailerTheme():
                    self.stop()

            # Check to see if the setting to restrict the theme duration is enabled
            # and if it is we need to stop the current theme playing
            self.themePlayer.checkEnding()

        # We have finished running, just make one last check to ensure
        # we do not need to stop any audio
        self.stop(True)
        del self.themePlayer

    # Works out if the currently displayed area on the screen is something
    # that is deemed a zone where themes should be played
    def isPlayingZone(self):
        if WindowShowing.isTvTunesOverrideContinuePlaying():
            return True
        if WindowShowing.isRecentEpisodesAdded():
            return False
        if WindowShowing.isPluginPath():
            return False
        if WindowShowing.isMovieInformation() and Settings.isPlayVideoInformation():
            return True
        if WindowShowing.isSeasons() and Settings.isPlayTvShowSeasons():
            return True
        if WindowShowing.isEpisodes() and Settings.isPlayTvShowEpisodes():
            return True
        # Only valid if wanting theme on movie list
        if WindowShowing.isMovies() and Settings.isPlayMovieList():
            return True
        # Only valid if wanting theme on TV list
        if WindowShowing.isTvShowTitles() and Settings.isPlayTvShowList():
            return True
        # Only valid if wanting theme on Music Video list
        if WindowShowing.isMusicVideoTitles() and Settings.isPlayMusicVideoList():
            return True
        if WindowShowing.isMusicSection():
            return True

        # Any other area is deemed to be a non play area
        return False

    # Locates the path to look for a theme to play based on what is
    # currently being displayed on the screen
    def getThemes(self):
        themePath = ""
        # Only need the theme path for videos
        if not WindowShowing.isMusicSection():
            # Check if the files are stored in a custom path
            if Settings.isCustomPathEnabled():
                if not WindowShowing.isMovies():
                    videotitle = xbmc.getInfoLabel("ListItem.TVShowTitle")
                else:
                    videotitle = xbmc.getInfoLabel("ListItem.Title")
                videotitle = normalize_string(videotitle)
                themePath = os_path_join(Settings.getCustomPath(), videotitle)

            # Looking at the TV Show information page
            elif WindowShowing.isMovieInformation() and (WindowShowing.isTvShowTitles() or WindowShowing.isTvShows()):
                themePath = xbmc.getInfoLabel("ListItem.FilenameAndPath")
            else:
                themePath = xbmc.getInfoLabel("ListItem.Path")

        # To try and reduce the amount of "noise" in the logging, where the
        # same check is logged again and again, we record if it has been
        # logged for this video, and then do not do it again until the
        # video changes and what we would print wound be different
        debug_logging_enabled = False

        # Only log if something is different from the last time we logged
        if self.lastLoggedThemePath != themePath:
            debug_logging_enabled = True
            self.lastLoggedThemePath = themePath

        log("TunesBackend: themePath = %s" % themePath, debug_logging_enabled)

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            movieSetMap = self._getMovieSetFileList()

            if Settings.isCustomPathEnabled():
                # Need to make the values part (the path) point to the custom path
                # rather than the video file
                for aKey in movieSetMap.keys():
                    videotitle = normalize_string(aKey)
                    movieSetMap[aKey] = os_path_join(Settings.getCustomPath(), videotitle)

            if len(movieSetMap) < 1:
                themefile = ThemeFiles("", debug_logging_enabled=debug_logging_enabled)
            else:
                themefile = ThemeFiles(themePath, movieSetMap.values(), debug_logging_enabled=debug_logging_enabled)

        # When the reference is into the database and not the file system
        # then don't return it
        elif themePath.startswith("videodb:"):
            # If in either the Tv Show List or the Movie list then
            # need to stop the theme is selecting the back button
            if WindowShowing.isMovies() or WindowShowing.isTvShowTitles():
                themefile = ThemeFiles("", debug_logging_enabled=debug_logging_enabled)
            else:
                # Load the previous theme
                themefile = self.newThemeFiles
        else:
            if WindowShowing.isMusicSection():
                themefile = MusicThemeFiles(debug_logging_enabled)
            else:
                themefile = ThemeFiles(themePath, debug_logging_enabled=debug_logging_enabled)

        return themefile

    # Gets the list of movies in a movie set
    def _getMovieSetFileList(self):
        # Create a map for Program name to video file
        movieSetMap = dict()

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            # Get Movie Set Data Base ID
            dbid = xbmc.getInfoLabel("ListItem.DBID")
            # Get movies from Movie Set
            json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieSetDetails", "params": {"setid": %s, "properties": [ "thumbnail" ], "movies": { "properties":  [ "file", "title"], "sort": { "order": "ascending",  "method": "title" }} },"id": 1 }' % dbid)
            json_query = unicode(json_query, 'utf-8', errors='ignore')
            json_query = simplejson.loads(json_query)
            if ("result" in json_query) and ('setdetails' in json_query['result']):
                # Get the list of movies paths from the movie set
                items = json_query['result']['setdetails']['movies']
                for item in items:
                    log("TunesBackend: Movie Set file (%s): %s" % (item['title'], item['file']))
                    movieSetMap[item['title']] = item['file']

        return movieSetMap

    # Returns True is started playing, False is delayed
    def start_playing(self):
        playlist = self.newThemeFiles.getThemePlaylist()

        if self.newThemeFiles.hasThemes():
            if self.newThemeFiles == self.prevThemeFiles:
                log("TunesBackend: Not playing the same files twice %s" % self.newThemeFiles.getPath())
                return True  # don't play the same tune twice (when moving from season to episodes etc)
            # Value that will force a quicker than normal fade in and out
            # this is needed if switching from one theme to the next, we
            # do not want a long pause starting and stopping
            fastFadeNeeded = False

            # Check if a theme is already playing, if there is we will need
            # to stop it before playing the new theme
            # Stop any audio playing
            if self.themePlayer.isPlayingTheme():
                fastFadeNeeded = True
                log("TunesBackend: Stopping previous theme: %s" % self.prevThemeFiles.getPath())
                self.themePlayer.endPlaying(fastFade=fastFadeNeeded)

            # Check if this should be delayed
            if not self.delayedStart.shouldStartPlaying(self.newThemeFiles):
                return False

            # Before we start playing the theme, highlight that TvTunes is active by
            # Setting the property that confluence reads
            xbmcgui.Window(10025).setProperty("TvTunesIsAlive", "true")
            xbmcgui.Window(10025).setProperty("PlayingBackgroundMedia", "true")

            # Store the new theme that is being played
            self.prevThemeFiles = self.newThemeFiles
            self.isAlive = True
            log("TunesBackend: start playing %s" % self.newThemeFiles.getPath())
            self.themePlayer.play(playlist, fastFade=fastFadeNeeded)
            # Set the option so other add-ons can work out if TvTunes is playing a theme
            xbmcgui.Window(10025).setProperty("TvTunesIsRunning", "true")
        else:
            log("TunesBackend: no themes found for %s" % self.newThemeFiles.getPath())
        return True

    def stop(self, immediate=False, fastFade=False):
        if self.isAlive:
            # If video is playing, check to see if it is a theme video
            if self.themePlayer.isPlayingTheme():
                if immediate:
                    log("TunesBackend: Stop playing")
                    self.themePlayer.stop()
                    while self.themePlayer.isPlaying():
                        xbmc.sleep(50)
                else:
                    log("TunesBackend: Ending playing")
                    self.themePlayer.endPlaying(fastFade)

            self.isAlive = False

            # If currently playing a video file, then we have been overridden,
            # and we need to restore all the settings, the player callbacks
            # will not be called, so just force it on stop
            self.themePlayer.restoreSettings()

        # Clear all the values stored
        self.newThemeFiles.clear()
        self.oldThemeFiles.clear()
        self.prevThemeFiles.clear()
        self.delayedStart.clear()
        # Clear the option used by other add-ons to work out if TvTunes is playing a theme
        xbmcgui.Window(10025).clearProperty("TvTunesIsRunning")
        # The following value is added for the Confluence skin to not show what is
        # currently playing, maybe change this name when we submit the pull request to
        # Confluence - new name: PlayingBackgroundMedia
        xbmcgui.Window(10025).clearProperty("TvTunesIsAlive")
        xbmcgui.Window(10025).clearProperty("PlayingBackgroundMedia")

        # Clear the Theme Player by resetting it
        self.themePlayer = ThemePlayer()
Пример #5
0
class TunesBackend():
    def __init__(self):
        self.themePlayer = ThemePlayer()
        log("### starting TvTunes Backend ###")
        self.newThemeFiles = ThemeFiles("")
        self.oldThemeFiles = ThemeFiles("")
        self.prevThemeFiles = ThemeFiles("")
        self.delayedStart = DelayedStartTheme()

        self.isAlive = False

        # Only used for logging filtering
        self.lastLoggedThemePath = ""

    def runAsAService(self):
        logVideoLibraryNotShowing = True

        while not xbmc.abortRequested:
            # Wait a little before starting the check each time
            xbmc.sleep(200)

            # Check the forced TV Tunes status at the start of the loop, if this is True
            # then we don't want to stop themes until the next iteration, this stops the case
            # where some checks are done and the value changes part was through a single
            # loop iteration
            isForcedTvTunesContinue = WindowShowing.isTvTunesOverrideContinuePlaying()

            # Stop the theme if the shutdown menu appears - it normally means
            # we are about to shut the system down, so get ahead of the game
            if WindowShowing.isShutdownMenu():
                self.stop(fastFade=True)
                continue

            # NOTE: The screensaver kicking in will only be picked up if the option
            # "Use Visualization if Playing Audio" is disabled
            if WindowShowing.isScreensaver():
                if self.isAlive:
                    log("TunesBackend: Screensaver active")
                    self.stop(fastFade=True)

                    # It may be possible that we stopped for the screen-saver about to kick in
                    # If we are using Gotham or higher, it is possible for us to re-kick off the
                    # screen-saver, otherwise the action of us stopping the theme will reset the
                    # timeout and the user will have to wait longer
                    log("TunesBackend: Restarting screensaver that TvTunes stopped")
                    xbmc.executebuiltin("ActivateScreensaver", True)
                continue

            # Check if TvTunes is blocked from playing any themes
            if xbmcgui.Window(10025).getProperty('TvTunesBlocked') not in [None, ""]:
                self.stop(fastFade=True)
                continue

            if (not WindowShowing.isVideoLibrary()) and (not WindowShowing.isMusicSection()):
                log("TunesBackend: Video Library no longer visible", logVideoLibraryNotShowing)
                logVideoLibraryNotShowing = False
                # End playing cleanly (including any fade out) and then stop everything
                self.stop()
                continue
            else:
                logVideoLibraryNotShowing = True

            # There is a valid page selected and there is currently nothing playing
            if self.isPlayingZone() and not WindowShowing.isTvTunesOverrideContinuePrevious():
                newThemes = self.getThemes()
                if self.newThemeFiles != newThemes:
                    self.newThemeFiles = newThemes

            # Check if the file path has changed, if so there is a new file to play
            if self.newThemeFiles != self.oldThemeFiles and self.newThemeFiles.hasThemes():
                log("TunesBackend: old path: %s" % self.oldThemeFiles.getPath())
                log("TunesBackend: new path: %s" % self.newThemeFiles.getPath())
                if self.start_playing():
                    # Now that playing has started, update the current themes that are being used
                    self.oldThemeFiles = self.newThemeFiles

            # Check the operations where wee are currently running and we need to stop
            # playing the current theme
            if self.isAlive:
                if self.themePlayer.isPlayingTheme():
                    # There is no theme at this location, so make sure we are stopped
                    if not self.newThemeFiles.hasThemes():
                        log("TunesBackend: No themes to play for current item")
                        self.themePlayer.endPlaying()
                        self.oldThemeFiles.clear()
                        self.prevThemeFiles.clear()
                        self.delayedStart.clear()
                        self.isAlive = False
                else:
                    # This will occur when a theme has stopped playing, maybe is is not set to loop
                    # There can be a delay when playing between playlist items, so give it a little
                    # time to start playing the next one
                    themeIsStillPlaying = False
                    maxLoop = 500
                    while (maxLoop > 0) and (not themeIsStillPlaying):
                        maxLoop = maxLoop - 1
                        xbmc.sleep(1)
                        if self.themePlayer.isPlayingTheme():
                            themeIsStillPlaying = True
                            break

                    if not themeIsStillPlaying:
                        log("TunesBackend: playing ended, restoring settings")
                        self.themePlayer.restoreSettings()
                        self.isAlive = False

            # This is the case where the user has moved from within an area where the themes
            # to an area where the theme is no longer played, so it will trigger a stop and
            # reset everything to highlight that nothing is playing
            if (not self.isPlayingZone()) and (not isForcedTvTunesContinue):
                self.stop()

            # Check to see if the setting to restrict the theme duration is enabled
            # and if it is we need to stop the current theme playing
            self.themePlayer.checkEnding()

        # We have finished running, just make one last check to ensure
        # we do not need to stop any audio
        self.stop(True)
        del self.themePlayer

    # Works out if the currently displayed area on the screen is something
    # that is deemed a zone where themes should be played
    def isPlayingZone(self):
        if WindowShowing.isTvTunesOverrideContinuePlaying():
            return True
        if WindowShowing.isRecentEpisodesAdded():
            return False
        if WindowShowing.isPluginPath():
            return False
        if WindowShowing.isMovieInformation() and Settings.isPlayVideoInformation():
            return True
        if WindowShowing.isSeasons() and Settings.isPlayTvShowSeasons():
            return True
        if WindowShowing.isEpisodes() and Settings.isPlayTvShowEpisodes():
            return True
        # Only valid if wanting theme on movie list
        if WindowShowing.isMovies() and Settings.isPlayMovieList():
            return True
        # Only valid if wanting theme on TV list
        if WindowShowing.isTvShowTitles() and Settings.isPlayTvShowList():
            return True
        # Only valid if wanting theme on Music Video list
        if WindowShowing.isMusicVideoTitles() and Settings.isPlayMusicVideoList():
            return True
        if WindowShowing.isMusicSection():
            return True

        # Any other area is deemed to be a non play area
        return False

    # Locates the path to look for a theme to play based on what is
    # currently being displayed on the screen
    def getThemes(self):
        themePath = ""
        # Only need the theme path for videos
        if not WindowShowing.isMusicSection():
            # Check if the files are stored in a custom path
            if Settings.isCustomPathEnabled():
                if not WindowShowing.isMovies():
                    videotitle = xbmc.getInfoLabel("ListItem.TVShowTitle")
                else:
                    videotitle = xbmc.getInfoLabel("ListItem.Title")
                videotitle = normalize_string(videotitle)
                themePath = os_path_join(Settings.getCustomPath(), videotitle)

            # Looking at the TV Show information page
            elif WindowShowing.isMovieInformation() and (WindowShowing.isTvShowTitles() or WindowShowing.isTvShows()):
                themePath = xbmc.getInfoLabel("ListItem.FilenameAndPath")
            else:
                themePath = xbmc.getInfoLabel("ListItem.Path")

        # To try and reduce the amount of "noise" in the logging, where the
        # same check is logged again and again, we record if it has been
        # logged for this video, and then do not do it again until the
        # video changes and what we would print wound be different
        debug_logging_enabled = False

        # Only log if something is different from the last time we logged
        if self.lastLoggedThemePath != themePath:
            debug_logging_enabled = True
            self.lastLoggedThemePath = themePath

        log("TunesBackend: themePath = %s" % themePath, debug_logging_enabled)

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            movieSetMap = self._getMovieSetFileList()

            if Settings.isCustomPathEnabled():
                # Need to make the values part (the path) point to the custom path
                # rather than the video file
                for aKey in movieSetMap.keys():
                    videotitle = normalize_string(aKey)
                    movieSetMap[aKey] = os_path_join(Settings.getCustomPath(), videotitle)

            if len(movieSetMap) < 1:
                themefile = ThemeFiles("", debug_logging_enabled=debug_logging_enabled)
            else:
                themefile = ThemeFiles(themePath, movieSetMap.values(), debug_logging_enabled=debug_logging_enabled)

        # When the reference is into the database and not the file system
        # then don't return it
        elif themePath.startswith("videodb:"):
            # If in either the Tv Show List or the Movie list then
            # need to stop the theme is selecting the back button
            if WindowShowing.isMovies() or WindowShowing.isTvShowTitles():
                themefile = ThemeFiles("", debug_logging_enabled=debug_logging_enabled)
            else:
                # Load the previous theme
                themefile = self.newThemeFiles
        else:
            if WindowShowing.isMusicSection():
                themefile = MusicThemeFiles(debug_logging_enabled)
            else:
                themefile = ThemeFiles(themePath, debug_logging_enabled=debug_logging_enabled)

        return themefile

    # Gets the list of movies in a movie set
    def _getMovieSetFileList(self):
        # Create a map for Program name to video file
        movieSetMap = dict()

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            # Get Movie Set Data Base ID
            dbid = xbmc.getInfoLabel("ListItem.DBID")
            # Get movies from Movie Set
            json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieSetDetails", "params": {"setid": %s, "properties": [ "thumbnail" ], "movies": { "properties":  [ "file", "title"], "sort": { "order": "ascending",  "method": "title" }} },"id": 1 }' % dbid)
            json_query = unicode(json_query, 'utf-8', errors='ignore')
            json_query = simplejson.loads(json_query)
            if ("result" in json_query) and ('setdetails' in json_query['result']):
                # Get the list of movies paths from the movie set
                items = json_query['result']['setdetails']['movies']
                for item in items:
                    log("TunesBackend: Movie Set file (%s): %s" % (item['title'], item['file']))
                    movieSetMap[item['title']] = item['file']

        return movieSetMap

    # Returns True is started playing, False is delayed
    def start_playing(self):
        playlist = self.newThemeFiles.getThemePlaylist()

        if self.newThemeFiles.hasThemes():
            if self.newThemeFiles == self.prevThemeFiles:
                log("TunesBackend: Not playing the same files twice %s" % self.newThemeFiles.getPath())
                return True  # don't play the same tune twice (when moving from season to episodes etc)
            # Value that will force a quicker than normal fade in and out
            # this is needed if switching from one theme to the next, we
            # do not want a long pause starting and stopping
            fastFadeNeeded = False

            # Check if a theme is already playing, if there is we will need
            # to stop it before playing the new theme
            # Stop any audio playing
            if self.themePlayer.isPlayingTheme():
                fastFadeNeeded = True
                log("TunesBackend: Stopping previous theme: %s" % self.prevThemeFiles.getPath())
                self.themePlayer.endPlaying(fastFade=fastFadeNeeded)

            # Check if this should be delayed
            if not self.delayedStart.shouldStartPlaying(self.newThemeFiles):
                return False

            # Before we start playing the theme, highlight that TvTunes is active by
            # Setting the property that confluence reads
            xbmcgui.Window(10025).setProperty("TvTunesIsAlive", "true")
            xbmcgui.Window(10025).setProperty("PlayingBackgroundMedia", "true")

            # Store the new theme that is being played
            self.prevThemeFiles = self.newThemeFiles
            self.isAlive = True
            log("TunesBackend: start playing %s" % self.newThemeFiles.getPath())
            self.themePlayer.play(playlist, fastFade=fastFadeNeeded)
            # Set the option so other add-ons can work out if TvTunes is playing a theme
            xbmcgui.Window(10025).setProperty("TvTunesIsRunning", "true")
        else:
            log("TunesBackend: no themes found for %s" % self.newThemeFiles.getPath())
        return True

    def stop(self, immediate=False, fastFade=False):
        if self.isAlive:
            # If video is playing, check to see if it is a theme video
            if self.themePlayer.isPlayingTheme():
                if immediate:
                    log("TunesBackend: Stop playing")
                    self.themePlayer.stop()
                    while self.themePlayer.isPlaying():
                        xbmc.sleep(50)
                else:
                    log("TunesBackend: Ending playing")
                    self.themePlayer.endPlaying(fastFade)

            self.isAlive = False

            # If currently playing a video file, then we have been overridden,
            # and we need to restore all the settings, the player callbacks
            # will not be called, so just force it on stop
            self.themePlayer.restoreSettings()

        # Clear all the values stored
        self.newThemeFiles.clear()
        self.oldThemeFiles.clear()
        self.prevThemeFiles.clear()
        self.delayedStart.clear()
        # Clear the option used by other add-ons to work out if TvTunes is playing a theme
        xbmcgui.Window(10025).clearProperty("TvTunesIsRunning")
        # The following value is added for the Confluence skin to not show what is
        # currently playing, maybe change this name when we submit the pull request to
        # Confluence - new name: PlayingBackgroundMedia
        xbmcgui.Window(10025).clearProperty("TvTunesIsAlive")
        xbmcgui.Window(10025).clearProperty("PlayingBackgroundMedia")

        # Clear the Theme Player by resetting it
        self.themePlayer = ThemePlayer()
Пример #6
0
    def getVideos(self, jsonGet, target):
        json_query = xbmc.executeJSONRPC(
            '{"jsonrpc": "2.0", "method": "VideoLibrary.%s", "params": {"properties": ["title", "file", "imdbnumber", "year"], "sort": { "method": "title" } }, "id": 1}'
            % jsonGet)
        json_query = unicode(json_query, 'utf-8', errors='ignore')
        json_response = simplejson.loads(json_query)
        log(json_response)
        videolist = []
        if ("result" in json_response) and (target in json_response['result']):
            for item in json_response['result'][target]:
                # Before we process anything make sure we are not due to shut down
                if xbmc.abortRequested:
                    return []

                videoItem = {}
                # Record if this is tvshows or movies
                videoItem['type'] = target
                videoItem['title'] = item['title'].encode("utf-8")
                videoItem['year'] = item['year']
                # The file is actually the path for a TV Show, the video file for movies
                videoItem['file'] = item['file']
                # The name is a bit misleading, it's the ID for whatever scanner was used
                videoItem['imdbnumber'] = str(item['imdbnumber'])

                # Not sure why there would be a video in the library without an ID, but check just in case
                if videoItem['imdbnumber'] in ["", None]:
                    continue

                isTvShow = False
                if target == 'tvshows':
                    isTvShow = True

                # We have an ID for the video, check to see if we already have
                # something uploaded with this ID
                matchedThemeIds = self._getThemes(videoItem['imdbnumber'],
                                                  isTvShow)

                if matchedThemeIds not in [None, ""]:
                    log("UploadThemes: Theme for target %s and id %s already in library"
                        % (target, videoItem['imdbnumber']))
                    continue

                # Get the themes if they exist
                themeFileMgr = ThemeFiles(videoItem['file'],
                                          videotitle=item['title'])

                # Make sure there are themes
                if not themeFileMgr.hasThemes():
                    continue

                if (len(themeFileMgr.getThemeLocations()) >
                        1) and self.skipMultipleThemes:
                    log("UploadThemes: Skipping multiple themes")
                    continue

                # Check if any of the themes available as suitable for upload
                requiredThemes = self._getThemesToUpload(
                    videoItem['imdbnumber'], themeFileMgr.getThemeLocations())
                if len(requiredThemes) < 1:
                    log("UploadThemes: No Required themes found")
                    continue

                # This video has themes that are needed
                videoItem['themes'] = requiredThemes

                # Also check our local record of things that have already been done
                if self.isThemeAlreadyUploaded(videoItem):
                    log("UploadThemes: Theme %s already uploaded" %
                        videoItem['imdbnumber'])
                    continue

                videolist.append(videoItem)

        # Before returning the list, randonise it so that things are not always in the same order
        random.shuffle(videolist)

        return videolist
Пример #7
0
class TunesBackend():
    def __init__(self):
        self.themePlayer = Player()
        self._stop = False
        log("### starting TvTunes Backend ###")
        self.newThemeFiles = ThemeFiles("")
        self.oldThemeFiles = ThemeFiles("")
        self.prevThemeFiles = ThemeFiles("")
        self.delayedStart = DelayedStartTheme()

        # Only used for logging filtering
        self.lastLoggedThemePath = ""

    def run(self):
        try:
            # Before we actually start playing something, make sure it is OK
            # to run, need to ensure there are not multiple copies running
            if not TvTunesStatus.isOkToRun():
                return

            while (not self._stop):
                # Check the forced TV Tunes status at the start of the loop, if this is True
                # then we don't want to stop themes until the next iteration, this stops the case
                # where some checks are done and the value changes part was through a single
                # loop iteration
                isForcedTvTunesContinue = WindowShowing.isTvTunesOverrideContinuePlaying()

                # If shutdown is in progress, stop quickly (no fade out)
                if WindowShowing.isShutdownMenu() or xbmc.abortRequested:
                    self.stop()
                    break

                # We only stop looping and exit this script if we leave the Video library
                # We get called when we enter the library, and the only times we will end
                # will be if:
                # 1) A Video is selected to play
                # 2) We exit to the main menu away from the video view
                if (not WindowShowing.isVideoLibrary()) or WindowShowing.isScreensaver() or Settings.isTimout():
                    log("TunesBackend: Video Library no longer visible")
                    # End playing cleanly (including any fade out) and then stop everything
                    if TvTunesStatus.isAlive():
                        self.themePlayer.endPlaying()
                    self.stop()

                    # It may be possible that we stopped for the screen-saver about to kick in
                    # If we are using Gotham or higher, it is possible for us to re-kick off the
                    # screen-saver, otherwise the action of us stopping the theme will reset the
                    # timeout and the user will have to wait longer
                    if Settings.isTimout() and (Settings.getXbmcMajorVersion() > 12):
                        xbmc.executebuiltin("xbmc.ActivateScreensaver", True)
                    break

                # There is a valid page selected and there is currently nothing playing
                if self.isPlayingZone() and not WindowShowing.isTvTunesOverrideContinuePrevious():
                    newThemes = self.getThemes()
                    if self.newThemeFiles != newThemes:
                        self.newThemeFiles = newThemes

                # Check if the file path has changed, if so there is a new file to play
                if self.newThemeFiles != self.oldThemeFiles and self.newThemeFiles.hasThemes():
                    log("TunesBackend: old path: %s" % self.oldThemeFiles.getPath())
                    log("TunesBackend: new path: %s" % self.newThemeFiles.getPath())
                    if self.start_playing():
                        self.oldThemeFiles = self.newThemeFiles

                # There is no theme at this location, so make sure we are stopped
                if not self.newThemeFiles.hasThemes() and self.themePlayer.isPlayingAudio() and TvTunesStatus.isAlive():
                    self.themePlayer.endPlaying()
                    self.oldThemeFiles.clear()
                    self.prevThemeFiles.clear()
                    self.delayedStart.clear()
                    TvTunesStatus.setAliveState(False)

                # This will occur when a theme has stopped playing, maybe is is not set to loop
                if TvTunesStatus.isAlive() and not self.themePlayer.isPlayingAudio():
                    log("TunesBackend: playing ends")
                    self.themePlayer.restoreSettings()
                    TvTunesStatus.setAliveState(False)

                # This is the case where the user has moved from within an area where the themes
                # to an area where the theme is no longer played, so it will trigger a stop and
                # reset everything to highlight that nothing is playing
                # Note: TvTunes is still running in this case, just not playing a theme
                if (not self.isPlayingZone()) and (not isForcedTvTunesContinue):
                    self.newThemeFiles.clear()
                    self.oldThemeFiles.clear()
                    self.prevThemeFiles.clear()
                    self.delayedStart.clear()
                    if self.themePlayer.isPlaying() and TvTunesStatus.isAlive():
                        log("TunesBackend: end playing")
                        self.themePlayer.endPlaying()
                    TvTunesStatus.setAliveState(False)

                self.themePlayer.checkEnding()

                # Wait a little before starting the check again
                xbmc.sleep(200)
        except:
            log("TunesBackend: %s" % traceback.format_exc())
            self.stop()

    # Works out if the currently displayed area on the screen is something
    # that is deemed a zone where themes should be played
    def isPlayingZone(self):
        if WindowShowing.isTvTunesOverrideContinuePlaying():
            return True
        if WindowShowing.isRecentEpisodesAdded():
            return False
        if WindowShowing.isPluginPath():
            return False
        if WindowShowing.isMovieInformation():
            return True
        if WindowShowing.isSeasons():
            return True
        if WindowShowing.isEpisodes():
            return True
        # Only valid if wanting theme on movie list
        if WindowShowing.isMovies() and Settings.isPlayMovieList():
            return True
        # Only valid if wanting theme on TV list
        if WindowShowing.isTvShowTitles() and Settings.isPlayTvShowList():
            return True
        # Only valid if wanting theme on Music Video list
        if WindowShowing.isMusicVideoTitles() and Settings.isPlayMusicVideoList():
            return True
        # Any other area is deemed to be a non play area
        return False

    # Locates the path to look for a theme to play based on what is
    # currently being displayed on the screen
    def getThemes(self):
        themePath = ""

        # Check if the files are stored in a custom path
        if Settings.isCustomPathEnabled():
            if not WindowShowing.isMovies():
                videotitle = xbmc.getInfoLabel("ListItem.TVShowTitle")
            else:
                videotitle = xbmc.getInfoLabel("ListItem.Title")
            videotitle = normalize_string(videotitle)
            themePath = os_path_join(Settings.getCustomPath(), videotitle)

        # Looking at the TV Show information page
        elif WindowShowing.isMovieInformation() and (WindowShowing.isTvShowTitles() or WindowShowing.isTvShows()):
            themePath = xbmc.getInfoLabel("ListItem.FilenameAndPath")
        else:
            themePath = xbmc.getInfoLabel("ListItem.Path")

        # To try and reduce the amount of "noise" in the logging, where the
        # same check is logged again and again, we record if it has been
        # logged for this video, and then do not do it again until the
        # video changes and what we would print wound be different
        debug_logging_enabled = False

        # Only log if something is different from the last time we logged
        if self.lastLoggedThemePath != themePath:
            debug_logging_enabled = True
            self.lastLoggedThemePath = themePath

        log("TunesBackend: themePath = %s" % themePath, debug_logging_enabled)

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            movieSetMap = self._getMovieSetFileList()

            if Settings.isCustomPathEnabled():
                # Need to make the values part (the path) point to the custom path
                # rather than the video file
                for aKey in movieSetMap.keys():
                    videotitle = normalize_string(aKey)
                    movieSetMap[aKey] = os_path_join(Settings.getCustomPath(), videotitle)

            if len(movieSetMap) < 1:
                themefile = ThemeFiles("", debug_logging_enabled=debug_logging_enabled)
            else:
                themefile = ThemeFiles(themePath, movieSetMap.values(), debug_logging_enabled=debug_logging_enabled)

        # When the reference is into the database and not the file system
        # then don't return it
        elif themePath.startswith("videodb:"):
            # If in either the Tv Show List or the Movie list then
            # need to stop the theme is selecting the back button
            if WindowShowing.isMovies() or WindowShowing.isTvShowTitles():
                themefile = ThemeFiles("", debug_logging_enabled=debug_logging_enabled)
            else:
                # Load the previous theme
                themefile = self.newThemeFiles
        else:
            themefile = ThemeFiles(themePath, debug_logging_enabled=debug_logging_enabled)

        return themefile

    # Gets the list of movies in a movie set
    def _getMovieSetFileList(self):
        # Create a map for Program name to video file
        movieSetMap = dict()

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            # Get Movie Set Data Base ID
            dbid = xbmc.getInfoLabel("ListItem.DBID")
            # Get movies from Movie Set
            json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieSetDetails", "params": {"setid": %s, "properties": [ "thumbnail" ], "movies": { "properties":  [ "file", "title"], "sort": { "order": "ascending",  "method": "title" }} },"id": 1 }' % dbid)
            json_query = unicode(json_query, 'utf-8', errors='ignore')
            json_query = simplejson.loads(json_query)
            if ("result" in json_query) and ('setdetails' in json_query['result']):
                # Get the list of movies paths from the movie set
                items = json_query['result']['setdetails']['movies']
                for item in items:
                    log("TunesBackend: Movie Set file (%s): %s" % (item['title'], item['file']))
                    movieSetMap[item['title']] = item['file']

        return movieSetMap

    # Returns True is started playing, False is delayed
    def start_playing(self):
        playlist = self.newThemeFiles.getThemePlaylist()

        if self.newThemeFiles.hasThemes():
            if self.newThemeFiles == self.prevThemeFiles:
                log("TunesBackend: Not playing the same files twice %s" % self.newThemeFiles.getPath())
                return True  # don't play the same tune twice (when moving from season to episodes etc)
            # Value that will force a quicker than normal fade in and out
            # this is needed if switching from one theme to the next, we
            # do not want a long pause starting and stopping
            fastFadeNeeded = False
            # Check if a theme is already playing, if there is we will need
            # to stop it before playing the new theme
            # Stop any audio playing
            if self.themePlayer.isPlayingAudio():  # and self.prevThemeFiles.hasThemes()
                fastFadeNeeded = True
                log("TunesBackend: Stopping previous theme: %s" % self.prevThemeFiles.getPath())
                self.themePlayer.endPlaying(fastFade=fastFadeNeeded)

            # Check if this should be delayed
            if not self.delayedStart.shouldStartPlaying(self.newThemeFiles):
                return False

            # Store the new theme that is being played
            self.prevThemeFiles = self.newThemeFiles
            TvTunesStatus.setAliveState(True)
            log("TunesBackend: start playing %s" % self.newThemeFiles.getPath())
            self.themePlayer.play(playlist, fastFade=fastFadeNeeded)
        else:
            log("TunesBackend: no themes found for %s" % self.newThemeFiles.getPath())
        return True

    def stop(self):
        log("TunesBackend: ### Stopping TvTunes Backend ###")
        if TvTunesStatus.isAlive() and not self.themePlayer.isPlayingVideo():
            log("TunesBackend: stop playing")
            self.themePlayer.stop()
            while self.themePlayer.isPlayingAudio():
                xbmc.sleep(50)
        TvTunesStatus.setAliveState(False)
        TvTunesStatus.clearRunningState()

        # If currently playing a video file, then we have been overridden,
        # and we need to restore all the settings, the player callbacks
        # will not be called, so just force it on stop
        self.themePlayer.restoreSettings()

        log("TunesBackend: ### Stopped TvTunes Backend ###")
        self._stop = True
Пример #8
0
    def getThemes(self):
        themePath = ""
        # Only need the theme path for videos
        if not WindowShowing.isMusicSection():
            # Check if the files are stored in a custom path
            if Settings.isCustomPathEnabled():
                if not WindowShowing.isMovies():
                    videotitle = xbmc.getInfoLabel("ListItem.TVShowTitle")
                else:
                    videotitle = xbmc.getInfoLabel("ListItem.Title")
                videotitle = normalize_string(videotitle)
                themePath = os_path_join(Settings.getCustomPath(), videotitle)

            # Looking at the TV Show information page
            elif WindowShowing.isMovieInformation() and (
                    WindowShowing.isTvShowTitles()
                    or WindowShowing.isTvShows()):
                themePath = xbmc.getInfoLabel("ListItem.FilenameAndPath")
            else:
                themePath = xbmc.getInfoLabel("ListItem.Path")

        # To try and reduce the amount of "noise" in the logging, where the
        # same check is logged again and again, we record if it has been
        # logged for this video, and then do not do it again until the
        # video changes and what we would print wound be different
        debug_logging_enabled = False

        # Only log if something is different from the last time we logged
        if self.lastLoggedThemePath != themePath:
            debug_logging_enabled = True
            self.lastLoggedThemePath = themePath

        log("TunesBackend: themePath = %s" % themePath, debug_logging_enabled)

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            movieSetMap = self._getMovieSetFileList()

            if Settings.isCustomPathEnabled():
                # Need to make the values part (the path) point to the custom path
                # rather than the video file
                for aKey in movieSetMap.keys():
                    videotitle = normalize_string(aKey)
                    movieSetMap[aKey] = os_path_join(Settings.getCustomPath(),
                                                     videotitle)

            if len(movieSetMap) < 1:
                themefile = ThemeFiles(
                    "", debug_logging_enabled=debug_logging_enabled)
            else:
                themefile = ThemeFiles(
                    themePath,
                    movieSetMap.values(),
                    debug_logging_enabled=debug_logging_enabled)

        # When the reference is into the database and not the file system
        # then don't return it
        elif themePath.startswith("videodb:"):
            # If in either the Tv Show List or the Movie list then
            # need to stop the theme is selecting the back button
            if WindowShowing.isMovies() or WindowShowing.isTvShowTitles():
                themefile = ThemeFiles(
                    "", debug_logging_enabled=debug_logging_enabled)
            else:
                # Load the previous theme
                themefile = self.newThemeFiles
        else:
            if WindowShowing.isMusicSection():
                themefile = MusicThemeFiles(debug_logging_enabled)
            else:
                themefile = ThemeFiles(
                    themePath, debug_logging_enabled=debug_logging_enabled)

                # Check if no themes were found for this item, there is a case if it is a
                # TV Show and it is nested Show-Name/Series-X/Episode-Directory/Episode.ext
                # Then this will not pick up themes in the root of the TV Show directory
                if (not themefile.hasThemes()) and (
                        not Settings.isCustomPathEnabled()
                ) and WindowShowing.isEpisodes():
                    tvshowTitle = xbmc.getInfoLabel("ListItem.TVShowTitle")
                    if tvshowTitle not in [None, ""]:
                        try:
                            # Make a call to the database to find out the root path of this TV Show
                            filterStr = '{"operator": "is", "field": "title", "value": "%s"}' % tvshowTitle
                            cmd = '{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": {"properties": ["file"], "filter": %s},"id": 1 }' % filterStr
                            json_query = xbmc.executeJSONRPC(cmd)
                            json_query = simplejson.loads(json_query)
                            if ("result" in json_query) and (
                                    'tvshows' in json_query['result']):
                                # Get the path to the TV Show and compare it to where we were previously
                                # looking
                                tvshowList = json_query['result']['tvshows']
                                if len(tvshowList) == 1:
                                    tvshowPath = json_query['result'][
                                        'tvshows'][0]['file']
                                    # Make sure we have not already checked this path
                                    # We will already have checked the parent path as well
                                    if (tvshowPath != themePath) and (
                                            tvshowPath !=
                                            os_path_split(themePath)[0]):
                                        # So we know that we haven't checked the root of this TV Show yet
                                        log(
                                            "TunesBackend: Checking root TV Show Path = %s"
                                            % tvshowPath,
                                            debug_logging_enabled)
                                        themefile = ThemeFiles(
                                            tvshowPath,
                                            debug_logging_enabled=
                                            debug_logging_enabled)
                        except:
                            log(
                                "TunesBackend: Failed to check root TV Show %s"
                                % traceback.format_exc(),
                                debug_logging_enabled)

        return themefile