Esempio n. 1
0
    def soap__generic(self, *args, **kwargs):
        """ generic UPnP service control method,
            which will be used if no soap_ACTIONNAME method
            in the server service control class can be found
        """
        try:
            action = self.actions[kwargs['soap_methodName']]
        except:
            return failure.Failure(errorCode(401))

        try:
            instance = int(kwargs['InstanceID'])
        except:
            instance = 0

        self.info("soap__generic", action, __name__, kwargs)
        del kwargs['soap_methodName']
        if( kwargs.has_key('X_UPnPClient') and
                kwargs['X_UPnPClient'] == 'XBox'):
            if(action.name == 'Browse' and
                    kwargs.has_key('ContainerID')):
                """ XXX: THIS IS SICK """
                kwargs['ObjectID'] = kwargs['ContainerID']
                del kwargs['ContainerID']

        in_arguments = action.get_in_arguments()
        for arg_name, arg in kwargs.iteritems():
            if arg_name.find('X_') == 0:
                continue
            l = [ a for a in in_arguments if arg_name == a.get_name()]
            if len(l) > 0:
                in_arguments.remove(l[0])
            else:
                self.critical('argument %s not valid for action %s' % (arg_name,action.name))
                return failure.Failure(errorCode(402))
        if len(in_arguments) > 0:
            self.critical('argument %s missing for action %s' %
                                ([ a.get_name() for a in in_arguments],action.name))
            return failure.Failure(errorCode(402))

        def callit( *args, **kwargs):
            #print 'callit args', args
            #print 'callit kwargs', kwargs
            result = {}
            callback = action.get_callback()
            if callback != None:
                return callback( **kwargs)
            return result

        def got_error(x):
            #print 'failure', x
            self.info('soap__generic error during call processing')
            return x

        # call plugin method for this action
        d = defer.maybeDeferred( callit, *args, **kwargs)
        d.addCallback( self.get_action_results, action, instance)
        d.addErrback(got_error)
        return d
    def upnp_PrepareForConnection(self, *args, **kwargs):
        self.info('upnp_PrepareForConnection')
        """ check if we really support that mimetype """
        RemoteProtocolInfo = kwargs['RemoteProtocolInfo']
        """ if we are a MR and this in not 'Input'
            then there is something strange going on
        """
        Direction = kwargs['Direction']
        if( self.device.device_type == 'MediaRenderer' and
            Direction == 'Output'):
            return failure.Failure(errorCode(702))
        if( self.device.device_type == 'MediaServer' and
            Direction != 'Input'):
            return failure.Failure(errorCode(702))
        """ the InstanceID of the MS ? """
        PeerConnectionID = kwargs['PeerConnectionID']
        """ ??? """
        PeerConnectionManager = kwargs['PeerConnectionManager']
        local_protocol_infos = None
        if self.device.device_type == 'MediaRenderer':
            local_protocol_infos = self.get_variable('SinkProtocolInfo').value
        if self.device.device_type == 'MediaServer':
            local_protocol_infos = self.get_variable('SourceProtocolInfo').value
        self.debug('ProtocalInfos:',RemoteProtocolInfo, '--', local_protocol_infos)

        try:
            remote_protocol,remote_network,remote_content_format,_ = RemoteProtocolInfo.split(':')
        except:
            self.warning("unable to process RemoteProtocolInfo", RemoteProtocolInfo)
            return failure.Failure(errorCode(701))

        for protocol_info in local_protocol_infos.split(','):
            #print remote_protocol,remote_network,remote_content_format
            #print protocol_info
            local_protocol,local_network,local_content_format,_ = protocol_info.split(':')
            #print local_protocol,local_network,local_content_format
            if((remote_protocol == local_protocol or
                remote_protocol == '*' or
                local_protocol == '*') and
               (remote_network == local_network or
                remote_network == '*' or
                local_network == '*') and
               (remote_content_format == local_content_format or
                remote_content_format == '*' or
                local_content_format == '*')):

                connection_id, avt_id, rcs_id = \
                    self.add_connection(RemoteProtocolInfo,
                                        Direction,
                                        PeerConnectionID,
                                        PeerConnectionManager)
                return {'ConnectionID': connection_id, 'AVTransportID': avt_id, 'RcsID': rcs_id}

        return failure.Failure(errorCode(701))
    def upnp_GetCurrentConnectionInfo(self, *args, **kwargs):
        ConnectionID = int(kwargs['ConnectionID'])
        """ return for this ConnectionID
            the associated InstanceIDs @ AVTransportID and RcsID
            ProtocolInfo
            PeerConnectionManager
            PeerConnectionID
            Direction
            Status

            or send a 706 if there isn't such a ConnectionID
        """
        connection = self.lookup_connection(ConnectionID)
        if connection == None:
            return failure.Failure(errorCode(706))
        else:
            return {'AVTransportID':connection['AVTransportID'],
                    'RcsID':connection['RcsID'],
                    'ProtocolInfo':connection['ProtocolInfo'],
                    'PeerConnectionManager':connection['PeerConnectionManager'],
                    'PeerConnectionID':connection['PeerConnectionID'],
                    'Direction':connection['Direction'],
                    'Status':connection['Status'],
                    }
    def upnp_Browse(self, *args, **kwargs):
        try:
            ObjectID = kwargs['ObjectID']
        except:
            self.debug("hmm, a Browse action and no ObjectID argument? An XBox maybe?")
            try:
                ObjectID = kwargs['ContainerID']
            except:
                ObjectID = 0
        BrowseFlag = kwargs['BrowseFlag']
        Filter = kwargs['Filter']
        StartingIndex = int(kwargs['StartingIndex'])
        RequestedCount = int(kwargs['RequestedCount'])
        SortCriteria = kwargs['SortCriteria']
        parent_container = None
        requested_id = None

        item = None
        total = 0
        items = []


        if BrowseFlag == 'BrowseDirectChildren':
            parent_container = str(ObjectID)
        else:
            requested_id = str(ObjectID)

        self.info("upnp_Browse request %r %r %r %r", ObjectID, BrowseFlag, StartingIndex, RequestedCount)

        didl = DIDLElement(upnp_client=kwargs.get('X_UPnPClient', ''),
                           requested_id=requested_id,
                           parent_container=parent_container,
                           transcoding=self.transcoding)

        def got_error(r):
            return r

        def process_result(result,total=None,found_item=None):
            if result == None:
                result = []
            if BrowseFlag == 'BrowseDirectChildren':
                l = []

                def process_items(result, tm):
                    if result == None:
                        result = []
                    for i in result:
                        if i[0] == True:
                            didl.addItem(i[1])

                    return build_response(tm)

                for i in result:
                    d = defer.maybeDeferred( i.get_item)
                    l.append(d)

                if found_item != None:
                    def got_child_count(count):
                        dl = defer.DeferredList(l)
                        dl.addCallback(process_items, count)
                        return dl

                    d = defer.maybeDeferred(found_item.get_child_count)
                    d.addCallback(got_child_count)

                    return d
                elif total == None:
                    total = item.get_child_count()

                dl = defer.DeferredList(l)
                dl.addCallback(process_items, total)
                return dl
            else:
                didl.addItem(result)
                total = 1

            return build_response(total)

        def build_response(tm):
            r = {'Result': didl.toString(), 'TotalMatches': tm,
                 'NumberReturned': didl.numItems()}

            if hasattr(item, 'update_id'):
                r['UpdateID'] = item.update_id
            elif hasattr(self.backend, 'update_id'):
                r['UpdateID'] = self.backend.update_id # FIXME
            else:
                r['UpdateID'] = 0

            return r

        def proceed(result):
            if BrowseFlag == 'BrowseDirectChildren':
                d = defer.maybeDeferred( result.get_children, StartingIndex, StartingIndex + RequestedCount)
            else:
                d = defer.maybeDeferred( result.get_item)

            d.addCallback(process_result,found_item=result)
            d.addErrback(got_error)
            return d


        root_id = ObjectID

        wmc_mapping = getattr(self.backend, "wmc_mapping", None)
        if(kwargs.get('X_UPnPClient', '') == 'XBox' and
            wmc_mapping != None and
            wmc_mapping.has_key(ObjectID)):
            """ fake a Windows Media Connect Server
            """
            root_id = wmc_mapping[ObjectID]
            if callable(root_id):
                item = root_id()
                if item  is not None:
                    if isinstance(item, list):
                        total = len(item)
                        if int(RequestedCount) == 0:
                            items = item[StartingIndex:]
                        else:
                            items = item[StartingIndex:StartingIndex+RequestedCount]
                        return process_result(items,total=total)
                    else:
                        if isinstance(item,defer.Deferred):
                            item.addCallback(proceed)
                            return item
                        else:
                            return proceed(item)

            item = self.backend.get_by_id(root_id)
            if item == None:
                return process_result([],total=0)

            if isinstance(item,defer.Deferred):
                item.addCallback(proceed)
                return item
            else:
                return proceed(item)

        item = self.backend.get_by_id(root_id)
        if item == None:
            return failure.Failure(errorCode(701))

        if isinstance(item,defer.Deferred):
            item.addCallback(proceed)
            return item
        else:
            return proceed(item)
    def upnp_Search(self, *args, **kwargs):
        ContainerID = kwargs['ContainerID']
        Filter = kwargs['Filter']
        StartingIndex = int(kwargs['StartingIndex'])
        RequestedCount = int(kwargs['RequestedCount'])
        SortCriteria = kwargs['SortCriteria']
        SearchCriteria = kwargs['SearchCriteria']

        total = 0
        root_id = 0
        item = None
        items = []

        parent_container = str(ContainerID)

        didl = DIDLElement(upnp_client=kwargs.get('X_UPnPClient', ''),
                           parent_container=parent_container,
                           transcoding=self.transcoding)

        def build_response(tm):
            r = {'Result': didl.toString(), 'TotalMatches': tm,
                 'NumberReturned': didl.numItems()}

            if hasattr(item, 'update_id'):
                r['UpdateID'] = item.update_id
            elif hasattr(self.backend, 'update_id'):
                r['UpdateID'] = self.backend.update_id # FIXME
            else:
                r['UpdateID'] = 0

            return r

        def got_error(r):
            return r

        def process_result(result,total=None,found_item=None):
            if result == None:
                result = []

            l = []

            def process_items(result, tm):
                if result == None:
                    result = []
                for i in result:
                    if i[0] == True:
                        didl.addItem(i[1])

                return build_response(tm)

            for i in result:
                d = defer.maybeDeferred( i.get_item)
                l.append(d)

            if found_item != None:
                def got_child_count(count):
                    dl = defer.DeferredList(l)
                    dl.addCallback(process_items, count)
                    return dl

                d = defer.maybeDeferred(found_item.get_child_count)
                d.addCallback(got_child_count)

                return d
            elif total == None:
                total = item.get_child_count()

            dl = defer.DeferredList(l)
            dl.addCallback(process_items, total)
            return dl

        def proceed(result):
            if(kwargs.get('X_UPnPClient', '') == 'XBox' and
               hasattr(result, 'get_artist_all_tracks')):
                d = defer.maybeDeferred( result.get_artist_all_tracks, StartingIndex, StartingIndex + RequestedCount)
            else:
                d = defer.maybeDeferred( result.get_children, StartingIndex, StartingIndex + RequestedCount)
            d.addCallback(process_result,found_item=result)
            d.addErrback(got_error)
            return d

        try:
            root_id = ContainerID
        except:
            pass

        wmc_mapping = getattr(self.backend, "wmc_mapping", None)
        if kwargs.get('X_UPnPClient', '') == 'XBox':
            if(wmc_mapping != None and
               wmc_mapping.has_key(ContainerID)):
                """ fake a Windows Media Connect Server
                """
                root_id = wmc_mapping[ContainerID]
                if callable(root_id):
                    item = root_id()
                    if item  is not None:
                        if isinstance(item, list):
                            total = len(item)
                            if int(RequestedCount) == 0:
                                items = item[StartingIndex:]
                            else:
                                items = item[StartingIndex:StartingIndex+RequestedCount]
                            return process_result(items,total=total)
                        else:
                            if isinstance(item,defer.Deferred):
                                item.addCallback(proceed)
                                return item
                            else:
                                return proceed(item)

                item = self.backend.get_by_id(root_id)
                if item == None:
                    return process_result([],total=0)

                if isinstance(item,defer.Deferred):
                    item.addCallback(proceed)
                    return item
                else:
                    return proceed(item)
        item = self.backend.get_by_id(root_id)
        mimecontainers = self.backend.get_x_containers()
        if (len(mimecontainers)):
                if "object.item.imageItem" in SearchCriteria:
                    item = self.backend.get_by_id(mimecontainers['imageItem'])
                elif "object.item.audioItem" in SearchCriteria:
                    item = self.backend.get_by_id(mimecontainers['audioItem'])
                elif "object.item.videoItem" in SearchCriteria:
                    item = self.backend.get_by_id(mimecontainers['videoItem'])
        if item == None:
            return failure.Failure(errorCode(708))

        if isinstance(item,defer.Deferred):
            item.addCallback(proceed)
            return item
        else:
            return proceed(item)