def onPlayBackStarted(self): xbmc.sleep(1000) self.type = None self.id = None # take the user start scrobble offset into account scrobbleStartOffset = utilities.getSettingAsInt( 'scrobble_start_offset') * 60 if scrobbleStartOffset > 0: waitFor = 10 waitedFor = 0 # check each 10 seconds if we can abort or proceed while not xbmc.abortRequested and scrobbleStartOffset > waitedFor: waitedFor += waitFor time.sleep(waitFor) if not self.isPlayingVideo(): logger.debug( '[traktPlayer] Playback stopped before reaching the scrobble offset' ) return # only do anything if we're playing a video if self.isPlayingVideo(): # get item data from json rpc result = utilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': { 'playerid': 1 }, 'id': 1 }) if result: logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) # check for exclusion _filename = None try: _filename = self.getPlayingFile() except: logger.debug( "[traktPlayer] onPlayBackStarted() - Exception trying to get playing filename, player suddenly stopped." ) return if utilities.checkExclusion(_filename): logger.debug( "[traktPlayer] onPlayBackStarted() - '%s' is in exclusion settings, ignoring." % _filename) return self.type = result['item']['type'] data = {'action': 'started'} # check type of item if 'id' not in result['item']: # do a deeper check to see if we have enough data to perform scrobbles logger.debug( "[traktPlayer] onPlayBackStarted() - Started playing a non-library file, checking available data." ) season = xbmc.getInfoLabel('VideoPlayer.Season') episode = xbmc.getInfoLabel('VideoPlayer.Episode') showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle') year = xbmc.getInfoLabel('VideoPlayer.Year') video_ids = xbmcgui.Window(10000).getProperty( 'script.trakt.ids') if video_ids: data['video_ids'] = json.loads(video_ids) logger.debug( "[traktPlayer] info - ids: %s, showtitle: %s, Year: %s, Season: %s, Episode: %s" % (video_ids, showtitle, year, season, episode)) if season and episode and (showtitle or video_ids): # we have season, episode and either a show title or video_ids, can scrobble this as an episode self.type = 'episode' data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = showtitle data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') if year.isdigit(): data['year'] = int(year) logger.debug( "[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' - %s - S%02dE%02d - %s." % (data['showtitle'], data['season'], data['episode'], data['title'])) elif (year or video_ids) and not season and not showtitle: # we have a year or video_id and no season/showtitle info, enough for a movie self.type = 'movie' data['type'] = 'movie' if year.isdigit(): data['year'] = int(year) data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') logger.debug( "[traktPlayer] onPlayBackStarted() - Playing a non-library 'movie' - %s (%s)." % (data['title'], data.get('year', 'NaN'))) elif showtitle: title, season, episode = utilities.regex_tvshow( False, showtitle) data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = title data['title'] = title logger.debug( "[traktPlayer] onPlayBackStarted() - Title: %s, showtitle: %s, season: %d, episode: %d" % (title, showtitle, season, episode)) else: logger.debug( "[traktPlayer] onPlayBackStarted() - Non-library file, not enough data for scrobbling, skipping." ) return elif self.type == 'episode' or self.type == 'movie': # get library id self.id = result['item']['id'] data['id'] = self.id data['type'] = self.type if self.type == 'episode': logger.debug( "[traktPlayer] onPlayBackStarted() - Doing multi-part episode check." ) result = utilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodeDetails', 'params': { 'episodeid': self.id, 'properties': ['tvshowid', 'season', 'episode', 'file'] }, 'id': 1 }) if result: logger.debug( "[traktPlayer] onPlayBackStarted() - %s" % result) tvshowid = int( result['episodedetails']['tvshowid']) season = int(result['episodedetails']['season']) currentfile = result['episodedetails']['file'] result = utilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': tvshowid, 'season': season, 'properties': ['episode', 'file'], 'sort': { 'method': 'episode' } }, 'id': 1 }) if result: logger.debug( "[traktPlayer] onPlayBackStarted() - %s" % result) # make sure episodes array exists in results if 'episodes' in result: multi = [] for i in range(result['limits']['start'], result['limits']['total']): if currentfile == result['episodes'][ i]['file']: multi.append(result['episodes'][i] ['episodeid']) if len(multi) > 1: data['multi_episode_data'] = multi data['multi_episode_count'] = len( multi) logger.debug( "[traktPlayer] onPlayBackStarted() - This episode is part of a multi-part episode." ) else: logger.debug( "[traktPlayer] onPlayBackStarted() - This is a single episode." ) else: logger.debug( "[traktPlayer] onPlayBackStarted() - Video type '%s' unrecognized, skipping." % self.type) return pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) plSize = len(pl) if plSize > 1: pos = pl.getposition() if not self.plIndex is None: logger.debug( "[traktPlayer] onPlayBackStarted() - User manually skipped to next (or previous) video, forcing playback ended event." ) self.onPlayBackEnded() self.plIndex = pos logger.debug( "[traktPlayer] onPlayBackStarted() - Playlist contains %d item(s), and is currently on item %d" % (plSize, (pos + 1))) self._playing = True # send dispatch self.action(data)
def test_regex_tvshow_title_4(): assert utilities.regex_tvshow('ShowTitle.Season 01 - Episode 02')[0] == 'ShowTitle'
def test_regex_tvshow_title_6(): assert utilities.regex_tvshow('ShowTitle - s01ep03')[0] == 'ShowTitle'
def onPlayBackStarted(self): xbmc.sleep(1000) self.type = None self.id = None # take the user start scrobble offset into account scrobbleStartOffset = kodiUtilities.getSettingAsInt( 'scrobble_start_offset') * 60 if scrobbleStartOffset > 0: waitFor = 10 waitedFor = 0 # check each 10 seconds if we can abort or proceed while not xbmc.abortRequested and scrobbleStartOffset > waitedFor: waitedFor += waitFor time.sleep(waitFor) if not self.isPlayingVideo(): logger.debug( '[traktPlayer] Playback stopped before reaching the scrobble offset' ) return # only do anything if we're playing a video if self.isPlayingVideo(): # get item data from json rpc logger.debug( "[traktPlayer] onPlayBackStarted() - Doing Player.GetItem kodiJsonRequest" ) result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': { 'playerid': 1 }, 'id': 1 }) if result: logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) # check for exclusion _filename = None try: _filename = self.getPlayingFile() except: logger.debug( "[traktPlayer] onPlayBackStarted() - Exception trying to get playing filename, player suddenly stopped." ) return if kodiUtilities.checkExclusion(_filename): logger.debug( "[traktPlayer] onPlayBackStarted() - '%s' is in exclusion settings, ignoring." % _filename) return self.type = result['item']['type'] data = {'action': 'started'} if (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr')): logger.debug( '[traktPlayer] Setting is enabled to try scrobbling mythtv pvr recording, if necessary.' ) # check type of item if 'id' not in result['item']: # do a deeper check to see if we have enough data to perform scrobbles logger.debug( "[traktPlayer] onPlayBackStarted() - Started playing a non-library file, checking available data." ) season = xbmc.getInfoLabel('VideoPlayer.Season') episode = xbmc.getInfoLabel('VideoPlayer.Episode') showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle') year = xbmc.getInfoLabel('VideoPlayer.Year') video_ids = xbmcgui.Window(10000).getProperty( 'script.trakt.ids') if video_ids: data['video_ids'] = json.loads(video_ids) logger.debug( "[traktPlayer] info - ids: %s, showtitle: %s, Year: %s, Season: %s, Episode: %s" % (video_ids, showtitle, year, season, episode)) if season and episode and (showtitle or video_ids): # we have season, episode and either a show title or video_ids, can scrobble this as an episode self.type = 'episode' data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = showtitle data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') if year.isdigit(): data['year'] = int(year) logger.debug( "[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' - %s - S%02dE%02d - %s." % (data['showtitle'], data['season'], data['episode'], data['title'])) elif (year or video_ids) and not season and not showtitle: # we have a year or video_id and no season/showtitle info, enough for a movie self.type = 'movie' data['type'] = 'movie' if year.isdigit(): data['year'] = int(year) data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') logger.debug( "[traktPlayer] onPlayBackStarted() - Playing a non-library 'movie' - %s (%s)." % (data['title'], data.get('year', 'NaN'))) elif showtitle: title, season, episode = utilities.regex_tvshow( showtitle) data['type'] = 'episode' data['season'] = season data['episode'] = episode data['title'] = data['showtitle'] = title logger.debug( "[traktPlayer] onPlayBackStarted() - Title: %s, showtitle: %s, season: %d, episode: %d" % (title, showtitle, season, episode)) else: logger.debug( "[traktPlayer] onPlayBackStarted() - Non-library file, not enough data for scrobbling, skipping." ) return elif self.type == 'episode' or self.type == 'movie': # get library id self.id = result['item']['id'] data['id'] = self.id data['type'] = self.type if self.type == 'episode': logger.debug( "[traktPlayer] onPlayBackStarted() - Doing multi-part episode check." ) result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodeDetails', 'params': { 'episodeid': self.id, 'properties': ['tvshowid', 'season', 'episode', 'file'] }, 'id': 1 }) if result: logger.debug( "[traktPlayer] onPlayBackStarted() - %s" % result) tvshowid = int( result['episodedetails']['tvshowid']) season = int(result['episodedetails']['season']) currentfile = result['episodedetails']['file'] result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': tvshowid, 'season': season, 'properties': ['episode', 'file'], 'sort': { 'method': 'episode' } }, 'id': 1 }) if result: logger.debug( "[traktPlayer] onPlayBackStarted() - %s" % result) # make sure episodes array exists in results if 'episodes' in result: multi = [] for i in range(result['limits']['start'], result['limits']['total']): if currentfile == result['episodes'][ i]['file']: multi.append(result['episodes'][i] ['episodeid']) if len(multi) > 1: data['multi_episode_data'] = multi data['multi_episode_count'] = len( multi) logger.debug( "[traktPlayer] onPlayBackStarted() - This episode is part of a multi-part episode." ) else: logger.debug( "[traktPlayer] onPlayBackStarted() - This is a single episode." ) elif (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr') and self.type == 'unknown' and result['item']['label']): # If we have label/id but no show type, then this might be a PVR recording. # DEBUG INFO: This code is useful when trying to figure out what info is available. Many of the fields # that you'd expect (TVShowTitle, episode, season, etc) are always blank. In Kodi v15, we got the show # and episode name in the VideoPlayer label. In v16, that's gone, but the Player.Filename infolabel # is populated with several interesting things. If these things change in future versions, uncommenting # this code will hopefully provide some useful info in the debug log. #logger.debug("[traktPlayer] onPlayBackStarted() - TEMP Checking all videoplayer infolabels.") #for il in ['VideoPlayer.Time','VideoPlayer.TimeRemaining','VideoPlayer.TimeSpeed','VideoPlayer.Duration','VideoPlayer.Title','VideoPlayer.TVShowTitle','VideoPlayer.Season','VideoPlayer.Episode','VideoPlayer.Genre','VideoPlayer.Director','VideoPlayer.Country','VideoPlayer.Year','VideoPlayer.Rating','VideoPlayer.UserRating','VideoPlayer.Votes','VideoPlayer.RatingAndVotes','VideoPlayer.mpaa','VideoPlayer.IMDBNumber','VideoPlayer.EpisodeName','VideoPlayer.PlaylistPosition','VideoPlayer.PlaylistLength','VideoPlayer.Cast','VideoPlayer.CastAndRole','VideoPlayer.Album','VideoPlayer.Artist','VideoPlayer.Studio','VideoPlayer.Writer','VideoPlayer.Tagline','VideoPlayer.PlotOutline','VideoPlayer.Plot','VideoPlayer.LastPlayed','VideoPlayer.PlayCount','VideoPlayer.VideoCodec','VideoPlayer.VideoResolution','VideoPlayer.VideoAspect','VideoPlayer.AudioCodec','VideoPlayer.AudioChannels','VideoPlayer.AudioLanguage','VideoPlayer.SubtitlesLanguage','VideoPlayer.StereoscopicMode','VideoPlayer.EndTime','VideoPlayer.NextTitle','VideoPlayer.NextGenre','VideoPlayer.NextPlot','VideoPlayer.NextPlotOutline','VideoPlayer.NextStartTime','VideoPlayer.NextEndTime','VideoPlayer.NextDuration','VideoPlayer.ChannelName','VideoPlayer.ChannelNumber','VideoPlayer.SubChannelNumber','VideoPlayer.ChannelNumberLabel','VideoPlayer.ChannelGroup','VideoPlayer.ParentalRating','Player.FinishTime','Player.FinishTime(format)','Player.Chapter','Player.ChapterCount','Player.Time','Player.Time(format)','Player.TimeRemaining','Player.TimeRemaining(format)','Player.Duration','Player.Duration(format)','Player.SeekTime','Player.SeekOffset','Player.SeekOffset(format)','Player.SeekStepSize','Player.ProgressCache','Player.Folderpath','Player.Filenameandpath','Player.StartTime','Player.StartTime(format)','Player.Title','Player.Filename']: # logger.debug("[traktPlayer] TEMP %s : %s" % (il, xbmc.getInfoLabel(il))) #for k,v in result.iteritems(): # logger.debug("[traktPlayer] onPlayBackStarted() - result - %s : %s" % (k,v)) #for k,v in result['item'].iteritems(): # logger.debug("[traktPlayer] onPlayBackStarted() - result.item - %s : %s" % (k,v)) # As of Kodi v16 with the MythTV PVR addon, the only way I could find to get the TV show and episode # info is from the Player.Filename infolabel. It shows up like this: # ShowName [sXXeYY ](year) EpisodeName, channel, PVRFileName # The season and episode info may or may not be present. For example: # Elementary s04e10 (2016) Alma Matters, TV (WWMT-HD), 20160129_030000.pvr # DC's Legends of Tomorrow (2016) Pilot, Part 2, TV (CW W MI), 20160129_010000.pvr foundLabel = xbmc.getInfoLabel('Player.Filename') logger.debug( "[traktPlayer] onPlayBackStarted() - Found unknown video type with label: %s. Might be a PVR episode, searching Trakt for it." % foundLabel) splitLabel = foundLabel.rsplit(", ", 2) logger.debug( "[traktPlayer] onPlayBackStarted() - Post-split of label: %s " % splitLabel) if len(splitLabel) != 3: logger.debug( "[traktPlayer] onPlayBackStarted() - Label doesn't have the ShowName sXXeYY (year) EpisodeName, channel, PVRFileName format that was expected. Giving up." ) return foundShowAndEpInfo = splitLabel[0] logger.debug( "[traktPlayer] onPlayBackStarted() - show plus episode info: %s" % foundShowAndEpInfo) splitShowAndEpInfo = re.split( ' (s\d\de\d\d)? ?\((\d\d\d\d)\) ', foundShowAndEpInfo, 1) logger.debug( "[traktPlayer] onPlayBackStarted() - Post-split of show plus episode info: %s " % splitShowAndEpInfo) if len(splitShowAndEpInfo) != 4: logger.debug( "[traktPlayer] onPlayBackStarted() - Show plus episode info doesn't have the ShowName sXXeYY (year) EpisodeName format that was expected. Giving up." ) return foundShowName = splitShowAndEpInfo[0] logger.debug( "[traktPlayer] onPlayBackStarted() - using show name: %s" % foundShowName) foundEpisodeName = splitShowAndEpInfo[3] logger.debug( "[traktPlayer] onPlayBackStarted() - using episode name: %s" % foundEpisodeName) foundEpisodeYear = splitShowAndEpInfo[2] logger.debug( "[traktPlayer] onPlayBackStarted() - using episode year: %s" % foundEpisodeYear) epYear = None try: epYear = int(foundEpisodeYear) except ValueError: epYear = None logger.debug( "[traktPlayer] onPlayBackStarted() - verified episode year: %d" % epYear) # All right, now we have the show name, episode name, and (maybe) episode year. All good, but useless for # scrobbling since Trakt only understands IDs, not names. data['video_ids'] = None data['season'] = None data['episode'] = None data['episodeTitle'] = None # First thing to try, a text query to the Trakt DB looking for this episode. Note # that we can't search for show and episode together, because the Trakt function gets confused and returns nothing. newResp = globals.traktapi.getTextQuery( foundEpisodeName, "episode", epYear) if not newResp: logger.debug( "[traktPlayer] onPlayBackStarted() - Empty Response from getTextQuery, giving up" ) else: logger.debug( "[traktPlayer] onPlayBackStarted() - Got Response from getTextQuery: %s" % str(newResp)) # We got something back. See if one of the returned values is for the show we're looking for. Often it's # not, but since there's no way to tell the search which show we want, this is all we can do. rightResp = None for thisResp in newResp: compareShowName = thisResp.show.title logger.debug( "[traktPlayer] onPlayBackStarted() - comparing show name: %s" % compareShowName) if thisResp.show.title == foundShowName: logger.debug( "[traktPlayer] onPlayBackStarted() - found the right show, using this response" ) rightResp = thisResp break if rightResp is None: logger.debug( "[traktPlayer] onPlayBackStarted() - Failed to find matching episode/show via text search." ) else: # OK, now we have a episode object to work with. self.type = 'episode' data['type'] = 'episode' # You'd think we could just use the episode key that Trakt just returned to us, but the scrobbler # function (see scrobber.py) only understands the show key plus season/episode values. showKeys = {} for eachKey in rightResp.show.keys: showKeys[eachKey[0]] = eachKey[1] data['video_ids'] = showKeys # For some reason, the Trakt search call returns the season and episode as an array in the pk field. # You'd think individual episode and season fields would be better, but whatever. data['season'] = rightResp.pk[0] data['episode'] = rightResp.pk[1] # At this point if we haven't found the episode data yet, the episode-title-text-search method # didn't work. if (not data['season']): # This text query API is basically the same as searching on the website. Works with alternative # titles, unlike the scrobble function. Though we can't use the episode year since that would only # match the show if we're dealing with season 1. logger.debug( "[traktPlayer] onPlayBackStarted() - Searching for show title via getTextQuery: %s" % foundShowName) newResp = globals.traktapi.getTextQuery( foundShowName, "show", None) if not newResp: logger.debug( "[traktPlayer] onPlayBackStarted() - Empty Show Response from getTextQuery, falling back on episode text query" ) else: logger.debug( "[traktPlayer] onPlayBackStarted() - Got Show Response from getTextQuery: %s" % str(newResp)) # We got something back. Have to assume the first show found is the right one; if there's more than # one, there's no way to know which to use. Pull the ids from the show data, and store 'em for scrobbling. showKeys = {} for eachKey in newResp[0].keys: showKeys[eachKey[0]] = eachKey[1] data['video_ids'] = showKeys # Now to find the episode. There's no search function to look for an episode within a show, but # we can get all the episodes and look for the title. while (not data['season']): logger.debug( "[traktPlayer] onPlayBackStarted() - Querying for all seasons/episodes of this show" ) epQueryResp = globals.traktapi.getShowWithAllEpisodesList( data['video_ids']['trakt']) if not epQueryResp: # Nothing returned. Giving up. logger.debug( "[traktPlayer] onPlayBackStarted() - No response received" ) break else: # Got the list back. Go through each season. logger.debug( "[traktPlayer] onPlayBackStarted() - Got response with seasons: %s" % str(epQueryResp)) for eachSeason in epQueryResp: # For each season, check each episode. logger.debug( "[traktPlayer] onPlayBackStarted() - Processing season: %s" % str(eachSeason)) for eachEpisodeNumber in eachSeason.episodes: thisEpTitle = None # Get the title. The try block is here in case the title doesn't exist for some entries. try: thisEpTitle = eachSeason.episodes[ eachEpisodeNumber].title except: thisEpTitle = None logger.debug( "[traktPlayer] onPlayBackStarted() - Checking episode number %d with title %s" % (eachEpisodeNumber, thisEpTitle)) if (foundEpisodeName == thisEpTitle ): # Found it! Save the data. The scrobbler wants season and episode number. Which for some # reason is stored as a pair in the first item in the keys array. data[ 'season'] = eachSeason.episodes[ eachEpisodeNumber].keys[ 0][0] data[ 'episode'] = eachSeason.episodes[ eachEpisodeNumber].keys[ 0][1] # Title too, just for the heck of it. Though it's not actually used. data[ 'episodeTitle'] = thisEpTitle break # If we already found our data, no need to go through the rest of the seasons. if (data['season']): break # Now we've done all we can. if (data['season']): # OK, that's everything. Data should be all set for scrobbling. logger.debug( "[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' : show trakt key %s, season: %d, episode: %d" % (data['video_ids'], data['season'], data['episode'])) else: # Still no data? Too bad, have to give up. logger.debug( "[traktPlayer] onPlayBackStarted() - Did our best, but couldn't get info for this show and episode. Skipping." ) return else: logger.debug( "[traktPlayer] onPlayBackStarted() - Video type '%s' unrecognized, skipping." % self.type) return pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) plSize = len(pl) if plSize > 1: pos = pl.getposition() if not self.plIndex is None: logger.debug( "[traktPlayer] onPlayBackStarted() - User manually skipped to next (or previous) video, forcing playback ended event." ) self.onPlayBackEnded() self.plIndex = pos logger.debug( "[traktPlayer] onPlayBackStarted() - Playlist contains %d item(s), and is currently on item %d" % (plSize, (pos + 1))) self._playing = True # send dispatch self.action(data)
def test_regex_tvshow_episode_6(): assert utilities.regex_tvshow('ShowTitle - s01ep09')[2] == 9
def test_regex_tvshow_title_4(): assert utilities.regex_tvshow( 'ShowTitle.Season 01 - Episode 02')[0] == 'ShowTitle'
def test_regex_tvshow_season_6(): assert utilities.regex_tvshow('ShowTitle - s01ep03')[1] == 1
def test_regex_tvshow_episode_4(): assert utilities.regex_tvshow('ShowTitle.Season 01 - Episode 09')[2] == 9
def test_regex_tvshow_season_4(): assert utilities.regex_tvshow('ShowTitle.Season 01 - Episode 02')[1] == 1
def test_regex_tvshow_season_5(): assert utilities.regex_tvshow('ShowTitle_[s01]_[e01]')[1] == 1
def test_regex_tvshow_season_3(): assert utilities.regex_tvshow('ShowTitle.109')[1] == 1
def test_regex_tvshow_title_5(): assert utilities.regex_tvshow('ShowTitle_[s01]_[e01]')[0] == 'ShowTitle'
def test_regex_tvshow_episode_3(): assert utilities.regex_tvshow('ShowTitle.109')[2] == 9
def test_regex_tvshow_episode_5(): assert utilities.regex_tvshow('ShowTitle_[s01]_[e09]')[2] == 9
def test_regex_tvshow_title_3(): assert utilities.regex_tvshow('ShowTitle.109')[0] == 'ShowTitle'
def onPlayBackStarted(self): xbmc.sleep(1000) self.type = None self.id = None # only do anything if we're playing a video if self.isPlayingVideo(): # get item data from json rpc result = utilities.xbmcJsonRequest({ 'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': { 'playerid': 1 }, 'id': 1 }) utilities.Debug("[traktPlayer] onPlayBackStarted() - %s" % result) # check for exclusion _filename = None try: _filename = self.getPlayingFile() except: utilities.Debug( "[traktPlayer] onPlayBackStarted() - Exception trying to get playing filename, player suddenly stopped." ) return if utilities.checkScrobblingExclusion(_filename): utilities.Debug( "[traktPlayer] onPlayBackStarted() - '%s' is in exclusion settings, ignoring." % _filename) return self.type = result['item']['type'] data = {'action': 'started'} # check type of item if self.type == 'unknown': # do a deeper check to see if we have enough data to perform scrobbles utilities.Debug( "[traktPlayer] onPlayBackStarted() - Started playing a non-library file, checking available data." ) season = xbmc.getInfoLabel('VideoPlayer.Season') episode = xbmc.getInfoLabel('VideoPlayer.Episode') showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle') year = xbmc.getInfoLabel('VideoPlayer.Year') utilities.Debug("[traktPlayer] info - showtitle:" + showtitle + ", Year:" + year + ", Season:" + season + ", Episode:" + episode) if season and episode and showtitle: # we have season, episode and show title, can scrobble this as an episode self.type = 'episode' data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = showtitle data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') if year.isdigit(): data['year'] = year utilities.Debug( "[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' - %s - S%02dE%02d - %s." % (data['showtitle'], data['season'], data['episode'], data['title'])) elif year and not season and not showtitle: # we have a year and no season/showtitle info, enough for a movie self.type = 'movie' data['type'] = 'movie' data['year'] = int(year) data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') utilities.Debug( "[traktPlayer] onPlayBackStarted() - Playing a non-library 'movie' - %s (%d)." % (data['title'], data['year'])) elif showtitle: title, season, episode = utilities.regex_tvshow( False, showtitle) data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = title data['title'] = title utilities.Debug( "[traktPlayer] onPlayBackStarted() - Title:" + title + ", showtitle:" + showtitle + ", season:" + season + ", episode:" + episode) else: utilities.Debug( "[traktPlayer] onPlayBackStarted() - Non-library file, not enough data for scrobbling, skipping." ) return elif self.type == 'episode' or self.type == 'movie': # get library id self.id = result['item']['id'] data['id'] = self.id data['type'] = self.type if self.type == 'episode': utilities.Debug( "[traktPlayer] onPlayBackStarted() - Doing multi-part episode check." ) result = utilities.xbmcJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodeDetails', 'params': { 'episodeid': self.id, 'properties': ['tvshowid', 'season', 'episode'] }, 'id': 1 }) if result: utilities.Debug( "[traktPlayer] onPlayBackStarted() - %s" % result) tvshowid = int(result['episodedetails']['tvshowid']) season = int(result['episodedetails']['season']) episode = int(result['episodedetails']['episode']) episode_index = episode - 1 result = utilities.xbmcJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': tvshowid, 'season': season, 'properties': ['episode', 'file'], 'sort': { 'method': 'episode' } }, 'id': 1 }) if result: utilities.Debug( "[traktPlayer] onPlayBackStarted() - %s" % result) # make sure episodes array exists in results if 'episodes' in result: multi = [] for i in range(episode_index, result['limits']['total']): if result['episodes'][i]['file'] == result[ 'episodes'][episode_index]['file']: multi.append( result['episodes'][i]['episodeid']) else: break if len(multi) > 1: data['multi_episode_data'] = multi data['multi_episode_count'] = len(multi) utilities.Debug( "[traktPlayer] onPlayBackStarted() - This episode is part of a multi-part episode." ) else: utilities.Debug( "[traktPlayer] onPlayBackStarted() - This is a single episode." ) else: utilities.Debug( "[traktPlayer] onPlayBackStarted() - Video type '%s' unrecognized, skipping." % self.type) return pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) plSize = len(pl) if plSize > 1: pos = pl.getposition() if not self.plIndex is None: utilities.Debug( "[traktPlayer] onPlayBackStarted() - User manually skipped to next (or previous) video, forcing playback ended event." ) self.onPlayBackEnded() self.plIndex = pos utilities.Debug( "[traktPlayer] onPlayBackStarted() - Playlist contains %d item(s), and is currently on item %d" % (plSize, (pos + 1))) self._playing = True # send dispatch self.action(data)
def onPlayBackStarted(self): xbmc.sleep(1000) self.type = None self.id = None # only do anything if we're playing a video if self.isPlayingVideo(): # get item data from json rpc result = utilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': {'playerid': 1}, 'id': 1}) logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) # check for exclusion _filename = None try: _filename = self.getPlayingFile() except: logger.debug("[traktPlayer] onPlayBackStarted() - Exception trying to get playing filename, player suddenly stopped.") return if utilities.checkExclusion(_filename): logger.debug("[traktPlayer] onPlayBackStarted() - '%s' is in exclusion settings, ignoring." % _filename) return self.type = result['item']['type'] data = {'action': 'started'} # check type of item if 'id' not in result['item']: # do a deeper check to see if we have enough data to perform scrobbles logger.debug("[traktPlayer] onPlayBackStarted() - Started playing a non-library file, checking available data.") season = xbmc.getInfoLabel('VideoPlayer.Season') episode = xbmc.getInfoLabel('VideoPlayer.Episode') showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle') year = xbmc.getInfoLabel('VideoPlayer.Year') video_ids = xbmcgui.Window(10000).getProperty('script.trakt.ids') if video_ids: data['video_ids'] = json.loads(video_ids) logger.debug("[traktPlayer] info - ids: %s, showtitle: %s, Year: %s, Season: %s, Episode: %s" % (video_ids, showtitle, year, season, episode)) if season and episode and (showtitle or video_ids): # we have season, episode and either a show title or video_ids, can scrobble this as an episode self.type = 'episode' data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = showtitle data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') if year.isdigit(): data['year'] = int(year) logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' - %s - S%02dE%02d - %s." % (data['showtitle'], data['season'], data['episode'], data['title'])) elif (year or video_ids) and not season and not showtitle: # we have a year or video_id and no season/showtitle info, enough for a movie self.type = 'movie' data['type'] = 'movie' if year.isdigit(): data['year'] = int(year) data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'movie' - %s (%s)." % (data['title'], data.get('year', 'NaN'))) elif showtitle: title, season, episode = utilities.regex_tvshow(False, showtitle) data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = title data['title'] = title logger.debug("[traktPlayer] onPlayBackStarted() - Title: %s, showtitle: %s, season: %d, episode: %d" % (title, showtitle, season, episode)) else: logger.debug("[traktPlayer] onPlayBackStarted() - Non-library file, not enough data for scrobbling, skipping.") return elif self.type == 'episode' or self.type == 'movie': # get library id self.id = result['item']['id'] data['id'] = self.id data['type'] = self.type if self.type == 'episode': logger.debug("[traktPlayer] onPlayBackStarted() - Doing multi-part episode check.") result = utilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodeDetails', 'params': {'episodeid': self.id, 'properties': ['tvshowid', 'season', 'episode', 'file']}, 'id': 1}) if result: logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) tvshowid = int(result['episodedetails']['tvshowid']) season = int(result['episodedetails']['season']) currentfile = result['episodedetails']['file'] result = utilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': tvshowid, 'season': season, 'properties': ['episode', 'file'], 'sort': {'method': 'episode'}}, 'id': 1}) if result: logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) # make sure episodes array exists in results if 'episodes' in result: multi = [] for i in range(result['limits']['start'], result['limits']['total']): if currentfile == result['episodes'][i]['file']: multi.append(result['episodes'][i]['episodeid']) if len(multi) > 1: data['multi_episode_data'] = multi data['multi_episode_count'] = len(multi) logger.debug("[traktPlayer] onPlayBackStarted() - This episode is part of a multi-part episode.") else: logger.debug("[traktPlayer] onPlayBackStarted() - This is a single episode.") else: logger.debug("[traktPlayer] onPlayBackStarted() - Video type '%s' unrecognized, skipping." % self.type) return pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) plSize = len(pl) if plSize > 1: pos = pl.getposition() if not self.plIndex is None: logger.debug("[traktPlayer] onPlayBackStarted() - User manually skipped to next (or previous) video, forcing playback ended event.") self.onPlayBackEnded() self.plIndex = pos logger.debug("[traktPlayer] onPlayBackStarted() - Playlist contains %d item(s), and is currently on item %d" % (plSize, (pos + 1))) self._playing = True # send dispatch self.action(data)
def onPlayBackStarted(self): xbmc.sleep(1000) self.type = None self.id = None # take the user start scrobble offset into account scrobbleStartOffset = kodiUtilities.getSettingAsInt('scrobble_start_offset')*60 if scrobbleStartOffset > 0: waitFor = 10 waitedFor = 0 # check each 10 seconds if we can abort or proceed while not xbmc.abortRequested and scrobbleStartOffset > waitedFor: waitedFor += waitFor time.sleep(waitFor) if not self.isPlayingVideo(): logger.debug('[traktPlayer] Playback stopped before reaching the scrobble offset') return # only do anything if we're playing a video if self.isPlayingVideo(): # get item data from json rpc logger.debug("[traktPlayer] onPlayBackStarted() - Doing Player.GetItem kodiJsonRequest") result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': {'playerid': 1}, 'id': 1}) if result: logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) # check for exclusion _filename = None try: _filename = self.getPlayingFile() except: logger.debug("[traktPlayer] onPlayBackStarted() - Exception trying to get playing filename, player suddenly stopped.") return if kodiUtilities.checkExclusion(_filename): logger.debug("[traktPlayer] onPlayBackStarted() - '%s' is in exclusion settings, ignoring." % _filename) return self.type = result['item']['type'] data = {'action': 'started'} if (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr')): logger.debug('[traktPlayer] Setting is enabled to try scrobbling mythtv pvr recording, if necessary.') # check type of item if 'id' not in result['item']: # do a deeper check to see if we have enough data to perform scrobbles logger.debug("[traktPlayer] onPlayBackStarted() - Started playing a non-library file, checking available data.") season = xbmc.getInfoLabel('VideoPlayer.Season') episode = xbmc.getInfoLabel('VideoPlayer.Episode') showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle') year = xbmc.getInfoLabel('VideoPlayer.Year') video_ids = xbmcgui.Window(10000).getProperty('script.trakt.ids') if video_ids: data['video_ids'] = json.loads(video_ids) logger.debug("[traktPlayer] info - ids: %s, showtitle: %s, Year: %s, Season: %s, Episode: %s" % (video_ids, showtitle, year, season, episode)) if season and episode and (showtitle or video_ids): # we have season, episode and either a show title or video_ids, can scrobble this as an episode self.type = 'episode' data['type'] = 'episode' data['season'] = int(season) data['episode'] = int(episode) data['showtitle'] = showtitle data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') if year.isdigit(): data['year'] = int(year) logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' - %s - S%02dE%02d - %s." % (data['showtitle'], data['season'], data['episode'], data['title'])) elif (year or video_ids) and not season and not showtitle: # we have a year or video_id and no season/showtitle info, enough for a movie self.type = 'movie' data['type'] = 'movie' if year.isdigit(): data['year'] = int(year) data['title'] = xbmc.getInfoLabel('VideoPlayer.Title') logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'movie' - %s (%s)." % (data['title'], data.get('year', 'NaN'))) elif showtitle: title, season, episode = utilities.regex_tvshow(showtitle) data['type'] = 'episode' data['season'] = season data['episode'] = episode data['title'] = data['showtitle'] = title logger.debug("[traktPlayer] onPlayBackStarted() - Title: %s, showtitle: %s, season: %d, episode: %d" % (title, showtitle, season, episode)) else: logger.debug("[traktPlayer] onPlayBackStarted() - Non-library file, not enough data for scrobbling, skipping.") return elif self.type == 'episode' or self.type == 'movie': # get library id self.id = result['item']['id'] data['id'] = self.id data['type'] = self.type if self.type == 'episode': logger.debug("[traktPlayer] onPlayBackStarted() - Doing multi-part episode check.") result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodeDetails', 'params': {'episodeid': self.id, 'properties': ['tvshowid', 'season', 'episode', 'file']}, 'id': 1}) if result: logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) tvshowid = int(result['episodedetails']['tvshowid']) season = int(result['episodedetails']['season']) currentfile = result['episodedetails']['file'] result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': tvshowid, 'season': season, 'properties': ['episode', 'file'], 'sort': {'method': 'episode'}}, 'id': 1}) if result: logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result) # make sure episodes array exists in results if 'episodes' in result: multi = [] for i in range(result['limits']['start'], result['limits']['total']): if currentfile == result['episodes'][i]['file']: multi.append(result['episodes'][i]['episodeid']) if len(multi) > 1: data['multi_episode_data'] = multi data['multi_episode_count'] = len(multi) logger.debug("[traktPlayer] onPlayBackStarted() - This episode is part of a multi-part episode.") else: logger.debug("[traktPlayer] onPlayBackStarted() - This is a single episode.") elif (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr') and self.type == 'unknown' and result['item']['label']): # If we have label/id but no show type, then this might be a PVR recording. # DEBUG INFO: This code is useful when trying to figure out what info is available. Many of the fields # that you'd expect (TVShowTitle, episode, season, etc) are always blank. In Kodi v15, we got the show # and episode name in the VideoPlayer label. In v16, that's gone, but the Player.Filename infolabel # is populated with several interesting things. If these things change in future versions, uncommenting # this code will hopefully provide some useful info in the debug log. #logger.debug("[traktPlayer] onPlayBackStarted() - TEMP Checking all videoplayer infolabels.") #for il in ['VideoPlayer.Time','VideoPlayer.TimeRemaining','VideoPlayer.TimeSpeed','VideoPlayer.Duration','VideoPlayer.Title','VideoPlayer.TVShowTitle','VideoPlayer.Season','VideoPlayer.Episode','VideoPlayer.Genre','VideoPlayer.Director','VideoPlayer.Country','VideoPlayer.Year','VideoPlayer.Rating','VideoPlayer.UserRating','VideoPlayer.Votes','VideoPlayer.RatingAndVotes','VideoPlayer.mpaa','VideoPlayer.IMDBNumber','VideoPlayer.EpisodeName','VideoPlayer.PlaylistPosition','VideoPlayer.PlaylistLength','VideoPlayer.Cast','VideoPlayer.CastAndRole','VideoPlayer.Album','VideoPlayer.Artist','VideoPlayer.Studio','VideoPlayer.Writer','VideoPlayer.Tagline','VideoPlayer.PlotOutline','VideoPlayer.Plot','VideoPlayer.LastPlayed','VideoPlayer.PlayCount','VideoPlayer.VideoCodec','VideoPlayer.VideoResolution','VideoPlayer.VideoAspect','VideoPlayer.AudioCodec','VideoPlayer.AudioChannels','VideoPlayer.AudioLanguage','VideoPlayer.SubtitlesLanguage','VideoPlayer.StereoscopicMode','VideoPlayer.EndTime','VideoPlayer.NextTitle','VideoPlayer.NextGenre','VideoPlayer.NextPlot','VideoPlayer.NextPlotOutline','VideoPlayer.NextStartTime','VideoPlayer.NextEndTime','VideoPlayer.NextDuration','VideoPlayer.ChannelName','VideoPlayer.ChannelNumber','VideoPlayer.SubChannelNumber','VideoPlayer.ChannelNumberLabel','VideoPlayer.ChannelGroup','VideoPlayer.ParentalRating','Player.FinishTime','Player.FinishTime(format)','Player.Chapter','Player.ChapterCount','Player.Time','Player.Time(format)','Player.TimeRemaining','Player.TimeRemaining(format)','Player.Duration','Player.Duration(format)','Player.SeekTime','Player.SeekOffset','Player.SeekOffset(format)','Player.SeekStepSize','Player.ProgressCache','Player.Folderpath','Player.Filenameandpath','Player.StartTime','Player.StartTime(format)','Player.Title','Player.Filename']: # logger.debug("[traktPlayer] TEMP %s : %s" % (il, xbmc.getInfoLabel(il))) #for k,v in result.iteritems(): # logger.debug("[traktPlayer] onPlayBackStarted() - result - %s : %s" % (k,v)) #for k,v in result['item'].iteritems(): # logger.debug("[traktPlayer] onPlayBackStarted() - result.item - %s : %s" % (k,v)) # As of Kodi v16 with the MythTV PVR addon, the only way I could find to get the TV show and episode # info is from the Player.Filename infolabel. It shows up like this: # ShowName [sXXeYY ](year) EpisodeName, channel, PVRFileName # The season and episode info may or may not be present. For example: # Elementary s04e10 (2016) Alma Matters, TV (WWMT-HD), 20160129_030000.pvr # DC's Legends of Tomorrow (2016) Pilot, Part 2, TV (CW W MI), 20160129_010000.pvr foundLabel = xbmc.getInfoLabel('Player.Filename') logger.debug("[traktPlayer] onPlayBackStarted() - Found unknown video type with label: %s. Might be a PVR episode, searching Trakt for it." % foundLabel) splitLabel = foundLabel.rsplit(", ", 2) logger.debug("[traktPlayer] onPlayBackStarted() - Post-split of label: %s " % splitLabel) if len(splitLabel) != 3: logger.debug("[traktPlayer] onPlayBackStarted() - Label doesn't have the ShowName sXXeYY (year) EpisodeName, channel, PVRFileName format that was expected. Giving up.") return foundShowAndEpInfo = splitLabel[0] logger.debug("[traktPlayer] onPlayBackStarted() - show plus episode info: %s" % foundShowAndEpInfo) splitShowAndEpInfo = re.split(' (s\d\de\d\d)? ?\((\d\d\d\d)\) ',foundShowAndEpInfo, 1) logger.debug("[traktPlayer] onPlayBackStarted() - Post-split of show plus episode info: %s " % splitShowAndEpInfo) if len(splitShowAndEpInfo) != 4: logger.debug("[traktPlayer] onPlayBackStarted() - Show plus episode info doesn't have the ShowName sXXeYY (year) EpisodeName format that was expected. Giving up.") return foundShowName = splitShowAndEpInfo[0] logger.debug("[traktPlayer] onPlayBackStarted() - using show name: %s" % foundShowName) foundEpisodeName = splitShowAndEpInfo[3] logger.debug("[traktPlayer] onPlayBackStarted() - using episode name: %s" % foundEpisodeName) foundEpisodeYear = splitShowAndEpInfo[2] logger.debug("[traktPlayer] onPlayBackStarted() - using episode year: %s" % foundEpisodeYear) epYear = None try: epYear = int(foundEpisodeYear) except ValueError: epYear = None logger.debug("[traktPlayer] onPlayBackStarted() - verified episode year: %d" % epYear) # All right, now we have the show name, episode name, and (maybe) episode year. All good, but useless for # scrobbling since Trakt only understands IDs, not names. data['video_ids'] = None data['season'] = None data['episode'] = None data['episodeTitle'] = None # First thing to try, a text query to the Trakt DB looking for this episode. Note # that we can't search for show and episode together, because the Trakt function gets confused and returns nothing. newResp = globals.traktapi.getTextQuery(foundEpisodeName, "episode", epYear) if not newResp: logger.debug("[traktPlayer] onPlayBackStarted() - Empty Response from getTextQuery, giving up") else: logger.debug("[traktPlayer] onPlayBackStarted() - Got Response from getTextQuery: %s" % str(newResp)) # We got something back. See if one of the returned values is for the show we're looking for. Often it's # not, but since there's no way to tell the search which show we want, this is all we can do. rightResp = None for thisResp in newResp: compareShowName = thisResp.show.title logger.debug("[traktPlayer] onPlayBackStarted() - comparing show name: %s" % compareShowName) if thisResp.show.title == foundShowName: logger.debug("[traktPlayer] onPlayBackStarted() - found the right show, using this response") rightResp = thisResp break if rightResp is None: logger.debug("[traktPlayer] onPlayBackStarted() - Failed to find matching episode/show via text search.") else: # OK, now we have a episode object to work with. self.type = 'episode' data['type'] = 'episode' # You'd think we could just use the episode key that Trakt just returned to us, but the scrobbler # function (see scrobber.py) only understands the show key plus season/episode values. showKeys = { } for eachKey in rightResp.show.keys: showKeys[eachKey[0]] = eachKey[1] data['video_ids'] = showKeys # For some reason, the Trakt search call returns the season and episode as an array in the pk field. # You'd think individual episode and season fields would be better, but whatever. data['season'] = rightResp.pk[0]; data['episode'] = rightResp.pk[1]; # At this point if we haven't found the episode data yet, the episode-title-text-search method # didn't work. if (not data['season']): # This text query API is basically the same as searching on the website. Works with alternative # titles, unlike the scrobble function. Though we can't use the episode year since that would only # match the show if we're dealing with season 1. logger.debug("[traktPlayer] onPlayBackStarted() - Searching for show title via getTextQuery: %s" % foundShowName) newResp = globals.traktapi.getTextQuery(foundShowName, "show", None) if not newResp: logger.debug("[traktPlayer] onPlayBackStarted() - Empty Show Response from getTextQuery, falling back on episode text query") else: logger.debug("[traktPlayer] onPlayBackStarted() - Got Show Response from getTextQuery: %s" % str(newResp)) # We got something back. Have to assume the first show found is the right one; if there's more than # one, there's no way to know which to use. Pull the ids from the show data, and store 'em for scrobbling. showKeys = { } for eachKey in newResp[0].keys: showKeys[eachKey[0]] = eachKey[1] data['video_ids'] = showKeys # Now to find the episode. There's no search function to look for an episode within a show, but # we can get all the episodes and look for the title. while (not data['season']): logger.debug("[traktPlayer] onPlayBackStarted() - Querying for all seasons/episodes of this show") epQueryResp = globals.traktapi.getShowWithAllEpisodesList(data['video_ids']['trakt']) if not epQueryResp: # Nothing returned. Giving up. logger.debug("[traktPlayer] onPlayBackStarted() - No response received") break; else: # Got the list back. Go through each season. logger.debug("[traktPlayer] onPlayBackStarted() - Got response with seasons: %s" % str(epQueryResp)) for eachSeason in epQueryResp: # For each season, check each episode. logger.debug("[traktPlayer] onPlayBackStarted() - Processing season: %s" % str(eachSeason)) for eachEpisodeNumber in eachSeason.episodes: thisEpTitle = None # Get the title. The try block is here in case the title doesn't exist for some entries. try: thisEpTitle = eachSeason.episodes[eachEpisodeNumber].title except: thisEpTitle = None logger.debug("[traktPlayer] onPlayBackStarted() - Checking episode number %d with title %s" % (eachEpisodeNumber, thisEpTitle)) if (foundEpisodeName == thisEpTitle): # Found it! Save the data. The scrobbler wants season and episode number. Which for some # reason is stored as a pair in the first item in the keys array. data['season'] = eachSeason.episodes[eachEpisodeNumber].keys[0][0] data['episode'] = eachSeason.episodes[eachEpisodeNumber].keys[0][1] # Title too, just for the heck of it. Though it's not actually used. data['episodeTitle'] = thisEpTitle break # If we already found our data, no need to go through the rest of the seasons. if (data['season']): break; # Now we've done all we can. if (data['season']): # OK, that's everything. Data should be all set for scrobbling. logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' : show trakt key %s, season: %d, episode: %d" % (data['video_ids'], data['season'], data['episode'])) else: # Still no data? Too bad, have to give up. logger.debug("[traktPlayer] onPlayBackStarted() - Did our best, but couldn't get info for this show and episode. Skipping.") return; else: logger.debug("[traktPlayer] onPlayBackStarted() - Video type '%s' unrecognized, skipping." % self.type) return pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) plSize = len(pl) if plSize > 1: pos = pl.getposition() if not self.plIndex is None: logger.debug("[traktPlayer] onPlayBackStarted() - User manually skipped to next (or previous) video, forcing playback ended event.") self.onPlayBackEnded() self.plIndex = pos logger.debug("[traktPlayer] onPlayBackStarted() - Playlist contains %d item(s), and is currently on item %d" % (plSize, (pos + 1))) self._playing = True # send dispatch self.action(data)