def set_playlist(self, item, listitem, db_id=None, transcode=False): ''' Verify seektime, set intros, set main item and set additional parts. Detect the seektime for video type content. Verify the default video action set in Kodi for accurate resume behavior. ''' seektime = window('jellyfin.resume.bool') window('jellyfin.resume', clear=True) if item['MediaType'] in ('Video', 'Audio'): resume = item['UserData'].get('PlaybackPositionTicks') if resume: if get_play_action() == "Resume": seektime = True if transcode and not seektime: choice = self.resume_dialog( api.API(item, self.server).adjust_resume( (resume or 0) / 10000000.0)) if choice is None: raise Exception("User backed out of resume dialog.") seektime = False if not choice else True if settings('enableCinema.bool') and not seektime: self._set_intros(item) self.set_listitem(item, listitem, db_id, seektime) playutils.set_properties(item, item['PlaybackInfo']['Method'], self.server_id) self.stack.append([item['PlaybackInfo']['Path'], listitem]) if item.get('PartCount'): self._set_additional_parts(item['Id'])
def _set_intros(self, item): ''' if we have any play them when the movie/show is not being resumed. ''' intros = TheVoid('GetIntros', {'ServerId': self.server_id, 'Id': item['Id']}).get() if intros['Items']: enabled = True if settings('askCinema') == "true": resp = dialog("yesno", heading="{emby}", line1=_(33016)) if not resp: enabled = False LOG.info("Skip trailers.") if enabled: for intro in intros['Items']: listitem = xbmcgui.ListItem() LOG.info("[ intro/%s ] %s", intro['Id'], intro['Name']) play = playutils.PlayUtils(intro, False, self.server_id, self.server) source = play.select_source(play.get_sources()) self.set_listitem(intro, listitem, intro=True) listitem.setPath(intro['PlaybackInfo']['Path']) playutils.set_properties(intro, intro['PlaybackInfo']['Method'], self.server_id) self.stack.append([intro['PlaybackInfo']['Path'], listitem]) window('emby.skip.%s' % intro['Id'], value="true")
def play_playlist(self, items, clear=True, seektime=None, audio=None, subtitle=None): ''' Play a list of items. Creates a new playlist. Add additional items as plugin listing. ''' item = items['Items'][0] playlist = self.get_playlist(item) player = xbmc.Player() # xbmc.executebuiltin("Playlist.Clear") # Clear playlist to remove the previous item from playlist position no.2 if clear: if player.isPlaying(): player.stop() xbmc.executebuiltin('ActivateWindow(busydialognocancel)') index = 0 else: index = max(playlist.getposition(), 0) + 1 # Can return -1 listitem = xbmcgui.ListItem() LOG.info("[ playlist/%s ] %s", item['Id'], item['Name']) play = playutils.PlayUtils(item, False, self.server_id, self.server, self.api_client) source = play.select_source(play.get_sources()) play.set_external_subs(source, listitem) item['PlaybackInfo']['AudioStreamIndex'] = audio or item['PlaybackInfo']['AudioStreamIndex'] item['PlaybackInfo']['SubtitleStreamIndex'] = subtitle or item['PlaybackInfo'].get('SubtitleStreamIndex') self.set_listitem(item, listitem, None, True if seektime else False) listitem.setPath(item['PlaybackInfo']['Path']) playutils.set_properties(item, item['PlaybackInfo']['Method'], self.server_id) playlist.add(item['PlaybackInfo']['Path'], listitem, index) index += 1 if clear: xbmc.executebuiltin('Dialog.Close(busydialognocancel)') player.play(playlist) server_address = item['PlaybackInfo']['ServerAddress'] token = item['PlaybackInfo']['Token'] for item in items['Items'][1:]: listitem = xbmcgui.ListItem() LOG.info("[ playlist/%s ] %s", item['Id'], item['Name']) self.set_listitem(item, listitem, None, False) path = '{}/Audio/{}/stream.mp3?static=true&api_key={}'.format( server_address, item['Id'], token) listitem.setPath(path) play = playutils.PlayUtils(item, False, self.server_id, self.server, self.api_client) source = play.select_source(play.get_sources()) play.set_external_subs(source, listitem) playutils.set_properties(item, item['PlaybackInfo']['Method'], self.server_id) playlist.add(path, listitem, index) index += 1
def _set_intros(self, item): ''' if we have any play them when the movie/show is not being resumed. ''' intros = self.api_client.get_intros(item['Id']) if intros['Items']: enabled = True if settings('askCinema') == "true": resp = dialog("yesno", "{jellyfin}", translate(33016)) if not resp: enabled = False LOG.info("Skip trailers.") if enabled: for intro in intros['Items']: listitem = xbmcgui.ListItem() LOG.info("[ intro/%s ] %s", intro['Id'], intro['Name']) play = playutils.PlayUtils(intro, False, self.server_id, self.server, self.api_client) play.select_source(play.get_sources()) self.set_listitem(intro, listitem, intro=True) listitem.setPath(intro['PlaybackInfo']['Path']) playutils.set_properties(intro, intro['PlaybackInfo']['Method'], self.server_id) self.stack.append([intro['PlaybackInfo']['Path'], listitem]) window('jellyfin.skip.%s' % intro['Id'], value="true")
def on_play(data, server): ''' Setup progress for jellyfin playback. ''' player = xbmc.Player() try: kodi_id = None if player.isPlayingVideo(): ''' Seems to misbehave when playback is not terminated prior to playing new content. The kodi id remains that of the previous title. Maybe onPlay happens before this information is updated. Added a failsafe further below. ''' item = player.getVideoInfoTag() kodi_id = item.getDbId() media = item.getMediaType() if kodi_id is None or int( kodi_id) == -1 or 'item' in data and 'id' in data[ 'item'] and data['item']['id'] != kodi_id: item = data['item'] kodi_id = item['id'] media = item['type'] LOG.info(" [ play ] kodi_id: %s media: %s", kodi_id, media) except (KeyError, TypeError): LOG.debug("Invalid playstate update") return if settings('useDirectPaths') == '1' or media == 'song': item = database.get_item(kodi_id, media) if item: try: file = player.getPlayingFile() except Exception as error: LOG.exception(error) return item = server.jellyfin.get_item(item[0]) item['PlaybackInfo'] = {'Path': file} playutils.set_properties( item, 'DirectStream' if settings('useDirectPaths') == '0' else 'DirectPlay')
def play_playlist(self, items, clear=True, seektime=None, audio=None, subtitle=None): ''' Play a list of items. Creates a new playlist. Add additional items as plugin listing. ''' item = items[0] playlist = self.get_playlist(item) if clear: playlist.clear() index = 0 else: index = max(playlist.getposition(), 0) + 1 # Can return -1 listitem = xbmcgui.ListItem() LOG.info("[ playlist/%s ] %s", item['Id'], item['Name']) play = playutils.PlayUtils(item, False, self.server_id, self.server) source = play.select_source(play.get_sources()) play.set_external_subs(source, listitem) item['PlaybackInfo']['AudioStreamIndex'] = audio or item[ 'PlaybackInfo']['AudioStreamIndex'] item['PlaybackInfo']['SubtitleStreamIndex'] = subtitle or item[ 'PlaybackInfo'].get('SubtitleStreamIndex') self.set_listitem(item, listitem, None, True if seektime else False) listitem.setPath(item['PlaybackInfo']['Path']) playutils.set_properties(item, item['PlaybackInfo']['Method'], self.server_id) playlist.add(item['PlaybackInfo']['Path'], listitem, index) index += 1 if clear: xbmc.Player().play(playlist) for item in items[1:]: listitem = xbmcgui.ListItem() LOG.info("[ playlist/%s ]", item) path = "plugin://plugin.video.emby/?mode=play&id=%s&playlist=true" % item listitem.setPath(path) playlist.add(path, listitem, index) index += 1
def _set_additional_parts(self, item_id): ''' Create listitems and add them to the stack of playlist. ''' parts = self.api_client.get_additional_parts(item_id) for part in parts['Items']: listitem = xbmcgui.ListItem() LOG.info("[ part/%s ] %s", part['Id'], part['Name']) play = playutils.PlayUtils(part, False, self.server_id, self.server, self.api_client) source = play.select_source(play.get_sources()) play.set_external_subs(source, listitem) self.set_listitem(part, listitem) listitem.setPath(part['PlaybackInfo']['Path']) playutils.set_properties(part, part['PlaybackInfo']['Method'], self.server_id) self.stack.append([part['PlaybackInfo']['Path'], listitem])
def _set_additional_parts(self, item_id, *args, **kwargs): ''' Create listitems and add them to the stack of playlist. ''' parts = TheVoid('GetAdditionalParts', { 'ServerId': self.server_id, 'Id': item_id }).get() for part in parts['Items']: listitem = xbmcgui.ListItem() LOG.info("[ part/%s ] %s", part['Id'], part['Name']) play = playutils.PlayUtils(part, False, self.server_id, self.server) source = play.select_source(play.get_sources()) play.set_external_subs(source, listitem) self.set_listitem(part, listitem) listitem.setPath(part['PlaybackInfo']['Path']) playutils.set_properties(part, part['PlaybackInfo']['Method'], self.server_id) self.stack.append([part['PlaybackInfo']['Path'], listitem])