Beispiel #1
0
 def listArtistsResults():
     cm = []
     for artist in result['artists']:
         params = {
             'path': 'artist',
             'name': utils.tryEncode(artist['name'])
         }
         if 'artistId' in artist:
             params = {
                 'path': 'search_result',
                 'artistid': artist['artistId'],
                 'query': utils.tryEncode(artist['name'])
             }
             cm = [(self.lang(30301),
                    "XBMC.RunPlugin(%s?action=play_all&artist_id=%s)" %
                    (utils.addon_url, artist['artistId']))]
         art = artist[
             'artistArtRef'] if 'artistArtRef' in artist else utils.addon.getAddonInfo(
                 'icon')
         listItems.append(
             self.createFolder(artist['name'],
                               params,
                               cm,
                               arturl=art,
                               fanarturl=art))
def getVideoFiles(plexId, params):
    """
    GET VIDEO EXTRAS FOR LISTITEM

    returns the video files for the item as plugin listing, can be used for
    browsing the actual files or videoextras etc.
    """
    if plexId is None:
        filename = params.get('filename')
        if filename is not None:
            filename = filename[0]
            import re
            regex = re.compile(r'''library/metadata/(\d+)''')
            filename = regex.findall(filename)
            try:
                plexId = filename[0]
            except IndexError:
                pass

    if plexId is None:
        log.info('No Plex ID found, abort getting Extras')
        return xbmcplugin.endOfDirectory(HANDLE)

    item = GetPlexMetadata(plexId)
    try:
        path = item[0][0][0].attrib['file']
    except:
        log.error('Could not get file path for item %s' % plexId)
        return xbmcplugin.endOfDirectory(HANDLE)
    # Assign network protocol
    if path.startswith('\\\\'):
        path = path.replace('\\\\', 'smb://')
        path = path.replace('\\', '/')
    # Plex returns Windows paths as e.g. 'c:\slfkjelf\slfje\file.mkv'
    elif '\\' in path:
        path = path.replace('\\', '\\\\')
    # Directory only, get rid of filename (!! exists() needs /  or \ at end)
    path = path.replace(os_path.basename(path), '')
    # Only proceed if we can access this folder
    import xbmcvfs
    if xbmcvfs.exists(path):
        # Careful, returns encoded strings!
        dirs, files = xbmcvfs.listdir(path)
        for file in files:
            file = path + tryDecode(file)
            li = ListItem(file, path=file)
            xbmcplugin.addDirectoryItem(handle=HANDLE,
                                        url=tryEncode(file),
                                        listitem=li)
        for dir in dirs:
            dir = path + tryDecode(dir)
            li = ListItem(dir, path=dir)
            xbmcplugin.addDirectoryItem(handle=HANDLE,
                                        url=tryEncode(dir),
                                        listitem=li,
                                        isFolder=True)
    else:
        log.warn('Kodi cannot access folder %s' % path)
    xbmcplugin.endOfDirectory(HANDLE)
Beispiel #3
0
    def singleNode(self, indexnumber, tagname, mediatype, itemtype):
        tagname = tryEncode(tagname)
        cleantagname = tryDecode(normalize_nodes(tagname))
        nodepath = tryDecode(
            xbmc.translatePath("special://profile/library/video/"))
        nodeXML = "%splex_%s.xml" % (nodepath, cleantagname)
        path = "library://video/plex_%s.xml" % cleantagname
        if v.KODIVERSION >= 17:
            # Krypton
            windowpath = "ActivateWindow(Videos,%s,return)" % path
        else:
            windowpath = "ActivateWindow(Video,%s,return)" % path

        # Create the video node directory
        if not exists_dir(nodepath):
            # We need to copy over the default items
            copytree(
                src=tryDecode(
                    xbmc.translatePath("special://xbmc/system/library/video")),
                dst=tryDecode(
                    xbmc.translatePath("special://profile/library/video")))

        labels = {
            'Favorite movies': 30180,
            'Favorite tvshows': 30181,
            'channels': 30173
        }
        label = lang(labels[tagname])
        embynode = "Plex.nodes.%s" % indexnumber
        window('%s.title' % embynode, value=label)
        window('%s.path' % embynode, value=windowpath)
        window('%s.content' % embynode, value=path)
        window('%s.type' % embynode, value=itemtype)

        if exists(tryEncode(nodeXML)):
            # Don't recreate xml if already exists
            return

        if itemtype == "channels":
            root = self.commonRoot(order=1,
                                   label=label,
                                   tagname=tagname,
                                   roottype=2)
            etree.SubElement(
                root, 'path'
            ).text = "plugin://plugin.video.plexkodiconnect/?id=0&mode=channels"
        else:
            root = self.commonRoot(order=1, label=label, tagname=tagname)
            etree.SubElement(root, 'order', {
                'direction': "ascending"
            }).text = "sorttitle"

        etree.SubElement(root, 'content').text = mediatype

        try:
            indent(root)
        except:
            pass
        etree.ElementTree(root).write(nodeXML, encoding="UTF-8")
Beispiel #4
0
def getVideoFiles(plexId, params):
    """
    GET VIDEO EXTRAS FOR LISTITEM

    returns the video files for the item as plugin listing, can be used for
    browsing the actual files or videoextras etc.
    """
    if plexId is None:
        filename = params.get('filename')
        if filename is not None:
            filename = filename[0]
            import re
            regex = re.compile(r'''library/metadata/(\d+)''')
            filename = regex.findall(filename)
            try:
                plexId = filename[0]
            except IndexError:
                pass

    if plexId is None:
        log.info('No Plex ID found, abort getting Extras')
        return xbmcplugin.endOfDirectory(HANDLE)

    item = GetPlexMetadata(plexId)
    try:
        path = item[0][0][0].attrib['file']
    except:
        log.error('Could not get file path for item %s' % plexId)
        return xbmcplugin.endOfDirectory(HANDLE)
    # Assign network protocol
    if path.startswith('\\\\'):
        path = path.replace('\\\\', 'smb://')
        path = path.replace('\\', '/')
    # Plex returns Windows paths as e.g. 'c:\slfkjelf\slfje\file.mkv'
    elif '\\' in path:
        path = path.replace('\\', '\\\\')
    # Directory only, get rid of filename (!! exists() needs /  or \ at end)
    path = path.replace(os_path.basename(path), '')
    # Only proceed if we can access this folder
    import xbmcvfs
    if xbmcvfs.exists(path):
        # Careful, returns encoded strings!
        dirs, files = xbmcvfs.listdir(path)
        for file in files:
            file = path + tryDecode(file)
            li = ListItem(file, path=file)
            xbmcplugin.addDirectoryItem(handle=HANDLE,
                                        url=tryEncode(file),
                                        listitem=li)
        for dir in dirs:
            dir = path + tryDecode(dir)
            li = ListItem(dir, path=dir)
            xbmcplugin.addDirectoryItem(handle=HANDLE,
                                        url=tryEncode(dir),
                                        listitem=li,
                                        isFolder=True)
    else:
        log.warn('Kodi cannot access folder %s' % path)
    xbmcplugin.endOfDirectory(HANDLE)
Beispiel #5
0
def getVideoFiles(plexId, params):
    """
    GET VIDEO EXTRAS FOR LISTITEM

    returns the video files for the item as plugin listing, can be used for
    browsing the actual files or videoextras etc.
    """
    if plexId is None:
        filename = params.get('filename')
        if filename is not None:
            filename = filename[0]
            import re
            regex = re.compile(r'''library/metadata/(\d+)''')
            filename = regex.findall(filename)
            try:
                plexId = filename[0]
            except IndexError:
                pass

    if plexId is None:
        log.info('No Plex ID found, abort getting Extras')
        return xbmcplugin.endOfDirectory(HANDLE)

    item = GetPlexMetadata(plexId)
    try:
        path = item[0][0][0].attrib['file']
    except:
        log.error('Could not get file path for item %s' % plexId)
        return xbmcplugin.endOfDirectory(HANDLE)
    # Assign network protocol
    if path.startswith('\\\\'):
        path = path.replace('\\\\', 'smb://')
        path = path.replace('\\', '/')
    # Plex returns Windows paths as e.g. 'c:\slfkjelf\slfje\file.mkv'
    elif '\\' in path:
        path = path.replace('\\', '\\\\')
    # Directory only, get rid of filename
    path = path.replace(basename(path), '')
    if exists_dir(path):
        for root, dirs, files in walk(path):
            for directory in dirs:
                item_path = tryEncode(join(root, directory))
                li = ListItem(item_path, path=item_path)
                xbmcplugin.addDirectoryItem(handle=HANDLE,
                                            url=item_path,
                                            listitem=li,
                                            isFolder=True)
            for file in files:
                item_path = tryEncode(join(root, file))
                li = ListItem(item_path, path=item_path)
                xbmcplugin.addDirectoryItem(handle=HANDLE,
                                            url=file,
                                            listitem=li)
            break
    else:
        log.error('Kodi cannot access folder %s' % path)
    xbmcplugin.endOfDirectory(HANDLE)
Beispiel #6
0
def getExtraFanArt(plexid, plexPath):
    """
    Get extrafanart for listitem
    will be called by skinhelper script to get the extrafanart
    for tvshows we get the plexid just from the path
    """
    import xbmcvfs
    log.debug('Called with plexid: %s, plexPath: %s' % (plexid, plexPath))
    if not plexid:
        if "plugin.video.plexkodiconnect" in plexPath:
            plexid = plexPath.split("/")[-2]
    if not plexid:
        log.error('Could not get a plexid, aborting')
        return xbmcplugin.endOfDirectory(HANDLE)

    # We need to store the images locally for this to work
    # because of the caching system in xbmc
    fanartDir = tryDecode(translatePath(
        "special://thumbnails/plex/%s/" % plexid))
    if not xbmcvfs.exists(fanartDir):
        # Download the images to the cache directory
        xbmcvfs.mkdirs(tryEncode(fanartDir))
        xml = GetPlexMetadata(plexid)
        if xml is None:
            log.error('Could not download metadata for %s' % plexid)
            return xbmcplugin.endOfDirectory(HANDLE)

        api = API(xml[0])
        backdrops = api.getAllArtwork()['Backdrop']
        for count, backdrop in enumerate(backdrops):
            # Same ordering as in artwork
            if os_path.supports_unicode_filenames:
                fanartFile = os_path.join(fanartDir,
                                          "fanart%.3d.jpg" % count)
            else:
                fanartFile = os_path.join(
                    tryEncode(fanartDir),
                    tryEncode("fanart%.3d.jpg" % count))
            li = ListItem("%.3d" % count, path=fanartFile)
            xbmcplugin.addDirectoryItem(
                handle=HANDLE,
                url=fanartFile,
                listitem=li)
            xbmcvfs.copy(backdrop, fanartFile)
    else:
        log.info("Found cached backdrop.")
        # Use existing cached images
        dirs, files = xbmcvfs.listdir(fanartDir)
        for file in files:
            fanartFile = os_path.join(fanartDir, tryDecode(file))
            li = ListItem(file, path=fanartFile)
            xbmcplugin.addDirectoryItem(handle=HANDLE,
                                        url=fanartFile,
                                        listitem=li)
    xbmcplugin.endOfDirectory(HANDLE)
