Exemplo n.º 1
0
    def check_existing_pms(self):
        """
        Check the PMS that was set in file settings.
        Will return False if we need to reconnect, because:
            PMS could not be reached (no matter the authorization)
            machineIdentifier did not match

        Will also set the PMS machineIdentifier in the file settings if it was
        not set before
        """
        answer = True
        chk = PF.check_connection(self.server, verifySSL=False)
        if chk is False:
            LOG.warn('Could not reach PMS %s', self.server)
            answer = False
        if answer is True and not self.serverid:
            LOG.info(
                'No PMS machineIdentifier found for %s. Trying to '
                'get the PMS unique ID', self.server)
            self.serverid = PF.GetMachineIdentifier(self.server)
            if self.serverid is None:
                LOG.warn('Could not retrieve machineIdentifier')
                answer = False
            else:
                settings('plex_machineIdentifier', value=self.serverid)
        elif answer is True:
            temp_server_id = PF.GetMachineIdentifier(self.server)
            if temp_server_id != self.serverid:
                LOG.warn(
                    'The current PMS %s was expected to have a '
                    'unique machineIdentifier of %s. But we got '
                    '%s. Pick a new server to be sure', self.server,
                    self.serverid, temp_server_id)
                answer = False
        return answer
Exemplo n.º 2
0
    def getPlayerProperties(self, playerid):
        info = {}
        try:
            # get info from the player
            props = self.js.jsonrpc("Player.GetProperties", {"playerid": playerid, "properties": ["time", "totaltime", "speed", "shuffled", "repeat"]})
            self.logMsg(self.js.jsonrpc("Player.GetItem", {"playerid": playerid, "properties": ["file", "showlink", "episode", "season"]}), 2)
            info['time'] = timeToMillis(props['time'])
            info['duration'] = timeToMillis(props['totaltime'])
            info['state'] = ("paused", "playing")[int(props['speed'])]
            info['shuffle'] = ("0","1")[props.get('shuffled', False)]
            info['repeat'] = pf.getPlexRepeat(props.get('repeat'))
            # New PMS playQueue attributes
            cf = self.xbmcplayer.getPlayingFile()
            info['playQueueID'] = window('playQueueID')
            info['playQueueVersion'] = window('playQueueVersion')
            info['playQueueItemID'] = window('plex_%s.playQueueItemID' % cf)
            info['guid'] = window('plex_%s.guid' % cf)

        except:
            info['time'] = 0
            info['duration'] = 0
            info['state'] = "stopped"
            info['shuffle'] = False
        # get the volume from the application
        info['volume'] = self.volume
        info['mute'] = self.mute

        return info
Exemplo n.º 3
0
    def getServer(self, prefix=True):
        # Original host
        self.servername = settings('plex_servername')
        HTTPS = settings('https') == "true"
        host = settings('ipaddress')
        port = settings('port')
        self.machineIdentifier = settings('plex_machineIdentifier')

        server = host + ":" + port

        if not host:
            LOG.debug("No server information saved.")
            return False

        # If https is true
        if prefix and HTTPS:
            server = "https://%s" % server
        # If https is false
        elif prefix and not HTTPS:
            server = "http://%s" % server
        # User entered IP; we need to get the machineIdentifier
        if self.machineIdentifier == '' and prefix is True:
            self.machineIdentifier = PF.GetMachineIdentifier(server)
            if self.machineIdentifier is None:
                self.machineIdentifier = ''
            settings('plex_machineIdentifier', value=self.machineIdentifier)
        LOG.debug('Returning active server: %s', server)
        return server
Exemplo n.º 4
0
 def setUserPref(self):
     LOG.debug('Setting user preferences')
     # Only try to get user avatar if there is a token
     if self.currToken:
         url = PF.GetUserArtworkURL(self.currUser)
         if url:
             window('PlexUserImage', value=url)
