Exemple #1
0
    def canDirectPlay(self, item, choice):
        maxResolution = item.settings.getMaxResolution(item.getQualityType(), self.isSupported4k(choice.media, choice.videoStream))
        height = choice.media.getVideoResolution()
        if height > maxResolution:
            util.LOG("MDE: (DP) Video height is greater than max allowed: {0} > {1}".format(height, maxResolution))
            if height > 1088 and item.settings.getPreference("allow_4k", True):
                util.LOG("MDE: (DP) Unsupported 4k media")
            return False

        maxBitrate = item.settings.getMaxBitrate(item.getQualityType())
        bitrate = choice.media.bitrate.asInt()
        if bitrate > maxBitrate:
            util.LOG("MDE: (DP) Video bitrate is greater than the allowed max: {0} > {1}".format(bitrate, maxBitrate))
            return False

        if choice.videoStream is None:
            util.ERROR_LOG("MDE: (DP) No video stream")
            return True

        if not item.settings.getGlobal("supports1080p60"):
            videoFrameRate = choice.videoStream.asInt()
            if videoFrameRate > 30 and height >= 1080:
                util.LOG("MDE: (DP) Frame rate is not supported for resolution: {0}@{1}".format(height, videoFrameRate))
                return False

        if choice.videoStream.codec == "hevc" and not item.settings.getPreference("allow_hevc", False):
            util.LOG("MDE: (DP) Codec is HEVC, which is disabled")
            return False

        return True
Exemple #2
0
def dl_tvh():
    import kodijsonrpc

    try:
        if not os.path.isdir('/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend'):
            show_error("tvheadend not installed")
            return

        selectConnections()

        #Set before so live TV is working when we set it
        util.LOG('Setting pvrmanager.syncchannelgroups to true...')
        result = kodijsonrpc.rpc.Settings.SetSettingValue(setting='pvrmanager.syncchannelgroups', value=True)
        util.LOG('Result: {0}'.format(result))

        with util.ServiceControl('service.multimedia.tvheadend.service'):
            removeDir("/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend/channel")
            removeDir("/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend/input/dvb")
            tarFile = "/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend/BackUp.tar.gz"
            downloadWithProgress(TVH_URL, tarFile, 'Downloading channel fix...')
            extractTar(tarFile, "/")
            os.remove(tarFile)

        xbmc.executebuiltin('Reboot')
    except DownloadCanceledException:
        show_error('Canceled')
    except:
        util.ERROR()
        show_error("Error")
Exemple #3
0
    def __init__(self, media=None, partIndex=0):
        self.media = media
        self.part = None
        self.forceTranscode = False
        self.isDirectPlayable = False
        self.videoStream = None
        self.audioStream = None
        self.subtitleStream = None
        self.isSelected = False
        self.subtitleDecision = self.SUBTITLES_DEFAULT

        self.sorts = util.AttributeDict()

        if media:
            self.indirectHeaders = media.indirectHeaders
            self.part = media.parts[partIndex]
            if self.part:
                # We generally just rely on PMS to have told us selected streams, so
                # initialize our streams accordingly.

                self.videoStream = self.part.getSelectedStreamOfType(plexstream.PlexStream.TYPE_VIDEO)
                self.audioStream = self.part.getSelectedStreamOfType(plexstream.PlexStream.TYPE_AUDIO)
                self.subtitleStream = self.part.getSelectedStreamOfType(plexstream.PlexStream.TYPE_SUBTITLE)
            else:
                util.WARN_LOG("Media does not contain a valid part")

            util.LOG("Choice media: {0} part:{1}".format(media, partIndex))
            for streamType in ("videoStream", "audioStream", "subtitleStream"):
                attr = getattr(self, streamType)
                if attr:
                    util.LOG("Choice {0}: {1}".format(streamType, repr(attr)))
        else:
            util.WARN_LOG("Could not create media choice for invalid media")
