A Python UPnP Media Server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.8 KiB

  1. #!/usr/bin/env python
  2. # Licensed under the MIT license
  3. # http://opensource.org/licenses/mit-license.php
  4. # (c) 2005, Tim Potter <tpot@samba.org>
  5. import random
  6. import socket
  7. import string
  8. import sys
  9. from twisted.python import log
  10. from twisted.internet import reactor
  11. def generateuuid():
  12. if False:
  13. return 'uuid:asdflkjewoifjslkdfj'
  14. return ''.join([ 'uuid:'] + map(lambda x: random.choice(string.letters), xrange(20)))
  15. listenAddr = sys.argv[1]
  16. if len(sys.argv) > 2:
  17. listenPort = int(sys.argv[2])
  18. if listenPort < 1024 or listenPort > 65535:
  19. raise ValueError, 'port out of range'
  20. else:
  21. listenPort = random.randint(10000, 65000)
  22. log.startLogging(sys.stdout)
  23. # Create SSDP server
  24. from SSDP import SSDPServer, SSDP_PORT, SSDP_ADDR
  25. s = SSDPServer()
  26. port = reactor.listenMulticast(SSDP_PORT, s)
  27. port.joinGroup(SSDP_ADDR)
  28. port.setLoopbackMode(0) # don't get our own sends
  29. uuid = generateuuid()
  30. urlbase = 'http://%s:%d/' % (listenAddr, listenPort)
  31. # Create SOAP server
  32. from twisted.web import server, resource, static
  33. from ContentDirectory import ContentDirectoryServer
  34. from ConnectionManager import ConnectionManagerServer
  35. class WebServer(resource.Resource):
  36. def __init__(self):
  37. resource.Resource.__init__(self)
  38. class RootDevice(static.Data):
  39. def __init__(self):
  40. r = {
  41. 'hostname': socket.gethostname(),
  42. 'uuid': uuid,
  43. 'urlbase': urlbase,
  44. }
  45. d = file('root-device.xml').read() % r
  46. static.Data.__init__(self, d, 'text/xml')
  47. root = WebServer()
  48. root.putChild('ContentDirectory', ContentDirectoryServer())
  49. root.putChild('ConnectionManager', ConnectionManagerServer())
  50. root.putChild('root-device.xml', RootDevice())
  51. # Area of server to serve media files from
  52. from MediaServer import MediaServer
  53. medianode = static.File('media')
  54. medianode.contentTypes.update( {
  55. '.wmv': 'video/x-ms-wmv',
  56. '.ts': 'video/mp2t',
  57. #'.ts': 'video/mpeg', # we may want this instead of mp2t
  58. '.mp4': 'video/mp4',
  59. })
  60. root.putChild('media', medianode)
  61. site = server.Site(root)
  62. reactor.listenTCP(listenPort, site)
  63. # we need to do this after the children are there, since we send notifies
  64. s.register('%s::upnp:rootdevice' % uuid,
  65. 'upnp:rootdevice',
  66. urlbase + 'root-device.xml')
  67. s.register(uuid,
  68. uuid,
  69. urlbase + 'root-device.xml')
  70. s.register('%s::urn:schemas-upnp-org:device:MediaServer:1' % uuid,
  71. 'urn:schemas-upnp-org:device:MediaServer:1',
  72. urlbase + 'root-device.xml')
  73. s.register('%s::urn:schemas-upnp-org:service:ConnectionManager:1' % uuid,
  74. 'urn:schemas-upnp-org:device:ConnectionManager:1',
  75. urlbase + 'root-device.xml')
  76. s.register('%s::urn:schemas-upnp-org:service:ContentDirectory:1' % uuid,
  77. 'urn:schemas-upnp-org:device:ContentDirectory:1',
  78. urlbase + 'root-device.xml')
  79. # Main loop
  80. reactor.run()