Exemplo n.º 5
0
    def _auto_pick_pms(self):
        """
        Will try to pick PMS based on machineIdentifier saved in file settings
        but only once

        Returns server or None if unsuccessful
        """
        https_updated = False
        checked_plex_tv = False
        server = None
        while True:
            if https_updated is False:
                serverlist = PF.discover_pms(self.plex_token)
                for item in serverlist:
                    if item.get('machineIdentifier') == self.serverid:
                        server = item
                if server is None:
                    name = settings('plex_servername')
                    LOG.warn(
                        'The PMS you have used before with a unique '
                        'machineIdentifier of %s and name %s is '
                        'offline', self.serverid, name)
                    return
            chk = self._check_pms_connectivity(server)
            if chk == 504 and https_updated is False:
                # switch HTTPS to HTTP or vice-versa
                if server['scheme'] == 'https':
                    server['scheme'] = 'http'
                else:
                    server['scheme'] = 'https'
                https_updated = True
                continue
            if chk == 401:
                LOG.warn('Not yet authorized for Plex server %s',
                         server['name'])
                if self.check_plex_tv_sign_in() is True:
                    if checked_plex_tv is False:
                        # Try again
                        checked_plex_tv = True
                        https_updated = False
                        continue
                    else:
                        LOG.warn('Not authorized even though we are signed '
                                 ' in to plex.tv correctly')
                        dialog(
                            'ok', lang(29999), '%s %s' %
                            (lang(39214), try_encode(server['name'])))
                        return
                else:
                    return
            # Problems connecting
            elif chk >= 400 or chk is False:
                LOG.warn('Problems connecting to server %s. chk is %s',
                         server['name'], chk)
                return
            LOG.info('We found a server to automatically connect to: %s',
                     server['name'])
            return server
Exemplo n.º 6
0
    def getPlayerProperties(self, playerid):
        try:
            # Get the playqueue
            playqueue = self.playqueue.playqueues[playerid]
            # get info from the player
            props = self.js.jsonrpc(
                "Player.GetProperties", {
                    "playerid":
                    playerid,
                    "properties": [
                        "type", "time", "totaltime", "speed", "shuffled",
                        "repeat"
                    ]
                })

            info = {
                'time': timeToMillis(props['time']),
                'duration': timeToMillis(props['totaltime']),
                'state': ("paused", "playing")[int(props['speed'])],
                'shuffle': ("0", "1")[props.get('shuffled', False)],
                'repeat': pf.getPlexRepeat(props.get('repeat')),
            }
            # Get the playlist position
            pos = self.js.jsonrpc("Player.GetProperties", {
                "playerid": playerid,
                "properties": ["position"]
            })['position']
            try:
                info['playQueueItemID'] = playqueue.items[pos].ID or 'null'
                info['guid'] = playqueue.items[pos].guid or 'null'
                info['playQueueID'] = playqueue.ID or 'null'
                info['playQueueVersion'] = playqueue.version or 'null'
                info['itemType'] = playqueue.items[pos].plex_type or 'null'
            except:
                info['itemType'] = props.get('type') or 'null'
        except:
            import traceback
            log.error("Traceback:\n%s" % traceback.format_exc())
            info = {
                'time': 0,
                'duration': 0,
                'state': 'stopped',
                'shuffle': False,
                'repeat': 0
            }

        # get the volume from the application
        info['volume'] = self.volume
        info['mute'] = self.mute

        info['plex_transient_token'] = playqueue.plex_transient_token

        return info
Exemplo n.º 7
0
 def __init__(self):
     LOG.debug('Entering initialsetup class')
     self.server = UserClient().getServer()
     self.serverid = settings('plex_machineIdentifier')
     # Get Plex credentials from settings file, if they exist
     plexdict = PF.GetPlexLoginFromSettings()
     self.myplexlogin = plexdict['myplexlogin'] == 'true'
     self.plex_login = plexdict['plexLogin']
     self.plex_token = plexdict['plexToken']
     self.plexid = plexdict['plexid']
     # Token for the PMS, not plex.tv
     self.pms_token = settings('accessToken')
     if self.plex_token:
         LOG.debug('Found a plex.tv token in the settings')