Exemple #4
0
    def getServerDecision(self):
        directPlay = not (self.metadata and self.metadata.isTranscoded)
        decisionPath = self.getDecisionPath(directPlay)
        newDecision = None

        if decisionPath:
            server = self.metadata.transcodeServer or self.item.getServer()
            request = plexrequest.PlexRequest(server, decisionPath)
            response = request.getWithTimeout(10)

            if response.isSuccess() and response.container:
                decision = serverdecision.ServerDecision(self, response, self)

                if decision.isSuccess():
                    util.LOG("MDE: Server was happy with client's original decision. {0}".format(decision))
                elif decision.isDecision(True):
                    util.WARN_LOG("MDE: Server was unhappy with client's original decision. {0}".format(decision))
                    return decision.getDecision()
                else:
                    util.LOG("MDE: Server was unbiased about the decision. {0}".format(decision))

                # Check if the server has provided a new media item to use it. If
                # there is no item, then we'll continue along as if there was no
                # decision made.
                newDecision = decision.getDecision(False)
            else:
                util.WARN_LOG("MDE: Server failed to provide a decision")
        else:
            util.WARN_LOG("MDE: Server or item does not support decisions")

        return newDecision or self
Exemple #5
0
def findResourceByID(resources, ID):
    """ Searches server.clientIdentifier """
    util.LOG('Looking for server by ID: {0}'.format(ID))
    for server in resources:
        if ID == server.clientIdentifier:
            util.LOG('Server found by ID: {0}'.format(server))
            return server
    util.LOG('Unable to find server by ID: {0}'.format(ID))
    raise exceptions.NotFound('Unable to find server by ID: {0}'.format(ID))
Exemple #6
0
def findResource(resources, search, port=32400):
    """ Searches server.name """
    search = search.lower()
    util.LOG('Looking for server: {0}'.format(search))
    for server in resources:
        if search == server.name.lower():
            util.LOG('Server found: {0}'.format(server))
            return server
    util.LOG('Unable to find server: {0}'.format(search))
    raise exceptions.NotFound('Unable to find server: {0}'.format(search))
Exemple #7
0
def start():
    util.LOG('[- START -----------------------] [{0}]'.format(
        util.ADDON.getAddonInfo('version')))
    util.setGlobalProperty('guide.filter', '')
    util.setGlobalProperty('section', '')

    with util.Cron(interval=5):
        bw = windows.BackgroundWindow.create()
        connected = False
        ID = util.loadTabloDeviceID()
        if ID:
            tablo.API.discover()
            connected = tablo.API.selectDevice(ID)

        while True:
            if not connected:
                if connected is None:
                    w = windows.ConnectWindow.open(updating=True)
                    del w
                    connected = False
                    if ID:
                        tablo.API.discover()
                        connected = tablo.API.selectDevice(ID)
                    continue
                else:
                    w = windows.ConnectWindow.open()
                    if w.exit or not tablo.API.deviceSelected():
                        return
                    del w

            if tablo.API.getUpdateStatus():
                util.DEBUG_LOG('Updating ({0})'.format(tablo.API.device.name))
                connected = None
                continue

            windows.WM.start()

            if windows.WM.exit:
                break

            connected = False

        bw.show()
        bw.setProperty('busy', '1')

        backgroundthread.BGThreader.shutdown()

        bw.doClose()
        del bw

    util.LOG('[- END -------------------------]')
Exemple #8
0
 def logState(self):
     util.LOG("Authenticated as {0}:{1}".format(self.ID, repr(self.title)))
     util.LOG("SignedIn: {0}".format(self.isSignedIn))
     util.LOG("Offline: {0}".format(self.isOffline))
     util.LOG("Authenticated: {0}".format(self.isAuthenticated))
     util.LOG("PlexPass: {0}".format(self.isPlexPass))
     util.LOG("Managed: {0}".format(self.isManaged))
     util.LOG("Protected: {0}".format(self.isProtected))
     util.LOG("Admin: {0}".format(self.isAdmin))
     util.LOG("AdminPlexPass: {0}".format(self.adminHasPlexPass))