def getExtraFanArt(plexid, plexPath):
    """
    Get extrafanart for listitem
    will be called by skinhelper script to get the extrafanart
    for tvshows we get the plexid just from the path
    """
    import xbmcvfs
    log.debug('Called with plexid: %s, plexPath: %s' % (plexid, plexPath))
    if not plexid:
        if "plugin.video.plexkodiconnect" in plexPath:
            plexid = plexPath.split("/")[-2]
    if not plexid:
        log.error('Could not get a plexid, aborting')
        return xbmcplugin.endOfDirectory(HANDLE)

    # We need to store the images locally for this to work
    # because of the caching system in xbmc
    fanartDir = tryDecode(
        translatePath("special://thumbnails/plex/%s/" % plexid))
    if not xbmcvfs.exists(fanartDir):
        # Download the images to the cache directory
        xbmcvfs.mkdirs(tryEncode(fanartDir))
        xml = GetPlexMetadata(plexid)
        if xml is None:
            log.error('Could not download metadata for %s' % plexid)
            return xbmcplugin.endOfDirectory(HANDLE)

        api = API(xml[0])
        backdrops = api.getAllArtwork()['Backdrop']
        for count, backdrop in enumerate(backdrops):
            # Same ordering as in artwork
            if os_path.supports_unicode_filenames:
                fanartFile = os_path.join(fanartDir, "fanart%.3d.jpg" % count)
            else:
                fanartFile = os_path.join(tryEncode(fanartDir),
                                          tryEncode("fanart%.3d.jpg" % count))
            li = ListItem("%.3d" % count, path=fanartFile)
            xbmcplugin.addDirectoryItem(handle=HANDLE,
                                        url=fanartFile,
                                        listitem=li)
            xbmcvfs.copy(backdrop, fanartFile)
    else:
        log.info("Found cached backdrop.")
        # Use existing cached images
        dirs, files = xbmcvfs.listdir(fanartDir)
        for file in files:
            fanartFile = os_path.join(fanartDir, tryDecode(file))
            li = ListItem(file, path=fanartFile)
            xbmcplugin.addDirectoryItem(handle=HANDLE,
                                        url=fanartFile,
                                        listitem=li)
    xbmcplugin.endOfDirectory(HANDLE)
Beispiel #8
0
 def listAlbumsResults():
     for album in result['albums']:
         if 'albumId' in album:
             listItems.extend(self.createAlbumFolder([album]))
         else:
             params = {
                 'path': 'album',
                 'album': utils.tryEncode(album['name']),
                 'artist': utils.tryEncode(album['artist'])
             }
             cm = self.getFilterContextMenuItems('album', album['name'])
             listItems.append(
                 self.createFolder(
                     "[%s] %s" % (album['artist'], album['name']),
                     params, cm, album['albumart'], album['artistart']))
    def emit(self, record):

        if self._get_log_level(record.levelno):
            try:
                xbmc.log(self.format(record), level=xbmc.LOGNOTICE)
            except UnicodeEncodeError:
                xbmc.log(tryEncode(self.format(record)), level=xbmc.LOGNOTICE)
Beispiel #10
0
    def single_urlencode(self, text):

        text = urllib.urlencode({'blahblahblah': utils.tryEncode(text)
                                 })  #urlencode needs a utf- string
        text = text[13:]

        return utils.tryDecode(text)  #return the result again as unicode
Beispiel #11
0
def getRealFileName(filename, isTemp=False):
    #get the filename path accessible by python if possible...
    
    if not xbmcvfs.exists(filename):
        logMsg( "File does not exist! %s" %(filename), 0)
        return (False, "")
    
    #if we use os.path method on older python versions (sunch as some android builds), we need to pass arguments as string
    if os.path.supports_unicode_filenames:
        checkfile = filename
    else:
        checkfile = utils.tryEncode(filename)
    
    # determine if our python module is able to access the file directly...
    if os.path.exists(checkfile):
        filename = filename
    elif os.path.exists(checkfile.replace("smb://","\\\\").replace("/","\\")):
        filename = filename.replace("smb://","\\\\").replace("/","\\")
    else:
        #file can not be accessed by python directly, we copy it for processing...
        isTemp = True
        if "/" in filename: filepart = filename.split("/")[-1]
        else: filepart = filename.split("\\")[-1]
        tempfile = "special://temp/"+filepart
        xbmcvfs.copy(filename, tempfile)
        filename = utils.tryDecode(xbmc.translatePath(tempfile))
        
    return (isTemp,filename)
Beispiel #12
0
def play_resume(playqueue, xml, stack):
    """
    If there exists a resume point, Kodi will ask the user whether to continue
    playback. We thus need to use setResolvedUrl "correctly". Mind that there
    might be several parts!
    """
    result = Playback_Successful()
    listitem = PKC_ListItem()
    # Only get the very first item of our playqueue (i.e. the very first part)
    stack_item = stack.pop(0)
    api = API(xml[0])
    item = PL.playlist_item_from_xml(playqueue,
                                     xml[0],
                                     kodi_id=stack_item['kodi_id'],
                                     kodi_type=stack_item['kodi_type'])
    api.setPartNumber(item.part)
    item.playcount = stack_item['playcount']
    item.offset = stack_item['offset']
    item.part = stack_item['part']
    api.CreateListItemFromPlexItem(listitem)
    playutils = PlayUtils(api, item)
    playurl = playutils.getPlayUrl()
    listitem.setPath(tryEncode(playurl))
    if item.playmethod in ('DirectStream', 'DirectPlay'):
        listitem.setSubtitles(api.externalSubs())
    else:
        playutils.audio_subtitle_prefs(listitem)
    result.listitem = listitem
    # Add to our playlist
    playqueue.items.append(item)
    # This will release default.py with setResolvedUrl
    pickle_me(result)
    # Add remaining parts to the playlist, if any
    if stack:
        _process_stack(playqueue, stack)
Beispiel #13
0
    def getCategoryStations(self, items):
        listItems = []

        default_thumb = utils.addon.getAddonInfo('icon')
        default_fanart = utils.addon.getAddonInfo('fanart')

        for item in items:
            #utils.log("STATION: "+repr(item))
            params = {
                'path': 'create_station',
                'name': utils.tryEncode(item['name'])
            }
            params.update(self.getStationSeed(item['seed']))
            url1 = item['compositeArtRefs'][0][
                'url'] if 'compositeArtRefs' in item and item[
                    'compositeArtRefs'] else default_thumb
            url2 = item['imageUrls'][0]['url'] if 'imageUrls' in item and item[
                'imageUrls'] else default_fanart
            folder = self.createFolder(item['name'],
                                       params,
                                       arturl=url1,
                                       fanarturl=url2)
            folder[1].setInfo(
                type='Music',
                infoLabels={
                    'comment':
                    item.get('description', 'No description'),
                    'date':
                    time.strftime(
                        '%d.%m.%Y',
                        time.gmtime(item.get('recentTimestamp', 0) / 1000000))
                })
            listItems.append(folder)
        return listItems
Beispiel #14
0
def getRealFileName(filename, isTemp=False):
    #get the filename path accessible by python if possible...

    if not xbmcvfs.exists(filename):
        logMsg("File does not exist! %s" % (filename), 0)
        return (False, "")

    #if we use os.path method on older python versions (sunch as some android builds), we need to pass arguments as string
    if os.path.supports_unicode_filenames:
        checkfile = filename
    else:
        checkfile = utils.tryEncode(filename)

    # determine if our python module is able to access the file directly...
    if os.path.exists(checkfile):
        filename = filename
    elif os.path.exists(
            checkfile.replace("smb://", "\\\\").replace("/", "\\")):
        filename = filename.replace("smb://", "\\\\").replace("/", "\\")
    else:
        #file can not be accessed by python directly, we copy it for processing...
        isTemp = True
        if "/" in filename: filepart = filename.split("/")[-1]
        else: filepart = filename.split("\\")[-1]
        tempfile = "special://temp/" + filepart
        xbmcvfs.copy(filename, tempfile)
        filename = utils.tryDecode(xbmc.translatePath(tempfile))

    return (isTemp, filename)
Beispiel #15
0
 def getRadioContextMenuItems(self, name, radio_id):
     cm = []
     name = quote_plus(utils.tryEncode(name))
     cm.append((self.lang(30301),
                "XBMC.RunPlugin(%s?action=play_all&radio_id=%s)" %
                (utils.addon_url, radio_id)))
     cm.append(
         (self.lang(30302),
          "XBMC.RunPlugin(%s?action=play_all&radio_id=%s&shuffle=true)" %
          (utils.addon_url, radio_id)))
     cm.append((self.lang(30312),
                "XBMC.RunPlugin(%s?action=play_all_yt&radio_id=%s)" %
                (utils.addon_url, radio_id)))
     cm.append(
         (self.lang(30321),
          "XBMC.RunPlugin(%s?action=play_all_yt&radio_id=%s&shuffle=true)" %
          (utils.addon_url, radio_id)))
     cm.append((self.lang(
         30306
     ), "XBMC.RunPlugin(%s?action=add_favourite&path=playlist&radio_id=%s&title=%s)"
                % (utils.addon_url, radio_id, name)))
     cm.append((self.lang(30315),
                "XBMC.RunPlugin(%s?action=add_to_queue&radio_id=%s)" %
                (utils.addon_url, radio_id)))
     cm.append(
         (self.lang(30318),
          "XBMC.RunPlugin(%s?action=delete_station&radio_id=%s&title=%s)" %
          (utils.addon_url, radio_id, name)))
     return cm
    def emit(self, record):

        if self._get_log_level(record.levelno):
            try:
                xbmc.log(self.format(record), level=xbmc.LOGNOTICE)
            except UnicodeEncodeError:
                xbmc.log(tryEncode(self.format(record)), level=xbmc.LOGNOTICE)