Exemplo n.º 8
0
    def getPlayerProperties(self, playerid):
        try:
            # Get the playqueue
            playqueue = self.playqueue.playqueues[playerid]
            # get info from the player
            props = self.js.jsonrpc(
                "Player.GetProperties",
                {"playerid": playerid,
                 "properties": ["time",
                                "totaltime",
                                "speed",
                                "shuffled",
                                "repeat"]})

            info = {
                'time': timeToMillis(props['time']),
                'duration': timeToMillis(props['totaltime']),
                'state': ("paused", "playing")[int(props['speed'])],
                'shuffle': ("0", "1")[props.get('shuffled', False)],
                'repeat': pf.getPlexRepeat(props.get('repeat')),
            }
            # Get the playlist position
            pos = self.js.jsonrpc(
                "Player.GetProperties",
                {"playerid": playerid,
                 "properties": ["position"]})['position']
            try:
                info['playQueueItemID'] = playqueue.items[pos].ID
                info['guid'] = playqueue.items[pos].guid
                info['playQueueID'] = playqueue.ID
                info['playQueueVersion'] = playqueue.version
            except:
                pass
        except:
            import traceback
            log.error("Traceback:\n%s" % traceback.format_exc())
            info = {
                'time': 0,
                'duration': 0,
                'state': 'stopped',
                'shuffle': False,
                'repeat': 0
            }

        # get the volume from the application
        info['volume'] = self.volume
        info['mute'] = self.mute

        return info
Exemplo n.º 9
0
    def playAll(self, itemids, startat):
        log = self.logMsg
        window = utils.window

        embyconn = utils.kodiSQL('emby')
        embycursor = embyconn.cursor()
        emby_db = embydb.Embydb_Functions(embycursor)

        player = xbmc.Player()
        playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        playlist.clear()

        log("---*** PLAY ALL ***---", 1)
        log("Items: %s and start at: %s" % (itemids, startat), 1)

        started = False
        window('emby_customplaylist', value="true")

        if startat != 0:
            # Seek to the starting position
            window('emby_customplaylist.seektime', str(startat))

        with embydb.GetEmbyDB() as emby_db:
            for itemid in itemids:
                embydb_item = emby_db.getItem_byId(itemid)
                try:
                    dbid = embydb_item[0]
                    mediatype = embydb_item[4]
                except TypeError:
                    # Item is not found in our database, add item manually
                    log(
                        "Item was not found in the database, manually adding item.",
                        1)
                    item = PlexFunctions.GetPlexMetadata(itemid)
                    if item is None or item == 401:
                        log('Could not download itemid %s' % itemid, -1)
                    else:
                        self.addtoPlaylist_xbmc(playlist, item)
                else:
                    # Add to playlist
                    self.addtoPlaylist(dbid, mediatype)

                log("Adding %s to playlist." % itemid, 1)

                if not started:
                    started = True
                    player.play(playlist)

        self.verifyPlaylist()
Exemplo n.º 10
0
    def getPlayerProperties(self, playerid):
        try:
            # get info from the player
            props = self.js.jsonrpc(
                "Player.GetProperties", {
                    "playerid":
                    playerid,
                    "properties":
                    ["time", "totaltime", "speed", "shuffled", "repeat"]
                })

            info = {
                'time': timeToMillis(props['time']),
                'duration': timeToMillis(props['totaltime']),
                'state': ("paused", "playing")[int(props['speed'])],
                'shuffle': ("0", "1")[props.get('shuffled', False)],
                'repeat': pf.getPlexRepeat(props.get('repeat')),
            }
            if self.playlist is not None:
                if self.playlist.QueueId() is not None:
                    info['playQueueID'] = self.playlist.QueueId()
                    info['playQueueVersion'] = self.playlist.PlayQueueVersion()
                    info['guid'] = self.playlist.Guid()
                    # Get the playlist position
                    pos = self.js.jsonrpc("Player.GetProperties", {
                        "playerid": playerid,
                        "properties": ["position"]
                    })
                    info['playQueueItemID'] = \
                        self.playlist.getQueueIdFromPosition(pos['position'])
        except:
            import traceback
            log.error("Traceback:\n%s" % traceback.format_exc())
            info = {
                'time': 0,
                'duration': 0,
                'state': 'stopped',
                'shuffle': False,
                'repeat': 0
            }

        # get the volume from the application
        info['volume'] = self.volume
        info['mute'] = self.mute

        return info
