Forked mumble-django project from https://bitbucket.org/Svedrin/mumble-django
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.

145 lines
5.6 KiB

  1. # -*- coding: utf-8 -*-
  2. # mumble-django contributed by withgod@sourceforge.net
  3. from PIL import Image
  4. from struct import pack, unpack
  5. from zlib import compress, decompress
  6. from mctl import MumbleCtlBase
  7. import dbus
  8. class MumbleCtlDbus(MumbleCtlBase):
  9. meta = None
  10. dbus_base='net.sourceforge.mumble.murmur'
  11. def __init__(self):
  12. # Prior to saving the model, connect to murmur via dbus and update its settings.
  13. self.meta = self._getDbusMeta();
  14. def _getDbusMeta( self ):
  15. return dbus.Interface( dbus.SystemBus().get_object( self.dbus_base, '/' ), 'net.sourceforge.mumble.Meta' );
  16. def _getDbusServerObject( self, srvid):
  17. "Connects to DBus and returns an mmServer object representing this Murmur instance."
  18. if srvid not in self.getBootedServers():
  19. raise Exception, 'No murmur process with the given server ID (%d) is running and attached to system dbus under %s.' % ( srvid, self.meta );
  20. return dbus.Interface( dbus.SystemBus().get_object( self.dbus_base, '/%d' % srvid ), 'net.sourceforge.mumble.Murmur' );
  21. def getAllConf(self, srvid):
  22. return MumbleCtlDbus.converDbusTypeToNative(self.meta.getAllConf(dbus.Int32(srvid)))
  23. def setConf(self, srvid, key, value):
  24. self.meta.setConf(dbus.Int32( srvid ), key, value)
  25. def getDefaultConf(self):
  26. return MumbleCtlDbus.converDbusTypeToNative(self.meta.getDefaultConf())
  27. def deleteServer( self, srvid ):
  28. srvid = dbus.Int32( srvid )
  29. if self.meta.isBooted( srvid ):
  30. self.meta.stop( srvid )
  31. self.meta.deleteServer( srvid )
  32. def newServer(self):
  33. return self.meta.newServer()
  34. def registerPlayer(self, srvid, name):
  35. return MumbleCtlDbus.converDbusTypeToNative(self._getDbusServerObject(srvid).registerPlayer(name))
  36. def unregisterPlayer(self, srvid, mumbleid):
  37. self._getDbusServerObject(srvid).unregisterPlayer(dbus.Int32( mumbleid ))
  38. def getChannels(self, srvid):
  39. return MumbleCtlDbus.converDbusTypeToNative(self._getDbusServerObject(srvid).getChannels())
  40. def getPlayers(self, srvid):
  41. return MumbleCtlDbus.converDbusTypeToNative(self._getDbusServerObject(srvid).getPlayers())
  42. def getRegisteredPlayers(self, srvid):
  43. return MumbleCtlDbus.converDbusTypeToNative(self._getDbusServerObject(srvid).getRegisteredPlayers(''))
  44. def getACL(self, srvid, identifier):
  45. return MumbleCtlDbus.converDbusTypeToNative(self._getDbusServerObject(srvid).getACL(identifier))
  46. def setACL(self, srvid, acl):
  47. self._getDbusServerObject(srvid).setACL(*acl.pack())
  48. def getBootedServers(self):
  49. return MumbleCtlDbus.converDbusTypeToNative(self.meta.getBootedServers())
  50. def getAllServers(self):
  51. return MumbleCtlDbus.converDbusTypeToNative(self.meta.getAllServers())
  52. def setSuperUserPassword(self, srvid, value):
  53. self.meta.setSuperUserPassword(dbus.Int32(srvid), value)
  54. def setRegistration(self, srvid, mumbleid, name, email, password):
  55. return MumbleCtlDbus.converDbusTypeToNative(self._getDbusServerObject(srvid).setRegistration(dbus.Int32(mumbleid), dbus.String(name), dbus.String(email), dbus.String(password)))
  56. def getTexture(self, srvid, mumbleid):
  57. texture = self._getDbusServerObject(srvid).getTexture(dbus.Int32(mumbleid));
  58. if len(texture) == 0:
  59. raise ValueError( "No Texture has been set." );
  60. # this returns a list of bytes.
  61. # first 4 bytes: Length of uncompressed string, rest: compressed data
  62. orig_len = ( texture[0] << 24 ) | ( texture[1] << 16 ) | ( texture[2] << 8 ) | ( texture[3] );
  63. # convert rest to string and run decompress
  64. bytestr = "";
  65. for byte in texture[4:]:
  66. bytestr += pack( "B", int(byte) );
  67. decompressed = decompress( bytestr );
  68. # iterate over 4 byte chunks of the string
  69. imgdata = "";
  70. for idx in range( 0, orig_len, 4 ):
  71. # read 4 bytes = BGRA and convert to RGBA
  72. bgra = unpack( "4B", decompressed[idx:idx+4] );
  73. imgdata += pack( "4B", bgra[2], bgra[1], bgra[0], bgra[3] );
  74. # return an 600x60 RGBA image object created from the data
  75. return Image.fromstring( "RGBA", ( 600, 60 ), imgdata);
  76. def setTexture(self, srvid, mumbleid, infile):
  77. # open image, convert to RGBA, and resize to 600x60
  78. img = Image.open( infile ).convert( "RGBA" ).transform( ( 600, 60 ), Image.EXTENT, ( 0, 0, 600, 60 ) );
  79. # iterate over the list and pack everything into a string
  80. bgrastring = "";
  81. for ent in list( img.getdata() ):
  82. # ent is in RGBA format, but Murmur wants BGRA (ARGB inverse), so stuff needs
  83. # to be reordered when passed to pack()
  84. bgrastring += pack( "4B", ent[2], ent[1], ent[0], ent[3] );
  85. # compress using zlib
  86. compressed = compress( bgrastring );
  87. # pack the original length in 4 byte big endian, and concat the compressed
  88. # data to it to emulate qCompress().
  89. texture = pack( ">L", len(bgrastring) ) + compressed;
  90. # finally call murmur and set the texture
  91. self._getDbusServerObject(srvid).setTexture(dbus.Int32( mumbleid ), texture)
  92. @staticmethod
  93. def converDbusTypeToNative(data):
  94. #i know dbus.* type is extends python native type.
  95. #but dbus.* type is not native type. it's not good transparent for using Ice/Dbus.
  96. ret = None
  97. if isinstance(data, tuple) or type(data) is data.__class__ is dbus.Array or data.__class__ is dbus.Struct:
  98. ret = []
  99. for x in data:
  100. ret.append(MumbleCtlDbus.converDbusTypeToNative(x))
  101. elif data.__class__ is dbus.Dictionary:
  102. ret = {}
  103. for x in data.items():
  104. ret[MumbleCtlDbus.converDbusTypeToNative(x[0])] = MumbleCtlDbus.converDbusTypeToNative(x[1])
  105. else:
  106. if data.__class__ is dbus.Boolean:
  107. ret = bool(data)
  108. elif data.__class__ is dbus.String:
  109. ret = unicode(data)
  110. elif data.__class__ is dbus.Int32 or data.__class__ is dbus.UInt32:
  111. ret = int(data)
  112. elif data.__class__ is dbus.Byte:
  113. ret = byte(data)
  114. return ret