Beispiel #1
0
    def toElement(self, **kwargs):

        root = Object.toElement(self, **kwargs)

        if self.childCount is not None:
            root.attrib['childCount'] = str(self.childCount)

        if self.createClass is not None:
            ET.SubElement(root, qname('createclass',
                                      UPNP_NS)).text = self.createClass

        if not isinstance(self.searchClass, (list, tuple)):
            self.searchClass = [self.searchClass]
        for i in self.searchClass:
            sc = ET.SubElement(root, qname('searchClass', UPNP_NS))
            sc.attrib['includeDerived'] = '1'
            sc.text = i

        if self.searchable is not None:
            if self.searchable in (1, '1', True, 'true', 'True'):
                root.attrib['searchable'] = '1'
            else:
                root.attrib['searchable'] = '0'

        for res in self.res:
            root.append(res.toElement(**kwargs))
        return root
Beispiel #2
0
    def new_subscriber(self, subscriber):
        notify = []
        for vdict in self._variables.values():
            notify += [v for v in vdict.values() if v.send_events == True]

        self.info("new_subscriber", subscriber, notify)
        if len(notify) <= 0:
            return

        root = ET.Element('e:propertyset')
        root.attrib['xmlns:e'] = 'urn:schemas-upnp-org:event-1-0'
        evented_variables = 0
        for n in notify:
            e = ET.SubElement(root, 'e:property')
            if n.name == 'LastChange':
                if subscriber['seq'] == 0:
                    text = self.build_last_change_event(n.instance, force=True)
                else:
                    text = self.build_last_change_event(n.instance)
                if text is not None:
                    ET.SubElement(e, n.name).text = text
                    evented_variables += 1
            else:
                ET.SubElement(e, n.name).text = str(n.value)
                evented_variables += 1

        if evented_variables > 0:
            xml = ET.tostring(root, encoding='utf-8')
            d, p = event.send_notification(subscriber, xml)
            self._pending_notifications[d] = p
            d.addBoth(self.rm_notification, d)
        self._subscribers[subscriber['sid']] = subscriber
Beispiel #3
0
 def build_last_change_event(self, instance=0, force=False):
     got_one = False
     root = ET.Element('Event')
     root.attrib['xmlns'] = self.event_metadata
     for instance, vdict in self._variables.items():
         e = ET.SubElement(root, 'InstanceID')
         e.attrib['val'] = str(instance)
         for variable in vdict.values():
             if (variable.name != 'LastChange'
                     and variable.name[0:11] != 'A_ARG_TYPE_'
                     and variable.never_evented == False
                     and (variable.updated == True or force == True)):
                 s = ET.SubElement(e, variable.name)
                 s.attrib['val'] = str(variable.value)
                 variable.updated = False
                 got_one = True
                 if variable.dependant_variable != None:
                     dependants = variable.dependant_variable.get_allowed_values(
                     )
                     if dependants != None and len(dependants) > 0:
                         s.attrib['channel'] = dependants[0]
     if got_one == True:
         return ET.tostring(root, encoding='utf-8')
     else:
         return None
Beispiel #4
0
    def upnp_X_GetFeatureList(self, **kwargs):
        Log.w()
        attrib = {
            "xmlns":
            "urn:schemas-upnp-org:av:avs",
            "xmlns:xsi":
            "http://www.w3.org/2001/XMLSchema-instance",
            "xsi:schemaLocation":
            "urn:schemas-upnp-org:av:avs http://www.upnp.org/schemas/av/avs.xsd"
        }
        features = ET.Element("Features")
        features.attrib.update(attrib)

        attrib = {"name": "samsung.com_BASICVIEW", "version": "1"}
        feature = ET.SubElement(features, "Feature")
        feature.attrib.update(attrib)
        #audio/video container id definition
        tag = ET.SubElement(feature, "container")
        tag.attrib.update({
            "type": DIDLLite.AudioItem.upnp_class,
            "id": str(self._audio.get_id())
        })
        tag = ET.SubElement(feature, "container")
        tag.attrib.update({
            "type": DIDLLite.VideoItem.upnp_class,
            "id": str(self._video.get_id())
        })
        return {"FeatureList": ET.tostring(features, "utf-8")}