Exemple #9
0
    def checkSelectedServerSearch(self):
        if not self.selectedServer and self.searchContext:
            # If we're still waiting on the resources response then there's no
            # reason to settle, so don't even iterate over our servers.

            if self.searchContext.waitingForResources:
                util.DEBUG_LOG("Still waiting for plex.tv resources")
                return

            waitingForPreferred = False
            waitingForOwned = False
            waitingForAnything = False
            waitingToTestAll = bool(self.deferReachabilityTimer)

            # Iterate over all our servers and see if we're waiting on any results
            servers = self.getServers()
            pendingCount = 0
            for server in servers:
                if server.pendingReachabilityRequests > 0:
                    pendingCount = pendingCount + server.pendingReachabilityRequests
                    if server.uuid == self.searchContext.preferredServer:
                        waitingForPreferred = True
                    elif server.owned:
                        waitingForOwned = True
                    else:
                        waitingForAnything = True

            pendingString = "{0} pending reachability tests".format(
                pendingCount)

            if waitingForPreferred:
                util.LOG("Still waiting for preferred server: " +
                         pendingString)
            elif waitingForOwned and (not self.searchContext.bestServer or
                                      not self.searchContext.bestServer.owned):
                util.LOG("Still waiting for an owned server: " + pendingString)
            elif waitingForAnything and not self.searchContext.bestServer:
                util.LOG(
                    "Still waiting for any server: {0}".format(pendingString))
            elif waitingToTestAll:
                util.LOG(
                    "Preferred server not reachable, testing all servers now")
                self.updateReachability(True, False, False)
            else:
                # No hope for anything better, let's select what we found
                util.LOG("Settling for the best server we found")
                self.setSelectedServer(
                    self.searchContext.bestServer
                    or self.searchContext.fallbackServer, True)
Exemple #10
0
    def removeServer(self, server):
        del self.serversByUuid[server.uuid]

        self.trigger('remove:server')

        if server == self.selectedServer:
            util.LOG("The selected server went away")
            self.setSelectedServer(None, force=True)

        if server == self.transcodeServer:
            util.LOG("The selected transcode server went away")
            self.transcodeServer = None

        if server == self.channelServer:
            util.LOG("The selected channel server went away")
            self.channelServer = None
    def chooseMedia(self, item, forceUpdate=False):
        # If we've already evaluated this item, use our previous choice.
        if not forceUpdate and item.mediaChoice is not None and item.mediaChoice.media is not None and not item.mediaChoice.media.isIndirect(
        ):
            return item.mediaChoice

        # See if we're missing media/stream details for this item.
        if item.isLibraryItem() and item.isVideoItem() and len(
                item.media) > 0 and not item.media[0].hasStreams():
            # TODO(schuyler): Fetch the details
            util.WARN_LOG("Can't make media choice, missing details")

        # Take a first pass through the media items to create an array of candidates
        # that we'll evaluate more completely. If we find a forced item, we use it.
        # If we find an indirect, we only keep a single candidate.
        indirect = False
        candidates = []
        maxResolution = item.settings.getMaxResolution(item.getQualityType())
        for mediaIndex in range(len(item.media)):
            media = item.media[mediaIndex]
            media.mediaIndex = mediaIndex
            if media.isSelected():
                candidates = []
                candidates.append(media)
                break
            if media.isIndirect():
                # Only add indirect media if the resolution fits. We cannot
                # exit early as the user may have selected media.

                indirect = True
                if media.getVideoResolution() <= maxResolution:
                    candidates.append(media)

            elif media.isAccessible():
                # Only consider testing available media
                candidates.append(media)

        # Only use the first indirect media item
        if indirect and candidates:
            candidates = candidates[0]

        # Make sure we have at least one valid item, regardless of availability
        if len(candidates) == 0:
            candidates.append(item.media[0])

        # Now that we have an array of candidates, evaluate them completely.
        choices = []
        for media in candidates:
            choice = None
            if media is not None:
                if item.isVideoItem():
                    choice = self.evaluateMediaVideo(item, media)
                elif item.isMusicItem():
                    choice = self.evaluateMediaMusic(item, media)
                else:
                    choice = mediachoice.MediaChoice(media)
                choices.append(choice)
        item.mediaChoice = self.sortChoices(choices)[-1]
        util.LOG("MDE: MediaChoice: {0}".format(item.mediaChoice))
        return item.mediaChoice
