diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py deleted file mode 100644 index aedb0e6f..00000000 --- a/resources/lib/playbackutils.py +++ /dev/null @@ -1,362 +0,0 @@ -# -*- coding: utf-8 -*- - -############################################################################### -from logging import getLogger -from urllib import urlencode -from threading import Thread - -from xbmc import getCondVisibility, Player -import xbmcgui - -import playutils as putils -from utils import window, settings, tryEncode, tryDecode, language as lang -import downloadutils - -from PlexAPI import API -from PlexFunctions import init_plex_playqueue -from PKC_listitem import PKC_ListItem as ListItem, convert_PKC_to_listitem -from playlist_func import add_item_to_kodi_playlist, \ - get_playlist_details_from_xml, add_listitem_to_Kodi_playlist, \ - add_listitem_to_playlist, remove_from_kodi_playlist, playlist_item_from_xml -from pickler import Playback_Successful -from plexdb_functions import Get_Plex_DB -import variables as v -import state - -############################################################################### - -LOG = getLogger("PLEX." + __name__) - -############################################################################### - - -class PlaybackUtils(): - - def __init__(self, xml, playqueue): - self.xml = xml - self.playqueue = playqueue - - def play(self, plex_id, kodi_id=None, plex_lib_UUID=None): - """ - plex_lib_UUID: xml attribute 'librarySectionUUID', needed for posting - to the PMS - """ - LOG.info("Playbackutils called") - item = self.xml[0] - api = API(item) - playqueue = self.playqueue - xml = None - result = Playback_Successful() - listitem = ListItem() - playutils = putils.PlayUtils(item) - playurl = playutils.getPlayUrl() - if not playurl: - LOG.error('No playurl found, aborting') - return - - if kodi_id in (None, 'plextrailer', 'plexnode'): - # Item is not in Kodi database, is a trailer/clip or plex redirect - # e.g. plex.tv watch later - api.CreateListItemFromPlexItem(listitem) - api.set_listitem_artwork(listitem) - if kodi_id == 'plexnode': - # Need to get yet another xml to get final url - window('plex_%s.playmethod' % playurl, clear=True) - xml = downloadutils.DownloadUtils().downloadUrl( - '{server}%s' % item[0][0].attrib.get('key')) - try: - xml[0].attrib - except (TypeError, AttributeError): - LOG.error('Could not download %s', - item[0][0].attrib.get('key')) - return - playurl = tryEncode(xml[0].attrib.get('key')) - window('plex_%s.playmethod' % playurl, value='DirectStream') - - playmethod = window('plex_%s.playmethod' % playurl) - if playmethod == "Transcode": - playutils.audioSubsPref(listitem, tryDecode(playurl)) - listitem.setPath(playurl) - api.set_playback_win_props(playurl, listitem) - result.listitem = listitem - return result - - kodi_type = v.KODITYPE_FROM_PLEXTYPE[api.getType()] - kodi_id = int(kodi_id) - - # ORGANIZE CURRENT PLAYLIST ################ - contextmenu_play = window('plex_contextplay') == 'true' - window('plex_contextplay', clear=True) - homeScreen = getCondVisibility('Window.IsActive(home)') - sizePlaylist = len(playqueue.items) - if contextmenu_play: - # Need to start with the items we're inserting here - startPos = sizePlaylist - else: - # Can return -1 - startPos = max(playqueue.kodi_pl.getposition(), 0) - self.currentPosition = startPos - - propertiesPlayback = window('plex_playbackProps') == "true" - introsPlaylist = False - dummyPlaylist = False - - LOG.info("Playing from contextmenu: %s", contextmenu_play) - LOG.info("Playlist start position: %s", startPos) - LOG.info("Playlist plugin position: %s", self.currentPosition) - LOG.info("Playlist size: %s", sizePlaylist) - - # RESUME POINT ################ - seektime, runtime = api.getRuntime() - if window('plex_customplaylist.seektime'): - # Already got seektime, e.g. from playqueue & Plex companion - seektime = int(window('plex_customplaylist.seektime')) - - # We need to ensure we add the intro and additional parts only once. - # Otherwise we get a loop. - if not propertiesPlayback: - window('plex_playbackProps', value="true") - LOG.info("Setting up properties in playlist.") - # Where will the player need to start? - # Do we need to get trailers? - trailers = False - if (api.getType() == v.PLEX_TYPE_MOVIE and - not seektime and - sizePlaylist < 2 and - settings('enableCinema') == "true"): - if settings('askCinema') == "true": - trailers = xbmcgui.Dialog().yesno( - lang(29999), - "Play trailers?") - trailers = True if trailers else False - else: - trailers = True - # Post to the PMS. REUSE THE PLAYQUEUE! - xml = init_plex_playqueue(plex_id, - plex_lib_UUID, - mediatype=api.getType(), - trailers=trailers) - try: - get_playlist_details_from_xml(playqueue, xml=xml) - except KeyError: - return - if (not homeScreen and not seektime and sizePlaylist < 2 and - window('plex_customplaylist') != "true" and - not contextmenu_play): - # Need to add a dummy file because the first item will fail - LOG.debug("Adding dummy file to playlist.") - dummyPlaylist = True - add_listitem_to_Kodi_playlist( - playqueue, - startPos, - xbmcgui.ListItem(), - playurl, - xml[0]) - # Remove the original item from playlist - remove_from_kodi_playlist( - playqueue, - startPos+1) - # Readd the original item to playlist - via jsonrpc so we have - # full metadata - add_item_to_kodi_playlist( - playqueue, - self.currentPosition+1, - kodi_id=kodi_id, - kodi_type=kodi_type, - file=playurl) - self.currentPosition += 1 - - # -- ADD TRAILERS ################ - if trailers: - for i, item in enumerate(xml): - if i == len(xml) - 1: - # Don't add the main movie itself - break - self.add_trailer(item) - introsPlaylist = True - - # -- ADD MAIN ITEM ONLY FOR HOMESCREEN ############## - if homeScreen and not seektime and not sizePlaylist: - # Extend our current playlist with the actual item to play - # only if there's no playlist first - LOG.info("Adding main item to playlist.") - add_item_to_kodi_playlist( - playqueue, - self.currentPosition, - kodi_id, - kodi_type) - - elif contextmenu_play: - if state.DIRECT_PATHS: - # Cannot add via JSON with full metadata because then we - # Would be using the direct path - LOG.debug("Adding contextmenu item for direct paths") - if window('plex_%s.playmethod' % playurl) == "Transcode": - playutils.audioSubsPref(listitem, tryDecode(playurl)) - api.CreateListItemFromPlexItem(listitem) - api.set_playback_win_props(playurl, listitem) - api.set_listitem_artwork(listitem) - add_listitem_to_Kodi_playlist( - playqueue, - self.currentPosition+1, - convert_PKC_to_listitem(listitem), - file=playurl, - kodi_item={'id': kodi_id, 'type': kodi_type}) - else: - # Full metadata$ - add_item_to_kodi_playlist( - playqueue, - self.currentPosition+1, - kodi_id, - kodi_type) - self.currentPosition += 1 - if seektime: - window('plex_customplaylist.seektime', value=str(seektime)) - - # Ensure that additional parts are played after the main item - self.currentPosition += 1 - - # -- CHECK FOR ADDITIONAL PARTS ################ - if len(item[0]) > 1: - self.add_part(item, api, kodi_id, kodi_type) - - if dummyPlaylist: - # Added a dummy file to the playlist, - # because the first item is going to fail automatically. - LOG.info("Processed as a playlist. First item is skipped.") - # Delete the item that's gonna fail! - del playqueue.items[startPos] - # Don't attach listitem - return result - - # We just skipped adding properties. Reset flag for next time. - elif propertiesPlayback: - LOG.debug("Resetting properties playback flag.") - window('plex_playbackProps', clear=True) - - # SETUP MAIN ITEM ########## - # For transcoding only, ask for audio/subs pref - if (window('plex_%s.playmethod' % playurl) == "Transcode" and - not contextmenu_play): - playutils.audioSubsPref(listitem, tryDecode(playurl)) - - listitem.setPath(playurl) - api.set_playback_win_props(playurl, listitem) - api.set_listitem_artwork(listitem) - - # PLAYBACK ################ - if (homeScreen and seektime and window('plex_customplaylist') != "true" - and not contextmenu_play): - LOG.info("Play as a widget item") - api.CreateListItemFromPlexItem(listitem) - result.listitem = listitem - return result - - elif ((introsPlaylist and window('plex_customplaylist') == "true") or - (homeScreen and not sizePlaylist) or - contextmenu_play): - # Playlist was created just now, play it. - # Contextmenu plays always need this - LOG.info("Play playlist from starting position %s", startPos) - # Need a separate thread because Player won't return in time - thread = Thread(target=Player().play, - args=(playqueue.kodi_pl, None, False, startPos)) - thread.setDaemon(True) - thread.start() - # Don't attach listitem - return result - else: - LOG.info("Play as a regular item") - result.listitem = listitem - return result - - def play_all(self): - """ - Play all items contained in the xml passed in. Called by Plex Companion - """ - LOG.info("Playbackutils play_all called") - window('plex_playbackProps', value="true") - self.currentPosition = 0 - for item in self.xml: - api = API(item) - successful = True - if api.getType() == v.PLEX_TYPE_CLIP: - self.add_trailer(item) - else: - with Get_Plex_DB() as plex_db: - db_item = plex_db.getItem_byId(api.getRatingKey()) - if db_item is not None: - successful = add_item_to_kodi_playlist( - self.playqueue, - self.currentPosition, - kodi_id=db_item[0], - kodi_type=db_item[4]) - if successful is True: - self.currentPosition += 1 - if len(item[0]) > 1: - self.add_part(item, - api, - db_item[0], - db_item[4]) - else: - # Item not in Kodi DB - self.add_trailer(item) - if successful is True: - self.playqueue.items[self.currentPosition - 1].id = item.get( - '%sItemID' % self.playqueue.kind) - - def add_trailer(self, item): - # Playurl needs to point back so we can get metadata! - path = "plugin://plugin.video.plexkodiconnect/movies/" - params = { - 'mode': "play", - 'dbid': 'plextrailer' - } - introAPI = API(item) - listitem = introAPI.CreateListItemFromPlexItem() - params['id'] = introAPI.getRatingKey() - params['filename'] = introAPI.getKey() - introPlayurl = path + '?' + urlencode(params) - introAPI.set_listitem_artwork(listitem) - # Overwrite the Plex url - listitem.setPath(introPlayurl) - LOG.info("Adding Plex trailer: %s", introPlayurl) - add_listitem_to_Kodi_playlist( - self.playqueue, - self.currentPosition, - listitem, - introPlayurl, - xml_video_element=item) - self.currentPosition += 1 - - def add_part(self, item, api, kodi_id, kodi_type): - """ - Adds an additional part to the playlist - """ - # Only add to the playlist after intros have played - for counter, part in enumerate(item[0]): - # Never add first part - if counter == 0: - continue - # Set listitem and properties for each additional parts - api.setPartNumber(counter) - additionalListItem = xbmcgui.ListItem() - playutils = putils.PlayUtils(item) - additionalPlayurl = playutils.getPlayUrl( - partNumber=counter) - LOG.debug("Adding additional part: %s, url: %s", - counter, additionalPlayurl) - api.CreateListItemFromPlexItem(additionalListItem) - api.set_playback_win_props(additionalPlayurl, - additionalListItem) - api.set_listitem_artwork(additionalListItem) - add_listitem_to_playlist( - self.playqueue, - self.currentPosition, - additionalListItem, - kodi_id=kodi_id, - kodi_type=kodi_type, - plex_id=api.getRatingKey(), - file=additionalPlayurl) - self.currentPosition += 1 - api.setPartNumber(0)