Beispiel #5
0
    def toElement(self, **kwargs):

        root = Object.toElement(self, **kwargs)

        if self.director is not None:
            ET.SubElement(root, qname('director',
                                      UPNP_NS)).text = self.director

        if self.refID is not None:
            ET.SubElement(root, 'refID').text = self.refID

        if self.actors is not None:
            for actor in self.actors:
                ET.SubElement(root, qname('actor', DC_NS)).text = actor

        #if self.language is not None:
        #    ET.SubElement(root, qname('language',DC_NS)).text = self.language

        if kwargs.get('transcoding', False) == True:
            res = self.res.get_matching(['*:*:*:*'], protocol_type='http-get')
            if len(res) > 0 and is_audio(res[0].protocolInfo):
                old_res = res[0]
                if (kwargs.get('upnp_client', '') == 'XBox'):
                    transcoded_res = old_res.transcoded('mp3')
                    if transcoded_res != None:
                        root.append(transcoded_res.toElement(**kwargs))
                    else:
                        root.append(old_res.toElement(**kwargs))
                else:
                    for res in self.res:
                        root.append(res.toElement(**kwargs))
                    transcoded_res = old_res.transcoded('lpcm')
                    if transcoded_res != None:
                        root.append(transcoded_res.toElement(**kwargs))
            elif len(res) > 0 and is_video(res[0].protocolInfo):
                old_res = res[0]
                for res in self.res:
                    root.append(res.toElement(**kwargs))
                transcoded_res = old_res.transcoded('mpegts')
                if transcoded_res != None:
                    root.append(transcoded_res.toElement(**kwargs))
            else:
                for res in self.res:
                    root.append(res.toElement(**kwargs))
        else:
            for res in self.res:
                root.append(res.toElement(**kwargs))

        return root
Beispiel #6
0
    def toElement(self, **kwargs):

        root = Item.toElement(self, **kwargs)

        if self.publisher is not None:
            ET.SubElement(root, qname('publisher',
                                      DC_NS)).text = self.publisher

        if self.language is not None:
            ET.SubElement(root, qname('language', DC_NS)).text = self.language

        if self.relation is not None:
            ET.SubElement(root, qname('relation', DC_NS)).text = self.relation

        if self.rights is not None:
            ET.SubElement(root, qname('rights', DC_NS)).text = self.rights

        return root
Beispiel #7
0
    def toElement(self, **kwargs):
        root = Item.toElement(self, **kwargs)

        for attr_name, ns in self.valid_attrs.iteritems():
            value = getattr(self, attr_name, None)
            if value:
                ET.SubElement(root, qname(attr_name, ns)).text = value

        return root
Beispiel #8
0
    def toElement(self, **kwargs):
        root = Item.toElement(self, **kwargs)

        if self.rating is not None:
            ET.SubElement(root, qname('rating',
                                      UPNP_NS)).text = str(self.rating)

        if self.storageMedium is not None:
            ET.SubElement(root, qname('storageMedium',
                                      UPNP_NS)).text = self.storageMedium

        if self.publisher is not None:
            ET.SubElement(root, qname('publisher',
                                      DC_NS)).text = self.contributor

        if self.rights is not None:
            ET.SubElement(root, qname('rights', DC_NS)).text = self.rights

        return root
Beispiel #9
0
    def toElement(self, **kwargs):

        root = AudioItem.toElement(self, **kwargs)

        if self.album is not None:
            ET.SubElement(root, qname('album', UPNP_NS)).text = self.album

        if self.playlist is not None:
            ET.SubElement(root, qname('playlist',
                                      UPNP_NS)).text = self.playlist

        if self.storageMedium is not None:
            ET.SubElement(root, qname('storageMedium',
                                      UPNP_NS)).text = self.storageMedium

        if self.contributor is not None:
            ET.SubElement(root, qname('contributor',
                                      DC_NS)).text = self.contributor

        return root