Beispiel #17
0
 def __repr__(self):
     answ = "<%s: " % (self.__class__.__name__)
     for key in self.__dict__:
         if type(getattr(self, key)) in (str, unicode):
             answ += '%s: %s, ' % (key, tryEncode(getattr(self, key)))
         else:
             # e.g. int
             answ += '%s: %s, ' % (key, str(getattr(self, key)))
     return answ[:-2] + ">"
Beispiel #18
0
 def listAlbumsResults():
     listItems.append(self.createFolder('[COLOR orange]*** '+self.lang(30206)+' ***[/COLOR]',{'path':'none'}))
     cm = []
     for album in result['albums']:
         params = {'path':"search_result",'query':utils.tryEncode(album[0])}
         if len(album) > 3:
             cm = [(self.lang(30301), "XBMC.RunPlugin(%s?action=play_all&album_id=%s)" % (utils.addon_url, album[3]))]
             params['albumid'] = album[3]
         listItems.append(self.createFolder("[%s] %s"%(album[1], album[0]), params, cm, album[2]))
Beispiel #19
0
 def __repr__(self):
     answ = "<%s: " % (self.__class__.__name__)
     for key in self.__dict__:
         if type(getattr(self, key)) in (str, unicode):
             answ += '%s: %s, ' % (key, tryEncode(getattr(self, key)))
         else:
             # e.g. int
             answ += '%s: %s, ' % (key, str(getattr(self, key)))
     return answ[:-2] + ">"
Beispiel #20
0
    def getPlayUrl(self, partNumber=None):
        """
        Returns the playurl for the part with number partNumber
        (movie might consist of several files)

        playurl is utf-8 encoded!
        """
        self.API.setPartNumber(partNumber)
        self.API.getMediastreamNumber()
        playurl = self.isDirectPlay()

        if playurl is not None:
            log.info("File is direct playing.")
            playurl = tryEncode(playurl)
            # Set playmethod property
            window('plex_%s.playmethod' % playurl, "DirectPlay")

        elif self.isDirectStream():
            log.info("File is direct streaming.")
            playurl = tryEncode(self.API.getTranscodeVideoPath('DirectStream'))
            # Set playmethod property
            window('plex_%s.playmethod' % playurl, "DirectStream")

        else:
            log.info("File is transcoding.")
            playurl = tryEncode(
                self.API.getTranscodeVideoPath(
                    'Transcode',
                    quality={
                        'maxVideoBitrate':
                        self.get_bitrate(),
                        'videoResolution':
                        self.get_resolution(),
                        'videoQuality':
                        '100',
                        'mediaBufferSize':
                        int(settings('kodi_video_cache')) / 1024,
                    }))
            # Set playmethod property
            window('plex_%s.playmethod' % playurl, value="Transcode")

        log.info("The playurl is: %s" % playurl)
        return playurl