Exemplo n.º 11
0
def _write_pms_settings(url, token):
    """
    Sets certain settings for server by asking for the PMS' settings
    Call with url: scheme://ip:port
    """
    xml = PF.get_PMS_settings(url, token)
    try:
        xml.attrib
    except AttributeError:
        LOG.error('Could not get PMS settings for %s', url)
        return
    for entry in xml:
        if entry.attrib.get('id', '') == 'allowMediaDeletion':
            settings('plex_allows_mediaDeletion',
                     value=entry.attrib.get('value', 'true'))
            window('plex_allows_mediaDeletion',
                   value=entry.attrib.get('value', 'true'))
Exemplo n.º 12
0
 def _check_pms_connectivity(server):
     """
     Checks for server's connectivity. Returns check_connection result
     """
     # Re-direct via plex if remote - will lead to the correct SSL
     # certificate
     if server['local']:
         url = ('%s://%s:%s' %
                (server['scheme'], server['ip'], server['port']))
         # Deactive SSL verification if the server is local!
         verifySSL = False
     else:
         url = server['baseURL']
         verifySSL = True
     chk = PF.check_connection(url,
                               token=server['token'],
                               verifySSL=verifySSL)
     return chk
Exemplo n.º 13
0
    def check_plex_tv_sign_in(self):
        """
        Checks existing connection to plex.tv. If not, triggers sign in

        Returns True if signed in, False otherwise
        """
        answer = True
        chk = PF.check_connection('plex.tv', token=self.plex_token)
        if chk in (401, 403):
            # HTTP Error: unauthorized. Token is no longer valid
            LOG.info('plex.tv connection returned HTTP %s', str(chk))
            # Delete token in the settings
            settings('plexToken', value='')
            settings('plexLogin', value='')
            # Could not login, please try again
            dialog('ok', lang(29999), lang(39009))
            answer = self.plex_tv_sign_in()
        elif chk is False or chk >= 400:
            # Problems connecting to plex.tv. Network or internet issue?
            LOG.info(
                'Problems connecting to plex.tv; connection returned '
                'HTTP %s', str(chk))
            dialog('ok', lang(29999), lang(39010))
            answer = False
        else:
            LOG.info('plex.tv connection with token successful')
            settings('plex_status', value=lang(39227))
            # Refresh the info from Plex.tv
            xml = DU().downloadUrl(
                'https://plex.tv/users/account',
                authenticate=False,
                headerOptions={'X-Plex-Token': self.plex_token})
            try:
                self.plex_login = xml.attrib['title']
            except (AttributeError, KeyError):
                LOG.error('Failed to update Plex info from plex.tv')
            else:
                settings('plexLogin', value=self.plex_login)
                home = 'true' if xml.attrib.get('home') == '1' else 'false'
                settings('plexhome', value=home)
                settings('plexAvatar', value=xml.attrib.get('thumb'))
                settings('plexHomeSize', value=xml.attrib.get('homeSize', '1'))
                LOG.info('Updated Plex info from plex.tv')
        return answer