Beispiel #10
0
 def to_element(self):
     root = ET.Element(self.name)
     for key, value in self.items():
         if isinstance(value, (dict, list)):
             root.append(value.to_element())
         else:
             s = ET.SubElement(root, key)
             if isinstance(value, basestring):
                 s.text = value
             else:
                 s.text = str(value)
     return root
Beispiel #11
0
    def propagate_notification(self, notify):
        #print "propagate_notification", notify
        if len(self._subscribers) <= 0:
            return
        if len(notify) <= 0:
            return

        root = ET.Element('e:propertyset')
        root.attrib['xmlns:e'] = 'urn:schemas-upnp-org:event-1-0'

        if isinstance(notify, variable.StateVariable):
            notify = [
                notify,
            ]

        evented_variables = 0
        for n in notify:
            e = ET.SubElement(root, 'e:property')
            if n.name == 'LastChange':
                text = self.build_last_change_event(instance=n.instance)
                if text is not None:
                    ET.SubElement(e, n.name).text = text
                    evented_variables += 1
            else:
                s = ET.SubElement(e, n.name).text = str(n.value)
                evented_variables += 1
                if n.dependant_variable != None:
                    dependants = n.dependant_variable.get_allowed_values()
                    if dependants != None and len(dependants) > 0:
                        s.attrib['channel'] = dependants[0]

        if evented_variables == 0:
            return
        xml = ET.tostring(root, encoding='utf-8')
        #print "propagate_notification", xml
        for s in self._subscribers.values():
            d, p = event.send_notification(s, xml)
            self._pending_notifications[d] = p
            d.addBoth(self.rm_notification, d)
Beispiel #12
0
 def save(self, file=None):
     if file == None:
         file = self.file
     e = ET.Element(self.name)
     for key, value in self.items():
         if isinstance(value, (dict, list)):
             e.append(value.to_element())
         else:
             s = ET.SubElement(e, key)
             if isinstance(value, basestring):
                 s.text = value
             else:
                 s.text = str(value)
     indent(e)
     db = ET.ElementTree(e)
     db.write(file, encoding='utf-8')
Beispiel #13
0
def build_soap_error(status, description='without words'):
    """ builds an UPnP SOAP error msg
    """
    root = ET.Element('s:Fault')
    ET.SubElement(root, 'faultcode').text = 's:Client'
    ET.SubElement(root, 'faultstring').text = 'UPnPError'
    e = ET.SubElement(root, 'detail')
    e = ET.SubElement(e, 'UPnPError')
    e.attrib['xmlns'] = 'urn:schemas-upnp-org:control-1-0'
    ET.SubElement(e, 'errorCode').text = str(status)
    ET.SubElement(e, 'errorDescription').text = UPNPERRORS.get(
        status, description)
    return build_soap_call(None, root, encoding=None)