Beispiel #21
0
    def _AutoPickPMS(self):
        """
        Will try to pick PMS based on machineIdentifier saved in file settings
        but only once

        Returns server or None if unsuccessful
        """
        httpsUpdated = False
        checkedPlexTV = False
        server = None
        while True:
            if httpsUpdated is False:
                serverlist = self._getServerList()
                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._checkServerCon(server)
            if chk == 504 and httpsUpdated is False:
                # Not able to use HTTP, try HTTPs for now
                server['scheme'] = 'https'
                httpsUpdated = True
                continue
            if chk == 401:
                LOG.warn('Not yet authorized for Plex server %s',
                         server['name'])
                if self.CheckPlexTVSignIn() is True:
                    if checkedPlexTV is False:
                        # Try again
                        checkedPlexTV = True
                        httpsUpdated = False
                        continue
                    else:
                        LOG.warn('Not authorized even though we are signed '
                                 ' in to plex.tv correctly')
                        self.dialog.ok(
                            lang(29999),
                            '%s %s' % (lang(39214), tryEncode(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
Beispiel #22
0
 def getSongContextMenu(self, song_id, title, display_name, song_type):
     cm = []
     title = quote_plus(utils.tryEncode(title))
     display_name = quote_plus(utils.tryEncode(display_name))
     if song_id.startswith('T'):
         cm.append((self.lang(30309),
                    "XBMC.RunPlugin(%s?action=add_library&song_id=%s)" %
                    (utils.addon_url, song_id)))
         cm.append((self.lang(30319),
                    "XBMC.RunPlugin(%s?action=artist_topsongs&song_id=%s)" %
                    (utils.addon_url, song_id)))
         cm.append((self.lang(30320),
                    "XBMC.RunPlugin(%s?action=related_artists&song_id=%s)" %
                    (utils.addon_url, song_id)))
     if song_type == 'library':
         cm.append((self.lang(30307),
                    "XBMC.RunPlugin(%s?action=add_playlist&song_id=%s)" %
                    (utils.addon_url, song_id)))
     elif song_type.startswith('playlist'):
         pl_id = song_type[8:]
         cm.append((self.lang(
             30322
         ), "XBMC.RunPlugin(%s?action=play_all&from_here=%s&playlist_id=%s)"
                    % (utils.addon_url, song_id, pl_id)))
         cm.append((self.lang(
             30308
         ), "XBMC.RunPlugin(%s?action=del_from_playlist&song_id=%s&playlist_id=%s)"
                    % (utils.addon_url, song_id, pl_id)))
     cm.append((self.lang(30409),
                "XBMC.RunPlugin(%s?action=set_thumbs&song_id=%s)" %
                (utils.addon_url, song_id)))
     cm.append((self.lang(30313),
                "XBMC.RunPlugin(%s?action=play_yt&display_name=%s)" %
                (utils.addon_url, display_name)))
     cm.append((self.lang(30311),
                "XBMC.RunPlugin(%s?action=search_yt&display_name=%s)" %
                (utils.addon_url, display_name)))
     cm.append(
         (self.lang(30310),
          "XBMC.RunPlugin(%s?action=start_radio&song_id=%s&title=%s)" %
          (utils.addon_url, song_id, title)))
     return cm
    def singleNode(self, indexnumber, tagname, mediatype, itemtype):

        tagname = tryEncode(tagname)
        cleantagname = normalize_nodes(tagname)
        nodepath = tryDecode(xbmc.translatePath(
            "special://profile/library/video/"))
        nodeXML = "%splex_%s.xml" % (nodepath, cleantagname)
        path = "library://video/plex_%s.xml" % cleantagname
        if self.kodiversion >= 17:
            # Krypton
            windowpath = "ActivateWindow(Videos,%s,return)" % path
        else:
            windowpath = "ActivateWindow(Video,%s,return)" % path

        # Create the video node directory
        if not xbmcvfs.exists(nodepath):
            # We need to copy over the default items
            shutil.copytree(
                src=tryDecode(xbmc.translatePath(
                    "special://xbmc/system/library/video")),
                dst=tryDecode(xbmc.translatePath(
                    "special://profile/library/video")))
            xbmcvfs.exists(path)

        labels = {

            'Favorite movies': 30180,
            'Favorite tvshows': 30181,
            'channels': 30173
        }
        label = lang(labels[tagname])
        embynode = "Plex.nodes.%s" % indexnumber
        window('%s.title' % embynode, value=label)
        window('%s.path' % embynode, value=windowpath)
        window('%s.content' % embynode, value=path)
        window('%s.type' % embynode, value=itemtype)

        if xbmcvfs.exists(nodeXML):
            # Don't recreate xml if already exists
            return

        if itemtype == "channels":
            root = self.commonRoot(order=1, label=label, tagname=tagname, roottype=2)
            etree.SubElement(root, 'path').text = "plugin://plugin.video.plexkodiconnect/?id=0&mode=channels"
        else:
            root = self.commonRoot(order=1, label=label, tagname=tagname)
            etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"

        etree.SubElement(root, 'content').text = mediatype

        try:
            indent(root)
        except: pass
        etree.ElementTree(root).write(nodeXML)
Beispiel #24
0
    def _AutoPickPMS(self):
        """
        Will try to pick PMS based on machineIdentifier saved in file settings
        but only once

        Returns server or None if unsuccessful
        """
        httpsUpdated = False
        checkedPlexTV = False
        server = None
        while True:
            if httpsUpdated is False:
                serverlist = self._getServerList()
                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._checkServerCon(server)
            if chk == 504 and httpsUpdated is False:
                # Not able to use HTTP, try HTTPs for now
                server['scheme'] = 'https'
                httpsUpdated = True
                continue
            if chk == 401:
                log.warn('Not yet authorized for Plex server %s'
                         % server['name'])
                if self.CheckPlexTVSignIn() is True:
                    if checkedPlexTV is False:
                        # Try again
                        checkedPlexTV = True
                        httpsUpdated = False
                        continue
                    else:
                        log.warn('Not authorized even though we are signed '
                                 ' in to plex.tv correctly')
                        self.dialog.ok(lang(29999), '%s %s'
                                       % (lang(39214),
                                          tryEncode(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
Beispiel #25
0
    def getPlayUrl(self, partNumber=None):
        """
        Returns the playurl for the part with number partNumber
        (movie might consist of several files)

        playurl is utf-8 encoded!
        """
        log = self.logMsg
        window = utils.window

        self.API.setPartNumber(partNumber)
        playurl = self.isDirectPlay()

        if playurl:
            log("File is direct playing.", 1)
            playurl = utils.tryEncode(playurl)
            # Set playmethod property
            window('emby_%s.playmethod' % playurl, "DirectPlay")

        elif self.isDirectStream():
            self.logMsg("File is direct streaming.", 1)
            playurl = utils.tryEncode(
                self.API.getTranscodeVideoPath('DirectStream'))
            # Set playmethod property
            utils.window('emby_%s.playmethod' % playurl, "DirectStream")

        else:
            self.logMsg("File is transcoding.", 1)
            quality = {
                'maxVideoBitrate': self.getBitrate(),
                'videoResolution': self.getResolution(),
                'videoQuality': '100'
            }
            playurl = utils.tryEncode(self.API.getTranscodeVideoPath(
                'Transcode',
                quality=quality))
            # Set playmethod property
            window('emby_%s.playmethod' % playurl, value="Transcode")

        log("The playurl is: %s" % playurl, 1)
        return playurl
Beispiel #26
0
    def getPlayUrl(self, partNumber=None):
        """
        Returns the playurl for the part with number partNumber
        (movie might consist of several files)

        playurl is utf-8 encoded!
        """
        log = self.logMsg
        window = utils.window

        self.API.setPartNumber(partNumber)
        playurl = self.isDirectPlay()

        if playurl:
            log("File is direct playing.", 1)
            playurl = utils.tryEncode(playurl)
            # Set playmethod property
            window('emby_%s.playmethod' % playurl, "DirectPlay")

        elif self.isDirectStream():
            self.logMsg("File is direct streaming.", 1)
            playurl = utils.tryEncode(
                self.API.getTranscodeVideoPath('DirectStream'))
            # Set playmethod property
            utils.window('emby_%s.playmethod' % playurl, "DirectStream")

        else:
            self.logMsg("File is transcoding.", 1)
            quality = {
                'maxVideoBitrate': self.getBitrate(),
                'videoResolution': self.getResolution(),
                'videoQuality': '100'
            }
            playurl = utils.tryEncode(
                self.API.getTranscodeVideoPath('Transcode', quality=quality))
            # Set playmethod property
            window('emby_%s.playmethod' % playurl, value="Transcode")

        log("The playurl is: %s" % playurl, 1)
        return playurl
Beispiel #27
0
 def __repr__(self):
     answ = "<%s: " % (self.__class__.__name__)
     # For some reason, can't use dir directly
     answ += "ID: %s, " % self.ID
     answ += "items: %s, " % self.items
     for key in self.__dict__:
         if key not in ("ID", 'items'):
             if type(getattr(self, key)) in (str, unicode):
                 answ += '%s: %s, ' % (key, tryEncode(getattr(self, key)))
             else:
                 # e.g. int
                 answ += '%s: %s, ' % (key, str(getattr(self, key)))
     return answ[:-2] + ">"
Beispiel #28
0
 def __repr__(self):
     answ = "<%s: " % (self.__class__.__name__)
     # For some reason, can't use dir directly
     answ += "ID: %s, " % self.ID
     answ += "items: %s, " % self.items
     for key in self.__dict__:
         if key not in ("ID", 'items'):
             if type(getattr(self, key)) in (str, unicode):
                 answ += '%s: %s, ' % (key, tryEncode(getattr(self, key)))
             else:
                 # e.g. int
                 answ += '%s: %s, ' % (key, str(getattr(self, key)))
     return answ[:-2] + ">"
Beispiel #29
0
 def getFilterContextMenuItems(self,
                               filter_type,
                               filter_criteria,
                               artist=''):
     cm = []
     filter_criteria = quote_plus(utils.tryEncode(filter_criteria))
     #filter_criteria = quote_plus(filter_criteria.encode('utf-8'), safe=':/'.encode('utf-8'))
     artist = quote_plus(utils.tryEncode(artist))
     cm.append(
         (self.lang(30306),
          "XBMC.RunPlugin(%s?action=add_favourite&path=%s&name=%s&title=%s)"
          %
          (utils.addon_url, filter_type, filter_criteria, filter_criteria)))
     cm.append((self.lang(
         30301
     ), "XBMC.RunPlugin(%s?action=play_all&filter_type=%s&filter_criteria=%s&artist=%s)"
                % (utils.addon_url, filter_type, filter_criteria, artist)))
     cm.append((self.lang(
         30302
     ), "XBMC.RunPlugin(%s?action=play_all&filter_type=%s&filter_criteria=%s&shuffle=true&artist=%s)"
                % (utils.addon_url, filter_type, filter_criteria, artist)))
     cm.append((self.lang(
         30312
     ), "XBMC.RunPlugin(%s?action=play_all_yt&filter_type=%s&filter_criteria=%s&artist=%s)"
                % (utils.addon_url, filter_type, filter_criteria, artist)))
     cm.append((self.lang(
         30321
     ), "XBMC.RunPlugin(%s?action=play_all_yt&filter_type=%s&filter_criteria=%s&shuffle=true&artist=%s)"
                % (utils.addon_url, filter_type, filter_criteria, artist)))
     cm.append((self.lang(
         30208
     ), "XBMC.RunPlugin(%s?action=search&filter_type=%s&filter_criteria=%s&artist=%s)"
                % (utils.addon_url, filter_type, filter_criteria, artist)))
     cm.append((self.lang(
         30315
     ), "XBMC.RunPlugin(%s?action=add_to_queue&filter_type=album&filter_criteria=%s&artist=%s)"
                % (utils.addon_url, filter_criteria, artist)))
     return cm
 def _addtoPlaylist(self, dbid=None, mediatype=None, url=None):
     pl = {
         'jsonrpc': "2.0",
         'id': 1,
         'method': "Playlist.Add",
         'params': {
             'playlistid': self.playlistId
         }
     }
     if dbid is not None:
         pl['params']['item'] = {'%sid' % tryEncode(mediatype): int(dbid)}
     else:
         pl['params']['item'] = {'file': url}
     log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
Beispiel #31
0
    def create_frame(data, opcode):
        """
        create frame to send text, binary and other data.

        data: data to send. This is string value(byte array).
            if opcode is OPCODE_TEXT and this value is uniocde,
            data value is conveted into unicode string, automatically.

        opcode: operation code. please see OPCODE_XXX.
        """
        if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode):
            data = utils.tryEncode(data)
        # mask must be set if send data from client
        return ABNF(1, 0, 0, 0, opcode, 1, data)
Beispiel #32
0
def conclude_playback(playqueue, pos):
    """
    ONLY if actually being played (e.g. at 5th position of a playqueue).

        Decide on direct play, direct stream, transcoding
        path to
            direct paths: file itself
            PMS URL
            Web URL
        audiostream (e.g. let user choose)
        subtitle stream (e.g. let user choose)
        Init Kodi Playback (depending on situation):
            start playback
            return PKC listitem attached to result
    """
    LOG.info('Concluding playback for playqueue position %s', pos)
    result = Playback_Successful()
    listitem = PKC_ListItem()
    item = playqueue.items[pos]
    if item.xml is not None:
        # Got a Plex element
        api = API(item.xml)
        api.setPartNumber(item.part)
        api.CreateListItemFromPlexItem(listitem)
        playutils = PlayUtils(api, item)
        playurl = playutils.getPlayUrl()
    else:
        playurl = item.file
    listitem.setPath(tryEncode(playurl))
    if item.playmethod in ('DirectStream', 'DirectPlay'):
        listitem.setSubtitles(api.externalSubs())
    else:
        playutils.audio_subtitle_prefs(listitem)
    if state.RESUME_PLAYBACK is True:
        state.RESUME_PLAYBACK = False
        if (item.offset is None and item.plex_type
                not in (v.PLEX_TYPE_SONG, v.PLEX_TYPE_CLIP)):
            with plexdb.Get_Plex_DB() as plex_db:
                plex_dbitem = plex_db.getItem_byId(item.plex_id)
                file_id = plex_dbitem[1] if plex_dbitem else None
            with kodidb.GetKodiDB('video') as kodi_db:
                item.offset = kodi_db.get_resume(file_id)
        LOG.info('Resuming playback at %s', item.offset)
        listitem.setProperty('StartOffset', str(item.offset))
        listitem.setProperty('resumetime', str(item.offset))
    # Reset the resumable flag
    state.RESUMABLE = False
    result.listitem = listitem
    pickle_me(result)
    LOG.info('Done concluding playback')
Beispiel #33
0
    def create_frame(data, opcode):
        """
        create frame to send text, binary and other data.

        data: data to send. This is string value(byte array).
            if opcode is OPCODE_TEXT and this value is uniocde,
            data value is conveted into unicode string, automatically.

        opcode: operation code. please see OPCODE_XXX.
        """
        if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode):
            data = utils.tryEncode(data)
        # mask must be set if send data from client
        return ABNF(1, 0, 0, 0, opcode, 1, data)
Beispiel #34
0
 def _addtoPlaylist(self, dbid=None, mediatype=None, url=None):
     pl = {
         'jsonrpc': "2.0",
         'id': 1,
         'method': "Playlist.Add",
         'params': {
             'playlistid': self.playlistId
         }
     }
     if dbid is not None:
         pl['params']['item'] = {'%sid' % tryEncode(mediatype): int(dbid)}
     else:
         pl['params']['item'] = {'file': url}
     log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
Beispiel #35
0
 def getPlaylistsContextMenuItems(self, name, playlist_type):
     cm = []
     name = quote_plus(utils.tryEncode(name))
     cm.append(
         (self.lang(30304),
          "XBMC.RunPlugin(%s?action=update_playlists&playlist_type=%s)" %
          (utils.addon_url, playlist_type)))
     cm.append((self.lang(
         30306
     ), "XBMC.RunPlugin(%s?action=add_favourite&path=playlists&playlist_type=%s&title=%s)"
                % (utils.addon_url, playlist_type, name)))
     cm.append(
         (self.lang(30316),
          "XBMC.RunPlugin(%s?action=create_playlist)" % utils.addon_url))
     return cm
 def __repr__(self):
     """
     Print the playlist, e.g. to log
     """
     answ = '{\'%s\': {' % (self.__class__.__name__)
     # For some reason, can't use dir directly
     answ += '\'id\': %s, ' % self.id
     for key in self.__dict__:
         if key in ('id', 'items', 'kodi_pl'):
             continue
         if isinstance(getattr(self, key), (str, unicode)):
             answ += '\'%s\': \'%s\', ' % (key,
                                           tryEncode(getattr(self, key)))
         else:
             # e.g. int
             answ += '\'%s\': %s, ' % (key, str(getattr(self, key)))
     return answ + '\'items\': %s}}' % self.items
Beispiel #37
0
def _prep_playlist_stack(xml):
    stack = []
    for item in xml:
        api = API(item)
        if (state.CONTEXT_MENU_PLAY is False
                and api.getType() != v.PLEX_TYPE_CLIP):
            # If user chose to play via PMS or force transcode, do not
            # use the item path stored in the Kodi DB
            with plexdb.Get_Plex_DB() as plex_db:
                plex_dbitem = plex_db.getItem_byId(api.getRatingKey())
            kodi_id = plex_dbitem[0] if plex_dbitem else None
            kodi_type = plex_dbitem[4] if plex_dbitem else None
        else:
            # We will never store clips (trailers) in the Kodi DB
            kodi_id = None
            kodi_type = None
        for part, _ in enumerate(item[0]):
            api.setPartNumber(part)
            if kodi_id is None:
                # Need to redirect again to PKC to conclude playback
                params = {
                    'mode': 'play',
                    'plex_id': api.getRatingKey(),
                    'plex_type': api.getType()
                }
                path = ('plugin://plugin.video.plexkodiconnect?%s' %
                        urlencode(params))
                listitem = api.CreateListItemFromPlexItem()
                listitem.setPath(tryEncode(path))
            else:
                # Will add directly via the Kodi DB
                path = None
                listitem = None
            stack.append({
                'kodi_id': kodi_id,
                'kodi_type': kodi_type,
                'file': path,
                'xml_video_element': item,
                'listitem': listitem,
                'part': part,
                'playcount': api.getViewCount(),
                'offset': api.getResume(),
                'id': api.getItemId()
            })
    return stack
Beispiel #38
0
def add_to_Kodi_playlist(playlist, xml_video_element):
    """
    Adds a new item to the Kodi playlist via JSON (at the end of the playlist).
    Pass in the PMS xml's video element (one level underneath MediaContainer).

    Returns a Playlist_Item or None if it did not work
    """
    item = playlist_item_from_xml(playlist, xml_video_element)
    params = {'playlistid': playlist.playlistid}
    if item.kodi_id:
        params['item'] = {'%sid' % item.kodi_type: item.kodi_id}
    else:
        params['item'] = {'file': tryEncode(item.file)}
    reply = JSONRPC('Playlist.Add').execute(params)
    if reply.get('error') is not None:
        log.error('Could not add item %s to Kodi playlist. Error: %s' %
                  (xml_video_element, reply))
        return None
    else:
        return item
 def __repr__(self):
     """
     Print the playlist item, e.g. to log
     """
     answ = '{\'%s\': {' % (self.__class__.__name__)
     answ += '\'id\': \'%s\', ' % self.id
     answ += '\'plex_id\': \'%s\', ' % self.plex_id
     for key in self.__dict__:
         if key in ('id', 'plex_id', 'xml'):
             continue
         if isinstance(getattr(self, key), (str, unicode)):
             answ += '\'%s\': \'%s\', ' % (key,
                                           tryEncode(getattr(self, key)))
         else:
             # e.g. int
             answ += '\'%s\': %s, ' % (key, str(getattr(self, key)))
     if self.xml is None:
         answ += '\'xml\': None}}'
     else:
         answ += '\'xml\': \'%s\'}}' % self.xml.tag
     return answ
Beispiel #40
0
    def getListennow(self, items):
        listItems = []
        default_art = utils.addon.getAddonInfo('icon')

        for item in items:
            suggestion = item.get('suggestion_text')
            image = item['images'][0][
                'url'] if 'images' in item else default_art

            if item['type'] == '1':
                album = item['album']
                listItems.extend(
                    self.createAlbumFolder([{
                        'name':
                        album['title'] + ' (' + suggestion + ')',
                        'artist':
                        album['artist_name'],
                        'albumArtRef':
                        image,
                        'albumId':
                        album['id']['metajamCompactKey']
                    }]))

            elif item['type'] == '3':
                radio = item['radio_station']
                params = {
                    'path':
                    'create_station',
                    'name':
                    utils.tryEncode('Radio %s (%s)' %
                                    (radio['title'], suggestion))
                }
                params.update(self.getStationSeed(radio['id']['seeds'][0]))
                listItems.append(
                    self.createFolder(params['name'], params, arturl=image))

            else:
                utils.log("ERROR item type unknown " + repr(item['type']))

        return listItems
Beispiel #41
0
    def getSearch(self, query):
        listItems = []

        def listAlbumsResults():
            listItems.append(self.createFolder('[COLOR orange]*** '+self.lang(30206)+' ***[/COLOR]',{'path':'none'}))
            cm = []
            for album in result['albums']:
                params = {'path':"search_result",'query':utils.tryEncode(album[0])}
                if len(album) > 3:
                    cm = [(self.lang(30301), "XBMC.RunPlugin(%s?action=play_all&album_id=%s)" % (utils.addon_url, album[3]))]
                    params['albumid'] = album[3]
                listItems.append(self.createFolder("[%s] %s"%(album[1], album[0]), params, cm, album[2]))

        if isinstance(query,basestring):
            result = self.api.getSearch(query)
            if result['albums']: listAlbumsResults()
            if result['artists']:
                listItems.append(self.createFolder('[COLOR orange]*** '+self.lang(30205)+' ***[/COLOR]',{'path':'none'}))
                cm = []
                for artist in result['artists']:
                    params = {'path':"search_result",'query':utils.tryEncode(artist[0])}
                    if len(artist) > 2:
                        cm = [(self.lang(30301), "XBMC.RunPlugin(%s?action=play_all&artist_id=%s)" % (utils.addon_url, artist[2]))]
                        params['artistid'] = artist[2]
                    listItems.append(self.createFolder(artist[0], params, cm, artist[1]))
            if result['tracks']:
                listItems.append(self.createFolder('[COLOR orange]*** '+self.lang(30213)+' ***[/COLOR]',{'path':'none'}))
                listItems.extend(self.addSongsFromLibrary(result['tracks'], 'library'))
        elif 'artistid' in query:
            result = self.api.getSearch(unquote_plus(query['query']))
            if result['albums']: listAlbumsResults()
            listItems.append(self.createFolder('[COLOR orange]*** '+self.lang(30213)+' ***[/COLOR]',{'path':'none'}))
            listItems.extend(self.addSongsFromLibrary(self.api.getArtist(query['artistid']), 'library'))
        elif 'albumid' in query:
            listItems.extend(self.addSongsFromLibrary(self.api.getAlbum(query['albumid']), 'library'))
        else:
            #listItems.extend(self.addSongsFromLibrary(self.api.getSearch(unquote_plus(query['query']))['tracks'], 'library'))
            listItems.extend(self.getSearch(unquote_plus(query['query'])))
        return listItems
Beispiel #42
0
    def audioSubsPref(self, listitem, url, part=None):
        lang = utils.language
        dialog = xbmcgui.Dialog()
        # For transcoding only
        # Present the list of audio to select from
        audioStreamsList = []
        audioStreams = []
        # audioStreamsChannelsList = []
        subtitleStreamsList = []
        subtitleStreams = ['1 No subtitles']
        downloadableStreams = []
        # selectAudioIndex = ""
        selectSubsIndex = ""
        playurlprefs = {}

        # Set part where we're at
        self.API.setPartNumber(part)
        if part is None:
            part = 0
        try:
            mediastreams = self.item[0][part]
        except (TypeError, KeyError, IndexError):
            return url

        audioNum = 0
        # Remember 'no subtitles'
        subNum = 1
        for stream in mediastreams:
            # Since Emby returns all possible tracks together, have to sort them.
            index = stream.attrib.get('id')
            type = stream.attrib.get('streamType')

            # Audio
            if type == "2":
                codec = stream.attrib.get('codec')
                channelLayout = stream.attrib.get('audioChannelLayout', "")
               
                try:
                    track = "%s %s - %s %s" % (audioNum+1, stream.attrib['language'], codec, channelLayout)
                except:
                    track = "%s 'unknown' - %s %s" % (audioNum+1, codec, channelLayout)
                
                #audioStreamsChannelsList[audioNum] = stream.attrib['channels']
                audioStreamsList.append(index)
                audioStreams.append(utils.tryEncode(track))
                audioNum += 1

            # Subtitles
            elif type == "3":
                '''if stream['IsExternal']:
                    continue'''
                try:
                    track = "%s %s" % (subNum+1, stream.attrib['language'])
                except:
                    track = "%s 'unknown' (%s)" % (subNum+1, stream.attrib.get('codec'))

                default = stream.attrib.get('default')
                forced = stream.attrib.get('forced')
                downloadable = stream.attrib.get('key')

                if default:
                    track = "%s - Default" % track
                if forced:
                    track = "%s - Forced" % track
                if downloadable:
                    downloadableStreams.append(index)

                subtitleStreamsList.append(index)
                subtitleStreams.append(utils.tryEncode(track))
                subNum += 1

        if audioNum > 1:
            resp = dialog.select(lang(33013), audioStreams)
            if resp > -1:
                # User selected audio
                playurlprefs['audioStreamID'] = audioStreamsList[resp]
            else: # User backed out of selection - let PMS decide
                pass
        else: # There's only one audiotrack.
            playurlprefs['audioStreamID'] = audioStreamsList[0]

        # Add audio boost
        playurlprefs['audioBoost'] = utils.settings('audioBoost')

        if subNum > 1:
            resp = dialog.select(lang(33014), subtitleStreams)
            if resp == 0:
                # User selected no subtitles
                playurlprefs["skipSubtitles"] = 1
            elif resp > -1:
                # User selected subtitles
                selectSubsIndex = subtitleStreamsList[resp-1]

                # Load subtitles in the listitem if downloadable
                if selectSubsIndex in downloadableStreams:

                    url = "%s/library/streams/%s" \
                          % (self.server, selectSubsIndex)
                    url = self.API.addPlexHeadersToUrl(url)
                    self.logMsg("Downloadable sub: %s: %s" % (selectSubsIndex, url), 1)
                    listitem.setSubtitles([utils.tryEncode(url)])
                else:
                    self.logMsg('Need to burn in subtitle %s' % selectSubsIndex, 1)
                    playurlprefs["subtitleStreamID"] = selectSubsIndex
                    playurlprefs["subtitleSize"] = utils.settings('subtitleSize')

            else: # User backed out of selection
                pass

        # Tell the PMS what we want with a PUT request
        # url = self.server + '/library/parts/' + self.item[0][part].attrib['id']
        # PlexFunctions.SelectStreams(url, playurlprefs)
        url += '&' + urlencode(playurlprefs)

        # Get number of channels for selected audio track
        # audioChannels = audioStreamsChannelsList.get(selectAudioIndex, 0)
        # if audioChannels > 2:
        #     playurlprefs += "&AudioBitrate=384000"
        # else:
        #     playurlprefs += "&AudioBitrate=192000"

        return url
    def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False):
        # Plex: reassign mediatype due to Kodi inner workings
        # How many items do we get at most?
        limit = "100"
        mediatypes = {
            'movie': 'movies',
            'show': 'tvshows',
            'photo': 'photos',
            'homevideo': 'homevideos',
            'musicvideos': 'musicvideos'
        }
        mediatype = mediatypes[mediatype]

        if viewtype == "mixed":
            dirname = "%s-%s" % (viewid, mediatype)
        else:
            dirname = viewid
        
        path = tryDecode(xbmc.translatePath(
            "special://profile/library/video/"))
        nodepath = tryDecode(xbmc.translatePath(
            "special://profile/library/video/Plex-%s/" % dirname))

        # Verify the video directory
        # KODI BUG
        # Kodi caches the result of exists for directories
        #  so try creating a file
        if IfExists(path) is False:
            shutil.copytree(
                src=tryDecode(xbmc.translatePath(
                    "special://xbmc/system/library/video")),
                dst=tryDecode(xbmc.translatePath(
                    "special://profile/library/video")))

        # Create the node directory
        if mediatype != "photos":
            if IfExists(nodepath) is False:
                # folder does not exist yet
                log.debug('Creating folder %s' % nodepath)
                xbmcvfs.mkdirs(tryEncode(nodepath))
                if delete:
                    dirs, files = xbmcvfs.listdir(tryEncode(nodepath))
                    for file in files:
                        xbmcvfs.delete(tryEncode(
                            (nodepath + tryDecode(file))))

                log.info("Sucessfully removed videonode: %s." % tagname)
                return

        # Create index entry
        nodeXML = "%sindex.xml" % nodepath
        # Set windows property
        path = "library://video/Plex-%s/" % dirname
        for i in range(1, indexnumber):
            # Verify to make sure we don't create duplicates
            if window('Plex.nodes.%s.index' % i) == path:
                return

        if mediatype == "photos":
            path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=getsubfolders" % indexnumber
            
        window('Plex.nodes.%s.index' % indexnumber, value=path)
        
        # Root
        if not mediatype == "photos":
            if viewtype == "mixed":
                specialtag = "%s-%s" % (tagname, mediatype)
                root = self.commonRoot(order=0, label=specialtag, tagname=tagname, roottype=0)
            else:
                root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0)
            try:
                indent(root)
            except: pass
            etree.ElementTree(root).write(nodeXML)

        nodetypes = {

            '1': "all",
            '2': "recent",
            '3': "recentepisodes",
            '4': "inprogress",
            '5': "inprogressepisodes",
            '6': "unwatched",
            '7': "nextepisodes",
            '8': "sets",
            '9': "genres",
            '10': "random",
            '11': "recommended",
            '12': "ondeck"
        }
        mediatypes = {
            # label according to nodetype per mediatype
            'movies': 
                {
                '1': tagname,
                '2': 30174,
                # '4': 30177,
                # '6': 30189,
                '8': 39501,
                '9': 135,
                '10': 30227,
                '11': 30230,
                '12': 39500,
                },

            'tvshows': 
                {
                '1': tagname,
                # '2': 30170,
                '3': 30174,
                # '4': 30171,
                # '5': 30178,
                # '7': 30179,
                '9': 135,
                '10': 30227,
                # '11': 30230,
                '12': 39500,
                },
                
            'homevideos': 
                {
                '1': tagname,
                '2': 30251,
                '11': 30253
                },
                
            'photos': 
                {
                '1': tagname,
                '2': 30252,
                '8': 30255,
                '11': 30254
                },

            'musicvideos': 
                {
                '1': tagname,
                '2': 30256,
                '4': 30257,
                '6': 30258
                }
        }

        # Key: nodetypes, value: sort order in Kodi
        sortorder = {
            '1': '3',  # "all",
            '2': '2',  # "recent",
            '3': '2',  # "recentepisodes",
            # '4': # "inprogress",
            # '5': # "inprogressepisodes",
            # '6': # "unwatched",
            # '7': # "nextepisodes",
            '8': '7',  # "sets",
            '9': '6',  # "genres",
            '10': '8',  # "random",
            '11': '5',  # "recommended",
            '12': '1',  # "ondeck"
        }

        nodes = mediatypes[mediatype]
        for node in nodes:

            nodetype = nodetypes[node]
            nodeXML = "%s%s_%s.xml" % (nodepath, viewid, nodetype)
            # Get label
            stringid = nodes[node]
            if node != "1":
                label = lang(stringid)
                if not label:
                    label = xbmc.getLocalizedString(stringid)
            else:
                label = stringid

            # Set window properties
            if (mediatype == "homevideos" or mediatype == "photos") and nodetype == "all":
                # Custom query
                path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=browseplex&type=%s"
                        % (viewid, mediatype))
            elif (mediatype == "homevideos" or mediatype == "photos"):
                # Custom query
                path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=browseplex&type=%s&folderid=%s"
                        % (viewid, mediatype, nodetype))
            elif nodetype == "nextepisodes":
                # Custom query
                path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=nextup&limit=%s" % (tagname, limit)
            # elif kodiversion == 14 and nodetype == "recentepisodes":
            elif nodetype == "recentepisodes":
                # Custom query
                path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=recentepisodes&type=%s&tagname=%s&limit=%s"
                    % (viewid, mediatype, tagname, limit))
            elif self.kodiversion == 14 and nodetype == "inprogressepisodes":
                # Custom query
                path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=%s" % (tagname, limit)
            elif nodetype == 'ondeck':
                # PLEX custom query
                if mediatype == "tvshows":
                    path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=ondeck&type=%s&tagname=%s&limit=%s"
                        % (viewid, mediatype, tagname, limit))
                elif mediatype =="movies":
                    # Reset nodetype; we got the label
                    nodetype = 'inprogress'
            else:
                path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype)
            
            if mediatype == "photos":
                windowpath = "ActivateWindow(Pictures,%s,return)" % path
            else:
                if self.kodiversion >= 17:
                    # Krypton
                    windowpath = "ActivateWindow(Videos,%s,return)" % path
                else:
                    windowpath = "ActivateWindow(Video,%s,return)" % path
            
            if nodetype == "all":

                if viewtype == "mixed":
                    templabel = "%s-%s" % (tagname, mediatype)
                else:
                    templabel = label

                embynode = "Plex.nodes.%s" % indexnumber
                window('%s.title' % embynode, value=templabel)
                window('%s.path' % embynode, value=windowpath)
                window('%s.content' % embynode, value=path)
                window('%s.type' % embynode, value=mediatype)
            else:
                embynode = "Plex.nodes.%s.%s" % (indexnumber, nodetype)
                window('%s.title' % embynode, value=label)
                window('%s.path' % embynode, value=windowpath)
                window('%s.content' % embynode, value=path)

            if mediatype == "photos":
                # For photos, we do not create a node in videos but we do want the window props
                # to be created.
                # To do: add our photos nodes to kodi picture sources somehow
                continue
            
            if xbmcvfs.exists(tryEncode(nodeXML)):
                # Don't recreate xml if already exists
                continue

            # Create the root
            if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes') or mediatype == "homevideos"):
                # Folder type with plugin path
                root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname, roottype=2)
                etree.SubElement(root, 'path').text = path
                etree.SubElement(root, 'content').text = "episodes"
            else:
                root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname)
                if nodetype in ('recentepisodes', 'inprogressepisodes'):
                    etree.SubElement(root, 'content').text = "episodes"
                else:
                    etree.SubElement(root, 'content').text = mediatype

                # Elements per nodetype
                if nodetype == "all":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                
                elif nodetype == "recent":
                    etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"
                    etree.SubElement(root, 'limit').text = limit
                    if settings('MovieShowWatched') == 'false':
                        rule = etree.SubElement(root,
                                                'rule',
                                                {'field': "playcount",
                                                 'operator': "is"})
                        etree.SubElement(rule, 'value').text = "0"
                
                elif nodetype == "inprogress":
                    etree.SubElement(root, 'rule', {'field': "inprogress", 'operator': "true"})
                    etree.SubElement(root, 'limit').text = limit
                    etree.SubElement(
                        root,
                        'order',
                        {'direction': 'descending'}
                    ).text = 'lastplayed'

                elif nodetype == "genres":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                    etree.SubElement(root, 'group').text = "genres"
                
                elif nodetype == "unwatched":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                    rule = etree.SubElement(root, "rule", {'field': "playcount", 'operator': "is"})
                    etree.SubElement(rule, 'value').text = "0"

                elif nodetype == "sets":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                    etree.SubElement(root, 'group').text = "tags"

                elif nodetype == "random":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "random"
                    etree.SubElement(root, 'limit').text = limit

                elif nodetype == "recommended":
                    etree.SubElement(root, 'order', {'direction': "descending"}).text = "rating"
                    etree.SubElement(root, 'limit').text = limit
                    rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
                    etree.SubElement(rule, 'value').text = "0"
                    rule2 = etree.SubElement(root, 'rule',
                        attrib={'field': "rating", 'operator': "greaterthan"})
                    etree.SubElement(rule2, 'value').text = "7"

                elif nodetype == "recentepisodes":
                    # Kodi Isengard, Jarvis
                    etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"
                    etree.SubElement(root, 'limit').text = limit
                    rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
                    etree.SubElement(rule, 'value').text = "0"

                elif nodetype == "inprogressepisodes":
                    # Kodi Isengard, Jarvis
                    etree.SubElement(root, 'limit').text = limit
                    rule = etree.SubElement(root, 'rule',
                        attrib={'field': "inprogress", 'operator':"true"})

            try:
                indent(root)
            except: pass
            etree.ElementTree(root).write(nodeXML)
 def notify(self, text):
     xbmc.executebuiltin("XBMC.Notification(%s,%s,5000,%s)" % (utils.plugin, utils.tryEncode(text), self.icon))
