@@ -47,9 +47,6 @@ import os.path
import random
import socket
import string
import sys
from twisted.python import log
from twisted.internet import reactor
from twisted.application import internet, service
from twisted.python import usage
@@ -64,120 +61,132 @@ class Options(usage.Options):
[ 'path', 'p', 'media', 'Root path of the media to be served.', ],
]
def parseArgs(self, addr, port=None):
self['addr'] = addr
if port is None:
def postOptions(self):
p = self['path']
if not os.path.isdir(p):
raise usage.UsageError, 'path %s does not exist' % `p`
def parseArgs(self, *args):
# XXX - twisted doesn't let you provide a message on what
# arguments are required, so we will do our own work in here.
if len(args) not in (1, 2):
raise usage.UsageError, 'Arguments: addr [ port ]'
self['addr'] = args[0]
if len(args) == 1:
port = random.randint(10000, 65000)
else:
port = int(port)
if listenPort < 1024 or listenPort > 65535:
port = int(args[1] )
if port < 1024 or p ort > 65535:
raise ValueError(
'port must be between 1024 and 65535')
self['port'] = port
listenAddr = config['addr']
listenPort = config['port']
application = service.Application("PyMeds")
# Create SSDP server
from SSDP import SSDPServer, SSDP_PORT, SSDP_ADDR
s = SSDPServer()
debug.insertnamespace('s', s)
port = internet.MulticastServer(SSDP_PORT, s, listenMultiple=True)
port.setServiceParent(application)
port.joinGroup(SSDP_ADDR)
port.setLoopbackMode(0) # don't get our own sends
uuid = generateuuid()
urlbase = 'http://%s:%d/' % (listenAddr, listenPort)
# Create SOAP server and content server
from twisted.web import server, resource, static
from ContentDirectory import ContentDirectoryServer
from ConnectionManager import ConnectionManagerServer
class WebServer(resource.Resource):
def __init__(self):
resource.Resource.__init__(self)
class RootDevice(static.Data):
def __init__(self):
r = {
'hostname': socket.gethostname(),
'uuid': uuid,
'urlbase': urlbase,
}
d = file('root-device.xml').read() % r
static.Data.__init__(self, d, 'text/xml')
root = WebServer()
debug.insertnamespace('root', root)
content = resource.Resource()
# This sets up the root to be the media dir so we don't have to enumerate
# the directory
cds = ContentDirectoryServer(config['title'], klass=FSDirectory,
path=config['path'], urlbase=os.path.join(urlbase, 'content'),
webbase=content)
debug.insertnamespace('cds', cds)
root.putChild('ContentDirectory', cds)
cds = cds.control
root.putChild('ConnectionManager', ConnectionManagerServer())
root.putChild('root-device.xml', RootDevice())
root.putChild('content', content)
# Purely to ensure some sane mime-types. On MacOSX I need these.
# XXX - There isn't any easier way to get to the mime-type dict that I know of.
medianode = static.File('pymediaserv')
medianode.contentTypes.update( {
# From: http://support.microsoft.com/kb/288102
'.asf': 'video/x-ms-asf',
'.asx': 'video/x-ms-asf',
'.wma': 'audio/x-ms-wma',
'.wax': 'audio/x-ms-wax',
'.wmv': 'video/x-ms-wmv',
'.wvx': 'video/x-ms-wvx',
'.wm': 'video/x-ms-wm',
'.wmx': 'video/x-ms-wmx',
# From: http://www.matroska.org/technical/specs/notes.html
'.mkv': 'video/x-matroska',
'.mka': 'audio/x-matroska',
#'.ts': 'video/mp2t',
'.ts': 'video/mpeg', # we may want this instead of mp2t
'.m2t': 'video/mpeg',
'.m2ts': 'video/mpeg',
'.mp4': 'video/mp4',
#'.mp4': 'video/mpeg',
'.dat': 'video/mpeg', # VCD tracks
'.ogm': 'application/ogg',
'.vob': 'video/mpeg',
#'.m4a': 'audio/mp4', # D-Link can't seem to play AAC files.
})
del medianode
site = server.Site(root)
internet.TCPServer(listenPort, site).setServiceParent(application)
# we need to do this after the children are there, since we send notifies
import urlparse
rdxml = urlparse.join(urlbase, 'root-device.xml')
s.register('%s::upnp:rootdevice' % uuid,
'upnp:rootdevice', rdxml)
s.register(uuid,
uuid,
rdxml)
s.register('%s::urn:schemas-upnp-org:device:MediaServer:1' % uuid,
'urn:schemas-upnp-org:device:MediaServer:1', rdxml)
s.register('%s::urn:schemas-upnp-org:service:ConnectionManager:1' % uuid,
'urn:schemas-upnp-org:device:ConnectionManager:1', rdxml)
s.register('%s::urn:schemas-upnp-org:service:ContentDirectory:1' % uuid,
'urn:schemas-upnp-org:device:ContentDirectory:1', rdxml)
def makeService(config):
listenAddr = config['addr']
listenPort = config['port']
serv = service.MultiService()
# Create SSDP server
from SSDP import SSDPServer, SSDP_PORT
s = SSDPServer()
debug.insertnamespace('s', s)
internet.MulticastServer(SSDP_PORT, s,
listenMultiple=True).setServiceParent(serv)
uuid = generateuuid()
urlbase = 'http://%s:%d/' % (listenAddr, listenPort)
# Create SOAP server and content server
from twisted.web import server, resource, static
from ContentDirectory import ContentDirectoryServer
from ConnectionManager import ConnectionManagerServer
class WebServer(resource.Resource):
def __init__(self):
resource.Resource.__init__(self)
class RootDevice(static.Data):
def __init__(self):
r = {
'hostname': socket.gethostname(),
'uuid': uuid,
'urlbase': urlbase,
}
d = file('root-device.xml').read() % r
static.Data.__init__(self, d, 'text/xml')
root = WebServer()
debug.insertnamespace('root', root)
content = resource.Resource()
# This sets up the root to be the media dir so we don't have to enumerate
# the directory
cds = ContentDirectoryServer(config['title'], klass=FSDirectory,
path=config['path'], urlbase=os.path.join(urlbase, 'content'),
webbase=content)
debug.insertnamespace('cds', cds)
root.putChild('ContentDirectory', cds)
cds = cds.control
root.putChild('ConnectionManager', ConnectionManagerServer())
root.putChild('root-device.xml', RootDevice())
root.putChild('content', content)
# Purely to ensure some sane mime-types. On MacOSX I need these.
# XXX - There isn't any easier way to get to the mime-type dict that I know of.
medianode = static.File('pymediaserv')
medianode.contentTypes.update( {
# From: http://support.microsoft.com/kb/288102
'.asf': 'video/x-ms-asf',
'.asx': 'video/x-ms-asf',
'.wma': 'audio/x-ms-wma',
'.wax': 'audio/x-ms-wax',
'.wmv': 'video/x-ms-wmv',
'.wvx': 'video/x-ms-wvx',
'.wm': 'video/x-ms-wm',
'.wmx': 'video/x-ms-wmx',
# From: http://www.matroska.org/technical/specs/notes.html
'.mkv': 'video/x-matroska',
'.mka': 'audio/x-matroska',
#'.ts': 'video/mp2t',
'.ts': 'video/mpeg', # we may want this instead of mp2t
'.m2t': 'video/mpeg',
'.m2ts': 'video/mpeg',
'.mp4': 'video/mp4',
#'.mp4': 'video/mpeg',
'.dat': 'video/mpeg', # VCD tracks
'.ogm': 'application/ogg',
'.vob': 'video/mpeg',
#'.m4a': 'audio/mp4', # D-Link can't seem to play AAC files.
})
del medianode
site = server.Site(root)
internet.TCPServer(listenPort, site).setServiceParent(serv)
# we need to do this after the children are there, since we send notifies
import urlparse
rdxml = urlparse.urljoin(urlbase, 'root-device.xml')
s.register('%s::upnp:rootdevice' % uuid,
'upnp:rootdevice', rdxml)
s.register(uuid,
uuid,
rdxml)
s.register('%s::urn:schemas-upnp-org:device:MediaServer:1' % uuid,
'urn:schemas-upnp-org:device:MediaServer:1', rdxml)
s.register('%s::urn:schemas-upnp-org:service:ConnectionManager:1' % uuid,
'urn:schemas-upnp-org:device:ConnectionManager:1', rdxml)
s.register('%s::urn:schemas-upnp-org:service:ContentDirectory:1' % uuid,
'urn:schemas-upnp-org:device:ContentDirectory:1', rdxml)
return serv