Beispiel #14
0
    def __init__(self,
                 hostname,
                 uuid,
                 urlbase,
                 xmlns='urn:schemas-upnp-org:device-1-0',
                 device_uri_base='urn:schemas-upnp-org:device',
                 device_type='BasicDevice',
                 version=2,
                 friendly_name='Coherence UPnP BasicDevice',
                 manufacturer='beebits.net',
                 manufacturer_url='http://coherence.beebits.net',
                 model_description='Coherence UPnP BasicDevice',
                 model_name='Coherence UPnP BasicDevice',
                 model_number=__version__,
                 model_url='http://coherence.beebits.net',
                 serial_number='0000001',
                 presentation_url='',
                 services=[],
                 devices=[],
                 icons=[],
                 dlna_caps=[]):
        uuid = str(uuid)
        root = ET.Element('root')
        root.attrib['xmlns'] = xmlns
        device_type_uri = ':'.join(
            (device_uri_base, device_type, str(version)))
        e = ET.SubElement(root, 'specVersion')
        ET.SubElement(e, 'major').text = '1'
        ET.SubElement(e, 'minor').text = '0'

        #ET.SubElement(root, 'URLBase').text = urlbase + uuid[5:] + '/'

        d = ET.SubElement(root, 'device')

        if device_type == 'MediaServer':
            x = ET.SubElement(d, 'dlna:X_DLNADOC')
            x.attrib['xmlns:dlna'] = 'urn:schemas-dlna-org:device-1-0'
            x.text = 'DMS-1.50'
            x = ET.SubElement(d, 'dlna:X_DLNADOC')
            x.attrib['xmlns:dlna'] = 'urn:schemas-dlna-org:device-1-0'
            x.text = 'M-DMS-1.50'
        elif device_type == 'MediaRenderer':
            x = ET.SubElement(d, 'dlna:X_DLNADOC')
            x.attrib['xmlns:dlna'] = 'urn:schemas-dlna-org:device-1-0'
            x.text = 'DMR-1.50'
            x = ET.SubElement(d, 'dlna:X_DLNADOC')
            x.attrib['xmlns:dlna'] = 'urn:schemas-dlna-org:device-1-0'
            x.text = 'M-DMR-1.50'

        if len(dlna_caps) > 0:
            if isinstance(dlna_caps, basestring):
                dlna_caps = [dlna_caps]
            for cap in dlna_caps:
                x = ET.SubElement(d, 'dlna:X_DLNACAP')
                x.attrib['xmlns:dlna'] = 'urn:schemas-dlna-org:device-1-0'
                x.text = cap

        ET.SubElement(d, 'deviceType').text = device_type_uri
        ET.SubElement(d, 'friendlyName').text = friendly_name
        ET.SubElement(d, 'manufacturer').text = manufacturer
        ET.SubElement(d, 'manufacturerURL').text = manufacturer_url
        ET.SubElement(d, 'modelDescription').text = model_description
        ET.SubElement(d, 'modelName').text = model_name
        ET.SubElement(d, 'modelNumber').text = model_number
        ET.SubElement(d, 'modelURL').text = model_url
        ET.SubElement(d, 'serialNumber').text = serial_number
        ET.SubElement(d, 'UDN').text = uuid
        ET.SubElement(d, 'UPC').text = ''
        ET.SubElement(d, 'presentationURL').text = presentation_url

        if len(services):
            e = ET.SubElement(d, 'serviceList')
            for service in services:
                id = service.get_id()
                s = ET.SubElement(e, 'service')
                try:
                    namespace = service.namespace
                except:
                    namespace = 'schemas-upnp-org'
                if (hasattr(service, 'version') and service.version < version):
                    v = service.version
                else:
                    v = version
                ET.SubElement(
                    s,
                    'serviceType').text = 'urn:%s:service:%s:%d' % (namespace,
                                                                    id, int(v))
                try:
                    namespace = service.id_namespace
                except:
                    namespace = 'upnp-org'
                ET.SubElement(
                    s,
                    'serviceId').text = 'urn:%s:serviceId:%s' % (namespace, id)
                ET.SubElement(
                    s, 'SCPDURL'
                ).text = '/' + uuid[5:] + '/' + id + '/' + service.scpd_url
                ET.SubElement(
                    s, 'controlURL'
                ).text = '/' + uuid[5:] + '/' + id + '/' + service.control_url
                ET.SubElement(s, 'eventSubURL').text = '/' + uuid[
                    5:] + '/' + id + '/' + service.subscription_url

        if len(devices):
            e = ET.SubElement(d, 'deviceList')

        if len(icons):
            e = ET.SubElement(d, 'iconList')
            for icon in icons:

                icon_path = ''
                if icon.has_key('url'):
                    if icon['url'].startswith('file://'):
                        icon_path = icon['url'][7:]
                    elif icon['url'] == '.face':
                        icon_path = os.path.join(os.path.expanduser('~'),
                                                 ".face")
                    else:
                        from pkg_resources import resource_filename
                        icon_path = os.path.abspath(
                            resource_filename(
                                __name__,
                                os.path.join('..', '..', '..', 'misc',
                                             'device-icons', icon['url'])))

                if os.path.exists(icon_path) == True:
                    i = ET.SubElement(e, 'icon')
                    for k, v in icon.items():
                        if k == 'url':
                            if v.startswith('file://'):
                                ET.SubElement(i, k).text = '/' + uuid[
                                    5:] + '/' + os.path.basename(v)
                                continue
                            elif v == '.face':
                                ET.SubElement(
                                    i, k
                                ).text = '/' + uuid[5:] + '/' + 'face-icon.png'
                                continue
                            else:
                                ET.SubElement(i, k).text = '/' + uuid[
                                    5:] + '/' + os.path.basename(v)
                                continue
                        ET.SubElement(i, k).text = str(v)

        #if self.has_level(LOG_DEBUG):
        #    indent( root)

        self.xml = """<?xml version="1.0" encoding="utf-8"?>""" + ET.tostring(
            root, encoding='utf-8')
        static.Data.__init__(self, self.xml, 'text/xml')