Beispiel #45
0
        addon = utils.addon

        # if version changed clear cache
        if not addon.getSetting('version') or addon.getSetting('version') != addon.getAddonInfo('version'):
           storage.clearCache()
           login.clearCookie()
           addon.setSetting('version', addon.getAddonInfo('version'))

        # check for initing cookies, db and library only on main menu
        storage.checkDbInit()

        login.checkCredentials()
        login.checkCookie()
        login.initDevice()

        # check if library needs to be loaded
        if addon.getSetting('fetched_all_songs') == '0':

            xbmc.executebuiltin("XBMC.Notification(%s,%s,5000,%s)" % (utils.plugin, utils.tryEncode(addon.getLocalizedString(30105)) ,addon.getAddonInfo('icon')))
            utils.log('Loading library')
            navigation.api.loadLibrary()

            if addon.getSetting('auto_export')=='true' and addon.getSetting('export_path'):
                import GoogleMusicActions
                GoogleMusicActions.GoogleMusicActions().exportLibrary(addon.getSetting('export_path'))

        navigation.listMenu()

    else:
        utils.log(" ARGV Nothing done.. verify params " + repr(params))
Beispiel #46
0
 def cacheTexture(self, url):
     # Cache a single image url to the texture cache
     if url and self.enableTextureCache:
         self.queue.put(double_urlencode(tryEncode(url)))
