From 1cecec9d85f5750be239b81494efb12d277636f6 Mon Sep 17 00:00:00 2001
From: John-Mark Gurney <jmg@funkthat.com>
Date: Fri, 26 Dec 2008 23:47:23 -0800
Subject: [PATCH] This change isn't complete, but I wanted to show the diffs
 here before I make them a subroutine...

[git-p4: depot-paths = "//depot/": change = 1269]
---
 pymeds.py | 80 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 43 insertions(+), 37 deletions(-)

diff --git a/pymeds.py b/pymeds.py
index c9a24d6..4e4dcb5 100755
--- a/pymeds.py
+++ b/pymeds.py
@@ -41,7 +41,6 @@ for i in modules:
 for i in modules:
 	debug.insertnamespace(i, modmap[i])
 
-from DIDLLite import TextItem, AudioItem, VideoItem, ImageItem, Resource, StorageFolder
 from FSStorage import FSDirectory
 import os
 import os.path
@@ -51,38 +50,51 @@ 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
 
 def generateuuid():
 	if False:
 		return 'uuid:asdflkjewoifjslkdfj'
 	return ''.join([ 'uuid:'] + map(lambda x: random.choice(string.letters), xrange(20)))
 
-listenAddr = sys.argv[1]
-if len(sys.argv) > 2:
-	listenPort = int(sys.argv[2])
-	if listenPort < 1024 or listenPort > 65535:
-		raise ValueError, 'port out of range'
-else:
-	listenPort = random.randint(10000, 65000)
+class Options(usage.Options):
+	optParameters = [
+		[ 'title', 't', 'My Media Server', 'Title of the server.', ],
+		[ 'path', 'p', 'media', 'Root path of the media to be served.', ],
+	    ]
 
-log.startLogging(sys.stdout)
+	def parseArgs(self, addr, port=None):
+		self['addr'] = addr
+		if port is None:
+			port = random.randint(10000, 65000)
+		else:
+			port = int(port)
+			if listenPort < 1024 or listenPort > 65535:
+				raise ValueError(
+				    'port must be between 1024 and 65535')
+		self['port'] = port
 
-# Create SSDP server
+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 = reactor.listenMulticast(SSDP_PORT, s, listenMultiple=True)
+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
-
+# Create SOAP server and content server
 from twisted.web import server, resource, static
 from ContentDirectory import ContentDirectoryServer
 from ConnectionManager import ConnectionManagerServer
@@ -104,16 +116,11 @@ class RootDevice(static.Data):
 root = WebServer()
 debug.insertnamespace('root', root)
 content = resource.Resource()
-mediapath = 'media'
-if not os.path.isdir(mediapath):
-	print >>sys.stderr, \
-	    'Sorry, %s is not a directory, no content to serve.' % `mediapath`
-	sys.exit(1)
-
-# This sets up the root to be the media dir so we don't have to
-# enumerate the directory
-cds = ContentDirectoryServer('My Media Server', klass=FSDirectory,
-    path=mediapath, urlbase=os.path.join(urlbase, 'content'), webbase=content)
+# 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
@@ -123,6 +130,7 @@ 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
@@ -135,6 +143,10 @@ medianode.contentTypes.update( {
 	'.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',
@@ -149,29 +161,23 @@ medianode.contentTypes.update( {
 del medianode
 
 site = server.Site(root)
-reactor.listenTCP(listenPort, site)
+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',
-		urlbase + 'root-device.xml')
+		'upnp:rootdevice', rdxml)
 
 s.register(uuid,
 		uuid,
-		urlbase + 'root-device.xml')
+		rdxml)
 
 s.register('%s::urn:schemas-upnp-org:device:MediaServer:1' % uuid,
-		'urn:schemas-upnp-org:device:MediaServer:1',
-		urlbase + 'root-device.xml')
+		'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',
-		urlbase + 'root-device.xml')
+		'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',
-		urlbase + 'root-device.xml')
-
-# Main loop
-
-reactor.run()
+		'urn:schemas-upnp-org:device:ContentDirectory:1', rdxml)