def getItemsFromString(dstring):
    try:
        data = json.loads(dstring)
        return [Item.fromDict(ddict) for ddict in data['items']]
    except ValueError:
        if dstring and dstring.startswith('{'):
            util.LOG(repr(dstring[:100]))
            util.ERROR()
        else:
            try:
                return getItemsFromXMLString(dstring)
            except:
                util.LOG(repr(dstring[:100]))
                util.ERROR()

    return None
Exemple #13
0
 def rebuild(self, item, decision=None):
     # item.settings = self.item.settings
     oldChoice = self.choice
     self.init(item, True)
     util.LOG("Replacing '{0}' with '{1}' and rebuilding.".format(oldChoice, self.choice))
     self.build()
     self.decision = decision
Exemple #14
0
    def setSelectedServer(self, server, force=False):
        # Don't do anything if the server is already selected.
        if self.selectedServer and self.selectedServer == server:
            return False

        if server:
            # Don't select servers that don't have connections.
            if not server.activeConnection:
                return False

            # Don't select servers that are not supported
            if not server.isSupported:
                return False

        if not self.selectedServer or force:
            util.LOG("Setting selected server to {0}".format(server))
            self.selectedServer = server

            # Update our saved state.
            self.saveState()

            # Notify anyone who might care.
            plexapp.APP.trigger("change:selectedServer", server=server)

            return True

        return False
Exemple #15
0
    def updateHomeUsers(self):
        # Ignore request and clear any home users we are not signed in
        if not self.isSignedIn:
            self.homeUsers = []
            if self.isOffline:
                self.homeUsers.append(MyPlexAccount())

            self.lastHomeUserUpdate = None
            return

        # Cache home users for 60 seconds, mainly to stop back to back tests
        epoch = time.time()
        if not self.lastHomeUserUpdate:
            self.lastHomeUserUpdate = epoch
        elif self.lastHomeUserUpdate + 60 > epoch:
            util.DEBUG_LOG(
                "Skipping home user update (updated {0} seconds ago)".format(
                    epoch - self.lastHomeUserUpdate))
            return

        req = myplexrequest.MyPlexRequest("/api/home/users")
        xml = req.getToStringWithTimeout()
        data = ElementTree.fromstring(xml)
        if data.attrib.get('size') and data.find('User') is not None:
            self.homeUsers = []
            for user in data.findall('User'):
                homeUser = HomeUser(user.attrib)
                homeUser.isAdmin = homeUser.admin == "1"
                homeUser.isManaged = homeUser.restricted == "1"
                homeUser.isProtected = homeUser.protected == "1"
                self.homeUsers.append(homeUser)

            self.lastHomeUserUpdate = epoch

        util.LOG("home users: {0}".format(self.homeUsers))
Exemple #16
0
    def updateReachability(self, force=True, allowFallback=False):
        if not force and self.activeConnection and self.activeConnection.state != plexresource.ResourceConnection.STATE_UNKNOWN:
            return

        util.LOG('Updating reachability for {0}: conns={1}, allowFallback={2}'.
                 format(repr(self.name), len(self.connections), allowFallback))

        epoch = time.time()
        retrySeconds = 60
        minSeconds = 10
        for i in range(len(self.connections)):
            conn = self.connections[i]
            diff = epoch - (conn.lastTestedAt or 0)
            if conn.hasPendingRequest:
                util.DEBUG_LOG(
                    "Skip reachability test for {0} (has pending request)".
                    format(conn))
            elif diff < minSeconds or (not self.isSecondary()
                                       and self.isReachable()
                                       and diff < retrySeconds):
                util.DEBUG_LOG(
                    "Skip reachability test for {0} (checked {1} secs ago)".
                    format(conn, diff))
            elif conn.testReachability(self, allowFallback):
                self.pendingReachabilityRequests += 1
                if conn.isSecure:
                    self.pendingSecureRequests += 1

                if self.pendingReachabilityRequests == 1:
                    self.trigger("started:reachability")

        if self.pendingReachabilityRequests <= 0:
            self.trigger("completed:reachability")