Beispiel #47
0
    def fullTextureCacheSync(self):
        """
        This method will sync all Kodi artwork to textures13.db
        and cache them locally. This takes diskspace!
        """
        if not dialog('yesno', "Image Texture Cache", lang(39250)):
            return

        log.info("Doing Image Cache Sync")

        # ask to rest all existing or not
        if dialog('yesno', "Image Texture Cache", lang(39251)):
            log.info("Resetting all cache data first")
            # Remove all existing textures first
            path = tryDecode(translatePath("special://thumbnails/"))
            if IfExists(path):
                allDirs, allFiles = listdir(path)
                for dir in allDirs:
                    allDirs, allFiles = listdir(path+dir)
                    for file in allFiles:
                        if os_path.supports_unicode_filenames:
                            delete(os_path.join(
                                path + tryDecode(dir),
                                tryDecode(file)))
                        else:
                            delete(os_path.join(
                                tryEncode(path) + dir,
                                file))

            # remove all existing data from texture DB
            connection = kodiSQL('texture')
            cursor = connection.cursor()
            cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
            rows = cursor.fetchall()
            for row in rows:
                tableName = row[0]
                if tableName != "version":
                    cursor.execute("DELETE FROM " + tableName)
            connection.commit()
            connection.close()

        # Cache all entries in video DB
        connection = kodiSQL('video')
        cursor = connection.cursor()
        # dont include actors
        cursor.execute("SELECT url FROM art WHERE media_type != 'actor'")
        result = cursor.fetchall()
        total = len(result)
        log.info("Image cache sync about to process %s video images" % total)
        connection.close()

        for url in result:
            self.cacheTexture(url[0])
        # Cache all entries in music DB
        connection = kodiSQL('music')
        cursor = connection.cursor()
        cursor.execute("SELECT url FROM art")
        result = cursor.fetchall()
        total = len(result)
        log.info("Image cache sync about to process %s music images" % total)
        connection.close()
        for url in result:
            self.cacheTexture(url[0])
