Viewing file: basics.py (13.4 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# -*- coding: utf-8 -*-
# Licensed under the MIT license # http://opensource.org/licenses/mit-license.php
# Copyright 2008 Frank Scholz <coherence@beebits.net>
import os.path
from twisted.python import util from twisted.web import resource, static from twisted.internet import reactor
from coherence import __version__
from coherence.extern.et import ET, indent
import coherence.extern.louie as louie
from coherence import log
class DeviceHttpRoot(resource.Resource, log.Loggable): logCategory = 'basicdevice'
def __init__(self, server): resource.Resource.__init__(self) self.server = server
def getChildWithDefault(self, path, request): self.info('DeviceHttpRoot %s getChildWithDefault ' % self.server.device_type, path, request.uri, request.client) self.info( request.getAllHeaders()) if self.children.has_key(path): return self.children[path] if request.uri == '/': return self return self.getChild(path, request)
def getChild(self, name, request): self.info('DeviceHttpRoot %s getChild %s ' % (name, request)) ch = None if ch is None: p = util.sibpath(__file__, name) if os.path.exists(p): ch = static.File(p) self.info('DeviceHttpRoot ch ', ch) return ch
def listchilds(self, uri): cl = '' for c in self.children: cl += '<li><a href=%s/%s>%s</a></li>' % (uri,c,c) return cl
def render(self,request): return '<html><p>root of the %s %s</p><p><ul>%s</ul></p></html>'% (self.server.backend.name, self.server.device_type, self.listchilds(request.uri))
class RootDeviceXML(static.Data):
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')
class BasicDeviceMixin(object):
def __init__(self, coherence, backend, **kwargs): self.coherence = coherence if not hasattr(self,'version'): self.version = int(kwargs.get('version',self.coherence.config.get('version',2)))
try: self.uuid = kwargs['uuid'] if not self.uuid.startswith('uuid:'): self.uuid = 'uuid:' + self.uuid except KeyError: from coherence.upnp.core.uuid import UUID self.uuid = UUID()
self.backend = None urlbase = self.coherence.urlbase if urlbase[-1] != '/': urlbase += '/' self.urlbase = urlbase + str(self.uuid)[5:]
kwargs['urlbase'] = self.urlbase self.icons = kwargs.get('iconlist', kwargs.get('icons', [])) if len(self.icons) == 0: if kwargs.has_key('icon'): if isinstance(kwargs['icon'],dict): self.icons.append(kwargs['icon']) else: self.icons = kwargs['icon']
louie.connect( self.init_complete, 'Coherence.UPnP.Backend.init_completed', louie.Any) louie.connect( self.init_failed, 'Coherence.UPnP.Backend.init_failed', louie.Any) reactor.callLater(0.2, self.fire, backend, **kwargs)
def init_failed(self, backend, msg): if self.backend != backend: return self.warning('backend not installed, %s activation aborted - %s' % (self.device_type,msg.getErrorMessage())) self.debug(msg) try: del self.coherence.active_backends[str(self.uuid)] except KeyError: pass
def register(self): s = self.coherence.ssdp_server uuid = str(self.uuid) host = self.coherence.hostname self.msg('%s register' % self.device_type) # we need to do this after the children are there, since we send notifies s.register('local', '%s::upnp:rootdevice' % uuid, 'upnp:rootdevice', self.coherence.urlbase + uuid[5:] + '/' + 'description-%d.xml' % self.version, host=host)
s.register('local', uuid, uuid, self.coherence.urlbase + uuid[5:] + '/' + 'description-%d.xml' % self.version, host=host)
version = self.version while version > 0: if version == self.version: silent = False else: silent = True s.register('local', '%s::urn:schemas-upnp-org:device:%s:%d' % (uuid, self.device_type, version), 'urn:schemas-upnp-org:device:%s:%d' % (self.device_type, version), self.coherence.urlbase + uuid[5:] + '/' + 'description-%d.xml' % version, silent=silent, host=host) version -= 1
for service in self._services: device_version = self.version service_version = self.version if hasattr(service,'version'): service_version = service.version silent = False
while service_version > 0: try: namespace = service.namespace except: namespace = 'schemas-upnp-org'
device_description_tmpl = 'description-%d.xml' % device_version if hasattr(service,'device_description_tmpl'): device_description_tmpl = service.device_description_tmpl
s.register('local', '%s::urn:%s:service:%s:%d' % (uuid,namespace,service.id, service_version), 'urn:%s:service:%s:%d' % (namespace,service.id, service_version), self.coherence.urlbase + uuid[5:] + '/' + device_description_tmpl, silent=silent, host=host)
silent = True service_version -= 1 device_version -= 1
def unregister(self):
if self.backend != None and hasattr(self.backend,'release'): self.backend.release()
if not hasattr(self,'_services'): """ seems we never made it to actually completing that device """ return
for service in self._services: try: service.check_subscribers_loop.stop() except: pass if hasattr(service,'check_moderated_loop') and service.check_moderated_loop != None: try: service.check_moderated_loop.stop() except: pass if hasattr(service,'release'): service.release() if hasattr(service,'_release'): service._release()
s = self.coherence.ssdp_server uuid = str(self.uuid) self.coherence.remove_web_resource(uuid[5:])
version = self.version while version > 0: s.doByebye('%s::urn:schemas-upnp-org:device:%s:%d' % (uuid, self.device_type, version)) for service in self._services: if hasattr(service,'version') and service.version < version: continue try: namespace = service.namespace except AttributeError: namespace = 'schemas-upnp-org' s.doByebye('%s::urn:%s:service:%s:%d' % (uuid,namespace,service.id, version))
version -= 1
s.doByebye(uuid) s.doByebye('%s::upnp:rootdevice' % uuid)
|