Exemple #17
0
    def query(self, path, method=None, **kwargs):
        method = method or self.session.get
        url = self.buildUrl(path, includeToken=True)
        # If URL is empty, try refresh resources and return empty set for now
        if not url:
            util.WARN_LOG(
                "Empty server url, returning None and refreshing resources")
            plexapp.refreshResources(True)
            return None
        util.LOG('{0} {1}'.format(
            method.__name__.upper(),
            re.sub('X-Plex-Token=[^&]+', 'X-Plex-Token=****', url)))
        try:
            response = method(url, **kwargs)
            if response.status_code not in (200, 201):
                codename = http.status_codes.get(response.status_code,
                                                 ['Unknown'])[0]
                raise exceptions.BadRequest('({0}) {1}'.format(
                    response.status_code, codename))
            data = response.text.encode('utf8')
        except asyncadapter.TimeoutException:
            util.ERROR()
            plexapp.refreshResources(True)
            return None
        except http.requests.ConnectionError:
            util.ERROR()
            return None

        return ElementTree.fromstring(data) if data else None
    def deleteRule(self, ep=None):
        if not self.rule and not ep:
            util.LOG('RecordDialog.deleteRule(): No rule to modify')
            return

        if self.parent:
            if ep:
                self.parent.deleteRule(self.series, ep=ep)
            else:
                self.parent.deleteRule(self.rule)
        else:
            if ep:
                self.storageServer.deleteRule(self.series, ep=ep)
            else:
                self.storageServer.deleteRule(self.rule)
                self.series['RecordingRule'] = 0

        if not ep:
            self.setProperty('show.hasRule', '')
            self.fillEpisodeList()

        self.series['RecordingRule'] = any([e.hasRule for e in self.episodes])
        self.showHideButton()

        if self.dialogSource == 'RULES':
            self.doClose()
Exemple #19
0
    def refreshManualConnections(self):
        manualConnections = self.getManualConnections()
        if not manualConnections:
            return

        util.LOG("Refreshing {0} manual connections".format(
            len(manualConnections)))

        for conn in manualConnections:
            # Default to http, as the server will need to be signed in for https to work,
            # so the client should too. We'd also have to allow hostname entry, instead of
            # IP address for the cert to validate.

            proto = "http"
            port = conn.port or "32400"
            serverAddress = "{0}://{1}:{2}".format(proto, conn.connection,
                                                   port)

            request = http.HttpRequest(serverAddress + "/identity")
            context = request.createRequestContext(
                "manual_connections",
                callback.Callable(self.onManualConnectionsResponse))
            context.serverAddress = serverAddress
            context.address = conn.connection
            context.proto = proto
            context.port = port
            context.timeout = 10000
            plexapp.APP.startRequest(request, context)
Exemple #20
0
def dl_restore():
    try:
        if not os.path.exists("/storage/backup"):
            os.makedirs("/storage/backup")

        SettingsBackup.backupAll()

        if not backupFreeSpace() >= 500:
            util.LOG('DELETING RECORDINGS')
            deleteRecordings()

        downloadWithProgress(RESTORE_URL, BACKUP_PATH,
                             'Downloading restore file...')
        # meheh. not an error
        show_error("Downloaded. Click OK to restore.")
        restore()
        return
    except DownloadCanceledException:
        show_error('Canceled')
    except:
        util.ERROR()
        show_error("Error")

    #We only get here on error
    if os.path.exists(BACKUP_PATH):
        os.remove(BACKUP_PATH)
    if os.path.exists(oscamBackupFile):
        os.remove(oscamBackupFile)