Beispiel #15
0
 def build_single_notification(self, instance, variable_name, value):
     root = ET.Element('e:propertyset')
     root.attrib['xmlns:e'] = 'urn:schemas-upnp-org:event-1-0'
     e = ET.SubElement(root, 'e:property')
     s = ET.SubElement(e, variable_name).text = str(value)
     return ET.tostring(root, encoding='utf-8')
Beispiel #16
0
    def build_xml(self):
        root = ET.Element('scpd')
        root.attrib['xmlns'] = 'urn:schemas-upnp-org:service-1-0'
        e = ET.SubElement(root, 'specVersion')
        ET.SubElement(e, 'major').text = '1'
        ET.SubElement(e, 'minor').text = '0'

        e = ET.SubElement(root, 'actionList')
        for action in self.service_server._actions.values():
            s = ET.SubElement(e, 'action')
            ET.SubElement(s, 'name').text = action.get_name()
            al = ET.SubElement(s, 'argumentList')
            for argument in action.get_arguments_list():
                a = ET.SubElement(al, 'argument')
                ET.SubElement(a, 'name').text = argument.get_name()
                ET.SubElement(a, 'direction').text = argument.get_direction()
                ET.SubElement(a, 'relatedStateVariable'
                              ).text = argument.get_state_variable()

        e = ET.SubElement(root, 'serviceStateTable')
        for var in self.service_server._variables[0].values():
            s = ET.SubElement(e, 'stateVariable')
            if var.send_events == True:
                s.attrib['sendEvents'] = 'yes'
            else:
                s.attrib['sendEvents'] = 'no'
            ET.SubElement(s, 'name').text = var.name
            ET.SubElement(s, 'dataType').text = var.data_type
            if (not var.has_vendor_values and len(var.allowed_values)):
                #if len(var.allowed_values):
                v = ET.SubElement(s, 'allowedValueList')
                for value in var.allowed_values:
                    ET.SubElement(v, 'allowedValue').text = value

            if (var.allowed_value_range != None
                    and len(var.allowed_value_range) > 0):
                complete = True
                for name, value in var.allowed_value_range.items():
                    if value == None:
                        complete = False
                if complete == True:
                    avl = ET.SubElement(s, 'allowedValueRange')
                    for name, value in var.allowed_value_range.items():
                        if value != None:
                            ET.SubElement(avl, name).text = str(value)

        return """<?xml version="1.0" encoding="utf-8"?>""" + ET.tostring(
            root, encoding='utf-8')
