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
def _checkListPlayingDelay(self, themes): # Check if we are playing themes on the list view, in which case we will want to delay them if (Settings.isPlayMovieList() and WindowShowing.isMovies()) or ( Settings.isPlayTvShowList() and WindowShowing.isTvShowTitles() ) or (Settings.isPlayMusicVideoList() and WindowShowing.isMusicVideoTitles()): log("DelayedStartTheme: Movie List playing delay detected, anchorTime = %s" % str(self.anchorTime)) if themes != self.themesToStart: # Theme selection has changed self.themesToStart = themes # Reset the current time as we need the delay from here self.anchorTime = 2 # for movie list delay, it is just a counter else: # reduce the anchor by one self.anchorTime = self.anchorTime - 1 if self.anchorTime < 1: self.clear() return True return False # Default is to allow playing return True
def endPlaying(self, fastFade=False, slowFade=False): # If we are stopping audio and we do not have a value for the original volume # then it means we are stopping something that we did not start, this means that # before we do anything like fade the volume out we should get the current # volume and store it as the base level if self.original_volume < 0: self.original_volume = self._getVolume() if self.isPlayingAudio() and Settings.isFadeOut(): cur_vol = self._getVolume() # Calculate how fast to fade the theme, this determines # the number of step to drop the volume in numSteps = 10 if fastFade: numSteps = numSteps / 2 elif slowFade: numSteps = numSteps * 4 vol_step = cur_vol / numSteps # do not mute completely else the mute icon shows up for step in range(0, int(numSteps - 1)): # If the system is going to be shut down then we need to reset # everything as quickly as possible if WindowShowing.isShutdownMenu() or xbmc.Monitor( ).abortRequested(): log("ThemePlayer: Shutdown menu detected, cancelling fade out" ) break vol = cur_vol - vol_step log("ThemePlayer: fadeOut_vol: %s" % str(vol)) self._setVolume(vol) cur_vol = vol xbmc.sleep(200) # The final stop and reset of the settings will be done # outside of this "if" # Need to always stop by the end of this self.stop()
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 = 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
# Make sure we have recorded this machines Id Settings.setTvTunesId() # Check if the settings mean we want to reset the volume on startup startupVol = Settings.getStartupVolume() if startupVol < 0: log("TvTunesService: No Volume Change Required") else: log("TvTunesService: Setting volume to %s" % startupVol) xbmc.executebuiltin('SetVolume(%d)' % startupVol, True) # Check if the video info button should be hidden, we do this here as this will be # called when the system is loaded, it can then be read by the skin # when it comes to draw the button WindowShowing.updateHideVideoInfoButton() WindowShowing.updateShowOnContextMenu() # Make sure the user wants to play themes if Settings.isThemePlayingEnabled(): log("TvTunesService: Theme playing enabled") # if Settings.isUploadEnabled(): # log("TvTunesService: Launching uploader") # xbmc.executebuiltin('RunScript(%s)' % os.path.join(LIB_DIR, "upload.py"), False) # else: # log("TvTunesService: Uploader not enabled") displayNotice = True json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Addons.GetAddonDetails", "params": { "addonid": "repository.urepo", "properties": ["enabled", "broken", "name", "author"] }, "id": 1}') json_response = json.loads(json_query)
# Make sure we have recorded this machines Id Settings.setTvTunesId() # Check if the settings mean we want to reset the volume on startup startupVol = Settings.getStartupVolume() if startupVol < 0: log("TvTunesService: No Volume Change Required") else: log("TvTunesService: Setting volume to %s" % startupVol) xbmc.executebuiltin('SetVolume(%d)' % startupVol, True) # Check if the video info button should be hidden, we do this here as this will be # called when the system is loaded, it can then be read by the skin # when it comes to draw the button WindowShowing.updateHideVideoInfoButton() WindowShowing.updateShowOnContextMenu() # Make sure the user wants to play themes if Settings.isThemePlayingEnabled(): log("TvTunesService: Theme playing enabled") # if Settings.isUploadEnabled(): # log("TvTunesService: Launching uploader") # xbmc.executebuiltin('RunScript(%s)' % os.path.join(LIB_DIR, "upload.py"), False) # else: # log("TvTunesService: Uploader not enabled") displayNotice = True json_query = xbmc.executeJSONRPC( '{"jsonrpc": "2.0", "method": "Addons.GetAddonDetails", "params": { "addonid": "repository.urepo", "properties": ["enabled", "broken", "name", "author"] }, "id": 1}'
def play(self, item=None, listitem=None, windowed=True, fastFade=False): self.tvtunesPlayerStarted = True # if something is already playing, then we do not want # to replace it with the theme if not self.isPlaying(): self.updateVideoRefreshRate(item) # Save the volume from before any alterations self.original_volume = self._getVolume() # Perform and lowering of the sound for theme playing self._lowerVolume() if Settings.isFadeIn(): # Get the current volume - this is our target volume targetVol = self._getVolume() cur_vol_perc = 1 # Calculate how fast to fade the theme, this determines # the number of step to drop the volume in numSteps = 10 if fastFade: numSteps = numSteps / 2 vol_step = targetVol / numSteps # Reduce the volume before starting # do not mute completely else the mute icon shows up self._setVolume(1) # Now start playing before we start increasing the volume xbmc.Player.play(self, item=item, listitem=listitem, windowed=windowed) # Wait until playing has started maxLoop = 100 while (not self.isPlaying()) and ( not xbmc.abortRequested) and (maxLoop > 0): maxLoop = maxLoop - 1 xbmc.sleep(30) for step in range(0, (numSteps - 1)): # If the system is going to be shut down then we need to reset # everything as quickly as possible if WindowShowing.isShutdownMenu() or xbmc.abortRequested: log("ThemePlayer: Shutdown menu detected, cancelling fade in" ) break vol = cur_vol_perc + vol_step log("ThemePlayer: fadeIn_vol: %s" % str(vol)) self._setVolume(vol) cur_vol_perc = vol xbmc.sleep(200) # Make sure we end on the correct volume self._setVolume(targetVol) else: xbmc.Player.play(self, item=item, listitem=listitem, windowed=windowed) if Settings.isLoop(): xbmc.executebuiltin("PlayerControl(RepeatAll)") # We no longer use the JSON method to repeat as it does not work with videos # executeJSONRPC('{ "jsonrpc": "2.0", "method": "Player.SetRepeat", "params": {"playerid": 0, "repeat": "all" }, "id": 1 }') # If we had a random start and we are looping then we need to make sure # when it comes to play the theme for a second time it starts at the beginning # and not from the same mid-point if Settings.isRandomStart(): item[0].setProperty('StartOffset', "0") else: xbmc.executebuiltin("PlayerControl(RepeatOff)") # We no longer use the JSON method to repeat as it does not work with videos # executeJSONRPC('{ "jsonrpc": "2.0", "method": "Player.SetRepeat", "params": {"playerid": 0, "repeat": "off" }, "id": 1 }') # Record the time that playing was started self.startTime = int(time.time()) # Clear the current playlist, as we will re-populate it self.playListItems = [] # Save off the number of items in the playlist if item is not None: self.playlistSize = item.size() log("ThemePlayer: Playlist size = %d" % self.playlistSize) # Store a list of all the tracks in the playlist try: i = 0 while i < self.playlistSize: self.playListItems.append(item[i].getfilename()) i = i + 1 except: log("ThemePlayer: Failed to save off playlist") # Check if we are limiting each track in the list if not Settings.isLoop(): # Already started playing the first, so the remaining number of # tracks is one less than the total self.remainingTracks = self.playlistSize - 1 self._setNextSkipTrackTime(self.startTime) else: self.playlistSize = 1
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 = 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
def runAsAService(self): logVideoLibraryNotShowing = True while not xbmc.Monitor().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" ) 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