forked from realXtend/taiga
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Curmur controls scripts for EC_VoiceChannel usage
- Loading branch information
mattiku
committed
Nov 11, 2010
1 parent
613b5e9
commit 56b6d43
Showing
5 changed files
with
303 additions
and
0 deletions.
There are no files selected for viewing
96 changes: 96 additions & 0 deletions
96
bin/ScriptEngines/PythonScript/mumble/MurmurControl/MumbleChannelManager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import sys | ||
import Ice | ||
import Murmur_ice | ||
|
||
class ChannelManager: | ||
''' | ||
All channels created by this script are marked by setting description field to 'EC_VoiceChannel' | ||
By calling 'remove_channel' onl subchannels marked as 'EC_VoiceChannel' are removed | ||
@todo: Channel name validator | ||
''' | ||
ROOT_ID = -1 | ||
def __init__(self, address, port): | ||
ic = Ice.initialize(sys.argv) | ||
base = ic.stringToProxy("Meta:tcp -h "+str(address)+" -p "+str(port)) | ||
meta_proxy = Murmur_ice._M_Murmur.MetaPrx.checkedCast(base) | ||
list = meta_proxy.getBootedServers() | ||
self._server_proxy = list[0] | ||
|
||
def get_or_create_channel(self, full_name): | ||
channel = self._get_channel_by_full_name(full_name) | ||
if channel is None: | ||
self._create_channel(full_name) | ||
|
||
def remove_channel(self, full_name): | ||
names = full_name.split('/') | ||
for depth in range(0,len(names)): | ||
name = names[depth] | ||
sub_channel_name = "" | ||
for i in range(0, len(names) - depth): | ||
if i == 0: | ||
sub_channel_name = names[i] | ||
else: | ||
sub_channel_name = sub_channel_name + '/'+ names[i] | ||
channel = self._get_channel_by_full_name(sub_channel_name) | ||
if channel is not None and channel.description == "EC_VoiceChannel" and len(self._get_children(channel)) == 0: | ||
self._server_proxy.removeChannel(channel.id) | ||
|
||
def _get_children(self, channel): | ||
children = [] | ||
channels = self._server_proxy.getChannels().values() | ||
for c in channels: | ||
if c.parent == channel.id: | ||
children.append(c) | ||
return children | ||
|
||
|
||
def _get_channel_by_full_name(self, full_name): | ||
''' | ||
return a channel with parent channels descriped by given 'full_name' | ||
''' | ||
names = full_name.split('/') | ||
tree = self._server_proxy.getTree() | ||
root = tree.c | ||
children = tree.children | ||
channel = None | ||
for depth in range(0,len(names)): | ||
name = names[depth] | ||
channel = None | ||
for child in children: | ||
if child.c.name == name: | ||
channel = child.c | ||
break | ||
if channel is None: | ||
return None | ||
children = child.children | ||
return channel | ||
|
||
def _create_channel(self, full_name): | ||
''' Created all necessary channels | ||
eg. "channelA/ChannelB" -> channelA, channelB | ||
''' | ||
names = full_name.split('/') | ||
tree = self._server_proxy.getTree() | ||
root = tree.c | ||
children = tree.children | ||
next_parent_id = tree.c.id | ||
for depth in range(0,len(names)): | ||
name = names[depth] | ||
channel = None | ||
for child in children: | ||
if child.c.name == name: | ||
channel = child.c | ||
next_parent_id = channel.id | ||
break | ||
if channel is None: | ||
id = self._server_proxy.addChannel(name, next_parent_id) | ||
new_channel = self._server_proxy.getChannels()[id] | ||
if new_channel is not None: | ||
new_channel.temporary = True # DOESN'T WORK! | ||
new_channel.description = "EC_VoiceChannel" | ||
self._server_proxy.setChannelState(new_channel) | ||
if depth < len(names)-1: | ||
self._create_channel(full_name) # recursive call ! | ||
return | ||
children = child.children |
141 changes: 141 additions & 0 deletions
141
bin/ScriptEngines/PythonScript/mumble/MurmurControl/MurmurControlService.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import sys, time | ||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer | ||
from MumbleChannelManager import ChannelManager | ||
|
||
''' | ||
Makes possible to add and delete Murmur channels using http requests. | ||
request format: <server host:port>/<secret>/CREATE_CHANNEL/<channel name> | ||
<server host:port>/<secret>/REMOVE_CHANNEL/<channel name> | ||
Idea of the secret is that only scripts which know the <Secret> are able to | ||
create or delete the channels | ||
''' | ||
|
||
SERVER_HOST_NAME = '' | ||
SERVER_PORT_NUMBER = 9999 | ||
|
||
SECRET = "qwerty123" # REMEMBER TO CHANGE THIS !!! | ||
|
||
MURMUR_HOST_NAME = "127.0.0.1" | ||
MURMUR_PORT_NUMBER = 6502 | ||
|
||
class RequestHandler(BaseHTTPRequestHandler): | ||
|
||
def do_GET(self): | ||
from_address, from_port = self.client_address | ||
if self._is_remove_request() and self._is_secret_ok(): | ||
full_name = self._get_full_channel_name() | ||
if full_name is not None: | ||
print(time.asctime() + " Remove request from %s: %s" % (from_address, full_name)) | ||
self._channel_manager = ChannelManager(MURMUR_HOST_NAME, MURMUR_PORT_NUMBER) | ||
self._channel_manager.remove_channel(full_name) | ||
self.send_response(200) | ||
self.send_header("Content-type", "text/html") | ||
self.end_headers() | ||
self.wfile.write("OK") | ||
return | ||
|
||
if self._is_create_request() and self._is_secret_ok(): | ||
full_name = self._get_full_channel_name() | ||
|
||
if full_name is not None: | ||
print(time.asctime() + " Create request from %s: %s" % (from_address, full_name)) | ||
self._channel_manager = ChannelManager(MURMUR_HOST_NAME, MURMUR_PORT_NUMBER) | ||
self._channel_manager.get_or_create_channel(full_name) | ||
self.send_response(200) | ||
self.send_header("Content-type", "text/html") | ||
self.end_headers() | ||
self.wfile.write("OK") | ||
return | ||
|
||
print(time.asctime() + " Bad request from %s: %s" % (from_address, self.path)) | ||
self.send_response(404) | ||
self.send_header("Content-type", "text/html") | ||
self.end_headers() | ||
self.wfile.write("FAIL") | ||
|
||
def _is_secret_ok(self): | ||
'''return True if the <secret> was corrent. Otherwise return false | ||
@param s http request | ||
''' | ||
try: | ||
secret = self.path.strip('/').split('/')[0] | ||
if secret == SECRET: | ||
return True | ||
else: | ||
return False | ||
except: | ||
return False | ||
|
||
def _is_remove_request(self): | ||
''' return True if the request was REMOVE_CHANNEL otherwise return False | ||
@param s http request | ||
''' | ||
try: | ||
command = self.path.strip('/').split('/')[1] | ||
if command == "REMOVE_CHANNEL": | ||
return True | ||
else: | ||
return False | ||
except: | ||
return False | ||
|
||
def _is_create_request(self): | ||
''' return True if the request was REMOVE_CHANNEL otherwise return False | ||
@param s http request | ||
''' | ||
try: | ||
command = self.path.strip('/').split('/')[1] | ||
if command == "CREATE_CHANNEL": | ||
return True | ||
else: | ||
return False | ||
except: | ||
return False | ||
|
||
def _get_full_channel_name(self): | ||
''' Return the full channel name in the request. | ||
if channel name cannot parsed from the request then return None | ||
''' | ||
try: | ||
parts = self.path.strip('/').split('/') | ||
full_name = None | ||
for i in range(2, len(parts)): | ||
if full_name is None: | ||
full_name = parts[i] | ||
else: | ||
full_name = full_name + "/" + parts[i] | ||
return full_name | ||
except: | ||
return None | ||
|
||
def log_message(format, *args): | ||
''' to disable default log messages''' | ||
return | ||
|
||
|
||
|
||
class Service(): | ||
|
||
def __init__(self): | ||
self._httpd = HTTPServer((SERVER_HOST_NAME, SERVER_PORT_NUMBER), RequestHandler) | ||
|
||
def run(self): | ||
try: | ||
self._httpd.serve_forever() | ||
except KeyboardInterrupt: | ||
pass | ||
self._httpd.server_close() | ||
|
||
if __name__ == '__main__': | ||
print ("To create and delete channels:") | ||
print (" http://%s:%s/%s/CREATE_CHANNEL/MyChannel/MySubChannel" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER, SECRET)) | ||
print (" http://%s:%s/%s/REMOVE_CHANNEL/MyChannel/MySubChannel" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER, SECRET)) | ||
print ("") | ||
print time.asctime(), "Service Starts - %s:%s" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER) | ||
print ("Press CRTL-C to quit service.") | ||
service = Service() | ||
service.run() | ||
print time.asctime(), "Service Stops - %s:%s" % (SERVER_HOST_NAME, SERVER_PORT_NUMBER) | ||
|
7 changes: 7 additions & 0 deletions
7
bin/ScriptEngines/PythonScript/mumble/MurmurControl/readme.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
If you want to enabled automatic mumble channel management: | ||
|
||
* run MurmurControlService.py script. | ||
- this must be run at the same computer than murmur server is running | ||
- This starts http server and creates and removes channels according requests from 'voicechannel.py' script. | ||
* set rex property 'ServerScriptClass' to 'voicechannel' for the object having EC_VoiceChannel component | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
print "Initializing voicehannel" | ||
import voicehannel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import urllib | ||
import rxactor | ||
|
||
''' | ||
This script ensures that there is a mumble channel existing for the EC_VoiceChannel component. | ||
When channelid attribute of EC_VoiceChannel component is changed the old channel is removed. | ||
''' | ||
|
||
SERVER_ADDRESS = "127.0.0.1:9999" # address of computer running MurmurControl/MurmurControlService.py | ||
SECRET = "qwerty123" # REMEMBER TO CHANGE THIS !!! @see MurmurControl/MurmurControlService.py | ||
|
||
CREATE_BASE_URL = "http://"+SERVER_ADDRESS+"/"+SECRET+"/CREATE_CHANNEL/" #todo get from ini | ||
REMOVE_BASE_URL = "http://"+SERVER_ADDRESS+"/"+SECRET+"/REMOVE_CHANNEL/" #todo get from ini | ||
|
||
class ChannelChecker(rxactor.Actor): | ||
@staticmethod | ||
def GetScriptClassName(): | ||
return "voicechannel.ChannelChecker" | ||
|
||
def EventCreated(self): | ||
self._cleanup_url = None | ||
self.SetTimer(0.5, True) # We poll EC_VoiceChannel for channelid attribute | ||
self.create_channel() | ||
# @todo replace polling with proper event handlers | ||
#rex_objects = self.MyWorld.CS.World.EventManager.OnClientConnect += self.clientConnectedHandle | ||
|
||
def EventDestroyed(self): | ||
self.cleanup() | ||
|
||
def create_channel(self): | ||
ec = self.rexGetECAttributes("EC_VoiceChannel") | ||
if ec is not None: | ||
cleanup_url = REMOVE_BASE_URL + str( ec["channelid"] ) | ||
if self._cleanup_url != cleanup_url: | ||
url = CREATE_BASE_URL + str( ec["channelid"] ) | ||
urllib.urlopen(url) | ||
self.cleanup() | ||
self._cleanup_url = cleanup_url | ||
|
||
def EventTimer(self): | ||
self.create_channel() | ||
|
||
def cleanup(self): | ||
if self._cleanup_url is not None: | ||
urllib.urlopen(self._cleanup_url) | ||
self._cleanup_url = None | ||
|
||
# @todo replace polling with proper event handlers | ||
#def clientConnectedHandle(self, client_core): | ||
# client_core.OnPrimFreeData += self.onPrimFreeData | ||
|
||
#def onPrimFreeData(self, client, data): | ||
# self.create_channel() | ||
|
||
|
||
|