Exemplo n.º 14
0
    def getPlayerProperties(self, playerid):
        info = {}
        try:
            # get info from the player
            props = self.js.jsonrpc(
                "Player.GetProperties", {
                    "playerid":
                    playerid,
                    "properties":
                    ["time", "totaltime", "speed", "shuffled", "repeat"]
                })
            self.logMsg(
                self.js.jsonrpc(
                    "Player.GetItem", {
                        "playerid": playerid,
                        "properties":
                        ["file", "showlink", "episode", "season"]
                    }), 2)
            info['time'] = timeToMillis(props['time'])
            info['duration'] = timeToMillis(props['totaltime'])
            info['state'] = ("paused", "playing")[int(props['speed'])]
            info['shuffle'] = ("0", "1")[props.get('shuffled', False)]
            info['repeat'] = pf.getPlexRepeat(props.get('repeat'))
            # New PMS playQueue attributes
            cf = self.xbmcplayer.getPlayingFile()
            info['playQueueID'] = window('playQueueID')
            info['playQueueVersion'] = window('playQueueVersion')
            info['playQueueItemID'] = window('plex_%s.playQueueItemID' % cf)
            info['guid'] = window('plex_%s.guid' % cf)

        except:
            info['time'] = 0
            info['duration'] = 0
            info['state'] = "stopped"
            info['shuffle'] = False
        # get the volume from the application
        info['volume'] = self.volume
        info['mute'] = self.mute

        return info
Exemplo n.º 15
0
 def _initiatePlaylist(self):
     log.info('Initiating playlist')
     playlist = None
     with embydb.GetEmbyDB() as emby_db:
         for item in self.items:
             itemid = item['plexId']
             embydb_item = emby_db.getItem_byId(itemid)
             try:
                 mediatype = embydb_item[4]
             except TypeError:
                 log.info('Couldnt find item %s in Kodi db' % itemid)
                 item = PlexFunctions.GetPlexMetadata(itemid)
                 if item in (None, 401):
                     log.info('Couldnt find item %s on PMS, trying next' %
                              itemid)
                     continue
                 if PlexAPI.API(item[0]).getType() == 'track':
                     playlist = xbmc.PlayList(xbmc.PLAYLIST_MUSIC)
                     log.info('Music playlist initiated')
                     self.typus = 'music'
                 else:
                     playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
                     log.info('Video playlist initiated')
                     self.typus = 'video'
             else:
                 if mediatype == 'song':
                     playlist = xbmc.PlayList(xbmc.PLAYLIST_MUSIC)
                     log.info('Music playlist initiated')
                     self.typus = 'music'
                 else:
                     playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
                     log.info('Video playlist initiated')
                     self.typus = 'video'
             break
     self.playlist = playlist
     if self.playlist is not None:
         self.playlistId = self.playlist.getPlayListId()
Exemplo n.º 16
0
    def _processItems(self, startitem, startPlayer=False):
        startpos = None
        with embydb.GetEmbyDB() as emby_db:
            for pos, item in enumerate(self.items):
                kodiId = None
                plexId = item['plexId']
                embydb_item = emby_db.getItem_byId(plexId)
                try:
                    kodiId = embydb_item[0]
                    mediatype = embydb_item[4]
                except TypeError:
                    log.info('Couldnt find item %s in Kodi db' % plexId)
                    xml = PlexFunctions.GetPlexMetadata(plexId)
                    if xml in (None, 401):
                        log.error('Could not download plexId %s' % plexId)
                    else:
                        log.debug('Downloaded xml metadata, adding now')
                        self._addtoPlaylist_xbmc(xml[0])
                else:
                    # Add to playlist
                    log.debug("Adding %s PlexId %s, KodiId %s to playlist." %
                              (mediatype, plexId, kodiId))
                    self._addtoPlaylist(kodiId, mediatype)
                # Add the kodiId
                if kodiId is not None:
                    item['kodiId'] = str(kodiId)
                if (startpos is None and startitem[1] == item[startitem[0]]):
                    startpos = pos

        if startPlayer is True and len(self.playlist) > 0:
            if startpos is not None:
                self.player.play(self.playlist, startpos=startpos)
            else:
                log.info('Never received a starting item for playlist, '
                         'starting with the first entry')
                self.player.play(self.playlist)