Exemple #21
0
    def getTranscodeServer(self, transcodeType=None):
        if not self.selectedServer:
            return None

        transcodeMap = {
            'audio': "supportsAudioTranscoding",
            'video': "supportsVideoTranscoding",
            'photo': "supportsPhotoTranscoding"
        }
        transcodeSupport = transcodeMap[transcodeType]

        # Try to use a better transcoding server for synced or secondary servers
        if self.selectedServer.synced or self.selectedServer.isSecondary():
            if self.transcodeServer and self.transcodeServer.isReachable():
                return self.transcodeServer

            self.transcodeServer = None
            for server in self.getServers():
                if not server.synced and server.isReachable(
                ) and self.compareServers(self.transcodeServer, server) < 0:
                    if not transcodeSupport or server.transcodeSupport:
                        self.transcodeServer = server

            if self.transcodeServer:
                transcodeTypeString = transcodeType or ''
                util.LOG(
                    "Found a better {0} transcode server than {1}, using: {2}".
                    format(transcodeTypeString, self.selectedserver,
                           self.transcodeServer))
                return self.transcodeServer

        return self.selectedServer
Exemple #22
0
    def getPostWithTimeout(self, seconds=10, body=None):
        if self._cancel:
            return

        self.logRequest(body, seconds, False)
        try:
            if self.method == 'PUT':
                res = self.session.put(self.url, timeout=seconds, stream=True)
            elif self.method == 'DELETE':
                res = self.session.delete(self.url,
                                          timeout=seconds,
                                          stream=True)
            elif self.method == 'HEAD':
                res = self.session.head(self.url, timeout=seconds, stream=True)
            elif self.method == 'POST' or body is not None:
                res = self.session.post(self.url,
                                        data=body,
                                        timeout=seconds,
                                        stream=True)
            else:
                res = self.session.get(self.url, timeout=seconds, stream=True)

            self.currentResponse = res

            if self._cancel:
                return None

            util.LOG("Got a {0} from {1}".format(res.status_code,
                                                 util.cleanToken(self.url)))
            # self.event = msg
            return res
        except Exception, e:
            util.WARN_LOG(
                "Request to {0} errored out after {1} ms: {2}".format(
                    self.url, seconds, e.message))
    def testReachability(self, server, allowFallback=False):
        # Check if we will allow the connection test. If this is a fallback connection,
        # then we will defer it until we "allowFallback" (test insecure connections
        # after secure tests have completed and failed). Insecure connections will be
        # tested if the policy "always" allows them, or if set to "same_network" and
        # the current connection is local and server has (publicAddressMatches=1).

        allowConnectionTest = not self.isFallback
        if not allowConnectionTest:
            insecurePolicy = plexapp.INTERFACE.getPreference("allow_insecure")
            if insecurePolicy == "always" or (insecurePolicy == "same_network"
                                              and server.sameNetwork
                                              and self.isLocal):
                allowConnectionTest = allowFallback
                server.hasFallback = not allowConnectionTest
                util.LOG('{0} for {1}'.format(
                    allowConnectionTest
                    and "Continuing with insecure connection testing"
                    or "Insecure connection testing is deferred", server))
            else:
                util.LOG(
                    "Insecure connections not allowed. Ignore insecure connection test for {0}"
                    .format(server))
                self.state = self.STATE_INSECURE
                callable = callback.Callable(server.onReachabilityResult,
                                             [self], random.randint(0, 256))
                callable.deferCall()
                return True

        if allowConnectionTest:
            if not self.isSecure and (
                    not allowFallback and server.hasSecureConnections()
                    or server.activeConnection
                    and server.activeConnection.state != self.STATE_REACHABLE
                    and server.activeConnection.isSecure):
                util.DEBUG_LOG("Invalid insecure connection test in progress")
            self.request = http.HttpRequest(self.buildUrl(server, "/"))
            context = self.request.createRequestContext(
                "reachability", callback.Callable(self.onReachabilityResponse))
            context.server = server
            context.timeout = 10000
            util.addPlexHeaders(self.request, server.getToken())
            self.hasPendingRequest = plexapp.APP.startRequest(
                self.request, context)
            return True

        return False
