|
- #!/usr/bin/env python
-
- # Licensed under the MIT license
- # http://opensource.org/licenses/mit-license.php
- # Copyright 2005, Tim Potter <tpot@samba.org>
- # Copyright 2006-2009 John-Mark Gurney <jmg@funkthat.com>
-
- __version__ = '$Change: 1740 $'
- # $Id: //depot/python/pymeds/main/pymeds.py#17 $
-
- # make sure debugging is initalized first, other modules can be pulled in
- # before the "real" debug stuff is setup. (hmm I could make this a two
- # stage, where we simulate a namespace to either be thrown away when the
- # time comes, or merge into the correct one)
- import debug # my debugging module
- debug.doDebugging(False) # open up debugging port
-
- # Modules to import, maybe config file or something?
- def tryloadmodule(mod):
- try:
- return __import__(mod)
- except ImportError:
- import traceback
- traceback.print_exc()
- pass
-
- # ZipStorage w/ tar support should be last as it will gobble up empty files.
- # These should be sorted by how much work they do, the least work the earlier.
- # mpegtsmod can be really expensive.
- modules = [
- 'audio',
- 'Clip',
- 'pyvr',
- 'audioraw',
- 'item',
- 'slinkemod',
- 'dvd',
- 'ZipStorage',
- 'mpegtsmod',
- ]
- modmap = {}
- for i in modules:
- modmap[i] = tryloadmodule(i)
-
- for i in modules:
- debug.insertnamespace(i, modmap[i])
-
- # Check to see which ones didn't get loaded
- checkmodules = [ x for x in modmap if modmap[x] is None ]
-
- if checkmodules:
- checkmodules.sort()
- print('The following modules were not loaded:', ', '.join(checkmodules))
-
- from FSStorage import FSDirectory
- import os
- import os.path
- import random
- import socket
- import string
- import urllib.parse
- from twisted.application import internet, service
- from twisted.python import usage
-
- def generateuuid():
- return ''.join([ 'uuid:'] + [random.choice(string.ascii_letters) for x in range(20)])
-
- class Options(usage.Options):
- checkpath = True
- optParameters = [
- [ 'title', 't', 'My Media Server', 'Title of the server.', ],
- [ 'path', 'p', 'media', 'Root path of the media to be served.', ],
- ]
-
- def postOptions(self):
- p = self['path']
- if self.checkpath and not os.path.isdir(p):
- raise usage.UsageError('path %s does not exist' % repr(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(args[1])
- if port < 1024 or port > 65535:
- raise ValueError(
- 'port must be between 1024 and 65535')
- self['port'] = port
-
- def fixupmimetypes():
- # 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.
- from twisted.web import static
- 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',
-
- '.flv': 'video/x-flv',
- #'.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.
- })
-
- def makeService(config):
- listenAddr = config['addr']
- listenPort = config['port']
-
- uuid = config.get('uuid', None)
- if uuid is None:
- 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 = open('root-device.xml').read() % r
- static.Data.__init__(self, bytes(d, 'ascii'), '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=urllib.parse.urljoin(urlbase, 'content'),
- webbase=content)
- debug.insertnamespace('cds', cds)
- root.putChild(b'ContentDirectory', cds)
- cds = cds.control
- root.putChild(b'ConnectionManager', ConnectionManagerServer())
- root.putChild(b'root-device.xml', RootDevice())
- root.putChild(b'content', content)
-
- fixupmimetypes()
-
- site = server.Site(root)
-
- # Create SSDP server
- from SSDP import SSDPServer, SSDP_PORT
-
- s = SSDPServer()
- debug.insertnamespace('s', s)
-
- class PyMedS(service.MultiService):
- def startService(self):
- service.MultiService.startService(self)
-
- rdxml = urllib.parse.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:service:ConnectionManager:1', rdxml)
-
- s.register('%s::urn:schemas-upnp-org:service:ContentDirectory:1' % uuid,
- 'urn:schemas-upnp-org:service:ContentDirectory:1', rdxml)
-
- def stopService(self):
- # Some reason stopProtocol isn't called
- s.doStop()
- service.MultiService.stopService(self)
-
- import pickle
- pickle.dump(cds, open('test.pickle', 'wb'), -1)
-
- serv = PyMedS()
-
- internet.TCPServer(listenPort, site, interface=listenAddr).setServiceParent(serv)
- internet.MulticastServer(SSDP_PORT, s,
- listenMultiple=True).setServiceParent(serv)
-
- return serv
|