Exemplo n.º 17
0
    def _user_pick_pms(self):
        """
        Lets user pick his/her PMS from a list

        Returns server or None if unsuccessful
        """
        https_updated = False
        # Searching for PMS
        dialog('notification',
               heading='{plex}',
               message=lang(30001),
               icon='{plex}',
               time=5000)
        while True:
            if https_updated is False:
                serverlist = PF.discover_pms(self.plex_token)
                # Exit if no servers found
                if not serverlist:
                    LOG.warn('No plex media servers found!')
                    dialog('ok', lang(29999), lang(39011))
                    return
                # Get a nicer list
                dialoglist = []
                for server in serverlist:
                    if server['local']:
                        # server is in the same network as client.
                        # Add"local"
                        msg = lang(39022)
                    else:
                        # Add 'remote'
                        msg = lang(39054)
                    if server.get('ownername'):
                        # Display username if its not our PMS
                        dialoglist.append(
                            '%s (%s, %s)' %
                            (server['name'], server['ownername'], msg))
                    else:
                        dialoglist.append('%s (%s)' % (server['name'], msg))
                # Let user pick server from a list
                resp = dialog('select', lang(39012), dialoglist)
                if resp == -1:
                    # User cancelled
                    return

            server = serverlist[resp]
            chk = self._check_pms_connectivity(server)
            if chk == 504 and https_updated is False:
                # Not able to use HTTP, try HTTPs for now
                serverlist[resp]['scheme'] = 'https'
                https_updated = True
                continue
            https_updated = False
            if chk == 401:
                LOG.warn('Not yet authorized for Plex server %s',
                         server['name'])
                # Please sign in to plex.tv
                dialog('ok', lang(29999),
                       lang(39013) + server['name'], lang(39014))
                if self.plex_tv_sign_in() is False:
                    # Exit while loop if user cancels
                    return
            # Problems connecting
            elif chk >= 400 or chk is False:
                # Problems connecting to server. Pick another server?
                answ = dialog('yesno', lang(29999), lang(39015))
                # Exit while loop if user chooses No
                if not answ:
                    return
            # Otherwise: connection worked!
            else:
                return server
Exemplo n.º 18
0
    def loadCurrUser(self, username, userId, usertoken, authenticated=False):
        LOG.debug('Loading current user')
        doUtils = self.doUtils

        self.currToken = usertoken
        self.currServer = self.getServer()
        self.ssl = self.getSSLverify()
        self.sslcert = self.getSSL()

        if authenticated is False:
            if self.currServer is None:
                return False
            LOG.debug('Testing validity of current token')
            res = PF.check_connection(self.currServer,
                                      token=self.currToken,
                                      verifySSL=self.ssl)
            if res is False:
                # PMS probably offline
                return False
            elif res == 401:
                LOG.error('Token is no longer valid')
                return 401
            elif res >= 400:
                LOG.error('Answer from PMS is not as expected. Retrying')
                return False

        # Set to windows property
        state.PLEX_USER_ID = userId or None
        state.PLEX_USERNAME = username
        # This is the token for the current PMS (might also be '')
        window('pms_token', value=usertoken)
        state.PMS_TOKEN = usertoken
        # This is the token for plex.tv for the current user
        # Is only '' if user is not signed in to plex.tv
        window('plex_token', value=settings('plexToken'))
        state.PLEX_TOKEN = settings('plexToken') or None
        window('plex_restricteduser', value=settings('plex_restricteduser'))
        state.RESTRICTED_USER = True \
            if settings('plex_restricteduser') == 'true' else False
        window('pms_server', value=self.currServer)
        window('plex_machineIdentifier', value=self.machineIdentifier)
        window('plex_servername', value=self.servername)
        window('plex_authenticated', value='true')
        state.AUTHENTICATED = True

        window('useDirectPaths', value='true'
               if settings('useDirectPaths') == "1" else 'false')
        state.DIRECT_PATHS = True if settings('useDirectPaths') == "1" \
            else False
        state.INDICATE_MEDIA_VERSIONS = True \
            if settings('indicate_media_versions') == "true" else False
        window('plex_force_transcode_pix', value='true'
               if settings('force_transcode_pix') == "1" else 'false')

        # Start DownloadUtils session
        doUtils.startSession(reset=True)
        # self.getAdditionalUsers()
        # Set user preferences in settings
        self.currUser = username
        self.setUserPref()

        # Writing values to settings file
        settings('username', value=username)
        settings('userid', value=userId)
        settings('accessToken', value=usertoken)
        return True
