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_ImportResource(self, *args, **kwargs): print 'upnp_ImportResource', args, kwargs SourceURI = kwargs['SourceURI'] DestinationURI = kwargs['DestinationURI'] if DestinationURI.endswith('?import'): id = DestinationURI.split('/')[-1] id = id[:-7] # remove the ?import else: return failure.Failure(errorCode(718)) item = self.get_by_id(id) if item == None: return failure.Failure(errorCode(718)) def gotPage(result): try: import cStringIO as StringIO except ImportError: import StringIO self.backend_import(item, StringIO.StringIO(result[0])) def gotError(error, url): self.warning("error requesting %s", url) self.info(error) return failure.Failure(errorCode(718)) d = getPage(SourceURI) d.addCallbacks(gotPage, gotError, None, None, [SourceURI], None) transfer_id = 0 # FIXME return {'TransferID': transfer_id}
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 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_Seek(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) Unit = kwargs['Unit'] Target = kwargs['Target'] if InstanceID != 0: return failure.Failure(errorCode(718)) if Unit in ['TRACK_NR']: if self.playcontainer == None: NextURI = self.server.av_transport_server.get_variable( 'NextAVTransportURI').value if NextURI != '': self.server.av_transport_server.set_variable( InstanceID, 'TransportState', 'TRANSITIONING') NextURIMetaData = self.server.av_transport_server.get_variable( 'NextAVTransportURIMetaData').value self.server.av_transport_server.set_variable( InstanceID, 'NextAVTransportURI', '') self.server.av_transport_server.set_variable( InstanceID, 'NextAVTransportURIMetaData', '') r = self.upnp_SetAVTransportURI( self, InstanceID=InstanceID, CurrentURI=NextURI, CurrentURIMetaData=NextURIMetaData) return r else: Target = int(Target) if 0 < Target <= len(self.playcontainer[2]): self.server.av_transport_server.set_variable( InstanceID, 'TransportState', 'TRANSITIONING') next_track = () item = self.playcontainer[2][Target - 1] local_protocol_infos = self.server.connection_manager_server.get_variable( 'SinkProtocolInfo').value.split(',') res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split( ':') didl = DIDLLite.DIDLElement() didl.addItem(item) next_track = (res.data, didl.toString(), remote_content_format) self.playcontainer[0] = Target - 1 if len(next_track) == 3: self.server.av_transport_server.set_variable( self.server.connection_manager_server. lookup_avt_id(self.current_connection_id), 'CurrentTrack', Target) self.load(next_track[0], next_track[1], next_track[2]) self.play() return {} return failure.Failure(errorCode(711)) return failure.Failure(errorCode(710))
def upnp_Seek(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) Unit = kwargs['Unit'] Target = kwargs['Target'] if InstanceID != 0: return failure.Failure(errorCode(718)) if Unit in ['ABS_TIME','REL_TIME']: old_state = self.server.av_transport_server.get_variable('TransportState').value self.server.av_transport_server.set_variable(InstanceID, 'TransportState', 'TRANSITIONING') sign = '' if Target[0] == '+': Target = Target[1:] sign = '+' if Target[0] == '-': Target = Target[1:] sign = '-' h,m,s = Target.split(':') seconds = int(h)*3600 + int(m)*60 + int(s) self.seek(sign+str(seconds), old_state) if Unit in ['TRACK_NR']: if self.playcontainer == None: NextURI = self.server.av_transport_server.get_variable('NextAVTransportURI',InstanceID).value if NextURI != '': self.server.av_transport_server.set_variable(InstanceID, 'TransportState', 'TRANSITIONING') NextURIMetaData = self.server.av_transport_server.get_variable('NextAVTransportURIMetaData').value self.server.av_transport_server.set_variable(InstanceID, 'NextAVTransportURI', '') self.server.av_transport_server.set_variable(InstanceID, 'NextAVTransportURIMetaData', '') r = self.upnp_SetAVTransportURI(self, InstanceID=InstanceID,CurrentURI=NextURI,CurrentURIMetaData=NextURIMetaData) return r else: Target = int(Target) if 0 < Target <= len(self.playcontainer[2]): self.server.av_transport_server.set_variable(InstanceID, 'TransportState', 'TRANSITIONING') next_track = () item = self.playcontainer[2][Target-1] local_protocol_infos=self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',') res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol,remote_network,remote_content_format,_ = res.protocolInfo.split(':') didl = DIDLLite.DIDLElement() didl.addItem(item) next_track = (res.data,didl.toString(),remote_content_format) self.playcontainer[0] = Target-1 if len(next_track) == 3: self.server.av_transport_server.set_variable(self.server.connection_manager_server.lookup_avt_id(self.current_connection_id), 'CurrentTrack',Target) self.load(next_track[0],next_track[1],next_track[2]) self.play() return {} return failure.Failure(errorCode(711)) return {}
def upnp_ImportResource(self, *args, **kwargs): SourceURI = kwargs['SourceURI'] DestinationURI = kwargs['DestinationURI'] if DestinationURI.endswith('?import'): id = DestinationURI.split('/')[-1] id = id[:-7] # remove the ?import else: return failure.Failure(errorCode(718)) item = self.get_by_id(id) if item is None: return failure.Failure(errorCode(718)) def gotPage(headers): # print('gotPage', headers) content_type = headers.get('content-type', []) if not isinstance(content_type, list): content_type = list(content_type) if len(content_type) > 0: extension = mimetypes.guess_extension(content_type[0], strict=False) item.set_path(None, extension) shutil.move(tmp_path, item.get_path()) item.rebuild(self.urlbase) if hasattr(self, 'update_id'): self.update_id += 1 if self.server: if hasattr(self.server, 'content_directory_server'): self.server.content_directory_server.set_variable( 0, 'SystemUpdateID', self.update_id) if item.parent is not None: value = (item.parent.get_id(), item.parent.get_update_id()) if self.server: if hasattr(self.server, 'content_directory_server'): self.server.content_directory_server.set_variable( 0, 'ContainerUpdateIDs', value) def gotError(error, url): self.warning(f'error requesting {url}') self.info(error) os.unlink(tmp_path) return failure.Failure(errorCode(718)) tmp_fp, tmp_path = tempfile.mkstemp() os.close(tmp_fp) utils.downloadPage(SourceURI, tmp_path).addCallbacks(gotPage, gotError, None, None, [SourceURI], None) transfer_id = 0 # FIXME return {'TransferID': transfer_id}
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 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 KeyError: return failure.Failure(errorCode(401)) try: instance = int(kwargs['InstanceID']) except (ValueError, KeyError): instance = 0 self.info(f'soap__generic {action} {__name__} {kwargs}') del kwargs['soap_methodName'] in_arguments = action.get_in_arguments() for arg_name, arg in kwargs.items(): if arg_name.find('X_') == 0: continue al = [a for a in in_arguments if arg_name == a.get_name()] if len(al) > 0: in_arguments.remove(al[0]) else: self.critical( f'argument {arg_name} not valid for action {action.name}') return failure.Failure(errorCode(402)) if len(in_arguments) > 0: args_names = [a.get_name() for a in in_arguments] self.critical(f'argument {args_names} ' f'missing for action {action.name}') return failure.Failure(errorCode(402)) def got_error(x): self.info('dbus error during call processing') return x # call plugin method for this action # print 'callit args', args # print 'callit kwargs', kwargs # print 'callit action', action # print 'callit dbus action', self.service.service.action d = defer.Deferred() self.service.service.call_action( action.name, dbus.Dictionary(kwargs, signature='ss'), reply_handler=d.callback, error_handler=d.errback, utf8_strings=True, ) d.addCallback(self.get_action_results, action, instance) d.addErrback(got_error) return d
def hidden_upnp_DestroyObject(self, *args, **kwargs): ObjectID = kwargs['ObjectID'] item = self.get_by_id(ObjectID) if item == None: return failure.Failure(errorCode(701)) print "upnp_DestroyObject", item.location try: item.location.remove() except Exception, msg: print Exception, msg return failure.Failure(errorCode(715))
def upnp_ImportResource(self, *args, **kwargs): SourceURI = kwargs['SourceURI'] DestinationURI = kwargs['DestinationURI'] if DestinationURI.endswith('?import'): id = DestinationURI.split('/')[-1] id = id[:-7] # remove the ?import else: return failure.Failure(errorCode(718)) item = self.get_by_id(id) if item == None: return failure.Failure(errorCode(718)) def gotPage(headers): #print "gotPage", headers content_type = headers.get('content-type',[]) if not isinstance(content_type, list): content_type = list(content_type) if len(content_type) > 0: extension = mimetypes.guess_extension(content_type[0], strict=False) item.set_path(None,extension) shutil.move(tmp_path, item.get_path()) item.rebuild(self.urlbase) if hasattr(self, 'update_id'): self.update_id += 1 if self.server: if hasattr(self.server,'content_directory_server'): self.server.content_directory_server.set_variable(0, 'SystemUpdateID', self.update_id) if item.parent is not None: value = (item.parent.get_id(),item.parent.get_update_id()) if self.server: if hasattr(self.server,'content_directory_server'): self.server.content_directory_server.set_variable(0, 'ContainerUpdateIDs', value) def gotError(error, url): self.warning("error requesting", url) self.info(error) os.unlink(tmp_path) return failure.Failure(errorCode(718)) tmp_fp, tmp_path = tempfile.mkstemp() os.close(tmp_fp) utils.downloadPage(SourceURI, tmp_path).addCallbacks(gotPage, gotError, None, None, [SourceURI], None) transfer_id = 0 #FIXME return {'TransferID': transfer_id}
def hidden_upnp_DestroyObject(self, *args, **kwargs): ObjectID = kwargs['ObjectID'] item = self.get_by_id(ObjectID) if item is None: return failure.Failure(errorCode(701)) self.info(f'upnp_DestroyObject: {item.location}') try: item.location.remove() except Exception as msg: self.error(f'upnp_DestroyObject [{Exception}]: {msg}') return failure.Failure(errorCode(715)) return {}
def hidden_upnp_DestroyObject(self, *args, **kwargs): ObjectID = kwargs['ObjectID'] item = self.get_by_id(ObjectID) if item == None: return failure.Failure(errorCode(701)) print("upnp_DestroyObject", item.location) try: item.location.remove() except Exception as msg: print(Exception, msg) return failure.Failure(errorCode(715)) return {}
def hidden_upnp_DestroyObject(self, *args, **kwargs): ObjectID = kwargs['ObjectID'] item = self.get_by_id(ObjectID) if item is None: return failure.Failure(errorCode(701)) def handle_success(deleted): print('deleted', deleted, kwargs['ObjectID']) if not deleted: return failure.Failure(errorCode(715)) return {} def handle_error(error): return failure.Failure(errorCode(701)) d = defer.Deferred() self.store_interface.Delete( int(item.real_id), reply_handler=lambda x: d.callback(x), error_handler=lambda x: d.errback(x), ) d.addCallback(handle_success) d.addErrback(handle_error) return d
def upnp_SetAVTransportURI(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) CurrentURI = kwargs['CurrentURI'] CurrentURIMetaData = kwargs['CurrentURIMetaData'] local_protocol_infos = \ self.server.connection_manager_server.get_variable( 'SinkProtocolInfo').value.split(',') # print '>>>', local_protocol_infos if len(CurrentURIMetaData) == 0: self.load(CurrentURI, CurrentURIMetaData) else: elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData) if elt.numItems() == 1: item = elt.getItems()[0] res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, \ remote_content_format, _ = res.protocolInfo.split( ':') self.load(res.data, CurrentURIMetaData) return {} return failure.Failure(errorCode(714))
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_CreateObject(self, *args, **kwargs): print "upnp_CreateObject", args, kwargs ContainerID = kwargs['ContainerID'] Elements = kwargs['Elements'] parent_item = self.get_by_id(ContainerID) if parent_item == None: return failure.Failure(errorCode(710)) if parent_item.item.restricted: return failure.Failure(errorCode(713)) if len(Elements) == 0: return failure.Failure(errorCode(712)) elt = DIDLElement.fromString(Elements) if elt.numItems() != 1: return failure.Failure(errorCode(712)) item = elt.getItems()[0] if(item.id != '' or item.parentID != ContainerID or item.restricted == True or item.title == ''): return failure.Failure(errorCode(712)) if item.upnp_class.startswith('object.container'): if len(item.res) != 0: return failure.Failure(errorCode(712)) return failure.Failure(errorCode(712)) ### FIXME new_item = self.get_by_id(new_id) didl = DIDLElement() didl.addItem(new_item.item) return {'ObjectID': id, 'Result': didl.toString()} if item.upnp_class.startswith('object.item.imageItem'): new_id = self.getnextID() new_id = 'upload.' + str(new_id) title = item.title or 'unknown' mimetype = 'image/jpeg' self.uploads[new_id] = FlickrItem(new_id, title, self.store[UNSORTED_CONTAINER_ID], mimetype, self.urlbase, ImageItem, store=self, update=False, proxy=self.proxy) new_item = self.uploads[new_id] for res in new_item.item.res: res.importUri = new_item.url + '?import' res.data = None didl = DIDLElement() didl.addItem(new_item.item) r = {'ObjectID': new_id, 'Result': didl.toString()} print r return r return failure.Failure(errorCode(712))
def upnp_SetPlayMode(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) NewPlayMode = kwargs['NewPlayMode'] supported_play_modes = self.server.av_transport_server.get_variable( 'CurrentPlayMode', instance=InstanceID).allowed_values if NewPlayMode not in supported_play_modes: return failure.Failure(errorCode(712)) if self.server: self.server.av_transport_server.set_variable( InstanceID, 'CurrentPlayMode', NewPlayMode) return {}
def upnp_X_COHERENCE_SetDisplayTime(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) NewDisplayTime = int(kwargs['NewDisplayTime']) if 0 <= NewDisplayTime <= 65535: self.display_time = NewDisplayTime try: self.display_loop.delay(self.display_time) except: pass if self.server: self.server.av_transport_server.set_variable( InstanceID, 'X_COHERENCE_DisplayTime', self.display_time) return {} return failure.Failure(errorCode(601))
def upnp_X_COHERENCE_SetDisplayTransition(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) NewDisplayTransition = kwargs['NewDisplayTransition'] supported_transition_modes = self.server.av_transport_server.get_variable( 'X_COHERENCE_DisplayTransition', instance=InstanceID).allowed_values if NewDisplayTransition in supported_transition_modes: self.display_transition = NewDisplayTransition self.controller.set_transition(NewDisplayTransition) if self.server: self.server.av_transport_server.set_variable( InstanceID, 'X_COHERENCE_DisplayTransition', self.display_transition) return {} return failure.Failure(errorCode(600))
def upnp_SetAVTransportURI(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) CurrentURI = kwargs['CurrentURI'] CurrentURIMetaData = kwargs['CurrentURIMetaData'] local_protocol_info=self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',') if len(CurrentURIMetaData)==0: self.load(CurrentURI,CurrentURIMetaData) return {} else: elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData) print elt.numItems() if elt.numItems() == 1: item = elt.getItems()[0] for res in item.res: print res.protocolInfo,local_protocol_info if res.protocolInfo in local_protocol_info: self.load(CurrentURI,CurrentURIMetaData) return {} return failure.Failure(errorCode(714))
def upnp_SetAVTransportURI(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) CurrentURI = kwargs['CurrentURI'] CurrentURIMetaData = kwargs['CurrentURIMetaData'] #print "upnp_SetAVTransportURI",InstanceID, CurrentURI, CurrentURIMetaData if CurrentURI.startswith('dlna-playcontainer://'): def handle_result(r): self.load(r[0], r[1], mimetype=r[2]) return {} def pass_error(r): return r d = defer.maybeDeferred(self.playcontainer_browse, CurrentURI) d.addCallback(handle_result) d.addErrback(pass_error) return d elif len(CurrentURIMetaData) == 0: self.playcontainer = None self.load(CurrentURI, CurrentURIMetaData) return {} else: local_protocol_infos = self.server.connection_manager_server.get_variable( 'SinkProtocolInfo').value.split(',') #print local_protocol_infos elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData) if elt.numItems() == 1: item = elt.getItems()[0] res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split( ':') self.playcontainer = None self.load(res.data, CurrentURIMetaData, mimetype=remote_content_format) return {} return failure.Failure(errorCode(714))
def upnp_SetAVTransportURI(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) CurrentURI = kwargs['CurrentURI'] CurrentURIMetaData = kwargs['CurrentURIMetaData'] local_protocol_info = self.server.connection_manager_server.get_variable( # noqa: E501 'SinkProtocolInfo').value.split(',') if len(CurrentURIMetaData) == 0: self.load(CurrentURI, CurrentURIMetaData) return {} else: elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData) print(elt.numItems()) if elt.numItems() == 1: item = elt.getItems()[0] for res in item.res: print(res.protocolInfo, local_protocol_info) if res.protocolInfo in local_protocol_info: self.load(CurrentURI, CurrentURIMetaData) return {} return failure.Failure(errorCode(714))
def upnp_SetAVTransportURI(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) CurrentURI = kwargs['CurrentURI'] CurrentURIMetaData = kwargs['CurrentURIMetaData'] local_protocol_infos = self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',') #print '>>>', local_protocol_infos if len(CurrentURIMetaData) == 0: self.load(CurrentURI, CurrentURIMetaData) else: elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData) if elt.numItems() == 1: item = elt.getItems()[0] res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split(':') self.load(res.data, CurrentURIMetaData) return {} return failure.Failure(errorCode(714))
def upnp_SetAVTransportURI(self, *args, **kwargs): InstanceID = int(kwargs["InstanceID"]) CurrentURI = kwargs["CurrentURI"] CurrentURIMetaData = kwargs["CurrentURIMetaData"] # print "upnp_SetAVTransportURI",InstanceID, CurrentURI, CurrentURIMetaData if CurrentURI.startswith("dlna-playcontainer://"): def handle_result(r): self.load(r[0], r[1], mimetype=r[2]) return {} def pass_error(r): return r d = defer.maybeDeferred(self.playcontainer_browse, CurrentURI) d.addCallback(handle_result) d.addErrback(pass_error) return d elif len(CurrentURIMetaData) == 0: self.playcontainer = None self.load(CurrentURI, CurrentURIMetaData) return {} else: local_protocol_infos = self.server.connection_manager_server.get_variable("SinkProtocolInfo").value.split( "," ) # print local_protocol_infos elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData) if elt.numItems() == 1: item = elt.getItems()[0] res = item.res.get_matching(local_protocol_infos, protocol_type="internal") if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split(":") self.playcontainer = None self.load(res.data, CurrentURIMetaData, mimetype=remote_content_format) return {} return failure.Failure(errorCode(714))
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 playcontainer_browse(self,uri): """ dlna-playcontainer://uuid%3Afe814e3e-5214-4c24-847b-383fb599ff01?sid=urn%3Aupnp-org%3AserviceId%3AContentDirectory&cid=1441&fid=1444&fii=0&sc=&md=0 """ from urllib import unquote from cgi import parse_qs from coherence.extern.et import ET from coherence.upnp.core.utils import parse_xml def handle_reply(r,uri,action,kw): try: next_track = () elt = DIDLLite.DIDLElement.fromString(r['Result']) item = elt.getItems()[0] local_protocol_infos=self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',') res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol,remote_network,remote_content_format,_ = res.protocolInfo.split(':') didl = DIDLLite.DIDLElement() didl.addItem(item) next_track = (res.data,didl.toString(),remote_content_format) """ a list with these elements: the current track index - will change during playback of the container items the initial complete playcontainer-uri a list of all the items in the playcontainer the action methods to do the Browse call on the device the kwargs for the Browse call - kwargs['StartingIndex'] will be modified during further Browse requests """ self.playcontainer = [int(kw['StartingIndex']),uri,elt.getItems()[:],action,kw] def browse_more(starting_index,number_returned,total_matches): self.info("browse_more", starting_index,number_returned,total_matches) try: def handle_error(r): pass def handle_reply(r,starting_index): elt = DIDLLite.DIDLElement.fromString(r['Result']) self.playcontainer[2] += elt.getItems()[:] browse_more(starting_index,int(r['NumberReturned']),int(r['TotalMatches'])) if((number_returned != 5 or number_returned < (total_matches-starting_index)) and (total_matches-number_returned) != starting_index): self.info("seems we have been returned only a part of the result") self.info("requested %d, starting at %d" % (5,starting_index)) self.info("got %d out of %d" % (number_returned, total_matches)) self.info("requesting more starting now at %d" % (starting_index+number_returned)) self.playcontainer[4]['StartingIndex'] = str(starting_index+number_returned) d = self.playcontainer[3].call(**self.playcontainer[4]) d.addCallback(handle_reply,starting_index+number_returned) d.addErrback(handle_error) except: import traceback traceback.print_exc() browse_more(int(kw['StartingIndex']),int(r['NumberReturned']),int(r['TotalMatches'])) if len(next_track) == 3: return next_track except: import traceback traceback.print_exc() return failure.Failure(errorCode(714)) def handle_error(r): return failure.Failure(errorCode(714)) try: udn,args = uri[21:].split('?') udn = unquote(udn) args = parse_qs(args) type = args['sid'][0].split(':')[-1] try: sc = args['sc'][0] except: sc = '' device = self.server.coherence.get_device_with_id(udn) service = device.get_service_by_type(type) action = service.get_action('Browse') kw = {'ObjectID':args['cid'][0], 'BrowseFlag':'BrowseDirectChildren', 'StartingIndex':args['fii'][0], 'RequestedCount':str(5), 'Filter':'*', 'SortCriteria':sc} d = action.call(**kw) d.addCallback(handle_reply,uri,action,kw) d.addErrback(handle_error) return d except: return failure.Failure(errorCode(714))
def handle_reply(r,uri,action,kw): try: next_track = () elt = DIDLLite.DIDLElement.fromString(r['Result']) item = elt.getItems()[0] local_protocol_infos=self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',') res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol,remote_network,remote_content_format,_ = res.protocolInfo.split(':') didl = DIDLLite.DIDLElement() didl.addItem(item) next_track = (res.data,didl.toString(),remote_content_format) """ a list with these elements: the current track index - will change during playback of the container items the initial complete playcontainer-uri a list of all the items in the playcontainer the action methods to do the Browse call on the device the kwargs for the Browse call - kwargs['StartingIndex'] will be modified during further Browse requests """ self.playcontainer = [int(kw['StartingIndex']),uri,elt.getItems()[:],action,kw] def browse_more(starting_index,number_returned,total_matches): self.info("browse_more", starting_index,number_returned,total_matches) try: def handle_error(r): pass def handle_reply(r,starting_index): elt = DIDLLite.DIDLElement.fromString(r['Result']) self.playcontainer[2] += elt.getItems()[:] browse_more(starting_index,int(r['NumberReturned']),int(r['TotalMatches'])) if((number_returned != 5 or number_returned < (total_matches-starting_index)) and (total_matches-number_returned) != starting_index): self.info("seems we have been returned only a part of the result") self.info("requested %d, starting at %d" % (5,starting_index)) self.info("got %d out of %d" % (number_returned, total_matches)) self.info("requesting more starting now at %d" % (starting_index+number_returned)) self.playcontainer[4]['StartingIndex'] = str(starting_index+number_returned) d = self.playcontainer[3].call(**self.playcontainer[4]) d.addCallback(handle_reply,starting_index+number_returned) d.addErrback(handle_error) except: import traceback traceback.print_exc() browse_more(int(kw['StartingIndex']),int(r['NumberReturned']),int(r['TotalMatches'])) if len(next_track) == 3: return next_track except: import traceback traceback.print_exc() return failure.Failure(errorCode(714))
def handle_reply(r, uri, action, kw): try: next_track = () elt = DIDLLite.DIDLElement.fromString(r['Result']) item = elt.getItems()[0] local_protocol_infos = self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',') res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split(':') didl = DIDLLite.DIDLElement() didl.addItem(item) next_track = (res.data, didl.toString(), remote_content_format) """ a list with these elements: the current track index - will change during playback of the container items the initial complete playcontainer-uri a list of all the items in the playcontainer the action methods to do the Browse call on the device the kwargs for the Browse call - kwargs['StartingIndex'] will be modified during further Browse requests """ self.playcontainer = [int(kw['StartingIndex']), uri, elt.getItems()[:], action, kw] def browse_more(starting_index, number_returned, total_matches): self.info("browse_more", starting_index, number_returned, total_matches) try: def handle_error(r): pass def handle_reply(r, starting_index): elt = DIDLLite.DIDLElement.fromString(r['Result']) self.playcontainer[2] += elt.getItems()[:] browse_more(starting_index, int(r['NumberReturned']), int(r['TotalMatches'])) if((number_returned != 5 or number_returned < (total_matches - starting_index)) and (total_matches - number_returned) != starting_index): self.info("seems we have been returned only a part of the result") self.info("requested %d, starting at %d" % (5, starting_index)) self.info("got %d out of %d" % (number_returned, total_matches)) self.info("requesting more starting now at %d" % (starting_index + number_returned)) self.playcontainer[4]['StartingIndex'] = str(starting_index + number_returned) d = self.playcontainer[3].call(**self.playcontainer[4]) d.addCallback(handle_reply, starting_index + number_returned) d.addErrback(handle_error) except: import traceback traceback.print_exc() browse_more(int(kw['StartingIndex']), int(r['NumberReturned']), int(r['TotalMatches'])) if len(next_track) == 3: return next_track except: import traceback traceback.print_exc() return failure.Failure(errorCode(714))
def upnp_Seek(self, *args, **kwargs): InstanceID = int(kwargs["InstanceID"]) Unit = kwargs["Unit"] Target = kwargs["Target"] if InstanceID != 0: return failure.Failure(errorCode(718)) if Unit in ["ABS_TIME", "REL_TIME"]: old_state = self.server.av_transport_server.get_variable("TransportState").value self.server.av_transport_server.set_variable(InstanceID, "TransportState", "TRANSITIONING") sign = "" if Target[0] == "+": Target = Target[1:] sign = "+" if Target[0] == "-": Target = Target[1:] sign = "-" h, m, s = Target.split(":") seconds = int(h) * 3600 + int(m) * 60 + int(s) self.seek(sign + str(seconds), old_state) if Unit in ["TRACK_NR"]: if self.playcontainer == None: NextURI = self.server.av_transport_server.get_variable("NextAVTransportURI", InstanceID).value if NextURI != "": self.server.av_transport_server.set_variable(InstanceID, "TransportState", "TRANSITIONING") NextURIMetaData = self.server.av_transport_server.get_variable("NextAVTransportURIMetaData").value self.server.av_transport_server.set_variable(InstanceID, "NextAVTransportURI", "") self.server.av_transport_server.set_variable(InstanceID, "NextAVTransportURIMetaData", "") r = self.upnp_SetAVTransportURI( self, InstanceID=InstanceID, CurrentURI=NextURI, CurrentURIMetaData=NextURIMetaData ) return r else: Target = int(Target) if 0 < Target <= len(self.playcontainer[2]): self.server.av_transport_server.set_variable(InstanceID, "TransportState", "TRANSITIONING") next_track = () item = self.playcontainer[2][Target - 1] local_protocol_infos = self.server.connection_manager_server.get_variable( "SinkProtocolInfo" ).value.split(",") res = item.res.get_matching(local_protocol_infos, protocol_type="internal") if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split(":") didl = DIDLLite.DIDLElement() didl.addItem(item) next_track = (res.data, didl.toString(), remote_content_format) self.playcontainer[0] = Target - 1 if len(next_track) == 3: self.server.av_transport_server.set_variable( self.server.connection_manager_server.lookup_avt_id(self.current_connection_id), "CurrentTrack", Target, ) self.load(next_track[0], next_track[1], next_track[2]) self.play() return {} return failure.Failure(errorCode(711)) return {}
def errback(r): return failure.Failure(errorCode(701))
def upnp_Browse(self, *args, **kwargs): try: ObjectID = kwargs['ObjectID'] except KeyError: self.debug('hmm, a Browse action and no ObjectID argument? ' + 'An XBox maybe?') try: ObjectID = kwargs['ContainerID'] except KeyError: 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(f'upnp_Browse request {ObjectID} {BrowseFlag} ' + f'{StartingIndex} {RequestedCount}') # self.debug(f'\t- kwargs: {kwargs}') 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 is None: result = [] if BrowseFlag == 'BrowseDirectChildren': cl = [] def process_items(result, tm): if result is None: result = [] for i in result: if i[0]: didl.addItem(i[1]) return build_response(tm) for i in result: d = defer.maybeDeferred(i.get_item) cl.append(d) if found_item is not None: def got_child_count(count): dl = defer.DeferredList(cl) dl.addCallback(process_items, count) return dl d = defer.maybeDeferred(found_item.get_child_count) d.addCallback(got_child_count) return d elif total is None: total = item.get_child_count() dl = defer.DeferredList(cl) 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 is not None and ObjectID in wmc_mapping): # 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 is 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 is None: return failure.Failure(errorCode(701)) if isinstance(item, defer.Deferred): item.addCallback(proceed) return item else: return proceed(item)
def gotError(error, url): self.warning(f'error requesting {url}') self.info(error) os.unlink(tmp_path) return failure.Failure(errorCode(718))
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 is None: result = [] for i in result: if i[0]: didl.addItem(i[1]) return build_response(tm) for i in result: d = defer.maybeDeferred(i.get_item) l.append(d) if found_item is not 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 is 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 is not 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 is 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 is None: return failure.Failure(errorCode(701)) if isinstance(item, defer.Deferred): item.addCallback(proceed) return item else: return proceed(item)
def upnp_CreateObject(self, *args, **kwargs): # print(f'CreateObject {kwargs}') if kwargs['ContainerID'] == 'DLNA.ORG_AnyContainer': if self.import_folder is not None: ContainerID = self.import_folder_id else: return failure.Failure(errorCode(712)) else: ContainerID = kwargs['ContainerID'] Elements = kwargs['Elements'] parent_item = self.get_by_id(ContainerID) if parent_item is None: return failure.Failure(errorCode(710)) if parent_item.item.restricted: return failure.Failure(errorCode(713)) if len(Elements) == 0: return failure.Failure(errorCode(712)) elt = DIDLElement.fromString(Elements) if elt.numItems() != 1: return failure.Failure(errorCode(712)) item = elt.getItems()[0] if item.parentID == 'DLNA.ORG_AnyContainer': item.parentID = ContainerID if (item.id != '' or item.parentID != ContainerID or item.restricted is True or item.title == ''): return failure.Failure(errorCode(712)) if '..' in item.title or '~' in item.title or os.sep in item.title: return failure.Failure(errorCode(712)) if item.upnp_class == 'object.container.storageFolder': if len(item.res) != 0: return failure.Failure(errorCode(712)) path = os.path.join(parent_item.get_path(), item.title) id = self.create('directory', path, parent_item) try: os.mkdir(path) except Exception: self.remove(id) return failure.Failure(errorCode(712)) if self.inotify is not None: mask = (IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO | IN_CHANGED) self.inotify.watch( path, mask=mask, autoAdd=False, callbacks=[partial(self.notify, parameter=id)], ) new_item = self.get_by_id(id) didl = DIDLElement() didl.addItem(new_item.item) return {'ObjectID': id, 'Result': didl.toString()} if item.upnp_class.startswith('object.item'): _, _, content_format, _ = item.res[0].protocolInfo.split(':') extension = mimetypes.guess_extension(content_format, strict=False) path = os.path.join(parent_item.get_realpath(), item.title + extension) id = self.create('item', path, parent_item) new_item = self.get_by_id(id) for res in new_item.item.res: res.importUri = new_item.url + '?import' res.data = None didl = DIDLElement() didl.addItem(new_item.item) return {'ObjectID': id, 'Result': didl.toString()} return failure.Failure(errorCode(712))
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 is not 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 is 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 is None: return failure.Failure(errorCode(701)) if isinstance(item, defer.Deferred): item.addCallback(proceed) return item else: return proceed(item)
def upnp_XBrowse(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 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 = DIDLLite.DIDLElement(upnp_client=kwargs.get('X_UPnPClient', ''), requested_id=requested_id, parent_container=parent_container) def build_response(tm): num_ret = didl.numItems() #if int(kwargs['RequestedCount']) != 0 and num_ret != int(kwargs['RequestedCount']): # num_ret = 0 #if RequestedCount == 0 and tm-StartingIndex != num_ret: # num_ret = 0 r = { 'Result': didl.toString(), 'TotalMatches': tm, 'NumberReturned': num_ret } self.info("upnp_Browse response %r %r", num_ret, tm) if hasattr(item, 'update_id'): r['UpdateID'] = item.update_id elif hasattr(self, 'update_id'): r['UpdateID'] = self.update_id # FIXME else: r['UpdateID'] = 0 return r total = 0 items = [] wmc_mapping = getattr(self, "wmc_mapping", None) if (kwargs.get('X_UPnPClient', '') == 'XBox' and wmc_mapping != None and ObjectID in wmc_mapping): """ fake a Windows Media Connect Server """ root_id = wmc_mapping[ObjectID] if isinstance(root_id, collections.Callable): 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] else: d = defer.maybeDeferred(item.get_children, StartingIndex, StartingIndex + RequestedCount) d.addCallback(process_result) d.addErrback(got_error) return d for i in items: didl.addItem(i.get_item()) return build_response(total) root_id = ObjectID item = self.get_by_id(root_id) if item is None: return failure.Failure(errorCode(701)) def got_error(r): return r def process_result(result, found_item): if result is 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) 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 else: didl.addItem(result) total = 1 return build_response(total) 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, result) d.addErrback(got_error) return d if isinstance(item, defer.Deferred): item.addCallback(proceed) return item else: return proceed(item)
def gotError(error, url): self.warning("error requesting %s", url) self.info(error) return failure.Failure(errorCode(718))
def handle_error(r): return failure.Failure(errorCode(714))
def upnp_Search(self, *args, **kwargs): self.init_cover_root() Log.d("%s" % (kwargs,)) ContainerID = kwargs['ContainerID'] StartingIndex = int(kwargs['StartingIndex']) RequestedCount = int(kwargs['RequestedCount']) SearchCriteria = kwargs['SearchCriteria'] total = 0 root_id = 0 item = None items = [] parent_container = None SearchCriteria = SearchCriteria.split(" ") if "derivedfrom" in SearchCriteria: if SearchCriteria[0] == "upnp:class": Log.d("Searching by class! %s" % (SearchCriteria,)) if SearchCriteria[2].find(DIDLLite.AudioItem.upnp_class) >= 0: parent_container = str(self._audio_all_id) elif SearchCriteria[2].find(DIDLLite.VideoItem.upnp_class) >= 0: parent_container = str(self._video_all_id) Log.d(parent_container) if not parent_container: parent_container = str(ContainerID) didl = DIDLLite.DIDLElement(upnp_client=kwargs.get('X_UPnPClient', ''), parent_container=parent_container, transcoding=self.server.content_directory_server.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, 'update_id'): r['UpdateID'] = self.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 = parent_container except: pass wmc_mapping = getattr(self, "wmc_mapping", None) if kwargs.get('X_UPnPClient', '') == 'XBox': if wmc_mapping and wmc_mapping.has_key(parent_container): """ fake a Windows Media Connect Server """ root_id = wmc_mapping[parent_container] 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.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.get_by_id(root_id) Log.w(item) if item == None: Log.w(701) return failure.Failure(errorCode(701)) if isinstance(item, defer.Deferred): item.addCallback(proceed) return item else: return proceed(item)
def gotError(error, url): self.warning("error requesting", url) self.info(error) os.unlink(tmp_path) return failure.Failure(errorCode(718))
def handle_success(deleted): print('deleted', deleted, kwargs['ObjectID']) if not deleted: return failure.Failure(errorCode(715)) return {}
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) if item == None: return failure.Failure(errorCode(701)) if isinstance(item, defer.Deferred): item.addCallback(proceed) return item else: return proceed(item)
def handle_error(error): return failure.Failure(errorCode(701))
def upnp_Search(self, *args, **kwargs): self.init_cover_root() Log.d("%s" % (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 = None SearchCriteria = SearchCriteria.split(" ") if "derivedfrom" in SearchCriteria: if SearchCriteria[0] == "upnp:class": Log.d("Searching by class! %s" % (SearchCriteria, )) if SearchCriteria[2].find(DIDLLite.AudioItem.upnp_class) >= 0: parent_container = str(self._audio_all_id) elif SearchCriteria[2].find( DIDLLite.VideoItem.upnp_class) >= 0: parent_container = str(self._video_all_id) Log.d(parent_container) if not parent_container: parent_container = str(ContainerID) didl = DIDLLite.DIDLElement( upnp_client=kwargs.get('X_UPnPClient', ''), parent_container=parent_container, transcoding=self.server.content_directory_server.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, 'update_id'): r['UpdateID'] = self.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 = parent_container except: pass wmc_mapping = getattr(self, "wmc_mapping", None) if kwargs.get('X_UPnPClient', '') == 'XBox': if wmc_mapping and wmc_mapping.has_key(parent_container): """ fake a Windows Media Connect Server """ root_id = wmc_mapping[parent_container] 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.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.get_by_id(root_id) Log.w(item) if item == None: Log.w(701) return failure.Failure(errorCode(701)) if isinstance(item, defer.Deferred): item.addCallback(proceed) return item else: return proceed(item)
def upnp_CreateObject(self, *args, **kwargs): if kwargs['ContainerID'] == 'DLNA.ORG_AnyContainer': """ for the moment """ return failure.Failure(errorCode(712)) else: ContainerID = kwargs['ContainerID'] Elements = kwargs['Elements'] parent_item = self.get_by_id(ContainerID) if parent_item == None: return failure.Failure(errorCode(710)) if parent_item.item.restricted: return failure.Failure(errorCode(713)) if len(Elements) == 0: return failure.Failure(errorCode(712)) elt = DIDLElement.fromString(Elements) if elt.numItems() != 1: return failure.Failure(errorCode(712)) item = elt.getItems()[0] if(item.id != '' or int(item.parentID) != ContainerID or item.restricted == True or item.title == ''): return failure.Failure(errorCode(712)) if('..' in item.title or '~' in item.title or os.sep in item.title): return failure.Failure(errorCode(712)) if item.upnp_class == 'object.container.storageFolder': if len(item.res) != 0: return failure.Failure(errorCode(712)) path = os.path.join(parent_item.get_path(),item.title) id = self.create('directory',path,parent_item) try: os.mkdir(path) except: self.remove(id) return failure.Failure(errorCode(712)) if self.inotify is not None: mask = IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO | IN_CHANGED self.inotify.watch(path, mask=mask, auto_add=False, callbacks=(self.notify,id)) new_item = self.get_by_id(id) didl = DIDLElement() didl.addItem(new_item.item) return {'ObjectID': id, 'Result': didl.toString()} if item.upnp_class.startswith('object.item.'): #path = os.path.join(parent_item.get_path(),item.title) id = self.create('item',None,parent_item) new_item = self.get_by_id(id) for res in new_item.item.res: res.importUri = new_item.url+'?import' res.data = None didl = DIDLElement() didl.addItem(new_item.item) return {'ObjectID': id, 'Result': didl.toString()} return failure.Failure(errorCode(712))
def playcontainer_browse(self, uri): """ dlna-playcontainer://uuid%3Afe814e3e-5214-4c24-847b-383fb599ff01?sid=urn%3Aupnp-org%3AserviceId%3AContentDirectory&cid=1441&fid=1444&fii=0&sc=&md=0 """ from urllib import unquote from cgi import parse_qs from coherence.extern.et import ET from coherence.upnp.core.utils import parse_xml def handle_reply(r, uri, action, kw): try: next_track = () elt = DIDLLite.DIDLElement.fromString(r['Result']) item = elt.getItems()[0] local_protocol_infos = self.server.connection_manager_server.get_variable('SinkProtocolInfo').value.split(',') res = item.res.get_matching(local_protocol_infos, protocol_type='internal') if len(res) == 0: res = item.res.get_matching(local_protocol_infos) if len(res) > 0: res = res[0] remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split(':') didl = DIDLLite.DIDLElement() didl.addItem(item) next_track = (res.data, didl.toString(), remote_content_format) """ a list with these elements: the current track index - will change during playback of the container items the initial complete playcontainer-uri a list of all the items in the playcontainer the action methods to do the Browse call on the device the kwargs for the Browse call - kwargs['StartingIndex'] will be modified during further Browse requests """ self.playcontainer = [int(kw['StartingIndex']), uri, elt.getItems()[:], action, kw] def browse_more(starting_index, number_returned, total_matches): self.info("browse_more", starting_index, number_returned, total_matches) try: def handle_error(r): pass def handle_reply(r, starting_index): elt = DIDLLite.DIDLElement.fromString(r['Result']) self.playcontainer[2] += elt.getItems()[:] browse_more(starting_index, int(r['NumberReturned']), int(r['TotalMatches'])) if((number_returned != 5 or number_returned < (total_matches - starting_index)) and (total_matches - number_returned) != starting_index): self.info("seems we have been returned only a part of the result") self.info("requested %d, starting at %d" % (5, starting_index)) self.info("got %d out of %d" % (number_returned, total_matches)) self.info("requesting more starting now at %d" % (starting_index + number_returned)) self.playcontainer[4]['StartingIndex'] = str(starting_index + number_returned) d = self.playcontainer[3].call(**self.playcontainer[4]) d.addCallback(handle_reply, starting_index + number_returned) d.addErrback(handle_error) except: import traceback traceback.print_exc() browse_more(int(kw['StartingIndex']), int(r['NumberReturned']), int(r['TotalMatches'])) if len(next_track) == 3: return next_track except: import traceback traceback.print_exc() return failure.Failure(errorCode(714)) def handle_error(r): return failure.Failure(errorCode(714)) try: udn, args = uri[21:].split('?') udn = unquote(udn) args = parse_qs(args) type = args['sid'][0].split(':')[-1] try: sc = args['sc'][0] except: sc = '' device = self.server.coherence.get_device_with_id(udn) service = device.get_service_by_type(type) action = service.get_action('Browse') kw = {'ObjectID':args['cid'][0], 'BrowseFlag':'BrowseDirectChildren', 'StartingIndex':args['fii'][0], 'RequestedCount':str(5), 'Filter':'*', 'SortCriteria':sc} d = action.call(**kw) d.addCallback(handle_reply, uri, action, kw) d.addErrback(handle_error) return d except: return failure.Failure(errorCode(714))