Exemple #24
0
    def collectDataFromRoot(self, data):
        # Make sure we're processing data for our server, and not some other
        # server that happened to be at the same IP.
        if self.uuid != data.attrib.get('machineIdentifier'):
            util.LOG(
                "Got a reachability response, but from a different server")
            return False

        self.serverClass = data.attrib.get('serverClass')
        self.supportsAudioTranscoding = data.attrib.get(
            'transcoderAudio') == '1'
        self.supportsVideoTranscoding = data.attrib.get(
            'transcoderVideo') == '1' or data.attrib.get(
                'transcoderVideoQualities')
        self.supportsVideoRemuxOnly = data.attrib.get(
            'transcoderVideoRemuxOnly') == '1'
        self.supportsPhotoTranscoding = data.attrib.get(
            'transcoderPhoto') == '1' or (
                not data.attrib.get('transcoderPhoto') and not self.synced
                and not self.isSecondary())
        self.allowChannelAccess = data.attrib.get(
            'allowChannelAccess') == '1' or (
                not data.attrib.get('allowChannelAccess') and self.owned
                and not self.synced and not self.isSecondary())
        self.supportsScrobble = not self.isSecondary() or self.synced
        self.allowsMediaDeletion = not self.synced and self.owned and data.attrib.get(
            'allowMediaDeletion') == '1'
        self.multiuser = data.attrib.get('multiuser') == '1'
        self.name = data.attrib.get('friendlyName') or self.name
        self.platform = data.attrib.get('platform')

        # TODO(schuyler): Process transcoder qualities

        self.rawVersion = data.attrib.get('version')
        if self.rawVersion:
            self.versionNorm = util.normalizedVersion(self.rawVersion)

        features = {
            'mkvTranscode': '0.9.11.11',
            'themeTranscode': '0.9.14.0',
            'allPartsStreamSelection': '0.9.12.5',
            'claimServer': '0.9.14.2',
            'streamingBrain': '1.2.0'
        }

        for f, v in features.items():
            if verlib.suggest_normalized_version(v) <= self.versionNorm:
                self.features[f] = True

        appMinVer = plexapp.INTERFACE.getGlobal('minServerVersionArr',
                                                '0.0.0.0')
        self.isSupported = self.isSecondary(
        ) or verlib.suggest_normalized_version(appMinVer) <= self.versionNorm

        util.DEBUG_LOG(
            "Server information updated from reachability check: {0}".format(
                self))

        return True
def fetchResources(token):
    headers = util.BASE_HEADERS.copy()
    headers['X-Plex-Token'] = token
    util.LOG('GET {0}?X-Plex-Token={1}'.format(RESOURCES, util.hideToken(token)))
    response = http.GET(RESOURCES)
    data = ElementTree.fromstring(response.text.encode('utf8'))
    import plexserver
    return [plexserver.PlexServer(elem) for elem in data]
    def evaluateMediaMusic(self, item, media):
        # Resolve indirects before doing anything else.
        if media.isIndirect():
            util.LOG("Resolve indirect media for {0}".format(item))
            media = media.resolveIndirect()

        choice = mediachoice.MediaChoice(media)
        if media is None:
            return choice

        # Verify the server supports audio transcoding, otherwise force direct play
        if not item.getServer().supportsAudioTranscoding:
            util.LOG(
                "MDE: force direct play because the server does not support audio transcoding"
            )
            choice.isDirectPlayable = True
            return choice

        # See if this part has a server decision to transcode and obey it
        if choice.part and choice.part.get(
                "decision", serverdecision.ServerDecision.DECISION_DIRECT_PLAY
        ) != serverdecision.ServerDecision.DECISION_DIRECT_PLAY:
            util.WARN_LOG("MDE: Server has decided this cannot direct play")
            return choice

        # Verify the codec and container are compatible
        codec = media.audioCodec
        container = media.get('container')
        canPlayCodec = item.settings.supportsAudioStream(
            codec, media.audioChannels.asInt())
        canPlayContainer = (
            codec == container) or True  # (container in ("mp4", "mka", "mkv"))

        choice.isDirectPlayable = (canPlayCodec and canPlayContainer)
        if choice.isDirectPlayable:
            # Inspect the audio stream attributes if the codec/container can direct
            # play. For now we only need to verify the sample rate.

            if choice.audioStream is not None and choice.audioStream.samplingRate.asInt(
            ) >= 192000:
                util.LOG("MDE: sampling rate is not compatible")
                choice.isDirectPlayable = False
        else:
            util.LOG("MDE: container or codec is incompatible")

        return choice