Beispiel #17
0
def build_soap_call(method,
                    arguments,
                    is_response=False,
                    encoding=SOAP_ENCODING,
                    envelope_attrib=None,
                    typed=None):
    """ create a shell for a SOAP request or response element
        - set method to none to omitt the method element and
          add the arguments directly to the body (for an error msg)
        - arguments can be a dict or an ET.Element
    """
    envelope = ET.Element("s:Envelope")
    if envelope_attrib:
        for n in envelope_attrib:
            envelope.attrib.update({n[0]: n[1]})
    else:
        envelope.attrib.update(
            {'s:encodingStyle': "http://schemas.xmlsoap.org/soap/encoding/"})
        envelope.attrib.update(
            {'xmlns:s': "http://schemas.xmlsoap.org/soap/envelope/"})

    body = ET.SubElement(envelope, "s:Body")

    if method:
        # append the method call
        if is_response is True:
            method += "Response"
        re = ET.SubElement(body, method)
        if encoding:
            re.set(NS_SOAP_ENV + "encodingStyle", encoding)
    else:
        re = body

    # append the arguments
    if isinstance(arguments, (dict, OrderedDict)):
        type_map = {
            str: 'xsd:string',
            unicode: 'xsd:string',
            int: 'xsd:int',
            float: 'xsd:float',
            bool: 'xsd:boolean'
        }

        for arg_name, arg_val in arguments.iteritems():
            arg_type = type_map[type(arg_val)]
            if arg_type == 'xsd:string' and type(arg_val) == unicode:
                arg_val = arg_val.encode('utf-8')
            if arg_type == 'xsd:int' or arg_type == 'xsd:float':
                arg_val = str(arg_val)
            if arg_type == 'xsd:boolean':
                arg_val = arg_val.lower()

            e = ET.SubElement(re, arg_name)
            if typed and arg_type:
                if not isinstance(type, ET.QName):
                    arg_type = ET.QName("http://www.w3.org/1999/XMLSchema",
                                        arg_type)
                e.set(NS_XSI + "type", arg_type)
            e.text = arg_val
    else:
        if arguments == None:
            arguments = {}
        re.append(arguments)

    preamble = """<?xml version="1.0" encoding="utf-8"?>"""
    return preamble + ET.tostring(envelope, 'utf-8')
Beispiel #18
0
 def toElement(self, **kwargs):
     root = ImageItem.toElement(self, **kwargs)
     if self.album is not None:
         ET.SubElement(root, qname('album', UPNP_NS)).text = self.album
     return root