Beispiel #48
0
    def FullTextureCacheSync(self):
        # This method will sync all Kodi artwork to textures13.db
        # and cache them locally. This takes diskspace!
        import xbmcaddon
        string = xbmcaddon.Addon().getLocalizedString

        if not xbmcgui.Dialog().yesno(
                "Image Texture Cache", string(39250)):
            return

        self.logMsg("Doing Image Cache Sync", 1)

        dialog = xbmcgui.DialogProgress()
        dialog.create("Emby for Kodi", "Image Cache Sync")

        # ask to rest all existing or not
        if xbmcgui.Dialog().yesno(
                "Image Texture Cache", string(39251), ""):
            self.logMsg("Resetting all cache data first", 1)
            # Remove all existing textures first
            path = utils.tryDecode(xbmc.translatePath("special://thumbnails/"))
            if utils.IfExists(path):
                allDirs, allFiles = xbmcvfs.listdir(path)
                for dir in allDirs:
                    allDirs, allFiles = xbmcvfs.listdir(path+dir)
                    for file in allFiles:
                        if os.path.supports_unicode_filenames:
                            xbmcvfs.delete(os.path.join(
                                path + utils.tryDecode(dir),
                                utils.tryDecode(file)))
                        else:
                            xbmcvfs.delete(os.path.join(
                                utils.tryEncode(path) + dir,
                                file))

            # remove all existing data from texture DB
            textureconnection = utils.kodiSQL('texture')
            texturecursor = textureconnection.cursor()
            texturecursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
            rows = texturecursor.fetchall()
            for row in rows:
                tableName = row[0]
                if(tableName != "version"):
                    texturecursor.execute("DELETE FROM " + tableName)
            textureconnection.commit()
            texturecursor.close()

        # Cache all entries in video DB
        connection = utils.kodiSQL('video')
        cursor = connection.cursor()
        cursor.execute("SELECT url FROM art WHERE media_type != 'actor'") # dont include actors
        result = cursor.fetchall()
        total = len(result)
        count = 1
        percentage = 0
        self.logMsg("Image cache sync about to process " + str(total) + " images", 1)
        for url in result:
            if dialog.iscanceled():
                break
            percentage = int((float(count) / float(total))*100)
            textMessage = str(count) + " of " + str(total) + " (" + str(len(self.imageCacheThreads)) + ")"
            dialog.update(percentage, "Updating Image Cache: " + textMessage)
            self.CacheTexture(url[0])
            count += 1
        cursor.close()

        # Cache all entries in music DB
        connection = utils.kodiSQL('music')
        cursor = connection.cursor()
        cursor.execute("SELECT url FROM art")
        result = cursor.fetchall()
        total = len(result)
        count = 1
        percentage = 0
        self.logMsg("Image cache sync about to process " + str(total) + " images", 1)
        for url in result:
            if dialog.iscanceled():
                break
            percentage = int((float(count) / float(total))*100)
            textMessage = str(count) + " of " + str(total)
            dialog.update(percentage, "Updating Image Cache: " + textMessage)
            self.CacheTexture(url[0])
            count += 1
        cursor.close()

        dialog.update(100, "Waiting for all threads to exit: " + str(len(self.imageCacheThreads)))
        self.logMsg("Waiting for all threads to exit", 1)
        while len(self.imageCacheThreads) > 0:
            for thread in self.imageCacheThreads:
                if thread.isFinished:
                    self.imageCacheThreads.remove(thread)
            dialog.update(100, "Waiting for all threads to exit: " + str(len(self.imageCacheThreads)))
            self.logMsg("Waiting for all threads to exit: " + str(len(self.imageCacheThreads)), 1)
            xbmc.sleep(500)

        dialog.close()