Exemplo n.º 19
0
        itemtype = "picture"

    if (not itemid or itemid
            == "-1") and xbmc.getInfoLabel("ListItem.Property(plexid)"):
        plexid = xbmc.getInfoLabel("ListItem.Property(plexid)")
    else:
        with embydb.GetEmbyDB() as emby_db:
            item = emby_db.getItem_byKodiId(itemid, itemtype)
        if item:
            plexid = item[0]

    logMsg("Contextmenu opened for plexid: %s  - itemtype: %s" %
           (plexid, itemtype))

    if plexid:
        item = PF.GetPlexMetadata(plexid)
        if item is None or item == 401:
            logMsg('Could not get item metadata for item %s' % plexid, -1)
            return
        API = PlexAPI.API(item[0])
        userdata = API.getUserData()
        likes = userdata['Likes']
        favourite = userdata['Favorite']

        options = []
        if likes == True:
            #clear like for the item
            options.append(utils.language(30402))
        if likes == False or likes == None:
            #Like the item
            options.append(utils.language(30403))
Exemplo n.º 20
0
    def play(self, itemid, dbid=None):

        log = self.logMsg
        window = utils.window
        settings = utils.settings

        item = self.item
        # Hack to get only existing entry in PMS response for THIS instance of
        # playbackutils :-)
        self.API = PlexAPI.API(item[0])
        API = self.API
        listitem = xbmcgui.ListItem()
        playutils = putils.PlayUtils(item[0])

        log("Play called.", 1)
        playurl = playutils.getPlayUrl()
        if not playurl:
            return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)

        if dbid in (None, '999999999', 'plexnode'):
            # Item is not in Kodi database, is a trailer or plex redirect
            # e.g. plex.tv watch later
            API.CreateListItemFromPlexItem(listitem)
            self.setArtwork(listitem)
            if dbid == 'plexnode':
                # Need to get yet another xml to get final url
                window('emby_%s.playmethod' % playurl, clear=True)
                xml = downloadutils.DownloadUtils().downloadUrl(
                    '{server}%s' % item[0][0][0].attrib.get('key'))
                if xml in (None, 401):
                    log(
                        'Could not download %s' %
                        item[0][0][0].attrib.get('key'), -1)
                    return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False,
                                                     listitem)
                playurl = xml[0].attrib.get('key').encode('utf-8')
                window('emby_%s.playmethod' % playurl, value='DirectStream')

            playmethod = window('emby_%s.playmethod' % playurl)
            if playmethod == "Transcode":
                window('emby_%s.playmethod' % playurl, clear=True)
                playurl = playutils.audioSubsPref(
                    listitem, playurl.decode('utf-8')).encode('utf-8')
                window('emby_%s.playmethod' % playurl, "Transcode")
            listitem.setPath(playurl)
            self.setProperties(playurl, listitem)
            return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)

        ############### ORGANIZE CURRENT PLAYLIST ################

        homeScreen = xbmc.getCondVisibility('Window.IsActive(home)')
        playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        startPos = max(playlist.getposition(), 0)  # Can return -1
        sizePlaylist = playlist.size()
        self.currentPosition = startPos

        propertiesPlayback = window('emby_playbackProps') == "true"
        introsPlaylist = False
        dummyPlaylist = False

        log("Playlist start position: %s" % startPos, 1)
        log("Playlist plugin position: %s" % self.currentPosition, 1)
        log("Playlist size: %s" % sizePlaylist, 1)

        ############### RESUME POINT ################

        seektime, runtime = API.getRuntime()

        # We need to ensure we add the intro and additional parts only once.
        # Otherwise we get a loop.
        if not propertiesPlayback:

            window('emby_playbackProps', value="true")
            log("Setting up properties in playlist.", 1)

            if (not homeScreen and not seektime
                    and window('emby_customPlaylist') != "true"):
                log("Adding dummy file to playlist.", 2)
                dummyPlaylist = True
                playlist.add(playurl, listitem, index=startPos)
                # Remove the original item from playlist
                self.pl.removefromPlaylist(startPos + 1)
                # Readd the original item to playlist - via jsonrpc so we have full metadata
                self.pl.insertintoPlaylist(
                    self.currentPosition + 1, dbid,
                    PF.GetKodiTypeFromPlex(API.getType()))
                self.currentPosition += 1

            ############### -- CHECK FOR INTROS ################

            if (settings('enableCinema') == "true" and not seektime):
                # if we have any play them when the movie/show is not being resumed
                xml = PF.GetPlexPlaylist(itemid,
                                         item.attrib.get('librarySectionUUID'),
                                         mediatype=API.getType())
                introsPlaylist = self.AddTrailers(xml)

            ############### -- 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("Adding main item to playlist.", 1)
                self.pl.addtoPlaylist(dbid,
                                      PF.GetKodiTypeFromPlex(API.getType()))

            # Ensure that additional parts are played after the main item
            self.currentPosition += 1

            ############### -- CHECK FOR ADDITIONAL PARTS ################

            if len(item[0][0]) > 1:
                # Only add to the playlist after intros have played
                for counter, part in enumerate(item[0][0]):
                    # Never add first part
                    if counter == 0:
                        continue
                    # Set listitem and properties for each additional parts
                    API.setPartNumber(counter)
                    additionalListItem = xbmcgui.ListItem()
                    additionalPlayurl = playutils.getPlayUrl(
                        partNumber=counter)
                    log("Adding additional part: %s" % counter, 1)

                    self.setProperties(additionalPlayurl, additionalListItem)
                    self.setArtwork(additionalListItem)
                    # NEW to Plex
                    API.CreateListItemFromPlexItem(additionalListItem)

                    playlist.add(additionalPlayurl,
                                 additionalListItem,
                                 index=self.currentPosition)
                    self.pl.verifyPlaylist()
                    self.currentPosition += 1
                API.setPartNumber = 0

            if dummyPlaylist:
                # Added a dummy file to the playlist,
                # because the first item is going to fail automatically.
                log("Processed as a playlist. First item is skipped.", 1)
                return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False,
                                                 listitem)

        # We just skipped adding properties. Reset flag for next time.
        elif propertiesPlayback:
            log("Resetting properties playback flag.", 2)
            window('emby_playbackProps', clear=True)

        #self.pl.verifyPlaylist()
        ########## SETUP MAIN ITEM ##########

        # For transcoding only, ask for audio/subs pref
        if window('emby_%s.playmethod' % playurl) == "Transcode":
            window('emby_%s.playmethod' % playurl, clear=True)
            playurl = playutils.audioSubsPref(
                listitem, playurl.decode('utf-8')).encode('utf-8')
            window('emby_%s.playmethod' % playurl, value="Transcode")

        listitem.setPath(playurl)
        self.setProperties(playurl, listitem)

        ############### PLAYBACK ################

        if homeScreen and seektime and window('emby_customPlaylist') != "true":
            log("Play as a widget item.", 1)
            API.CreateListItemFromPlexItem(listitem)
            xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)

        elif ((introsPlaylist and window('emby_customPlaylist') == "true")
              or (homeScreen and not sizePlaylist)):
            # Playlist was created just now, play it.
            log("Play playlist.", 1)
            xbmc.Player().play(playlist, startpos=startPos)

        else:
            log("Play as a regular item.", 1)
            xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)