Beispiel #19
0
    def toElement(self, **kwargs):

        root = ET.Element(self.elementName)

        #if self.id == 1000:
        #    root.attrib['id'] = '0'
        #    ET.SubElement(root, 'dc:title').text = 'root'
        #else:
        #    root.attrib['id'] = str(self.id)
        #    ET.SubElement(root, 'dc:title').text = self.title

        root.attrib['id'] = str(self.id)
        ET.SubElement(root, qname('title', DC_NS)).text = self.title

        #if self.title != None:
        #    ET.SubElement(root, 'dc:title').text = self.title
        #else:
        #    ET.SubElement(root, 'dc:title').text = 'root'

        root.attrib['parentID'] = str(self.parentID)

        if (kwargs.get('upnp_client', '') != 'XBox'):
            if self.refID:
                root.attrib['refID'] = str(self.refID)

        if kwargs.get('requested_id', None):
            if kwargs.get('requested_id') == '0':
                t = root.find(qname('title', DC_NS))
                t.text = 'root'
            #if kwargs.get('requested_id') != '0' and kwargs.get('requested_id') != root.attrib['id']:
            if kwargs.get('requested_id') != root.attrib['id']:
                if (kwargs.get('upnp_client', '') != 'XBox'):
                    root.attrib['refID'] = root.attrib['id']
                r_id = kwargs.get('requested_id')
                root.attrib['id'] = r_id
                r_id = r_id.split('@', 1)
                try:
                    root.attrib['parentID'] = r_id[1]
                except IndexError:
                    pass
                if (kwargs.get('upnp_client', '') != 'XBox'):
                    self.info("Changing ID from %r to %r, with parentID %r",
                              root.attrib['refID'], root.attrib['id'],
                              root.attrib['parentID'])
                else:
                    self.info("Changing ID from %r to %r, with parentID %r",
                              self.id, root.attrib['id'],
                              root.attrib['parentID'])
        elif kwargs.get('parent_container', None):
            if (kwargs.get('parent_container') != '0' and
                    kwargs.get('parent_container') != root.attrib['parentID']):
                if (kwargs.get('upnp_client', '') != 'XBox'):
                    root.attrib['refID'] = root.attrib['id']
                root.attrib['id'] = '@'.join(
                    (root.attrib['id'], kwargs.get('parent_container')))
                root.attrib['parentID'] = kwargs.get('parent_container')
                if (kwargs.get('upnp_client', '') != 'XBox'):
                    self.info(
                        "Changing ID from %r to %r, with parentID from %r to %r",
                        root.attrib['refID'], root.attrib['id'], self.parentID,
                        root.attrib['parentID'])
                else:
                    self.info(
                        "Changing ID from %r to %r, with parentID from %r to %r",
                        self.id, root.attrib['id'], self.parentID,
                        root.attrib['parentID'])

        ET.SubElement(root, qname('class', UPNP_NS)).text = self.upnp_class

        if kwargs.get('upnp_client', '') == 'XBox':
            u = root.find(qname('class', UPNP_NS))
            if (kwargs.get('parent_container', None) != None
                    and u.text.startswith('object.container')):
                if kwargs.get('parent_container') in ('14', '15', '16'):
                    u.text = 'object.container.storageFolder'
            if self.upnp_class == 'object.container':
                u.text = 'object.container.storageFolder'

        if self.restricted:
            root.attrib['restricted'] = '1'
        else:
            root.attrib['restricted'] = '0'

        if self.creator is not None:
            ET.SubElement(root, qname('creator', DC_NS)).text = self.creator

        if self.writeStatus is not None:
            ET.SubElement(root, qname('writeStatus',
                                      UPNP_NS)).text = self.writeStatus

        if self.date is not None:
            if isinstance(self.date, datetime):
                ET.SubElement(root, qname('date',
                                          DC_NS)).text = self.date.isoformat()
            else:
                ET.SubElement(root, qname('date', DC_NS)).text = self.date
        else:
            ET.SubElement(root,
                          qname('date',
                                DC_NS)).text = utils.datefaker().isoformat()

        if self.albumArtURI is not None:
            e = ET.SubElement(root, qname('albumArtURI', UPNP_NS))
            e.text = self.albumArtURI
            e.attrib['xmlns:dlna'] = 'urn:schemas-dlna-org:metadata-1-0'
            e.attrib['dlna:profileID'] = 'JPEG_TN'

        if self.artist is not None:
            ET.SubElement(root, qname('artist', UPNP_NS)).text = self.artist

        if self.genre is not None:
            ET.SubElement(root, qname('genre', UPNP_NS)).text = self.genre

        if self.genres is not None:
            for genre in self.genres:
                ET.SubElement(root, qname('genre', UPNP_NS)).text = genre

        if self.originalTrackNumber is not None:
            ET.SubElement(root,
                          qname('originalTrackNumber',
                                UPNP_NS)).text = str(self.originalTrackNumber)

        if self.description is not None:
            ET.SubElement(root, qname('description',
                                      DC_NS)).text = self.description

        if self.longDescription is not None:
            ET.SubElement(root, qname('longDescription',
                                      UPNP_NS)).text = self.longDescription

        if self.server_uuid is not None:
            ET.SubElement(root, qname('server_uuid',
                                      UPNP_NS)).text = self.server_uuid

        return root