From 2549b610a84a5e17aad9d8dbc8422f0719709436 Mon Sep 17 00:00:00 2001 From: James Meyer Date: Thu, 27 Sep 2012 00:04:37 -0500 Subject: LinHES-system: enhance msg_client.py and msg_deamon.py to support : msg_client.py --clear --tag to clear the queue, with the --tag then the whole queue is cleared --msg --tag to add messages to que --kill kill whatever is currently being displayed --- abs/core/LinHES-system/msg_client.py | 31 ++- abs/core/LinHES-system/msg_daemon.py | 375 +++++++++++++++++++++++++++++++---- 2 files changed, 364 insertions(+), 42 deletions(-) diff --git a/abs/core/LinHES-system/msg_client.py b/abs/core/LinHES-system/msg_client.py index 3c53857..175933f 100755 --- a/abs/core/LinHES-system/msg_client.py +++ b/abs/core/LinHES-system/msg_client.py @@ -3,6 +3,8 @@ import socket import sys +import argparse +import pickle # Create a UDS socket sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) @@ -33,10 +35,25 @@ def send_message(message): if __name__ == "__main__": - if len(sys.argv) == 2: - send_message(sys.argv[1]) - else: - print "Unknown command" - print "usage: %s msg to display" % sys.argv[0] - sys.exit(2) - sys.exit(0) + parser = argparse.ArgumentParser() + + parser.add_argument('--tag', action='store', dest='tag',help='message tag') + parser.add_argument('--timeout', action='store', dest='timeout',help='time to display message') + action = parser.add_mutually_exclusive_group(required=True) + action.add_argument('--msg', action='store', dest='msg', help='Add message to the queue') + action.add_argument('--clear', action='store_true', help='Remove message from queue that match tag') + action.add_argument('--kill', action='store_true', help='Kill current msg thats displayed') + + results = parser.parse_args() + resultsdict = vars(results) + + if results.msg : + cmd = "msg" + elif results.clear: + cmd = "clear" + elif results.kill: + cmd = "kill" + + arg_dict = {'cmd':cmd , 'msg':resultsdict['msg'] , 'tag':resultsdict['tag'] , 'timeout':resultsdict['timeout']} + send_message(pickle.dumps(arg_dict)) + #sys.exit(0) diff --git a/abs/core/LinHES-system/msg_daemon.py b/abs/core/LinHES-system/msg_daemon.py index 5ca5b09..b766aae 100755 --- a/abs/core/LinHES-system/msg_daemon.py +++ b/abs/core/LinHES-system/msg_daemon.py @@ -4,43 +4,348 @@ import socket import sys import os -from subprocess import call +import pickle +import operator +import threading +import time +import aosd +import ConfigParser +import multiprocessing +import subprocess,signal + +sys.path.append('/etc') server_address = '/run/msg_socket' +class msg_aosd(): + def scroll(self,osd, width, height, display_time,position): + pos = position + step = 1 -# Make sure the socket does not already exist -try: - os.unlink(server_address) -except OSError: - if os.path.exists(server_address): - raise -# Create a UDS socket -sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) -# Bind the socket to the port -print >>sys.stderr, 'starting up on %s' % server_address -sock.bind(server_address) -#change permissions of socket -os.chmod(server_address,0777) - -# Listen for incoming connections -sock.listen(1) - -while True: - # Wait for a connection - connection, client_address = sock.accept() - try: - #print >>sys.stderr, 'connection from', client_address - msg="" - # Receive the data in small chunks and retransmit it - while True: - data = connection.recv(16) - msg+=data - if data: - continue + osd.set_position(pos, width, height) + (x, y, _, _) = osd.get_geometry() + osd.set_position_offset(width, height) + osd.show() + + x -= 1 + y += height - 1; + for i in range(1, height + 1, step): + osd.loop_for(5) + y -= step + osd.set_geometry(x, y, width, i) + + osd.set_position(pos, width, height) + osd.set_position_offset(-1, -1) + (x, y, _, _) = osd.get_geometry() + #time to display + osd.loop_for(display_time) + for i in range(height, 0, -step): + y += step + osd.set_geometry(x, y, width, i); + osd.loop_for(1); + + osd.hide(); + + def setup(self,font_color,font_type): + osd = aosd.AosdText() + osd.set_transparency(aosd.TRANSPARENCY_COMPOSITE) + if osd.get_transparency() != aosd.TRANSPARENCY_COMPOSITE: + osd.set_transparency(aosd.TRANSPARENCY_NONE) + + osd.geom_x_offset = 10 + osd.geom_y_offset = 0 + + osd.back_color = "white" + osd.back_opacity = 50 + + osd.shadow_color = "black" + osd.shadow_opacity = 127 + osd.shadow_x_offset = 2 + osd.shadow_y_offset = 2 + + osd.fore_color = font_color + osd.fore_opacity = 255 + + osd.set_font(font_type) + osd.wrap = aosd.PANGO_WRAP_WORD_CHAR + osd.alignment = aosd.PANGO_ALIGN_LEFT + osd.set_layout_width(osd.get_screen_wrap_width()) + return osd + + def set_string(self, osd, text): + osd.set_text(text) + return osd.get_text_size() + + def setup_config(self): + module_config = ConfigParser.RawConfigParser() + try: + module_config.read('/usr/MythVantage/etc/msg.cfg') + except: + pass + return module_config + + + + def display (self,flags,display_time=-1): + """ + parse the msg for display. + """ + try: + text,config_section=flags.split("|") + if config_section == '': + config_section="default" + except: + text=flags + config_section="default" + + module_config = self.setup_config() + + position=6 + font_color="green" + font_type="Times New Roman Italic 36" + + if display_time <= 0 : + try: + display_time = int(module_config.get(config_section,"display_time")) + except: + display_time = 5000 + pass + try: + position = int(module_config.get(config_section,"position")) + except: + pass + try: + font_color = module_config.get(config_section,"font_color") + except: + pass + try: + font_type = module_config.get(config_section,"font_type") + except: + pass + + #this bit of code converts a \n to EOL/BREAK + textline=text.split('\\n') + try: + textline.remove(' ') + except: + pass + text=chr(10).join(textline) + + #cmd = sub_process.Popen("/usr/bin/wall %s" % text,stdout=sub_process.PIPE,shell=True) + #data = cmd.communicate()[0] + osd = self.setup(font_color, font_type) + width, height = self.set_string(osd, text) + self.scroll(osd, width, height, display_time, position) + + return ("Message delivered") + + +class msg_xosd(): + """Crude wrapper for xosd_cat""" + def __init__ (self): + pass + + def set_default_values(self): + self.color="yellow" + self.outline="2" + self.outlinecolour="black" + self.shadow="0" + self.shadowcolour="black" + self.font="-adobe-helvetica-bold-*-*-*-34-*-*-*-*-*-*-*" + return + + def set_parameters(self): + xosd_cfg={} + file_name = "/etc/osd_cat.cfg" + try: + config_file = open(file_name) + except: + set_default_values() + return + + for line in config_file: + line = line.strip() + if line and line[0] is not "#" and line[-1] is not "=": + var, val = line.rsplit("=", 1) + val = val.split("#")[0] + val = val.strip('"') + xosd_cfg[var.strip()] = val.strip() + self.color = xosd_cfg['color'] + self.outline = xosd_cfg['outline'] + self.outlinecolour = xosd_cfg['outlinecolour'] + self.shadow = xosd_cfg['shadow'] + self.shadowcolour = xosd_cfg['shadowcolour'] + self.font = xosd_cfg['font'] + + def display(self,msg,display_time): + self.set_parameters() + cmd = "echo -e \"%s\" | DISPLAY=127.0.0.1:0 osd_cat --pos=middle --align=center --offset=200 --delay=%s --color=%s --outline=%s --outlinecolour=%s --shadow=%s --shadowcolour=%s --font=\"%s\"" %(msg,display_time,self.color,self.outline,self.outlinecolour,self.shadow,self.shadowcolour,self.font) + #set a process group on the OS, so that the kill gets them all. No one survives or becomes a zombie + self.p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,preexec_fn=os.setsid) + self.processID = self.p.pid + stdout,stderr = self.p.communicate() + + def kill(self): + try: + os.killpg(self.processID,signal.SIGTERM) + except: + pass + +class Msg_Queue(): + def __init__(self): + self.msglist=[] + self.msg_slot = 0 + + def get_msg(self): + return self.msglist.pop(0) + pass + + def add_msg(self,cmddict): + #print "Adding msg to msg queue" + self.inc_last_msg_slot() + cmddict['slot'] = self.msg_slot + self.msglist.append(cmddict) + + + def clear_msg(self,msg_tag): + #print "Clearing out list of %s" %msg_tag + #loop over list in reverse + for i in xrange(len(self.msglist) - 1, -1, -1): + #access list by index, look at the key tag + if self.msglist[i]['tag'] == msg_tag: + del self.msglist[i] + + def clear(self): + #print "Clearing out entire queue" + del self.msglist[:] + + def sort(self,keyvalue): + self.msglist.sort(key=operator.itemgetter(keyvalue)) + + def search(self,key,value): + pass + + def print_queue(self): + print "############################" + for i in self.msglist: + for key, value in i.iteritems(): + print key,":", value + print "-----" + + def get_last_msg_slot(self): + return self.msg_slot + + def inc_last_msg_slot(self): + self.msg_slot = self.msg_slot + 1 + + +class msg_queue_runner(threading.Thread): + """Threaded Queue runner for testing things""" + def __init__(self, msg_queue): + threading.Thread.__init__(self) + self.msg_queue = msg_queue + self.out_msg = msg_aosd() + self.out_xosd = msg_xosd() + + def get_current_style(self): + style = "default" + if os.path.exists('/etc/X11/WINDOWMANAGER'): + command = ['bash', '-c', 'source /etc/X11/WINDOWMANAGER && echo $STARTUP_STYLE'] + proc = subprocess.Popen(command, stdout = subprocess.PIPE) + + for line in proc.stdout: + if line.strip() == "": + style = "default" else: - call(["/usr/LH/bin/lh_message.sh", msg]) - break + style = line.strip() + break + proc.communicate() + else: + style = "default" + return style + + + def kill_current(self): + style = self.get_current_style() + #print "Killing current display" + if style == "enhanced": + self.p.terminate() + elif style == "default": + #self.p.terminate() + self.out_xosd.kill() + + def run(self): + while True: + try: + msgdict = self.msg_queue.get_msg() + style = self.get_current_style() + if msgdict['timeout'] == None: + display_time = 3 + + # display message here + msgtext = msgdict['msg'] + if style == "enhanced": + display_time = display_time * 1000 + self.p = multiprocessing.Process(target=self.out_msg.display, args=(msgtext,display_time)) + self.p.start() + self.p.join() + elif style == "default": + display_time = int(msgdict['timeout']) + self.out_xosd.display(msgtext,display_time) + + except: + time.sleep(1) + continue + + +msg_queue = Msg_Queue() + + +if __name__ == "__main__": + # Make sure the socket does not already exist + try: + os.unlink(server_address) + except OSError: + if os.path.exists(server_address): + raise + # Create a UDS socket + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + # Bind the socket to the port + print >>sys.stderr, 'starting up on %s' % server_address + sock.bind(server_address) + #change permissions of socket + os.chmod(server_address,0777) + + # Listen for incoming connections + sock.listen(1) + #start msg display thread + msgthread = msg_queue_runner(msg_queue) + msgthread.setDaemon(True) + msgthread.start() + + + #main loop that reads in the cmddict, never exits + while True: + # Wait for a connection + connection, client_address = sock.accept() + try: + sf = connection.makefile("r+b", bufsize=0) + data = sf.read() + cmddict = (pickle.loads(data)) + + if cmddict['cmd'] == "msg": + #add to msg_queue + msg_queue.add_msg(cmddict) + elif cmddict['cmd'] == 'clear': + if cmddict['tag'] == '' or cmddict['tag'] == None : + msg_queue.clear() + else: + msg_queue.clear_msg(cmddict['tag']) + elif cmddict['cmd'] == 'kill': + msgthread.kill_current() + ## call(["/usr/LH/bin/lh_message.sh", msg]) + #break + finally: + # Clean up the connection + connection.close() + - finally: - # Clean up the connection - connection.close() -- cgit v0.12