Exemple #27
0
    def __getattr__(self, attr):
        a = PlexValue('', self)
        a.NA = True

        try:
            setattr(self, attr, a)
        except AttributeError:
            util.LOG('Failed to set attribute: {0} ({1})'.format(attr, self.__class__))

        return a
Exemple #28
0
def updateCore(force=False):
    if not force: return
    import xbmc
    import os, urllib, urllib2
    import tarfile

    util.LOG('Checking for new youtube_dl core version...')

    currentVersion = util.getSetting('core_version')
    try:
        newVersion = urllib2.urlopen(VERSION_URL).read().strip()
        if currentVersion == newVersion:
            util.LOG('Core version up to date')
            return False
    except:
        util.ERROR()
        return False

    util.LOG('Updating youtube_dl core to new version: {0}'.format(newVersion))

    profile = xbmc.translatePath(
        util.ADDON.getAddonInfo('profile')).decode('utf-8')
    archivePath = os.path.join(profile, 'youtube_dl.tar.gz')
    extractedPath = os.path.join(profile, 'youtube-dl')

    try:
        if os.path.exists(extractedPath):
            import shutil
            shutil.rmtree(extractedPath, ignore_errors=True)
            util.LOG('Old version removed')

        urllib.urlretrieve(LATEST_URL, filename=archivePath)
        with tarfile.open(archivePath, mode='r:gz') as tf:
            members = [
                m for m in tf.getmembers()
                if m.name.startswith('youtube-dl/youtube_dl')
            ]  #get just the files from the youtube_dl source directory
            tf.extractall(path=profile, members=members)
    except:
        util.ERROR('Core update FAILED')

    util.LOG('Core update complete')
    return True
Exemple #29
0
    def discoveryFinished(self, *args, **kwargs):
        # Time's up, report whatever we found
        self.close()

        if self.servers:
            util.LOG("Finished GDM discovery, found {0} server(s)".format(
                len(self.servers)))
            import plexapp
            plexapp.SERVERMANAGER.updateFromConnectionType(
                self.servers, plexconnection.PlexConnection.SOURCE_DISCOVERED)
            self.servers = None
Exemple #30
0
def migrateDB(DB, version):
    util.LOG('Migrating database from version {0} to {1}'.format(
        version, DATABASE_VERSION))
    from peewee.playhouse import migrate
    migrator = migrate.SqliteMigrator(DB)
    migratorW = migrate.SqliteMigrator(W_DB)

    if version < 1:
        try:
            migrate.migrate(
                migrator.add_column('RatingsBumpers', 'style',
                                    peewee.CharField(default='Classic')))
        except peewee.OperationalError:
            util.MINOR_ERROR('Migration (RatingsBumpers: Add style column)')
        except:
            util.ERROR()
            return False

    if version < 2:
        try:
            migrate.migrate(
                migrator.add_column('RatingSystem', 'regions',
                                    peewee.CharField(null=True)),
                migrator.drop_not_null('RatingSystem', 'context'),
            )
        except peewee.OperationalError:
            util.MINOR_ERROR('Migration (RatingSystem: Add region column)')
        except:
            util.ERROR()
            return False

    if version < 5:
        try:
            migrate.migrate(
                migratorW.add_column('Trailers', 'is3D',
                                     peewee.BooleanField(default=False)), )
        except peewee.OperationalError:
            util.MINOR_ERROR('Migration (Trailers: Add is3D column)')
        except:
            util.ERROR()
            return False

    if version < 6:
        try:
            migrate.migrate(
                migratorW.add_column('Trailers', 'verified',
                                     peewee.BooleanField(default=True)), )
        except peewee.OperationalError:
            util.MINOR_ERROR('Migration (Trailers: Add verified column)')
        except:
            util.ERROR()
            return False

    return True