Beispiel #49
0
    def single_urlencode(self, text):

        text = urllib.urlencode({'blahblahblah': utils.tryEncode(text)}) #urlencode needs a utf- string
        text = text[13:]

        return utils.tryDecode(text) #return the result again as unicode
    def audioSubsPref(self, listitem, url, part=None):
        dialog = xbmcgui.Dialog()
        # For transcoding only
        # Present the list of audio to select from
        audioStreamsList = []
        audioStreams = []
        # audioStreamsChannelsList = []
        subtitleStreamsList = []
        subtitleStreams = ['1 No subtitles']
        downloadableStreams = []
        # selectAudioIndex = ""
        selectSubsIndex = ""
        playurlprefs = {}

        # Set part where we're at
        self.API.setPartNumber(part)
        if part is None:
            part = 0
        try:
            mediastreams = self.item[0][part]
        except (TypeError, KeyError, IndexError):
            return url

        audioNum = 0
        # Remember 'no subtitles'
        subNum = 1
        defaultSub = None
        for stream in mediastreams:
            # Since Plex returns all possible tracks together, have to sort
            # them.
            index = stream.attrib.get('id')
            type = stream.attrib.get('streamType')

            # Audio
            if type == "2":
                codec = stream.attrib.get('codec')
                channelLayout = stream.attrib.get('audioChannelLayout', "")
               
                try:
                    track = "%s %s - %s %s" % (audioNum+1, stream.attrib['language'], codec, channelLayout)
                except:
                    track = "%s 'unknown' - %s %s" % (audioNum+1, codec, channelLayout)
                audioStreamsList.append(index)
                audioStreams.append(tryEncode(track))
                audioNum += 1

            # Subtitles
            elif type == "3":
                try:
                    track = "%s %s" % (subNum+1, stream.attrib['language'])
                except:
                    track = "%s 'unknown' (%s)" % (subNum+1, stream.attrib.get('codec'))

                default = stream.attrib.get('default')
                forced = stream.attrib.get('forced')
                downloadable = stream.attrib.get('key')

                if default:
                    track = "%s - Default" % track
                if forced:
                    track = "%s - Forced" % track
                if downloadable:
                    downloadableStreams.append(index)
                else:
                    track = "%s (burn-in)" % track
                if stream.attrib.get('selected') == '1' and downloadable:
                    # Only show subs without asking user if they can be
                    # turned off
                    defaultSub = index

                subtitleStreamsList.append(index)
                subtitleStreams.append(tryEncode(track))
                subNum += 1

        if audioNum > 1:
            resp = dialog.select(lang(33013), audioStreams)
            if resp > -1:
                # User selected audio
                playurlprefs['audioStreamID'] = audioStreamsList[resp]
            else: # User backed out of selection - let PMS decide
                pass
        else: # There's only one audiotrack.
            playurlprefs['audioStreamID'] = audioStreamsList[0]

        # Add audio boost
        playurlprefs['audioBoost'] = settings('audioBoost')

        selectSubsIndex = None
        if subNum > 1:
            if (settings('pickPlexSubtitles') == 'true' and
                    defaultSub is not None):
                log.info('Using default Plex subtitle: %s' % defaultSub)
                selectSubsIndex = defaultSub
            else:
                resp = dialog.select(lang(33014), subtitleStreams)
                if resp > 0:
                    selectSubsIndex = subtitleStreamsList[resp-1]
                else:
                    # User selected no subtitles or backed out of dialog
                    playurlprefs["skipSubtitles"] = 1
            if selectSubsIndex is not None:
                # Load subtitles in the listitem if downloadable
                if selectSubsIndex in downloadableStreams:
                    sub_url = self.API.addPlexHeadersToUrl(
                        "%s/library/streams/%s"
                        % (self.server, selectSubsIndex))
                    log.info("Downloadable sub: %s: %s"
                             % (selectSubsIndex, sub_url))
                    listitem.setSubtitles([tryEncode(sub_url)])
                    # Don't additionally burn in subtitles
                    playurlprefs["skipSubtitles"] = 1
                else:
                    log.info('Need to burn in subtitle %s' % selectSubsIndex)
                    playurlprefs["subtitleStreamID"] = selectSubsIndex
                    playurlprefs["subtitleSize"] = settings('subtitleSize')

        url += '&' + urlencode(playurlprefs)

        # Get number of channels for selected audio track
        # audioChannels = audioStreamsChannelsList.get(selectAudioIndex, 0)
        # if audioChannels > 2:
        #     playurlprefs += "&AudioBitrate=384000"
        # else:
        #     playurlprefs += "&AudioBitrate=192000"

        return url
    def play(self, itemid, dbid=None):

        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])

        self.logMsg("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):
                    self.logMsg('Could not download %s'
                        % item[0][0][0].attrib.get('key'), -1)
                    return xbmcplugin.setResolvedUrl(
                        int(sys.argv[1]), False, listitem)
                playurl = utils.tryEncode(xml[0].attrib.get('key'))
                window('emby_%s.playmethod' % playurl, value='DirectStream')

            playmethod = window('emby_%s.playmethod' % playurl)
            if playmethod == "Transcode":
                window('emby_%s.playmethod' % playurl, clear=True)
                playurl = utils.tryEncode(playutils.audioSubsPref(
                    listitem, utils.tryDecode(playurl)))
                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('plex_playbackProps') == "true"
        introsPlaylist = False
        dummyPlaylist = False

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

        ############### 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('plex_playbackProps', value="true")
            self.logMsg("Setting up properties in playlist.", 1)

            if (not homeScreen and not seektime and
                    window('plex_customplaylist') != "true"):
                self.logMsg("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
                self.logMsg("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)
                    self.logMsg("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.
                self.logMsg("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:
            self.logMsg("Resetting properties playback flag.", 2)
            window('plex_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 = utils.tryEncode(playutils.audioSubsPref(
                listitem, utils.tryDecode(playurl)))
            window('emby_%s.playmethod' % playurl, value="Transcode")

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

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

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

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

        else:
            self.logMsg("Play as a regular item.", 1)
            xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
    def PlayBackStart(self, data):
        """
        Called whenever a playback is started
        """
        log = self.logMsg
        window = utils.window
        # Get currently playing file - can take a while. Will be utf-8!
        try:
            currentFile = self.xbmcplayer.getPlayingFile()
        except:
            currentFile = None
            count = 0
            while currentFile is None:
                xbmc.sleep(100)
                try:
                    currentFile = self.xbmcplayer.getPlayingFile()
                except:
                    pass
                if count == 50:
                    log("No current File - Cancelling OnPlayBackStart...", -1)
                    return
                else:
                    count += 1
        # Just to be on the safe side
        currentFile = utils.tryDecode(currentFile)
        log("Currently playing file is: %s" % currentFile, 1)

        # Get the type of media we're playing
        try:
            typus = data['item']['type']
        except (TypeError, KeyError):
            log("Item is invalid for PMS playstate update.", 0)
            return
        log("Playing itemtype is (or appears to be): %s" % typus, 1)

        # Try to get a Kodi ID
        # If PKC was used - native paths, not direct paths
        plexid = utils.window('emby_%s.itemid'
                              % utils.tryEncode(currentFile))
        # Get rid of the '' if the window property was not set
        plexid = None if not plexid else plexid
        kodiid = None
        if plexid is None:
            log('Did not get Plex id from window properties', 1)
            try:
                kodiid = data['item']['id']
            except (TypeError, KeyError):
                log('Did not get a Kodi id from Kodi, darn', 1)
        # For direct paths, if we're not streaming something
        # When using Widgets, Kodi doesn't tell us shit so we need this hack
        if (kodiid is None and plexid is None and typus != 'song'
                and not currentFile.startswith('http')):
            try:
                filename = currentFile.rsplit('/', 1)[1]
                path = currentFile.rsplit('/', 1)[0] + '/'
            except IndexError:
                filename = currentFile.rsplit('\\', 1)[1]
                path = currentFile.rsplit('\\', 1)[0] + '\\'
            log('Trying to figure out playing item from filename: %s and '
                'path: %s' % (filename, path), 1)
            with kodidb.GetKodiDB('video') as kodi_db:
                try:
                    kodiid, typus = kodi_db.getIdFromFilename(filename, path)
                except TypeError:
                    log('Aborting playback report', 1)
                    return

        if plexid is None:
            # Get Plex' item id
            with embydb.GetEmbyDB() as emby_db:
                emby_dbitem = emby_db.getItem_byKodiId(kodiid, typus)
            try:
                plexid = emby_dbitem[0]
            except TypeError:
                log("No Plex id returned for kodiid %s" % kodiid, 1)
                log('Aborting playback report', 1)
                return
        log("Found Plex id %s for Kodi id %s for type %s"
            % (plexid, kodiid, typus), 1)

        # Set some stuff if Kodi initiated playback
        if ((utils.settings('useDirectPaths') == "1" and not typus == "song")
                or
                (typus == "song" and utils.settings('enableMusic') == "true")):
            if self.StartDirectPath(plexid,
                                    typus,
                                    utils.tryEncode(currentFile)) is False:
                log('Could not initiate monitoring; aborting', -1)
                return

        # Save currentFile for cleanup later and to be able to access refs
        window('plex_lastPlayedFiled', value=currentFile)
        window('Plex_currently_playing_itemid', value=plexid)
        window("emby_%s.itemid" % utils.tryEncode(currentFile), value=plexid)
        log('Finish playback startup', 1)
Beispiel #53
0
    def PlayBackStart(self, data):
        """
        Called whenever a playback is started
        """
        # Get currently playing file - can take a while. Will be utf-8!
        try:
            currentFile = self.xbmcplayer.getPlayingFile()
        except:
            currentFile = None
            count = 0
            while currentFile is None:
                sleep(100)
                try:
                    currentFile = self.xbmcplayer.getPlayingFile()
                except:
                    pass
                if count == 50:
                    log.info("No current File, cancel OnPlayBackStart...")
                    return
                else:
                    count += 1
        # Just to be on the safe side
        currentFile = tryDecode(currentFile)
        log.debug("Currently playing file is: %s" % currentFile)

        # Get the type of media we're playing
        try:
            typus = data['item']['type']
        except (TypeError, KeyError):
            log.info("Item is invalid for PMS playstate update.")
            return
        log.debug("Playing itemtype is (or appears to be): %s" % typus)

        # Try to get a Kodi ID
        # If PKC was used - native paths, not direct paths
        plexid = window('plex_%s.itemid' % tryEncode(currentFile))
        # Get rid of the '' if the window property was not set
        plexid = None if not plexid else plexid
        kodiid = None
        if plexid is None:
            log.debug('Did not get Plex id from window properties')
            try:
                kodiid = data['item']['id']
            except (TypeError, KeyError):
                log.debug('Did not get a Kodi id from Kodi, darn')
        # For direct paths, if we're not streaming something
        # When using Widgets, Kodi doesn't tell us shit so we need this hack
        if (kodiid is None and plexid is None and typus != 'song'
                and not currentFile.startswith('http')):
            (kodiid, typus) = get_kodiid_from_filename(currentFile)
            if kodiid is None:
                return

        if plexid is None:
            # Get Plex' item id
            with plexdb.Get_Plex_DB() as plexcursor:
                plex_dbitem = plexcursor.getItem_byKodiId(kodiid, typus)
            try:
                plexid = plex_dbitem[0]
            except TypeError:
                log.info("No Plex id returned for kodiid %s. Aborting playback"
                         " report" % kodiid)
                return
        log.debug("Found Plex id %s for Kodi id %s for type %s"
                  % (plexid, kodiid, typus))

        # Set some stuff if Kodi initiated playback
        if ((settings('useDirectPaths') == "1" and not typus == "song")
                or
                (typus == "song" and settings('enableMusic') == "true")):
            if self.StartDirectPath(plexid,
                                    typus,
                                    tryEncode(currentFile)) is False:
                log.error('Could not initiate monitoring; aborting')
                return

        # Save currentFile for cleanup later and to be able to access refs
        window('plex_lastPlayedFiled', value=currentFile)
        window('plex_currently_playing_itemid', value=plexid)
        window("plex_%s.itemid" % tryEncode(currentFile), value=plexid)
        log.info('Finish playback startup')
Beispiel #54
0
    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":
                window('plex_%s.playmethod' % playurl, clear=True)
                playurl = tryEncode(playutils.audioSubsPref(
                    listitem, tryDecode(playurl)))
                window('plex_%s.playmethod' % playurl, "Transcode")
            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?")
                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 window('useDirectPaths') == 'true':
                    # 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":
                        window('plex_%s.playmethod' % playurl,
                               clear=True)
                        playurl = tryEncode(playutils.audioSubsPref(
                            listitem, tryDecode(playurl)))
                        window('plex_%s.playmethod' % playurl,
                               value="Transcode")
                    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),
                        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):
            window('plex_%s.playmethod' % playurl, clear=True)
            playurl = tryEncode(playutils.audioSubsPref(
                listitem, tryDecode(playurl)))
            window('plex_%s.playmethod' % playurl, value="Transcode")

        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 _sanitizePath(self, name):
     name = "".join(i for i in name if i not in "\/:*?<>|,;$%\"\'.`")
     if len(name) > 50: name = name[:50]
     return utils.tryEncode(name).strip()